const char * UsageLines [] = {
	"Usage: circletopbm (width) (height)",
	"Writes unfilled circles to standard output as a PBM image.",
	"Each standard input line is of the form:",
	"\t(across1),(down1) (radius) [# (comment) ]",
	"Topmost row of pixels is considered - (height)/2 down.",
	"Leftmost column of pixels is considered - (width)/2 across.",
	"February 25, 2011.  Newest is at gopher -p users/julianbr sdf.org",
	};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );


struct  Circle {
	int across, down, radius;
	struct Circle * next;
	};

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


void ReadCircles (struct Circle * * CirclesPtr)
	{
	struct Circle * * CirclePtr;
	unsigned long int LineNum;
	int across, down, radius;
	int IsEmpty, IsNegative, FoundRadius;
	char c;

	LineNum = 0;
	CirclesPtr [0] = NULL;
	CirclePtr = CirclesPtr;
	c = getchar ();
	while (c != EOF) {
		LineNum++;
		IsEmpty = 1;
		while (c == ' ')
			c = getchar ();
		if (c != EOF && c != '\n' && c != '#')
			IsEmpty = 0;
		IsNegative = 0;
		if (c == '-')
			IsNegative = 1;
		if (c == '+' || c == '-')
			c = getchar ();
		across = 0;
		while (c >= '0' && c <= '9') {
			across = 10*across + (c - '0');
			c = getchar ();
			}
		if (IsNegative)
			across = - across;
		if (c == ',')
			c = getchar ();
		IsNegative = 0;
		if (c == '-')
			IsNegative = 1;
		if (c == '+' || c == '-')
			c = getchar ();
		down = 0;
		while (c >= '0' && c <= '9') {
			down = 10*down + (c - '0');
			c = getchar ();
			}
		if (IsNegative)
			down = - down;
		while (c == ' ')
			c = getchar ();
		IsNegative = 0;
		if (c == '-')
			IsNegative = 1;
		if (c == '+' || c == '-')
			c = getchar ();
		FoundRadius = 0;
		radius = 0;
		while (c >= '0' && c <= '9') {
			FoundRadius = 1;
			radius = 10*radius + (c - '0');
			c = getchar ();
			}
		if (IsNegative)
			radius = - radius;
		while (c == ' ')
			c = getchar ();
		if (c != EOF && c != '\n' && c != '#') {
			fprintf (stderr, "***circletopbm: Improper");
			fprintf (stderr, " '%c'", c);
			fprintf (stderr, " line %lu\n", LineNum);
			}
		else if (!IsEmpty && !FoundRadius) {
			fprintf (stderr, "***circletopbm: Incomplete");
			fprintf (stderr, " data");
			fprintf (stderr, " in line #%lu\n", LineNum);
			}
		else if (!IsEmpty) {
			CirclePtr [0] = malloc (sizeof (CirclePtr [0] [0] ) );
			if (CirclePtr [0] == NULL) {
				fprintf (stderr, "***circletopbm: Not");
				fprintf (stderr, " enough memory in");
				fprintf (stderr, " line #%lu\n", LineNum);
				}
			else {
				CirclePtr [0]->across = across;
				CirclePtr [0]->down = down;
				CirclePtr [0]->radius = radius;
				CirclePtr [0]->next = NULL;
				CirclePtr = & CirclePtr [0]->next;
				}
			}
		while (c != EOF && c != '\n')
			c = getchar ();
		if (c != EOF)
			c = getchar ();
		}
	}


void WriteCircles (
		int width, int height,
		struct Circle * Circles)
	{
	struct Circle * Circle;
	int across, down, x, y, temp;
	int OutputWeight, OutputValue, IsDark, radius2;

	printf ("P4\n");
	printf ("%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++) {
			IsDark = 0;
			Circle = Circles;
			while (Circle != NULL) {
				radius2 = Circle->radius*Circle->radius;
				x = across - Circle->across;
				y = down - Circle->down;
				if (x < 0)
					x = - x;
				if (y < 0)
					y = - y;
				if (x < y) {
					temp = x;
					x = y;
					y = temp;
					}
				if ((x*x + y*y <= radius2
						&& x*x + x + 1 + y*y > radius2)
				|| (x*x + y*y >= radius2
						&& x*x - x + y*y < radius2) )
					IsDark = 1;
				Circle = Circle->next;
				}
			if (IsDark)
				OutputValue += OutputWeight;
			OutputWeight /= 2;
			if (OutputWeight == 0) {
				putchar (OutputValue);
				OutputWeight = 128;
				OutputValue = 0;
				}
			}
		if (OutputWeight < 128)
			putchar (OutputValue);
		}
	}


void CloseCircles (struct Circle * Circles)
	{
	struct Circle * Circle, * NextCircle;

	Circle = Circles;
	while (Circle != NULL) {
		NextCircle = Circle->next;
		free (Circle);
		Circle = NextCircle;
		}
	}


int main (int argc, char * argv [] )
	{
	struct Circle * Circles;
	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) {
		ReadCircles (& Circles);
		WriteCircles (width, height, Circles);
		CloseCircles (Circles);
		}
	else {
		fprintf (stderr, "***Usage: circletopbm");
		fprintf (stderr, " (width) (height)\n");
		}
	return 0;
	}