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;
       }