#include <stdio.h>                          /* version 2026-04-08 23:25 UTC+2 */
#include "no3in_functions.h"                /* Achim Flammenkamp, Bielefeld   */
#ifndef  FREE
#define  FREE  '.'
#endif
#ifndef  MARK
#define  MARK  'o'
#endif
#ifndef  DATABASE
#define  DATABASE  "database" // should be readable and for update also writable
#endif


int main(int argc, char *argv[])
{
int  i, j, h, k, n;
unsigned  x[2*MAX_N], y[2*MAX_N], grid[MAX_N][MAX_N];
unsigned  flag, set, anz, valid, norm, new, stored, leadin;
char  buffer[2*MAX_N+4], *database, errline[16];
FILE  *gp, *fp;
flag=0;
database= DATABASE;
for (i=1;i<argc && argv[i][0]=='-';i++)
{ 
   if (!argv[i][1] || argv[i][1]=='-' || argv[i][2])
      break;
   switch (argv[i][1])
   { 
      case 'm': flag |= 1;  break; // show configuration as ASCII grafic
      case 'v': flag |= 2;  break; // verbose output
      case 'c': flag |= 4;  break; // only check configuration for validity
      case 'n': flag |= 8;  break; // only check and normalize configuration
      case 's': flag |= 16; break; // search configuration but don't store
      case 'd': i++;
                database= argv[i];
                if (!(gp=fopen(database,"r")) )
                {  if (!(gp=fopen(database,"a")) )
                   {  fprintf(stderr,"%s can neither be read nor created\n",
                              database);
                      return 2;
                   }
                   else if (flag&2)
                      fprintf(stdout,"%s was created\n",database);
                }
                fclose(gp); 
                break;
      case '?': printf("usage: %s [-mcnsv?][-d DATABASE] [coded_config_file]\n"
                       ,argv[0]);
                printf("       -?   gives this short explanation and exits\n");
                printf("       -m   show configuration as ASCII grafic\n");
                printf("       -c   only check configuration for validity\n");
                printf("       -n   only check and normalize configuration\n");
                printf("       -s   search configuration but never store\n");
                printf("       -v   verbose output\n");
                printf("       -d DATABASE   if DATABASE can't be opened for"
                       " reading it may be created\n");
                printf("       --   indicates end of option list\n");
                return  0;
      default:  fprintf(stderr,"unknown option %s ignored\n",argv[i]);
                printf("usage: %s [-mcnsv?][-d DATABASE] [coded_config_file]\n"
                       ,argv[0]);
                return -1;
   }
}
if (!(fp= (argc>i ? fopen(argv[i],"r") : stdin)))
   return  fprintf(stderr,"Error: can't open %s\n",argv[i]), -1;
else if (!fp)
{  printf("usage: %s [-mcnsv?][-d DATABASE] [coded_config_file]\n",argv[0]);
   return -1;
}
valid= norm= new= stored= 0;
for(set=1;get_next_coded_config(fp,buffer);set++)
{  sprintf(errline," in line %u",set);
   switch (n=decode(buffer,x,y,&leadin))
   {  case -1: return fprintf(stderr,"decode error: n too large %u > %d%s\n",
                                     n,MAX_N,errline), -2;
      case -2: return fprintf(stderr,"decode error: illegal character%s\n",
                                     errline), -3;
      case -3: return fprintf(stderr,"decode error: alphabet error or symme"
                                     "try sign invalid %s\n",errline), -4;
      case -4: return fprintf(stderr,"decode error: odd number of characters"
                                     "%s\n",errline), -5;
      case -5: return fprintf(stderr,"decode error: the maximal character"
                                     " is != n%s\n",errline), -6;
      case -6: return fprintf(stderr,"decode error: more than 2 markers in"
                                     " a column%s\n",errline), -7;
   }
   if (!n)
   {  // degenerated case: grid size is 0
#ifdef  SIMPLE
      printf("n = 0\n");
#else
      printf("%3u. Lösung:",set);
      for (j=0;SYMM[j];j++)
         if (buffer[0]==SYMM[j])
            break;
      if (SYMM[j] && SYMM[j+1])
         printf("    Sym.-Gruppe  %s",symclass(j));
      printf("\n");
#endif
      valid++;  // should/can be in database as default
      continue;
   }
   anz= 2*n;
   for (h=anz;h--;anz--)
      if (x[h] != ~0 && y[h] != ~0)
         break;
   if (flag&1)
      print_config(2*n+leadin,buffer,set,FREE,MARK,stdout);
   if (n == 1)
      return  fprintf(stderr,"location multiple placed%s\n",errline), -8;
   if (h= check_validity(n,x,y))
      return  fprintf(stderr,"%d violating tripels%s\n",h,errline), -9;
   k= symmetry_index(n,x,y,0);
   if (k == 9)
      return  fprintf(stderr,"symmetry_check: internal error%s\n",errline), -10;
#ifdef  SIMPLE
   if (leadin)
      printf("symmetry %s\n",symclass(k));
#endif
   if (leadin && SYMM[k] != buffer[0])
   {  fprintf(stderr,"wrong symmetry character %c changed to correct %c %s\n",
              buffer[0],SYMM[k],errline);
      buffer[0]= SYMM[k];
   }
   valid++;
   if (flag&4)
      ;   // only check configurations for validity
   else if (flag&8)
   {  if (normalize(n,x,y))
      {  norm++;
         if (flag&2)
            fprintf(stdout,"%uth configuration was normalized\n",set);
      }
   }
   else if (gp= fopen(database,"r"))
   {  char  config[2*MAX_N+4];
      if (normalize(n,x,y))
      {  norm++;
         if (flag&2)
            fprintf(stdout,"%uth configuration was normalized  ",set);
         if (encode(n,x,y,buffer,k) < 0)
            return  fprintf(stderr,"not exactly two positions in each row%s\n",
                            errline), -12;
      }
      for (h=0; k=0,fgets(config,2*MAX_N+4,gp);h++)
      {  for (k=1;config[k]>' '&&buffer[k]>' ';k++)
            if (buffer[k] != config[k])
               break;
         if (config[k]<=' ' && buffer[k]<=' ')
            break;
      }
      fclose(gp);
      if (!k)
      {  new++;
         buffer[2*n+1]= '\n';
         buffer[2*n+2]= '\0';
         if (flag&16)
         {  if (flag&2)
               fprintf(stdout,"%uth configuration NOT in database\n",set);
         }
         else if (gp= fopen(database,"a"))
         {  if (fputs(buffer,gp) >= 0)
               stored++;
            fclose(gp);
            if (flag&2)
               fprintf(stdout,"%uth configuration stored in database\n",set);
         }
         else
         {  fprintf(stderr,"can't open %s for appending %uth configuration\n",
                    database,set); 
            if (flag&2)
               fputs(buffer,stdout);
         }
      }
      else
      {  if (flag&2)
            fprintf(stdout,"%uth configuration in database in line %u\n",set,h+1);
         if (config[0] != buffer[0])
         {  fprintf(stderr,"WARNING  wrong symmetry character %c  "
                    "correct is %c %s\n",buffer[0],config[0],errline);
         }
      }
   }
   else
      fprintf(stderr,"Error: can't open %s for reading\n",database);
}
if (fp != stdin)
   fclose(fp);
fprintf(stderr,"%u configurations decoded of which are %u valid",set-1,valid);
if (!(flag&4))
{  fprintf(stderr,", %u normalized",norm);
   if (!(flag&8))
   {  fprintf(stderr,", %u new",new);
      if (!(flag&16))
         fprintf(stderr," and %u stored",stored);
   }
}
fputs("\n",stderr);
return  0;
}
