home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / database / cdbms / schema.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-01  |  11.3 KB  |  496 lines

  1. /* --------------- schema.c ------------------ */
  2.  
  3. /*  Read a file from the standard input.
  4.  *  Write one of three schema files to the standard output
  5.  *  depending on the runtime switch.
  6.  *  If -1 is on the command line,
  7.  *        the #define statements are built.
  8.  *  If -2 is on the command line,
  9.  *        the file of ascii strings for 
  10.  *      file and data element names is built.
  11.  *  If -3 is on the command line,
  12.  *  the data base schema array source file is built.
  13.  */
  14.  
  15. #include <stdio.h>
  16. #define SCHEMA
  17. #include "cdata.h"
  18.  
  19. #define MXCAT 3    /* maximum elements concatenated per index */
  20. #define NAMLEN 31
  21.  
  22. struct dict {                /* data element dictionary    */
  23.     char dename [NAMLEN+1];    /*     name                    */
  24.     char detype;            /*     type                    */
  25.     int delen;                /*     length                    */
  26.     char *demask;            /*     display mask            */
  27. } dc [MXELE];
  28. int dectr = 0;                /* data elements in dictionary */
  29. int fctr = 0;                /* files in data base            */
  30. char filename [MXFILS] [NAMLEN+1];    /* file name strings   */
  31. int fileele [MXFILS] [MXELE];        /* elements in files   */
  32. int ndxele [MXFILS] [MXINDEX] [MXCAT];     /* indices           */
  33.  
  34. char word[NAMLEN+1];
  35. char *malloc();
  36. int lnctr = 0;    /* input stream line counter */
  37. char ln [160];
  38.  
  39. /* -------- error messages ----------- */
  40. char *ers[] = {    "invalid name",                    /*  1 */
  41.                 "invalid length",                /*  2 */
  42.                 "comma missing",                /*  3 */
  43.                 "invalid data type",            /*  4 */
  44.                 "quote missing",                /*  5 */
  45.                 "#schema missing",                /*  6 */
  46.                    "#<command> missing",            /*  7 */ 
  47.                 "unexpected end of file",        /*  8 */
  48.                 "duplicate file name",            /*  9 */
  49.                 "unknown data element",            /* 10 */
  50.                 "too many data elements",        /* 11 */
  51.                 "out of memory",                /* 12 */
  52.                 "unknown file name",            /* 13 */
  53.                 "too many indices in file",        /* 14 */
  54.                 "too many elements in index",    /* 15 */
  55.                 "duplicate data element",        /* 16 */
  56.                 "too many files",                /* 17 */
  57.                 "invalid command line switch"   /* 18 */
  58. };
  59.  
  60. void de_dict(), files(), keys(), schout(), defout(),
  61.      lcase(), strout(), error(), get_line(), skip_white(), 
  62.      name_val(), numb_val(), expect_comma(), depart();
  63. char *get_word();
  64. #define iswhite(c) ((c)==' '||(c)=='\t')
  65. #define REMARK ';'
  66.  
  67. /* ----------------- main program -------------- */
  68. main(argc, argv)
  69. int argc;
  70. char *argv[];
  71. {
  72.     get_line();
  73.     if (strncmp(ln, "#schema ", 8))
  74.         error(6);
  75.     else    {
  76.         get_word(ln + 8);
  77.         name_val();
  78.         printf("\n/");
  79.         printf("* ------------- %s ------------ */\n", word);
  80.     }
  81.     get_line();
  82.     while (strncmp(ln, "#end schema", 11))    {
  83.         if (strncmp(ln, "#dictionary", 11) == 0)
  84.             de_dict();
  85.         else if (strncmp(ln, "#file ", 6) == 0)
  86.             files();
  87.         else if (strncmp(ln, "#key ", 5) == 0)
  88.             keys();
  89.         else
  90.             error(7);
  91.         get_line();
  92.     }
  93.     if (argc > 1)    {
  94.         if (strcmp(argv[1], "-1") == 0)
  95.             defout();
  96.         else if (strcmp(argv[1], "-2") == 0)
  97.             strout();
  98.         else if (strcmp(argv[1], "-3") == 0)
  99.             schout();
  100.         else
  101.             error(18);
  102.     }
  103.     else
  104.         error(18);
  105.     depart(0);
  106. }
  107.  
  108. /* -------- build the data element dictionary ---------- */
  109. static void de_dict()
  110. {
  111.     char *cp, *cp1;
  112.     int el;
  113.     while (TRUE)    {
  114.         get_line();
  115.         if (strncmp(ln, "#end dictionary", 15) == 0)
  116.             break;
  117.         if (dectr == MXELE)    {
  118.             error(11);
  119.             continue;
  120.         }
  121.         cp = get_word(ln);
  122.         name_val();
  123.         for (el = 0; el < dectr; el++)
  124.             if (strcmp(word, dc[el].dename) == 0)    {
  125.                 error(16);
  126.                 continue;
  127.             }
  128.         strcpy(dc[dectr].dename, word);
  129.         expect_comma(&cp);
  130.         skip_white(&cp);
  131.         switch (*cp)    {
  132.             case 'A':
  133.             case 'Z':
  134.             case 'C':
  135.             case 'N':
  136.             case 'D':    break;
  137.             default :    error(4);
  138.                         continue;
  139.         }
  140.         dc[dectr].detype = *cp++;
  141.         expect_comma(&cp);
  142.         cp = get_word(cp);
  143.         numb_val();
  144.         dc[dectr].delen = atoi(word);
  145.         expect_comma(&cp);
  146.         skip_white(&cp);
  147.         if (*cp != '"')    {
  148.             error(5);
  149.             continue;
  150.         }
  151.         cp1 = cp + 1;
  152.         while (*cp1 != '"' && *cp1 && *cp1 != '\n')
  153.             cp1++;
  154.         if (*cp1++ != '"')    {
  155.             error(5);
  156.             continue;
  157.         }
  158.         *cp1 = '\0';
  159.         if ((dc[dectr].demask = malloc((cp1-cp)+1)) == 0)    {
  160.             error(12);
  161.             depart(1);
  162.         }
  163.         strcpy(dc[dectr].demask, cp);
  164.         dectr++;
  165.     }
  166. }
  167.  
  168. /* ----------- build the file definitions ---------------- */
  169. static void files()
  170. {
  171.     int i, el = 0;
  172.     if (fctr == MXFILS)
  173.         error(17);
  174.     get_word(ln + 6);                /* get the file name     */
  175.     name_val();                         /* validate it            */
  176.     for (i = 0; i < fctr; i++)        /* already assigned?    */
  177.         if (strcmp(word, filename[i]) == 0)
  178.             error(9); 
  179.     strcpy(filename[fctr], word);
  180.     /* ---------- process the file's data elements -------- */
  181.     while (TRUE)    {
  182.         get_line();
  183.         if (strncmp(ln, "#end file", 9) == 0)
  184.             break;
  185.         if (el == MXELE)    {
  186.             error(11);
  187.             continue;
  188.         }
  189.         get_word(ln);                 /* get a data element     */
  190.         for (i = 0; i < dectr; i++)     /* in dictionary?        */
  191.             if (strcmp(word, dc[i].dename) == 0)
  192.                 break;
  193.         if (i == dectr)
  194.             error(10);
  195.         else if (fctr < MXFILS)
  196.             fileele [fctr] [el++] = i + 1; /* post to file    */
  197.     }
  198.     if (fctr < MXFILS)
  199.         fctr++;
  200. }
  201.  
  202. /* ----------- build the index descriptions ------------ */
  203. static void keys()
  204. {
  205.     char *cp;
  206.     int f, el, x, cat = 0;
  207.     cp = get_word(ln + 5);        /* get the file name */
  208.     for (f = 0; f < fctr; f++)    /* in the schema?     */
  209.         if (strcmp(word, filename[f]) == 0)
  210.             break; 
  211.     if (f == fctr)    {
  212.         error(13);
  213.         return;
  214.     }
  215.     for (x = 0; x < MXINDEX; x++)
  216.         if (*ndxele [f] [x] == 0)
  217.             break;
  218.     if (x == MXINDEX)    {
  219.         error(14);
  220.         return;
  221.     }
  222.     while (cat < MXCAT)    {
  223.         cp = get_word(cp);                 /* get index name */
  224.         for (el = 0; el < dectr; el++)    /* in dictionary? */
  225.             if (strcmp(word, dc[el].dename) == 0)
  226.                 break;
  227.         if (el == dectr)    {
  228.             error(10);
  229.             break;
  230.         }
  231.         ndxele [f] [x] [cat++] = el + 1; /* post element */
  232.         skip_white(&cp);
  233.         if (*cp++ != ',')           /* concatenated index? */
  234.             break;
  235.         if (cat == MXCAT)    {
  236.             error(15);
  237.             break;
  238.         }
  239.     }
  240. }
  241.  
  242. /* ---------- write the schema source language ---------- */
  243. static void schout()
  244. {
  245.     int f, el, x, x1, cat, fel;
  246.     char name [NAMLEN+1];
  247.  
  248.     /*  ---------  data element lengths  ----------  */
  249.     printf("\n\nint ellen [] = {");
  250.     for (el = 0; el < dectr; el++)        {
  251.         if ((el % 25) == 0)
  252.             printf("\n\t");
  253.         printf((el < dectr-1 ? "%d," : "%d"),dc[el].delen);
  254.     }
  255.     printf("\n};\n");
  256.     /* ---------- write the file contents arrays ------- */
  257.     for (f = 0; f < fctr; f++)    {
  258.         lcase(name, filename [f]);
  259.         printf("\n\nint f_%s [] = {", name);
  260.         el = 0;
  261.         while ((fel = fileele[f] [el++]) != 0)
  262.             printf("\n\t%s,", dc[fel-1].dename);
  263.         printf("\n\t0\n};");
  264.     }
  265.     /* ------- write the file list pointer array ------- */
  266.     printf("\n\nint *file_ele [] = {");
  267.     for (f = 0; f < fctr; f++)    {
  268.         lcase(name, filename [f]);
  269.         printf("\n\tf_%s,", name);
  270.     }
  271.     printf("\n\t0\n};\n");
  272.     /* ----------- write the index arrays -------------- */
  273.     for (f = 0; f < fctr; f++)    {
  274.         lcase(name, filename [f]);
  275.         for (x = 0; x < MXINDEX; x++)    {
  276.             if (*ndxele [f] [x] == 0)
  277.                 break;
  278.             printf("\nint x%d_%s [] = {", x + 1, name);
  279.             for (cat = 0; cat < MXCAT; cat++)
  280.                 if (ndxele [f] [x] [cat])
  281.                     printf("\n\t%s,",
  282.                         dc[ndxele [f] [x] [cat] - 1].dename);
  283.             printf("\n\t0\n};\n");
  284.         }
  285.         printf("\nint *x_%s [] = {", name);
  286.         for (x1 = 0; x1 < x; x1++)
  287.             printf("\n\tx%d_%s,", x1 + 1, name);
  288.         printf("\n\t0\n};\n");
  289.     }
  290.     printf("\nint **index_ele [] = {");            
  291.     for (f = 0; f < fctr; f++)    {
  292.         lcase(name, filename [f]);
  293.         printf("\n\tx_%s,", name);
  294.     }
  295.     printf("\n\t0\n};\n");
  296. }
  297.  
  298.  
  299.  
  300.  
  301. /* -- write the schema #defines and struct definitions -- */
  302. static void defout()
  303. {
  304.     int f, el, fel;
  305.     char name [NAMLEN+1];
  306.  
  307.     /*  --------  data element defines  ---------  */
  308.     for (el = 0; el < dectr; el++)
  309.         printf("\n#define %s %d", dc[el].dename, el + 1);
  310.     putchar('\n');
  311.     /* ------- write the file #define statements -------- */
  312.     for (f = 0; f < fctr; f++)
  313.         printf("\n#define %s %d", filename [f], f);
  314.     putchar('\n');
  315.     /* ---------- write the record structures ------------ */
  316.     for (f = 0; f < fctr; f++)    {
  317.         lcase(name, filename [f]);
  318.         printf("\nstruct %s {", name);
  319.         el = 0;
  320.         while ((fel = fileele[f] [el++]) != 0)    {
  321.             lcase(name, dc[fel-1].dename);
  322.             printf("\n\tchar %s [%d];",
  323.                     name, dc[fel-1].delen + 1);
  324.         }
  325.         printf("\n};\n");
  326.     }
  327. }
  328.  
  329. /* ----- write the file and data element ascii strings ---- */
  330. static void strout()
  331. {
  332.     int el, f;
  333.  
  334.     /*  --------  data element ascii names  ---------  */
  335.     printf("\nchar *denames [] = {");
  336.     for (el = 0; el < dectr; el++)
  337.         printf("\n\t\"%s\",", dc[el].dename);
  338.     printf("\n\t0\n};\n");
  339.     /*  --------  data element types  ------------  */
  340.     printf("\nchar eltype [] = \"");
  341.     for (el = 0; el < dectr; el++)    
  342.         putchar(dc[el].detype);
  343.     printf("\";\n");
  344.     /*  ----------  data element display masks  ---------  */
  345.     printf ("\nchar *elmask [] = {");
  346.     for (el = 0; el < dectr; el++)    
  347.         printf((el < dectr-1 ?
  348.                 "\n\t%s," :
  349.                 "\n\t%s"),dc[el].demask);
  350.     printf("\n};\n");
  351.     /* ------ write the ascii file name strings -------- */
  352.     printf("\nchar *dbfiles [] = {");
  353.     for (f = 0; f < fctr; f++)
  354.         printf("\n\t\"%s\",", filename [f]);
  355.     printf("\n\t0\n};\n");
  356. }
  357.  
  358.  
  359.  
  360.  
  361. /* -------- convert a name to lower case ---------- */
  362. static void lcase(s1, s2)
  363. char *s1, *s2;
  364. {
  365.     while (*s2)    {
  366.         *s1 = tolower(*s2);
  367.         s1++;
  368.         s2++;
  369.     }
  370.     *s1 = '\0';
  371. }
  372.  
  373. /* -----------  errors  -------------- */
  374. static void error(n)
  375. int n;
  376. {
  377.     static int erct = 0;
  378.     static int erlin = 0;
  379.  
  380.     if (erlin != lnctr)    {
  381.         erlin = lnctr;
  382.         fprintf(stderr, "\nLine %d: %s", lnctr, ln);
  383.     }
  384.     fprintf(stderr, "\n  Error %d: %s", n, ers[n-1]);
  385.     if (erct++ == 5)    {
  386.         erct =0;
  387.         fprintf(stderr, "\nContinue? (y/n) ... ");
  388.         if (tolower(getc(stderr)) != 'y')
  389.             depart(1);
  390.     }
  391. }
  392.  
  393. /* --- get a line of data from the schema input stream --- */
  394. static void get_line()
  395. {
  396.     *ln = '\0';
  397.     while (*ln == '\0' || *ln == REMARK || *ln == '\n')    {
  398.         if (fgets(ln,120,stdin) == 0)    {
  399.             error(8);
  400.             depart(1);
  401.         }
  402.         lnctr++;
  403.     }
  404. }
  405.  
  406. /* ---------- skip over white space --------- */
  407. static void skip_white(s)
  408. char **s;
  409. {
  410.     while (iswhite(**s))
  411.         (*s)++;
  412. }
  413.  
  414. /* ----------- get a word from a line of input ----------- */
  415. static char *get_word(cp)
  416. char *cp;
  417. {
  418.     int wl = 0, fst = 0;
  419.  
  420.     skip_white(&cp);
  421.     while (*cp && *cp != '\n' &&
  422.             *cp != ',' &&
  423.                 iswhite(*cp) == 0)    {
  424.         if (wl == NAMLEN && fst == 0)    {
  425.             error(1);
  426.             fst++;
  427.         }
  428.         else
  429.             word [wl++] = *cp++;
  430.     }
  431.     word [wl] = '\0';
  432.     return cp;
  433. }
  434.  
  435. /* ---------- validate a name --------------- */
  436. static void name_val()
  437. {
  438.     char *s = word;
  439.     if (isalpha(*s))    {
  440.         while (isalpha(*s) || isdigit(*s) || *s == '_')    {
  441.             *s = toupper(*s);
  442.             s++;
  443.         }
  444.         if (*s == '\0')
  445.             return;
  446.     }
  447.     error(1);
  448. }
  449.  
  450. /* ---------- validate a number ------------- */
  451. static void numb_val()
  452. {
  453.     char *s = word;
  454.     do    {
  455.         if (isdigit(*s++) == 0)    {
  456.             error(2);
  457.             break;
  458.         }
  459.     } while (*s);
  460. }
  461.  
  462. /* ----------- expect a comma next ---------- */
  463. static void expect_comma(cp)
  464. char **cp;
  465. {
  466.     skip_white(cp);
  467.     if (*(*cp)++ != ',')
  468.         error(3);
  469. }
  470.  
  471. /* --------- terminate schema program ------------- */
  472. static void depart(n)
  473. int n;
  474. {
  475.     int el;
  476.  
  477.     for (el = 0; el < dectr; el++)
  478.         free(dc[el].demask);
  479.     exit(n);
  480. }
  481.  
  482. #if COMPILER == WIZARD
  483. /* --- strncmp function to replace non-standard version --- */
  484. int strncmp(s1, s2, n)
  485. char *s1, *s2;
  486. {
  487.     int i;
  488.  
  489.     while (n--)
  490.         if (i = (*s1++ - *s2++))
  491.             return i;
  492.     return 0;
  493. }
  494. #endif
  495.  
  496.