const char * UsageLines [] = {
	"Usage: linetopbm (width) (height)",
	"Reads space-separated points, from standard input, in the form",
	"\tacross,down",
	"\twhere across and down are positive or negative integers.",
	"Writes, to standard output, a P4 PBM image.",
	"A line one pixel wide will join the points on each input line",
	"\t(that has at least two points).",
	"On each input line, everything after # is treated as a comment.",
	"The leftmost column of pixels is considered - (width)/2 across.",
	"The topmost row of pixels is considered - (height)/2 down.",
	"August 26, 2011.  Newest is at gopher -p users/julianbr sdf.org",
	};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );


struct Segment {
	int across1;
	int down1;
	int across2;
	int down2;
	struct Segment * next;
	};

#include <stdlib.h>
#include <stdio.h>


int ReadSegments (struct Segment * * SegmentsPtr)
	{
	struct Segment * * SegmentPtr;
	unsigned int LineNum;
	int IsNegative, FoundAcross, across, FoundDown, down;
	int PreviousAcross, PreviousDown, PreviousPoint;
	int c, ok;

	ok = 1;
	LineNum = 0;
	SegmentsPtr [0] = NULL;
	SegmentPtr = SegmentsPtr;
	c = getchar ();
	while (c != EOF) {
		LineNum++;
		PreviousPoint = 0;
		while (c != EOF && c != '\n') {
			while (c == ' ')
				c = getchar ();
			/* read across */
			IsNegative = 0;
			if (c == '+')
				c = getchar ();
			else if (c == '-') {
				IsNegative = 1;
				c = getchar ();
				}
			FoundAcross = 0;
			across = 0;
			while (c >= '0' && c <= '9') {
				FoundAcross = 1;
				across = 10*across + (c - '0');
				c = getchar ();
				}
			if (IsNegative)
				across = - across;
			if (c == ',')
				c = getchar ();
			else
				FoundAcross = 0;

			/* read down */
			IsNegative = 0;
			if (c == '+')
				c = getchar ();
			else if (c == '-') {
				IsNegative = 1;
				c = getchar ();
				}
			FoundDown = 0;
			down = 0;
			while (c >= '0' && c <= '9') {
				FoundDown = 1;
				down = 10*down + (c - '0');
				c = getchar ();
				}
			if (IsNegative)
				down = - down;

			if (c != EOF && c != '\n' && c != ' ' && c != '#') {
				fprintf (stderr, "***linetopbm: Improper");
				fprintf (stderr, " '%c'", c);
				fprintf (stderr, " in line #%u.\n", LineNum);
				while (c != EOF && c != '\n' && c != ' '
							&& c != '#')
					c = getchar ();
				ok = 0;
				}
			else if (FoundAcross && !FoundDown) {
				fprintf (stderr, "***linetopbm: Incomplete");
				
				fprintf (stderr, " across,down");
				fprintf (stderr, " in line #%u.\n", LineNum);
				ok = 0;
				}
			else if (FoundAcross && FoundDown) {
				if (PreviousPoint) {
					/* Add segment */;
					SegmentPtr [0] = malloc (
						sizeof (SegmentPtr [0] [0] ) );
					if (SegmentPtr [0] == NULL) {
						fprintf (stderr, "***");
						fprintf (stderr, "linetopbm:");
						fprintf (stderr, " Not enough");
						fprintf (stderr, " memory.\n");
						ok = 0;
						}
					else {
						SegmentPtr [0]->across1
							= PreviousAcross;
						SegmentPtr [0]->down1
							= PreviousDown;
						SegmentPtr [0]->across2
							= across;
						SegmentPtr [0]->down2
							= down;
						SegmentPtr [0]->next
							= NULL;
						SegmentPtr
						= & SegmentPtr [0]->next;
						}
					}
				PreviousPoint = 1;
				PreviousAcross = across;
				PreviousDown = down;
				}
			if (c == '#') {
				while (c != EOF && c != '\n')
					c = getchar ();
				}
			}
		if (c != EOF)
			c = getchar ();
		}
	return ok;
	}


int IsOnSegment (int across, int down, struct Segment * Segments)
	{
	struct Segment * Segment;
	int m, n, x, y, temp;

	Segment = Segments;
	while (Segment != NULL) {
		if (Segment->across1 > Segment->across2) {
			m = Segment->across1 - Segment->across2 + 1;
			y = Segment->across1 - across;
			}
		else {
			m = Segment->across2 - Segment->across1 + 1;
			y = across - Segment->across1;
			}
		if (Segment->down1 > Segment->down2) {
			n = Segment->down1 - Segment->down2 + 1;
			x = Segment->down1 - down;
			}
		else {
			n = Segment->down2 - Segment->down1 + 1;
			x = down - Segment->down1;
			}
		if (m > n) {
			temp = n;
			n = m;
			m = temp;
			temp = y;
			y = x;
			x = temp;
			}
		if (x >= 0 && x < n) {
			if (y == (m/2 + m*x)/n)
				return 1;
			}
		Segment = Segment->next;
		}
	return 0;
	}


void WriteSegments (
		struct Segment * Segments,
		int width,
		int height)
	{
	/* int i, j, k, m, LineSize, OutputBuffer, pixel; */
	int across, down, OutputWeight, OutputValue;

	printf ("P4\n%d %d\n", width, height);
	for (down = - height/2; down < height - height/2; down++) {
		OutputWeight = 128;
		OutputValue = 0;
		for (across = - width/2; across < width - width/2; across++) {
			if (IsOnSegment (across, down, Segments) )
				OutputValue += OutputWeight;
			OutputWeight /= 2;
			if (OutputWeight == 0) {
				putchar (OutputValue);
				OutputWeight = 128;
				OutputValue = 0;
				}
			}
		if (OutputWeight < 128)
			putchar (OutputValue);
		}
	}


void CloseSegments (struct Segment * Segments)
	{
	struct Segment * Segment, * NextSegment;

	Segment = Segments;
	while (Segment != NULL) {
		NextSegment = Segment->next;
		free (Segment);
		Segment = NextSegment;
		}
	}


int main (int argc, char * argv [] )
	{
	struct Segment * Segments;
	int width, height, i;
	char c;

	if (argc < 2) {
		for (i = 0; i < NumUsageLines; i++)
			printf ("%s\n", UsageLines [i] );
		}
	else if (argc == 3
			&& sscanf (argv [1], "%d%c", & width, & c) == 1
			&& width > 0
			&& sscanf (argv [2], "%d%c", & height, & c) == 1
			&& height > 0) {
		if (ReadSegments (& Segments) )
			WriteSegments (Segments, width, height);
		CloseSegments (Segments);
		}
	else {
		fprintf (stderr, "Usage: linetopbm");
		fprintf (stderr, " (width) (height)\n");
		}
	return 0;
	}