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

#define MAX_LIN_LEN 1024
#define MAX_ERRORS    16
#define MAX_DRINKS  1024
#define ALC_UNIT    0.0275

#define LIMIT_ACC_QUANTITY     60.0
#define LIMIT_ACC_SQ_QUANTITY 200.0
#define LIMIT_NUM_ALC_DAYS     12

#define HEADER_1 "   ALCOBOL Compiler 2001-12-28 13:40:00 MET\n"
#define HEADER_2 "   ALCOBOL Compiler 2001-12-29 22:22:22 MET\n"
#define HEADER_3 "   ALCOBOL Compiler 2003-08-03 17:00:00 MEST\n"
#define HEADER_4 "   ALCOBOL Compiler 2003-12-13 19:38:57 MET\n"



FILE          *dp;
char          data_path_name [127];
int           verbose          = 0;
int           first_line       = 0;
int           last_line        = 2000000000;
int           line             = 1;
int           num_declarations = 0;
int           qdebug           = 0;
int	      dump_alcolines   = 0;
int	      dump_drinks      = 0;
int	      dump_dt          = 0;
int	      dump_m           = 0;
int           what_path_file   = 0;
int           check_year       = 0;
int           check_month      = 0;
int           check_day        = 0;

int           num_errors_00 = 0; /* all errors */
int           num_errors_01 = 0;
int           num_errors_02 = 0;
int           num_errors_03 = 0;
int           num_errors_04 = 0;
int           num_errors_05 = 0;
int           num_errors_06 = 0;
int           num_errors_07 = 0;
int           num_errors_08 = 0;
int           num_errors_09 = 0;

int           num_errors_10 = 0;
int           num_errors_11 = 0;
int           num_errors_12 = 0;
int           num_errors_13 = 0;
int           num_errors_14 = 0;
int           num_errors_15 = 0;
int           num_errors_16 = 0;
int           num_errors_17 = 0;
int           num_errors_18 = 0;
int           num_errors_19 = 0;

char          qqqq = ' ';
double        altogether_quantity = 0.0;

typedef struct {int           qtype;
                double        qfloat;
                int           qint;
                int           qyear;
                int           qmonth;
                int           qday;
                char          qstring [72];}
        qtoken_type;

typedef struct {char          drink [72];
                int           drink_len;
                double        percentage;
                double        default_size;
                int           used;}
        qdrink_type;

typedef struct alcoline_type *alcoline_type_p;

typedef struct alcoline_type
               {char            person [72];
                int             person_len;
                char            place [72];
                int             place_len;
                double          quantity;
                char            drink [72];
                int             drink_len;
                int             year;
                int             month;
                int             day;
		int             line_number;
                int             sequence_number;
                alcoline_type_p next;}
	alcoline_type;

typedef struct daily_consumption_type *daily_consumption_type_p;

typedef struct daily_consumption_type
               {double          quantity;
		double          sq_quantity;
                int             year;
                int             month;
                int             day;
                int             sequence_number;
                daily_consumption_type_p next;}
        daily_consumption_type;

typedef struct monthly_consumption_type *monthly_consumption_type_p;

typedef struct monthly_consumption_type
               {double          acc_quantity;
		double          acc_sq_quantity;
		int             first_alc_day;
		int             last_alc_day;
	        int             num_alc_days;
                int             year;
                int             month;
                monthly_consumption_type_p next;}
        monthly_consumption_type;

/* here are our lists : */

alcoline_type_p            alcolines                   = 0;
alcoline_type_p            current_alcoline            = 0;

daily_consumption_type_p   daily_consumption           = 0;
daily_consumption_type_p   current_daily_consumption   = 0;

monthly_consumption_type_p monthly_consumption         = 0;
monthly_consumption_type_p current_monthly_consumption = 0;

int number_of_drinks = 0;

qdrink_type drinks [MAX_DRINKS];

qtoken_type qtoken;

#define Q_NOTHING          0
#define Q_ALCOLINES_BEGIN  1
#define Q_ALCOLINES_END    2
#define Q_DATE             3
#define Q_INT              4
#define Q_FLOAT            5
#define Q_NAME             6
#define Q_SEPARATOR        7
#define Q_LINE_END         8
#define Q_FILE_END         9
#define Q_DECLARE         10
#define Q_DEFAULT         11



void help (char *q);

void analyze_data ();

void qget_token ();

void printf_qtoken ();

void qgetch ();

void qerror (int q);

void create_daily_tables ();

void create_monthly_tables ();

void summary ();

void error_recovery ();

void check_sequenced_date ();



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



main (int argc, char *argv [])

{
   int  lp;
   int  qq;
   char qqq;
   int  num_bytes;

   printf ("\n   ALCOBOL Compiler\n\n");

   qq = 1;
   while (qq < argc)
   {
      if ('-' == argv[qq][0])
      {
	 if ((!strcmp("-h", argv[qq])) || (!strcmp("--help", argv[qq])))
         {
	    help (argv[0]);
	    exit (6174);
         }
	 else if ((!strcmp("-v", argv[qq])) || (!strcmp("--verbose", argv[qq])))
         {
	    verbose++;
            printf (">>>   verbosity %i\n", verbose);
         }
	 else if ((!strcmp("-pf", argv[qq])) || (!strcmp("--pathfile", argv[qq])))
         {
	    what_path_file++;
            printf (">>>   number of path file %i\n", what_path_file);
         }
	 else if ((!strcmp("-da", argv[qq])) || (!strcmp("--dumpalcolines", argv[qq])))
         {
	    dump_alcolines++;
            printf (">>>   dump alcolines %i\n", dump_alcolines);
         }
	 else if ((!strcmp("-dd", argv[qq])) || (!strcmp("--dumpdrinks", argv[qq])))
         {
	    dump_drinks++;
            printf (">>>   dump drinks %i\n", dump_drinks);
         }
	 else if ((!strcmp("-dt", argv[qq])) || (!strcmp("--dumpdaily", argv[qq])))
         {
	    dump_dt++;
            printf (">>>   dump daily table %i\n", dump_dt);
         }
	 else if ((!strcmp("-dm", argv[qq])) || (!strcmp("--dumpmonthly", argv[qq])))
         {
	    dump_m++;
            printf (">>>   dump monthly table %i\n", dump_m);
         }
	 else if ((!strcmp("-f", argv[qq])) || (!strcmp("--first", argv[qq])))
         {
	    qq++;
            if (qq < argc)
	    {
	       first_line = atoi (argv[qq]);
	    }
            else
            {
	       first_line = 0;
            }
            printf (">>>   first line %i\n", first_line);
         }
	 else if ((!strcmp("-l", argv[qq])) || (!strcmp("--last", argv[qq])))
         {
	    qq++;
            if (qq < argc)
	    {
	       last_line = atoi (argv[qq]);
	    }
            else
            {
	       last_line = 2000000000;
            }
            printf (">>>   last line %i\n", last_line);
         }
         else
         {
            printf (">>>   Do not understand: %s\n", argv [qq]);
         }
         qq++;
      }
      else
      {
         break;
      }
   }

#ifdef OLD_FILE_NAMES

   switch (what_path_file)
   {
      case 0 : strcpy (path_file_name, "./alcobol.data.path.00"); break;
      case 1 : strcpy (path_file_name, "./alcobol.data.path.01"); break;
      case 2 : strcpy (path_file_name, "./alcobol.data.path.02"); break;
      case 3 : strcpy (path_file_name, "./alcobol.data.path.03"); break;
      case 4 : strcpy (path_file_name, "./alcobol.data.path.04"); break;
      case 5 : strcpy (path_file_name, "./alcobol.data.path.05"); break;
      case 6 : strcpy (path_file_name, "./alcobol.data.path.06"); break;
      case 7 : strcpy (path_file_name, "./alcobol.data.path.07"); break;
      case 8 : strcpy (path_file_name, "./alcobol.data.path.08"); break;
      case 9 : strcpy (path_file_name, "./alcobol.data.path.09"); break;
      default : qerror (11); exit (6174); break;
   }

   if ((fp = fopen (path_file_name, "rb")) == (FILE *)NULL)
   {
      printf (">>>   file not there : %s\n", path_file_name);
      qerror (15);
      return;
   }
   else
   {
      num_bytes = 0;
      if (verbose) printf (">>>   file alcobol.data.path found\n");
      while (0 == feof (fp))
      {
         if (0 == feof (fp))
         {
            qqq = fgetc (fp);
            data_path_name [num_bytes] = qqq;
            if ((qqq != ' ') && (qqq != 0) && (qqq != 13) && (qqq != 10) && (qqq != EOF))
	    {
               num_bytes++;
	    }
	 }
      }
      data_path_name [num_bytes] = 0;
      fclose (fp);
      if (verbose) printf (">>>   file %s will contain the data.\n", data_path_name);
      analyze_data ();
      create_daily_tables ();
      create_monthly_tables ();
      summary ();
   }
   if (verbose) printf ("\n");

#else

   switch (what_path_file)
   {
      case 0 : strcpy (data_path_name, "./alcobol.data.00"); break;
      case 1 : strcpy (data_path_name, "./alcobol.data.01"); break;
      case 2 : strcpy (data_path_name, "./alcobol.data.02"); break;
      case 3 : strcpy (data_path_name, "./alcobol.data.03"); break;
      case 4 : strcpy (data_path_name, "./alcobol.data.04"); break;
      case 5 : strcpy (data_path_name, "./alcobol.data.05"); break;
      case 6 : strcpy (data_path_name, "./alcobol.data.06"); break;
      case 7 : strcpy (data_path_name, "./alcobol.data.07"); break;
      case 8 : strcpy (data_path_name, "./alcobol.data.08"); break;
      case 9 : strcpy (data_path_name, "./alcobol.data.09"); break;
      default : qerror (11); exit (6174); break;
   }
   data_path_name [17] = 0; /* not really necessary! */
   analyze_data ();
   create_daily_tables ();
   create_monthly_tables ();
   summary ();
   if (verbose) printf ("\n");

#endif
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void help (char *q)

{
   printf ("\n");
   printf ("   usage: %10s [  -h | --help          ]\n", q);
   printf ("\n");
   printf ("   usage: %10s [  -v | --verbose       ] ...\n", q);
   printf ("                     [  -f | --first n       ] ...\n");
   printf ("                     [  -l | --last  n       ] ...\n");
   printf ("                     [ -da | --dumpalcolines ] ...\n");
   printf ("                     [ -dd | --dumpdrinks    ] ...\n");
   printf ("                     [ -dt | --dumpdaily     ] ...\n");
   printf ("                     [ -dm | --dumpmonthly   ] ...\n");
   printf ("                     [ -pf | --pathfile      ] ...\n");
   printf ("\n");
   printf (HEADER_1);
   printf (HEADER_2);
   printf (HEADER_3);
   printf (HEADER_4);
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void analyze_data ()

{
   if ((dp = fopen (data_path_name, "rb")) == (FILE *)NULL)
   {
      printf (">>>   file not there\n");
      return;
   }
   else
   {
      qtoken.qtype = Q_NOTHING;
      qgetch ();
      if (verbose) printf (">>>   file %s found\n", data_path_name);

      (void) qget_token (); if (2 == verbose) { printf_qtoken (); }

      while (qtoken.qtype != Q_ALCOLINES_BEGIN)
      {
         (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
      }

      while ((0 == feof (dp)) && (qtoken.qtype != Q_ALCOLINES_END))
      {
         if (0 == feof (dp))
         {

	    if (qtoken.qtype == Q_ALCOLINES_BEGIN)
            {
               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> alcolines begin line\n");
               }
	       (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
	       if (qtoken.qtype != Q_LINE_END) { qerror (1); }
	       (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
	    }
	    else if (qtoken.qtype == Q_ALCOLINES_END)
            {
               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> alcolines end line\n");
               }
	       (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
	       if (qtoken.qtype != Q_LINE_END) { qerror (1); }
	       (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
	    }
            else if (qtoken.qtype == Q_LINE_END)
	    {
               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> empty line\n");
               }
	       (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
	    }
            else if (qtoken.qtype == Q_NAME) /* data line analysis */
	    {
	       if ((0 == alcolines) && (0 == current_alcoline))
	       {
                  current_alcoline = malloc (sizeof (alcoline_type));
                  current_alcoline->next        = 0;
                  current_alcoline->person_len  = 0;
                  current_alcoline->place_len   = 0;
                  current_alcoline->drink_len   = 0;
                  current_alcoline->line_number = line;
                  alcolines = current_alcoline;
               }
               else
               {
                  current_alcoline = alcolines;
		  while (current_alcoline->next) {current_alcoline = current_alcoline->next;}
                  current_alcoline->next = malloc (sizeof (alcoline_type));
                  current_alcoline = current_alcoline->next;
                  current_alcoline->next        = 0;
                  current_alcoline->person_len  = 0;
                  current_alcoline->place_len   = 0;
                  current_alcoline->drink_len   = 0;
                  current_alcoline->line_number = line;
               }

               /* *current_alcoline may be written onto now. */

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: who ...\n");
               }

	       while (qtoken.qtype == Q_NAME) /* who */
	       {
                   /*********** who data begin *************************/
		   (void) strcpy (
		   &current_alcoline->person [current_alcoline->person_len],
                                   (char *) &qtoken.qstring);
                   current_alcoline->person_len = current_alcoline->person_len + strlen (qtoken.qstring);
                   current_alcoline->person [current_alcoline->person_len] = ' ';
                   current_alcoline->person_len++;
                   /*********** who data end ***************************/

	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }

               /*********** who data begin *************************/
               current_alcoline->person_len--;
               current_alcoline->person [current_alcoline->person_len] = 0;
               /*********** who data end ***************************/

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: who: %s\n", &current_alcoline->person );
               }

               if (qtoken.qtype == Q_SEPARATOR)
	       {
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		   qerror (3); error_recovery ();
               }

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: where ...\n");
               }

	       while (qtoken.qtype == Q_NAME) /* where */
	       {
                   /*********** where data begin ***********************/
		   (void) strcpy (
		   &current_alcoline->place [current_alcoline->place_len],
                                   (char *) &qtoken.qstring);
                   current_alcoline->place_len = current_alcoline->place_len + strlen (qtoken.qstring);
                   current_alcoline->place [current_alcoline->place_len] = ' ';
                   current_alcoline->place_len++;
                   /*********** where data end *************************/

	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }

               /*********** where data begin ***********************/
               current_alcoline->place_len--;
               current_alcoline->place [current_alcoline->place_len] = 0;
               /*********** where data end *************************/

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: where: %s\n", &current_alcoline->place);
               }

               if (qtoken.qtype == Q_SEPARATOR)
	       {
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		  qerror (3); error_recovery ();
               }

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: quantity\n");
               }

               current_alcoline->quantity = 0.0; /* default */

               if (qtoken.qtype == Q_FLOAT) /* optional float quantity */
	       {
                   current_alcoline->quantity = qtoken.qfloat;
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else if (qtoken.qtype == Q_INT) /* optional int quantity */
	       {
                   current_alcoline->quantity = (double)qtoken.qint;
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: what ...\n");
               }

	       while (qtoken.qtype == Q_NAME) /* what */
	       {
                   /*********** what data begin ************************/
		   (void) strcpy (
		   &current_alcoline->drink [current_alcoline->drink_len],
                                   (char *) &qtoken.qstring);
                   current_alcoline->drink_len = current_alcoline->drink_len + strlen (qtoken.qstring);
                   current_alcoline->drink [current_alcoline->drink_len] = ' ';
                   current_alcoline->drink_len++;
                   /*********** what data end **************************/

	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }

               /*********** what data begin ************************/
               current_alcoline->drink_len--;
               current_alcoline->drink [current_alcoline->drink_len] = 0;
               /*********** what data end **************************/

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: what: %s\n", &current_alcoline->drink);
               }

               if (qtoken.qtype == Q_SEPARATOR)
	       {
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		  qerror (3); error_recovery ();
               }

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: date\n");
               }

               if (qtoken.qtype == Q_DATE) /* obligate date */
	       {
                   check_sequenced_date ();
                   current_alcoline->year  = qtoken.qyear;
                   current_alcoline->month = qtoken.qmonth;
                   current_alcoline->day   = qtoken.qday;
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		  qerror (4); error_recovery ();
               }

               if (qtoken.qtype == Q_SEPARATOR)
	       {
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		  qerror (3); error_recovery ();
               }

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> data line: sequence number\n");
               }

               if (qtoken.qtype == Q_INT) /* obligate sequence number */
	       {
                   current_alcoline->sequence_number  = qtoken.qint;
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		  qerror (5); error_recovery ();
               }

               if (qtoken.qtype == Q_LINE_END) /* obligate line end */
	       {
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else if (qtoken.qtype == Q_SEPARATOR) /* optional comment after separator */
	       {
                  if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
                  {
                     printf (">>> >>> >>> data line: comment\n");
                  }

	          while (qtoken.qtype != Q_LINE_END) /* the comment */
	          {
	             (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
                  }
               }
               else
               {
		  qerror (6); error_recovery ();
               }
            }
            else if (qtoken.qtype == Q_DECLARE) /* declare line analysis */
	    {
               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> declare line: declare\n");
               }
	       (void) qget_token (); if (2 == verbose) { printf_qtoken (); } /* skip declare */
               drinks [number_of_drinks].drink_len = 0;
               num_declarations++;


               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> declare line: what\n");
               }
               if (qtoken.qtype == Q_NAME)
	       {
	          while (qtoken.qtype == Q_NAME) /* declare line what */
	          {
		     (void) strcpy (&drinks [number_of_drinks].drink[drinks [number_of_drinks].drink_len],
                                    (char *) &qtoken.qstring);
                     drinks [number_of_drinks].drink_len =
			 drinks [number_of_drinks].drink_len + strlen (qtoken.qstring);

                     drinks [number_of_drinks].drink[drinks [number_of_drinks].drink_len] = ' ';
                     drinks [number_of_drinks].drink_len++;

	             (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
                  }
	       }
               else
               {
		   qerror (9); error_recovery ();
               }

               drinks [number_of_drinks].drink_len--;
               drinks [number_of_drinks].drink[drinks [number_of_drinks].drink_len] = 0;

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> declare line: alc percentage\n");
               }
               if (qtoken.qtype == Q_FLOAT) /* declare line: alc percentage */
	       {
		  drinks [number_of_drinks].percentage = qtoken.qfloat;
	          (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		   qerror (8); error_recovery ();
               }

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> declare line: default\n");
               }
               if (qtoken.qtype == Q_DEFAULT)
	       {
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		   qerror (10); error_recovery ();
               }


               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> declare line: default drink size \n");
               }
               if (qtoken.qtype == Q_FLOAT) /* declare line: default drink size */
	       {
		  drinks [number_of_drinks].default_size = qtoken.qfloat;
	          (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else
               {
		   qerror (8); error_recovery ();
               }
	       drinks [number_of_drinks].used = 0;
               number_of_drinks++;

               if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
               {
                  printf (">>> >>> >>> declare line: line end without comment\n");
               }
               if (qtoken.qtype == Q_LINE_END) /* obligate line end */
	       {
	           (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
               }
               else if (qtoken.qtype == Q_SEPARATOR) /* optional comment after separator */
	       {
                  if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
                  {
                     printf (">>> >>> >>> declare line: comment\n");
                  }

	          while (qtoken.qtype != Q_LINE_END) /* the comment */
	          {
	             (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
                  }
               }
               else
               {
		  qerror (6); error_recovery ();
               }

	    }
            else
            {
               qerror (2);
            }
	 }
      }
      fclose (dp);
   }
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void qget_token ()

{
   int cnt;
   int found_nodig;
   int found_dot;
   int found_hyp;
   int the_digit;
   int must_be_name = 0;
   float qfac;

   if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
   {
       printf ("\n");
       printf (">>> qget_token () ------- trace verbose == 3 begin -----------\n");
   }

   qtoken.qstring [0] = '?';
   qtoken.qstring [1] = 0;

   qtoken.qtype = Q_ALCOLINES_END;

   while (' ' == qqqq)
   {
      qgetch ();
   }

   /******** leading spaces now skipped. ********/

   if (0 != feof (dp))
   {
      qtoken.qtype = Q_FILE_END;
      qtoken.qstring [0] = '<';
      qtoken.qstring [1] = 'E';
      qtoken.qstring [2] = 'O';
      qtoken.qstring [3] = 'F';
      qtoken.qstring [4] = '>';
      qtoken.qstring [5] =   0;
   }
   else if (qqqq == 13)
   {
      qgetch ();
      if (qqqq == 10)
      {
         qtoken.qtype = Q_LINE_END;
         qtoken.qtype = Q_NOTHING;
         qtoken.qstring [0] = '<';
         qtoken.qstring [1] = '1';
         qtoken.qstring [2] = '3';
         qtoken.qstring [3] = '>';
         qtoken.qstring [4] = '<';
         qtoken.qstring [5] = '1';
         qtoken.qstring [6] = '0';
         qtoken.qstring [7] = '>';
         qtoken.qstring [8] =   0;
         qgetch ();
      }
      else /* isolated 13 is whitespace */
      {
         qtoken.qtype = Q_NOTHING;
         qtoken.qstring [0] = '<';
         qtoken.qstring [1] = '?';
         qtoken.qstring [2] = '?';
         qtoken.qstring [3] = '>';
         qtoken.qstring [4] =   0;
      }
   }
   else if (qqqq == 10)
   {
      qtoken.qtype = Q_LINE_END;
      line++;
      qtoken.qstring [0] = '<';
      qtoken.qstring [1] = '1';
      qtoken.qstring [2] = '0';
      qtoken.qstring [3] = '>';
      qtoken.qstring [4] =   0;
      qgetch ();
   }
   else if (qqqq == ',')
   {
      qtoken.qtype = Q_SEPARATOR;
      qtoken.qstring [0] = ',';
      qtoken.qstring [1] =   0;
      qgetch ();
   }
   else
   {
      qtoken.qtype = Q_NAME;
      cnt = 0;

      if ('"' == qqqq) /* enclosed name */
      {
	 qgetch (); /* skip " */
         qtoken.qstring [cnt] = qqqq;
         cnt++;
         qgetch ();
         while (('"' != qqqq)
              && (10 != qqqq)
              && (13 != qqqq)
             && (EOF != qqqq)
             && (',' != qqqq))
         {
	    qtoken.qstring [cnt] = qqqq;
            cnt++;
            qgetch ();
         }
         if (('"' == qqqq))
         {
            qgetch (); /* skip " */
         }
	 else
         {
	     qerror (7);
         }
         must_be_name = 1;

      }
      else /* non "..." enclosed name */
      {
         qtoken.qstring [cnt] = qqqq;
         cnt++;
         qgetch ();
         while ((' ' != qqqq)
              && (10 != qqqq)
              && (13 != qqqq)
             && (EOF != qqqq)
             && (',' != qqqq))
         {
	    qtoken.qstring [cnt] = qqqq;
            cnt++;
            qgetch ();
         }
      }

      qtoken.qstring [cnt] = 0;

      if (!strcmp ("alcolines_begin", qtoken.qstring))
      {
	 qtoken.qtype = Q_ALCOLINES_BEGIN;
      }
      else if (!strcmp ("alcolines_end", qtoken.qstring))
      {
         qtoken.qtype = Q_ALCOLINES_END;
      }
      else if (!strcmp ("declare", qtoken.qstring))
      {
         qtoken.qtype = Q_DECLARE;
      }
      else if (!strcmp ("default", qtoken.qstring))
      {
         qtoken.qtype = Q_DEFAULT;
      }
   }

   /* Now: is Q_NAME maybe something else? */

   if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
   {
      printf (">>> qtoken.qstring = %s\n", qtoken.qstring);
      printf (">>> must_be_name   = %i\n", must_be_name);
   }

   if ((Q_NAME == qtoken.qtype) && (!must_be_name))
   {
      found_nodig    = 0;
      found_dot      = 0;
      found_hyp      = 0;

      qtoken.qfloat  = 0.0;
      qtoken.qint    = 0;
      qtoken.qyear   = 0;
      qtoken.qmonth  = 0;
      qtoken.qday    = 0;



      cnt            = 0;
      while (0 != qtoken.qstring [cnt])
      {
         if ('.' == qtoken.qstring [cnt])
	 {
	    if (found_nodig) must_be_name = 1;
            found_nodig = 1;
            found_dot = 1;
            qtoken.qfloat = qtoken.qint;
            qfac = 0.1;
            if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
            {
               printf (">>> dot found\n");
	    }
         }
         if ('-' == qtoken.qstring [cnt])
	 {
            found_nodig = 1;
            found_hyp++; /* count number of hyphens! */
            if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
            {
               printf (">>> hyphen found\n");
	    }
            if ( 1 == found_hyp)
	    {
	       qtoken.qyear = qtoken.qint;
            }
         }
	 if (!isdigit (qtoken.qstring [cnt]))
	 {
	    if (('-' != qtoken.qstring [cnt]) && ('.' != qtoken.qstring [cnt]))
	    {
	       must_be_name = 1;
            }
            found_nodig = 1;
            the_digit = 0;
         }
	 else
	 {
	     switch (qtoken.qstring [cnt])
	     {
		 case '0' : the_digit = 0; break;
		 case '1' : the_digit = 1; break;
		 case '2' : the_digit = 2; break;
		 case '3' : the_digit = 3; break;
		 case '4' : the_digit = 4; break;
		 case '5' : the_digit = 5; break;
		 case '6' : the_digit = 6; break;
		 case '7' : the_digit = 7; break;
		 case '8' : the_digit = 8; break;
		 case '9' : the_digit = 9; break;
		 default  : the_digit = 0; break;
	     }
         }
         if ((isdigit (qtoken.qstring [cnt])) && (found_dot))
	 {
	    qtoken.qfloat = qtoken.qfloat + qfac * the_digit;
            qfac = qfac / 10.0;
         }
         if ((isdigit (qtoken.qstring [cnt])) && (!found_dot) && (!found_hyp))
	 {
	    qtoken.qint = qtoken.qint * 10 + the_digit;
         }
	 if ((isdigit (qtoken.qstring [cnt])) && ( 1 == found_hyp))
	 {
	    qtoken.qmonth = qtoken.qmonth * 10 + the_digit;
         }
	 if ((isdigit (qtoken.qstring [cnt])) && ( 2 == found_hyp))
	 {
	    qtoken.qday = qtoken.qday * 10 + the_digit;
         }
         cnt++;
      } /* while */

      if ((found_dot) && (!found_hyp))
      {
         qtoken.qtype = Q_FLOAT;
         if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
         {
            printf (">>> Q_FLOAT\n");
         }
      }

      if ((!found_nodig) && (!found_dot) && (!found_hyp))
      {
         qtoken.qtype = Q_INT;
         if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
         {
            printf (">>> Q_INT\n");
         }
      }

      if ( 2 == found_hyp)
      {
         qtoken.qtype = Q_DATE;
         if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
         {
            printf (">>> Q_DATE\n");
         }
         /* 2 to 4 digits corection */
         if (100 > qtoken.qyear)
	 {
            if (80 > qtoken.qyear)
	    {
	       qtoken.qyear = qtoken.qyear + 2000;
            }
            else
            {
	       qtoken.qyear = qtoken.qyear + 1900;
            }
         }
      }

      if ( 3 <= found_hyp)
      {
         qtoken.qtype = Q_NAME;
         if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
         {
            printf (">>> Q_NAME decision 1\n");
         }
      }

      if (( found_hyp) && (found_dot))
      {
         qtoken.qtype = Q_NAME;
         if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
         {
            printf (">>> Q_NAME decision 2\n");
         }
      }
   }

   if (must_be_name)
   {
      qtoken.qtype = Q_NAME;
      if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
      {
         printf (">>> Q_NAME decision 3\n");
      }
   }

   if (( line >= first_line ) && (line <= last_line) && (verbose == 3))
   {
       printf (">>> final result :");
       printf_qtoken ();
       printf ("\n");
       printf (">>> qget_token () ------- trace verbose == 3 end -------------\n\n");
   }
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void printf_qtoken ()

{
   int q;

   if (( line >= first_line ) && (line <= last_line))
   {
      switch (qtoken.qtype)
      {
         case Q_NOTHING         :	 printf (" NOTHING"); break;
         case Q_ALCOLINES_BEGIN :	 printf (" ALC.BEG"); break;
         case Q_ALCOLINES_END   :	 printf (" ALC.END"); break;
         case Q_DATE            :	 printf (" %04i-%02i-%02i", qtoken.qyear, qtoken.qmonth, qtoken.qday); break;
         case Q_INT             :	 printf (" %6i", qtoken.qint); break;
         case Q_FLOAT           :	 printf (" %6.3f ", qtoken.qfloat); break;
         case Q_NAME            :	 printf (" %9s ", qtoken.qstring); break;
         case Q_SEPARATOR       :	 printf (" , "); break;
         case Q_LINE_END        :	 printf ("\n"); break;
         case Q_FILE_END        :	 printf (" FILE_END\n"); break;
         case Q_DECLARE         :	 printf (" declare");
         case Q_DEFAULT         :	 printf (" default");
         default                :	 printf (" what is that?"); break;
      }
      if (Q_LINE_END == qtoken.qtype)
      {
         printf ("--------------------------------------------------------");
         printf ("------------------------------------------------------\n");
      }
   }
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void qgetch ()

{
   if (( line >= first_line ) && (line <= last_line) && (verbose == 4))
   {
      printf (">>>   qgetch ()\n");
   }
   if (0 == feof (dp))
   {
      qqqq = fgetc (dp);
   }
   else
   {
      qqqq = EOF;
   }

   if (( line >= first_line ) && (line <= last_line) && (verbose == 4))
   {
      printf (">>>   qqqq = %i\n", qqqq);
   }
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void qerror (int q)

{
    num_errors_00++;
    printf ("\n>>> %i-th error %i at line %i: ", num_errors_00, q, line);
    switch (q)
    {
	case  1 : printf ("ill alcolines begin line\n");        num_errors_01++; break;
	case  2 : printf ("unknown symbol at start of line\n"); num_errors_02++; break;
	case  3 : printf ("separator expected\n");              num_errors_03++; break;
	case  4 : printf ("date expected\n");                   num_errors_04++; break;
	case  5 : printf ("sequence number expected\n");        num_errors_05++; break;
	case  6 : printf ("line end expected\n");               num_errors_06++; break;
	case  7 : printf ("ill enclosed token\n");              num_errors_07++; break;
	case  8 : printf ("float number expected\n");           num_errors_08++; break;
	case  9 : printf ("drink name expected\n");             num_errors_09++; break;
	case 10 : printf ("default expected\n");                num_errors_10++; break;
	case 11 : printf ("data file missing - FATAL\n");       num_errors_11++; break;
	case 12 : printf ("dates not in ascending order\n");    num_errors_12++; break;
	case 13 : printf ("unknown drink\n");                   num_errors_13++; break;
	case 14 : printf ("Error in sequence number\n");        num_errors_14++; break;
	case 15 : printf ("file ot there\n");                   num_errors_15++; break;
	case 16 : printf ("...\n");                             num_errors_16++; break;
	case 17 : printf ("...\n");                             num_errors_17++; break;
	case 18 : printf ("...\n");                             num_errors_18++; break;
	case 19 : printf ("...\n");                             num_errors_19++; break;
	default : printf ("...\n");                                              break;
    }
    if (MAX_ERRORS < num_errors_00)
    {
        printf ("\n>>> too many errors ...\n");
	exit (6174);
    }
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void create_daily_tables ()

{
   int qcnt;
   int drink_cnt;
   int drink_found;
   int drink_number;

   qcnt = 0;
   current_alcoline = alcolines;

   while (current_alcoline)
   {
      qcnt++;
      line = current_alcoline->line_number;

      if (daily_consumption) /* list already begun */
      {
         if ((current_alcoline->year  == check_year) &&
             (current_alcoline->month == check_month) &&
	     (current_alcoline->day   == check_day))
	 {
	 }
         else /* need new consumption entry */
	 {
	    int seq_num;

            current_daily_consumption->next = malloc (sizeof (daily_consumption_type));
            seq_num = current_daily_consumption->sequence_number;
            current_daily_consumption = current_daily_consumption->next;

            check_year  = current_alcoline->year;
            check_month = current_alcoline->month;
	    check_day   = current_alcoline->day;

            current_daily_consumption->year            = check_year;
            current_daily_consumption->month           = check_month;
	    current_daily_consumption->day             = check_day;

            current_daily_consumption->quantity        = 0.0;
            current_daily_consumption->sequence_number = seq_num + 1;
            current_daily_consumption->next            = 0;
	 }
      }
      else /* no daily list yet, need also new consumption entry */
      {
         daily_consumption = malloc (sizeof (daily_consumption_type));
         current_daily_consumption = daily_consumption;

         check_year  = current_alcoline->year;
         check_month = current_alcoline->month;
	 check_day   = current_alcoline->day;

         current_daily_consumption->year            = check_year;
         current_daily_consumption->month           = check_month;
	 current_daily_consumption->day             = check_day;

         current_daily_consumption->quantity        = 0.0;
         current_daily_consumption->sequence_number = current_alcoline->sequence_number;
         current_daily_consumption->next            = 0;
      }

      /* fill her up */

      drink_found = 0;
      drink_number = -1;
      for (drink_cnt = number_of_drinks; drink_cnt >= 0; drink_cnt--)
      {
	  if (!strcmp (drinks [drink_cnt].drink, current_alcoline->drink))
	  {
             drink_found = 1;
             drink_number = drink_cnt;
             drinks [drink_cnt].used++;
          }
      }

      if (current_daily_consumption->sequence_number != current_alcoline->sequence_number)
      {
         qerror (14);
         /* readjusting: */
         current_daily_consumption->sequence_number = current_alcoline->sequence_number;
      }

      if (drink_found)
      {


	  if (0.0 == current_alcoline->quantity)
	  {
             current_daily_consumption->quantity = current_daily_consumption->quantity
		+ drinks[drink_number].percentage * 0.01 * drinks[drink_number].default_size;
             altogether_quantity = altogether_quantity
		+ drinks[drink_number].percentage * 0.01 * drinks[drink_number].default_size;
	  }
          else
	  {
             current_daily_consumption->quantity = current_daily_consumption->quantity
	        + drinks[drink_number].percentage * 0.01 * current_alcoline->quantity;
             altogether_quantity = altogether_quantity
	        + drinks[drink_number].percentage * 0.01 * current_alcoline->quantity;
	  }

         /* keep sq_quantity always up to date : */
         current_daily_consumption->sq_quantity =
            current_daily_consumption->quantity *
	    current_daily_consumption->quantity;

      }
      else
      {
         qerror (13);
      }

      current_alcoline = current_alcoline->next;
   }

   if (verbose)
   {
       printf (">>>   %i alcolines found.\n", qcnt);
   }
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void create_monthly_tables ()

{
   current_daily_consumption = daily_consumption;

   while (current_daily_consumption)
   {
      if (monthly_consumption) /* list already begun */
      {
         if ((current_daily_consumption->year  == check_year) &&
             (current_daily_consumption->month == check_month))
	 {
	 }
         else /* need new monthly entry */
	 {
            current_monthly_consumption->next = malloc (sizeof (monthly_consumption_type));
            current_monthly_consumption = current_monthly_consumption->next;

            current_monthly_consumption->first_alc_day = current_daily_consumption->sequence_number;
            current_monthly_consumption->last_alc_day  = current_daily_consumption->sequence_number - 1;

            check_year  = current_daily_consumption->year;
            check_month = current_daily_consumption->month;

            current_monthly_consumption->year  = check_year;
            current_monthly_consumption->month = check_month;

            current_monthly_consumption->acc_quantity    = 0.0;
            current_monthly_consumption->acc_sq_quantity = 0.0;
            current_monthly_consumption->next            = 0;
            current_monthly_consumption->num_alc_days    = 0;
         }
      }
      else /* no monthly list yet */
      {
         monthly_consumption = malloc (sizeof (monthly_consumption_type));
         current_monthly_consumption = monthly_consumption;

         current_monthly_consumption->first_alc_day = current_daily_consumption->sequence_number;
         current_monthly_consumption->last_alc_day  = current_daily_consumption->sequence_number - 1;

         check_year  = current_daily_consumption->year;
         check_month = current_daily_consumption->month;

         current_monthly_consumption->year    = check_year;
         current_monthly_consumption->month   = check_month;

         current_monthly_consumption->acc_quantity    = 0.0;
         current_monthly_consumption->acc_sq_quantity = 0.0;
         current_monthly_consumption->next            = 0;
         current_monthly_consumption->num_alc_days    = 0;
      }

      /* fill her up */

      current_monthly_consumption->acc_quantity
         = current_monthly_consumption->acc_quantity    + current_daily_consumption->quantity;
      current_monthly_consumption->acc_sq_quantity
         = current_monthly_consumption->acc_sq_quantity + current_daily_consumption->sq_quantity;

      current_monthly_consumption->num_alc_days++;
      current_monthly_consumption->last_alc_day++;

      current_daily_consumption = current_daily_consumption->next;
   }
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void summary ()

{
   if (1 == dump_drinks)
   {
      printf ("\n");
      printf ("  num                         drink  ln        percentage    default_size  used\n");
      printf ("\n");
      for (qdebug = 0; qdebug < number_of_drinks; qdebug++)
      {
         printf ("%5i%30s", qdebug + 1, drinks [qdebug].drink);
	 printf (" (%02i) ", strlen (drinks [qdebug].drink) );
         printf ("%16.3f", drinks [qdebug].percentage);
	 printf ("%16.6f", drinks [qdebug].default_size);
	 printf ("%6i", drinks [qdebug].used);
         printf ("\n");
      }
      printf ("\n");
   }
   else if  (1 < dump_drinks)
   {
      printf ("\n");
      printf ("  num                                           drink  ln        percentage    default_size  used\n");
      printf ("\n");
      for (qdebug = 0; qdebug < number_of_drinks; qdebug++)
      {
         printf ("%5i%48s", qdebug + 1, drinks [qdebug].drink);
	 printf (" (%02i) ", strlen (drinks [qdebug].drink) );
         printf ("%16.3f", drinks [qdebug].percentage);
	 printf ("%16.6f", drinks [qdebug].default_size);
	 printf ("%6i", drinks [qdebug].used);
         printf ("\n");
      }
      printf ("\n");
   }

   if (1 == dump_alcolines)
   {
      printf ("\n");
      printf ("   alcolines (name len 12) :\n");
      printf ("\n");
      current_alcoline = alcolines;
      qdebug = 0;
      while (current_alcoline)
      {
         printf ("%5i%12s", qdebug, current_alcoline->person);
	 printf (" (%02i)",  strlen (current_alcoline->person) );

         printf ("   %12s",           current_alcoline->place);
	 printf (" (%02i)", strlen (current_alcoline->place) );

         printf ("%16.3f", current_alcoline->quantity);

         printf ("   %12s",           current_alcoline->drink);
	 printf (" (%02i)", strlen (current_alcoline->drink) );

	 printf ("   %04i-%02i-%02i", current_alcoline->year,
                                        current_alcoline->month,
		                        current_alcoline->day);

         printf ("%8i\n", current_alcoline->sequence_number);
         current_alcoline = current_alcoline->next;
	 qdebug++;
      }
   }
   else if (2 == dump_alcolines)
   {
      printf ("\n");
      printf ("   alcolines (name len 24) :\n");
      printf ("\n");
      current_alcoline = alcolines;
      qdebug = 0;
      while (current_alcoline)
      {
         printf ("%5i%24s", qdebug, current_alcoline->person);
	 printf (" (%02i)",  strlen (current_alcoline->person) );

         printf ("   %24s",           current_alcoline->place);
	 printf (" (%02i)", strlen (current_alcoline->place) );

         printf ("%16.3f", current_alcoline->quantity);

         printf ("   %24s",           current_alcoline->drink);
	 printf (" (%02i)", strlen (current_alcoline->drink) );

	 printf ("   %04i-%02i-%02i", current_alcoline->year,
                                        current_alcoline->month,
		                        current_alcoline->day);

         printf ("%8i\n", current_alcoline->sequence_number);
         current_alcoline = current_alcoline->next;
	 qdebug++;
      }
   }
   else if (2 < dump_alcolines)
   {
      printf ("\n");
      printf ("   alcolines (name len 48) :\n");
      printf ("\n");
      current_alcoline = alcolines;
      qdebug = 0;
      while (current_alcoline)
      {
         printf ("%5i%48s", qdebug, current_alcoline->person);
	 printf (" (%02i)",  strlen (current_alcoline->person) );

         printf ("   %48s",           current_alcoline->place);
	 printf (" (%02i)", strlen (current_alcoline->place) );

         printf ("%16.3f", current_alcoline->quantity);

         printf ("   %48s",           current_alcoline->drink);
	 printf (" (%02i)", strlen (current_alcoline->drink) );

	 printf ("   %04i-%02i-%02i", current_alcoline->year,
                                        current_alcoline->month,
		                        current_alcoline->day);

         printf ("%8i\n", current_alcoline->sequence_number);
         current_alcoline = current_alcoline->next;
	 qdebug++;
      }
   }

   if (dump_dt)
   {
      int prev_month = -1;

      current_daily_consumption = daily_consumption;

      printf ("\n");
      printf ("   -------------------------------------------------------\n");
      printf ("\n");
      printf ("          linear       quadratic               date      sequence-number\n");
      printf ("\n");

      while (current_daily_consumption)
      {
          if (prev_month != current_daily_consumption->month)
	  {
              prev_month = current_daily_consumption->month;
              printf ("   -------------------------------------------------------\n");
          }

	  printf ("%16.1f",
		  current_daily_consumption->quantity / ALC_UNIT);

	  printf ("%16.1f",
	          current_daily_consumption->sq_quantity / ALC_UNIT / ALC_UNIT);

	  printf ("         %4i-%02i-%02i",
		  current_daily_consumption->year,
		  current_daily_consumption->month,
		  current_daily_consumption->day);

	  printf ("%7i",
		  current_daily_consumption->sequence_number);

	  printf ("\n");
	  current_daily_consumption = current_daily_consumption->next;
      }
      printf ("   -------------------------------------------------------\n");
   }

   if (dump_m)
   {
      int prev_year = -1;
      int qw;

      current_monthly_consumption = monthly_consumption;

      printf ("\n");
      printf ("   ---------------------------------------------   -----------------\n");
      printf ("\n");
      printf ("          linear       quadratic\n");
      printf ("    accumulation    accumulation           month   alcodays\n");
      printf ("\n");

      while (current_monthly_consumption)
      {
          if (prev_year != current_monthly_consumption->year)
	  {
              prev_year = current_monthly_consumption->year;
              printf ("   ---------------------------------------------   -----------------\n");
          }

	  if (LIMIT_ACC_QUANTITY < current_monthly_consumption->acc_quantity / ALC_UNIT)
	  {
	      printf ("      (!)");
          }
          else
          {
	      printf ("         ");
          }

	  printf ("%7.1f",
		  current_monthly_consumption->acc_quantity / ALC_UNIT);

	  if (LIMIT_ACC_SQ_QUANTITY < current_monthly_consumption->acc_sq_quantity / ALC_UNIT / ALC_UNIT)
	  {
	      printf ("      (!)");
          }
          else
          {
	      printf ("         ");
          }

	  printf ("%7.1f",
	          current_monthly_consumption->acc_sq_quantity / ALC_UNIT / ALC_UNIT);

	  printf ("         %4i-%02i",
		  current_monthly_consumption->year,
		  current_monthly_consumption->month);

	  printf ("   %4i .. %4i   ", current_monthly_consumption->first_alc_day,
                                 current_monthly_consumption->last_alc_day);

	  printf ("%2i", current_monthly_consumption->num_alc_days);


	  if (LIMIT_NUM_ALC_DAYS < current_monthly_consumption->num_alc_days)
	  {
	     printf (" (!) !");
          }
          else
          {
	     printf ("     !");
          }

          for (qw = 0 ; qw < current_monthly_consumption->num_alc_days; qw++)
          {
	     printf ("*");
          }

	  printf ("\n");
	  current_monthly_consumption = current_monthly_consumption->next;
      }
      printf ("   ---------------------------------------------   -----------------\n");
   }

   printf ("\n");
   printf ("   Lines have been processed  =%5i\n", line);
   printf ("   Number of declarations     =%5i (of max %i)\n", num_declarations, MAX_DRINKS);
   printf ("   Number of errors           =%5i\n", num_errors_00);
   printf ("   Altogether Alcohol Volume  =%8.2f ltr\n", altogether_quantity);
   printf ("   Altogether Alcohol Mass    =%8.2f kg\n", altogether_quantity * 0.8);
   printf ("   Altogether Alcohol Units   =%8.2f\n", altogether_quantity / ALC_UNIT);
   if (num_errors_00)
   {
      printf ("   There were %i errors : \n", num_errors_00);
      if (num_errors_01) { printf ("   There were %i errors of type  1\n", num_errors_01); }
      if (num_errors_02) { printf ("   There were %i errors of type  2\n", num_errors_02); }
      if (num_errors_03) { printf ("   There were %i errors of type  3\n", num_errors_03); }
      if (num_errors_04) { printf ("   There were %i errors of type  4\n", num_errors_04); }
      if (num_errors_05) { printf ("   There were %i errors of type  5\n", num_errors_05); }
      if (num_errors_06) { printf ("   There were %i errors of type  6\n", num_errors_06); }
      if (num_errors_07) { printf ("   There were %i errors of type  7\n", num_errors_07); }
      if (num_errors_08) { printf ("   There were %i errors of type  8\n", num_errors_08); }
      if (num_errors_09) { printf ("   There were %i errors of type  9\n", num_errors_09); }
      if (num_errors_10) { printf ("   There were %i errors of type 10\n", num_errors_10); }
      if (num_errors_11) { printf ("   There were %i errors of type 11\n", num_errors_11); }
      if (num_errors_12) { printf ("   There were %i errors of type 12\n", num_errors_12); }
      if (num_errors_13) { printf ("   There were %i errors of type 13\n", num_errors_13); }
      if (num_errors_14) { printf ("   There were %i errors of type 14\n", num_errors_14); }
      if (num_errors_15) { printf ("   There were %i errors of type 15\n", num_errors_15); }
      if (num_errors_16) { printf ("   There were %i errors of type 16\n", num_errors_16); }
      if (num_errors_17) { printf ("   There were %i errors of type 17\n", num_errors_17); }
      if (num_errors_18) { printf ("   There were %i errors of type 18\n", num_errors_18); }
      if (num_errors_19) { printf ("   There were %i errors of type 19\n", num_errors_19); }
   }
   printf ("\n");
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void error_recovery ()

{
   while (qtoken.qtype != Q_LINE_END)
   {
      if (( line >= first_line ) && (line <= last_line) && (verbose >= 1))
      {
         printf (">>> skipping this token\n");
      }
      (void) qget_token (); if (2 == verbose) { printf_qtoken (); }
   }

}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



void check_sequenced_date ()

{
   int wrong_seq_found = 0;

   if (0 == check_year) /* init first date */
   {
      check_year  = qtoken.qyear;
      check_month = qtoken.qmonth;
      check_day   = qtoken.qday;
   }
   else
   {
      if (qtoken.qyear < check_year)
      {
         wrong_seq_found = 1;
      }
      else if (qtoken.qyear == check_year)
      {
         if (qtoken.qmonth < check_month)
         {
            wrong_seq_found = 1;

         }
         else if (qtoken.qmonth == check_month)
         {
            if (qtoken.qday < check_day)
            {
               wrong_seq_found = 1;
            }
	 }
      }
   }

   if (wrong_seq_found)
   {
      qerror (12);
   }
   else
   {
      check_year  = qtoken.qyear;
      check_month = qtoken.qmonth;
      check_day   = qtoken.qday;
   }
}



/**********************************************************************/
/*                                                                    */
/*                                                                    */
/*                                                                    */
/**********************************************************************/



#ifdef TAKEN_FROM_GERCT



Betrifft: 
                   ALCOBOL - die Sprache
          Datum: 
                   Fri, 18 Jul 2003 00:42:08 +0200
             Von: 
                   "Herwig Huener & Josella S. Playton" <Herwig@Herwig-Huener.de>
 Newsgruppen: 
                   ger.ct




2003-07-18 00:41:00 MESZ

Statt einer EBNF-Orgie einfach ein Beispiel:

----------------------------------------------------------

alcolines_begin

declare      Bier         5.5     default     0.5
declare      Guinness     5.5     default     0.56826125
declare      Wein        11.0     default     0.25



Donald Duck,  EntenHausen,      0.25 Bier,    99-08-19   000
Daisy Duck,   TuntenHausen,     Guinness,     99-10-11,  001
Miss Sophy,   "90. Geburtstag", 5.5 Wein,     99-11-18,  002

Britney,      Mont Blanc,       2.0 Bier,     02-07-15,  003
Britney,      Mont Blanc,       1.0 Wein,     02-07-15,  003
Britney,      Mont Blanc,       5.0 Guinness, 02-07-15,  003

Britney,      Mont Blanc,       Guinness,     02-09-01,  004

alcolines_end

----------------------------------------------------------

Das ist der SprachUmfang, den der ALCOBOL-Compiler jetzt
versteht, und der verschiedenen AusWertungen unterzogen
werden kann. Sowie er einigermassen stabil ist, bringe
ich die Source auf meine HP.

Es gibt nur fuenf verschiedene ALCOBOL-SatzTypen.

alcolines_begin

und

alcolines_end

klammern den formalen Teil ein - alles vor alcolines_begin
und nach alcolines_end ist Kommentar. Das ermoeglich die
EinBettung von ALCOBOL-Programmen in andere Dokumente,
etwa in C-Programmen.

LeerZeilen gibts auch - und sie sind erwartungsgemaess
Semantik-frei.

declare <GetraenkName> <Alkohol-Gehalt> default <Default-Menge>

Deklariert ein Getraenk. Default-Menge ist die Menge,
die angenommen wird, wenn in den eigentlichen DatenZeilen
keine Menge (<quantity>) steht.

Die DatenZeile:

<mit wem>, <wo>, [<quantity>] <GetraenkeName>, <Datum>,
<sequence-number>

Obligatorische Kommas beachten.

Semantische SpielRegeln, die der ALCOBOL-Compiler ueberpruefen
muss:

--> Getraenke muessen vor ihrer Verwendung in DatenZeilen in einer
    declare-Zeile deklariert werden.

--> Datum in DateinZeilen monoton ansteigend - es kann mehrere
    DatenZeilen fuer einen Tag geben.

--> Die alphanumerischen Symbole <Alkohol-Gehalt>, <mit wem>, <wo>,
    <GetraenkeName>, <Datum>, <sequence-number> duerfen nicht als
    Fest- oder GleitKommaZahl oder als Datum interpretierbar sein.
    Ausserdem duerfen sie kein Komma enthalten. Sonst geht fast
    alles, sogar LeerZeichen mittendrin.

--> Getraenke, die in keiner DatenZeile benutzt werden:
    Warnung

--> Datum: zweistellige JahresAngabe wird nach
    79 ==> 2079 / 80 ==> 1980 ueberfuehrt.

----------------------------------------------------------

Das ist schon die ganze SprachBeschreibung. Zweifellos so
einfach, dass man seinen AlkoholVerbrauch in ALCOBOL
in nicht-nuechternen Zustand notieren kann.

Die Auswertungen kann nun jeder so implementieren, wie er Lust
hat - so kann man etwa eine ZusammenStellung bezueglich der
<mit wem> machen, was ich selbst nicht vorhabe. Die rigide
ZeilenStruktur ist sinnvoll, wenn man ein ALCOBOL-Programm
mit den ueblichen Unix-Mitteln bearbeiten will. ALCOBOL
ist nicht berechnungs-universell und braucht deshalb ja
nicht alles moegliche von anderen ProgrammierSrachen zu
uebernehmen.

WeiterEntwicklung: Anstatt die AusWertung in einem
ALCOBOL-"Compiler" fest zu verdrahten, waere es naheliegend,
die Art der AusWertung mit weiteren zu definierenden
SprachElementen zu beschreiben - das werde ich aber nicht
mehr machen. Dabei waere es wirklich sinnvoll, denn etwa
eine SchadensFunktion ist fuer jeden Menschen verschieden,
und die medizinischen Kenntnisse werden sich da auch noch
aendern.

Aufwendig war die Sache bislang sowieso: Ich habe einen Tag
gebraucht, um meine 1155 AlkoholTage - etwa 2200 DatenZeilen
- seit 1980 in korrektes ALCOBOL zu ueberfuehren. Dabei
mussten 151 "declare"-Zeilen geschrieben werden - ich
wusste gar nicht, wie viele verschiedene Getraenke ich kenne!
(obwohl: Was ist "diverses"? und welchen AlkoholGehalt hatte
das?)

Da in den DatenZeilen die Information, mit wem zusammen
man etwas getrunken hat, enthalten ist (ob man allein oder
in Gesellschaft trinkt hat ja bei der AlkoholKrankheit
einen diagnostischen Nutzen), faellt ein ALCOBOL-Programm
wahrscheinlich unter das DatenSchutzGesetz.

Alles in allem: Das AufSchreiben der ALCOBOL-Zeilen ist
so laestig, das man sich jedesmal ueberlegt: Muss man
heute wirklich etwas Alkoholisches zu sich nehmen?
Wo tut man den Zettel mit den ALCOBOL-Zeilen hin, bis
man das naechste Mal Zugang zum Rechner hat? - Daraus
kann ganz zwanglos ein erheblicher Beitrag zur
Praevention entstehen.

Und das waere es auch wert.

Herwig

-- 
Herwig Huener   http://www.quantenrente.de             +49
Josella Simone  http://www.Josella-Simone-Playton.de  8095
Playton         webmaster!@!Herwig-Huener.de          2230
GruberStrasse 10 A / D-85655 GrossHelfenDorf / Bayern / EU



Betrifft: 
                   alcobol.c
          Datum: 
                   Thu, 24 Jul 2003 09:10:48 +0200
             Von: 
                   "Herwig Huener & Josella S. Playton" <Herwig@Herwig-Huener.de>
 Newsgruppen: 
                   ger.ct




2003-07-24 08:40:00 MESZ

Ich sehe nicht ein, warum ich anderen das
MissEmpfindungsErlebnis ersparen soll, das ich jetzt
hatte. Wer also dem eigenen AlkoholKonsum
hinterherrecherchieren will, hat jetzt die Gelegenheit
dazu.

Wie das Data-Sheet (ALCOBOL-"Programmm") aussehen soll,
habe ich in einem ParallelThread gezeigt
("ALCOBOL - die Sprache").

Unter
http://www.Herwig-Huener.de/alcobol.c
gibt es jetzt eine fruehe Version des ALCOBOL-Compilers.

Bitte keine Software-Engineering oder ProgrammierStil
- Kritik - er ist noch lange nicht fertig. Benutzung
wie folgt:

alcobol.c in ein eigenes Direktory hineinkopieren. Ein

   $ make alcobol

erledigt alles weitere.

Im selben Directory liegen die Data-Sheets. Die heissen
alcobol.data.00 bis alcobol.data.09. Unix-typisch koennen
das (Sym-)Links woanders hinsein. Mit

   $ alcobol

wird die erste benutzt, mit

   $ alcobol -pf

die zweite, mit

   $ alcobol -pf -pf

die dritte - und so weiter.

Der alcobol-Aufruf alleine bringt nur ein Summary:

   $ alcobol -pf

   ALCOBOL Compiler

>>>   number of path file 1

   Lines have been processed  =   44
   Number of declarations     =    5
   Number of errors           =    0
   Altogether Alcohol Volume  =    2.34 ltr
   Altogether Alcohol Mass    =    1.87 kg
   Altogether Alcohol Units   =   85.12

Da ist zu lesen, wieviele Zeilen der Compiler gelesen hat
(44), wieviele Getraenke-Deklarationen er verstanden hat
(hier 5, meine real-life Datei weisst 154 auf), und
wieviel Alkohol in der gesamten Datei enthalten ist.

Die "Alcohol Unit" ist etwa 27.5 cm^3 und entspricht der Menge
Alkohol, die etwa in einem halben Liter Bier oder einem
Viertel Wein enthalten ist. Damit hat man eine RechenUnit,
die man auch ohne ein Programm leidlich gut verfolgen kann.

   $ alcobol -da

und

   $alcobol -dd

listen im wesentlichen die EingangsInformationen aus der
Daten-Datei - was der ALCOBOL-Compiler verstanden zu haben
glaubt. Normalerweise uninteressant.

   $ alcobol -dt

ist schon interessanter. Aufsummierung des Alkohol-Konsums fuer
jeden Tag (erste Spalte). Hier wird bereits die oben angegebene
Alkohol-Unit verwendet.

Zweite Spalte: eine vermutete nichtlineare SchadensFunktion
des Alkohols - hier einfach das Quadrat der taeglichen Menge.

Dann Datum und Sequence-Number. Sequence-Nummer ist beim Fuehren
der Alkohol-Datei obligatorisch, um Konsistenz sicherzustellen.
Nicht wegen Reminiszenzen an COBOL, sondern um das spaetere
"versehentliche" Loeschen einzelner Zeilen unwahrscheinlicher zu
machen.

   $ alcobol -dm

Die jeweilige MonatsBilanz. Es gibt (im Moment noch festcodierte)
Warnungen, wenn die lineare AufSummierung 60 Units pro Monat
uebersteigt, wenn die quadratische AufSummierung 200 QuadratUnits
uebersteigt, und wenn die Anzahl der Tage, an denen Alkohol
getrunken wird, groesser als 12 ist.

So, das ist der momentane FunktionsUmfang. Plattform- und
Getraenke-neutral. An Verbesserung wird gearbeitet. Bessere
User-Instruktions werden zu gegebener Zeit auf der HP
erscheinen.

Wer es ausprobieren will, kann die Beispiels-alcobol-Datei
aus dem ParallelThread verwenden.

Das Ganze ist in GPL gedacht, aber das steht noch nirgends.

Ich weiss, dass das ganze Programm eigentlich eine geistlose
AufAddierMaschine ist - aber das Programm, das meine
WaldLaeufe verwaltet, tut auch nichts anderes, und trotzdem
ist es seit fast 20 Jahren im Einsatz.

Herwig

-- 
Herwig Huener   http://www.quantenrente.de             +49
Josella Simone  http://www.Josella-Simone-Playton.de  8095
Playton         webmaster!@!Herwig-Huener.de          2230
GruberStrasse 10 A / D-85655 GrossHelfenDorf / Bayern / EU



#endif

