home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / MBASE / MBASE50.TAR / mbase / src / build.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-21  |  19.3 KB  |  739 lines

  1. /*
  2.  * METALBASE 5.0
  3.  *
  4.  * Released October 1st, 1992 by Huan-Ti [ richid@owlnet.rice.edu ]
  5.  *                                       [ t-richj@microsoft.com ]
  6.  *
  7.  * Special thanks go to Mike Cuddy (mcuddy@fensende.rational.com) for his
  8.  * suggestions and code.
  9.  *
  10.  */
  11.  
  12. #define BLAST_C  /* I know, I know... */
  13. #include "mbase.h"
  14. #include "internal.h"
  15.  
  16. #define cr(x) ((x) == 0) ? DUBCR : SNGCR
  17.  
  18. #ifdef MSDOS
  19. #define DESCLINE "/*\r\n * This file was created by MetalBase version 5.0 to reflect the structure\r\n * of the relation \"%s\".\r\n *\r\n * MetalBase 5.0 released October 1st, 1992 by richid@owlnet.rice.edu\r\n *\r\n */\r\n\r\ntypedef struct\r\n { "
  20. #else
  21. #define DESCLINE "/*\n * This file was created by MetalBase version 5.0 to reflect the structure\n * of the relation \"%s\".\n *\n * MetalBase 5.0 released October 1st, 1992 by virtual!richid@owlnet.rice.edu\n *\n */\n\ntypedef struct\n { "
  22. #endif
  23.  
  24. #define lineF "Fields______________________________________________________%s"
  25. #define lineI "\nIndices_____________________________________________________%s"
  26.  
  27. #define RBC '}'
  28.  
  29. #ifdef LONGARGS
  30.    void   strlwrcpy (char *, char *);
  31.    void   struprcpy (char *, char *);
  32.    void   strmax    (char *, int);
  33.    char  *repeat    (char,   int);
  34.    void   main      (int,    char **);
  35.    void   endoffile (int,    int);
  36.    int    get_names (int,    char **);
  37.    void   write_it  (int,    int);
  38.    int    contains_serial (char *);
  39. #else
  40.    void   strlwrcpy();
  41.    void   struprcpy();
  42.    void   strmax();
  43.    char  *repeat();
  44.    void   main();
  45.    void   endoffile();
  46.    int    get_names();
  47.    void   write_it();
  48.    int    contains_serial();
  49. #endif
  50.  
  51. #define  Printf   if (!quiet)  printf
  52. #define fPrintf   if (!quiet) fprintf
  53.  
  54. #define qt(x) (quiet ? "" : x)
  55.  
  56. #define usage() \
  57.    fprintf (stderr, "build: format: build [-q] [-h] schema.s%s", SNGCR);
  58.  
  59. #define fatal() { \
  60.                 fflush(stdout); \
  61.                 fprintf(stderr,"Cannot build relation--%s.%s",mb_error,SNGCR); \
  62.                 break; \
  63.                 }
  64.  
  65. #define comment() skip(fh,";"); while (skip (fh, "#"))  goeol(fh,NULL);
  66.  
  67. /*
  68.  ******************************************************************************
  69.  *
  70.  */
  71.  
  72. static char *types[] =
  73.  { "char *", "short", "ushort", "long", "ulong",  "float",
  74.    "double", "money", "time",   "date", "serial", "phone"  };
  75.  
  76. /*
  77.  ******************************************************************************
  78.  *
  79.  */
  80.  
  81. relation *data;
  82.  
  83. char   strname[40] = "";     /* Structure name (set by "typedef") */
  84. char   rel[128],  hdr[128];  /* Filenames for relation and header */
  85. char   names[20], nameb[40]; /* Name, and upper-case name         */
  86. int    column=1;             /* Column we're displaying data in   */
  87. int    header=0,  quiet=0;   /* Set by -q and -h on command-line  */
  88. int    num_f=0,   num_i=0;   /* Start with 0 fields and 0 indices */
  89. int    hasser=0;             /* 1 if we encounter a serial field  */
  90.  
  91.  
  92. /*
  93.  ******************************************************************************
  94.  *
  95.  */
  96.  
  97. void
  98. main  (argc, argv)
  99. int    argc;
  100. char **argv;
  101. {
  102.    int        stage;     /* Processing stage; 1==fields, 2==indices, 3==done */
  103.    int        fh;        /* File handle for schema                           */
  104.    char       name[20];  /* Field/Index name                                 */
  105.    ftype      typ;       /* Field type (or, for indices, 0==nodups, 1==dups) */
  106.    int        siz;       /* Field size (for character arrays only)           */ 
  107.    int        isExt;     /* TRUE if it's an external type, FALSE if not      */
  108.    char       desc[128]; /* Character array of field numbers, for indices    */
  109.  
  110.    long       nexts = 0L;
  111.    char       temp[128];
  112.    char       t2[128];
  113.    int        i;
  114.  
  115.  
  116.    fh = get_names (argc, argv);  /* fh = file handle of relation */
  117.  
  118.    if ((data = mb_new()) == RNULL)
  119.       {
  120.       fprintf (stderr, "Cannot build relation--%s.%s", mb_error, SNGCR);
  121.       exit(1);
  122.       }
  123.  
  124.    for (stage = 1; stage != 3; )
  125.       {
  126.       strlwrcpy (temp, getword (fh));   /* temp = keyword */
  127.  
  128.       if (! strcmp (temp, "field"))
  129.          {
  130.          if (stage == 2)  /* Done with fields? */
  131.             {
  132.             fflush (stdout);
  133.             fprintf (stderr, "%s%sField %s declared after indices.%s",
  134.                      qt(SNGCR), qt(cr(column)), getword(fh), SNGCR);
  135.             break;
  136.             }
  137.  
  138.          strlwrcpy (temp, getword (fh));  /* New field?  Obtain, in lower,  */
  139.          strmax (temp, 20);            /* its name.  Put it in 'temp' first */
  140.          strcpy (name, temp);          /* in case it's really long.         */
  141.  
  142.          if (mb_getname (data, name, 0) != -1)
  143.             {
  144.             fflush  (stdout);
  145.             fprintf (stderr, "%sField %s declared twice.%s", qt(cr(column)),
  146.                              name, SNGCR);
  147.             break;
  148.             }
  149.  
  150.          (void)skip (fh, "type");         /* Got its name, and it's new.  So */
  151.          strlwrcpy (temp, getword (fh));  /* get its field type...           */
  152.  
  153.          isExt = 0;
  154.          if (! strcmp (temp, "extern") || ! strcmp (temp, "external"))
  155.             {
  156.             isExt = 1;
  157.             strlwrcpy (temp, getword (fh));  /* External?  Get the next word. */
  158.             }
  159.  
  160.          typ = (ftype)-1;
  161.          if (! strcmp (temp, "char") || ! strcmp (temp, "character") ||
  162.              ! strcmp (temp, "string"))
  163.             {
  164.             typ = T_CHAR;
  165.             }
  166.          if (! strcmp (temp, "short"))    typ = T_SHORT;
  167.          if (! strcmp (temp, "ushort"))   typ = T_USHORT;
  168.          if (! strcmp (temp, "long"))     typ = T_LONG;
  169.          if (! strcmp (temp, "ulong"))    typ = T_ULONG;
  170.          if (! strcmp (temp, "float"))    typ = T_FLOAT;
  171.          if (! strcmp (temp, "double"))   typ = T_DOUBLE;
  172.          if (! strcmp (temp, "money"))    typ = T_MONEY;
  173.          if (! strcmp (temp, "time"))     typ = T_TIME;
  174.          if (! strcmp (temp, "date"))     typ = T_DATE;
  175.          if (! strcmp (temp, "serial"))   typ = T_SERIAL;
  176.          if (! strcmp (temp, "phone"))    typ = T_PHONE;
  177.  
  178.          if (typ == (ftype)-1)
  179.             {
  180.             fflush  (stdout);
  181.             fprintf (stderr, "%sType %s (field %s) undefined.%s",
  182.                              qt(cr(column)), temp, name, SNGCR);
  183.             break;
  184.             }
  185.  
  186.          if (isExt)
  187.             {
  188.             sprintf (temp, "ix_%s", name);
  189.             sprintf (desc, "%d",    num_i);
  190.  
  191.             if (mb_addindex (data, temp, 1, desc) != MB_OKAY)
  192.                fatal();
  193.  
  194.             if (typ == T_SERIAL)
  195.                typ = T_LONG;
  196.             }
  197.  
  198.          if (typ == T_SERIAL)
  199.             {
  200.             if (hasser)
  201.                {
  202.                fflush  (stdout);
  203.                fprintf (stderr, "%sMore than one serial field specified.%s",
  204.                         qt(cr (column)), SNGCR);
  205.                break;
  206.                }
  207.             hasser = 1;
  208.  
  209.             if (skip (fh, "start"))
  210.                nexts = atol (getword (fh));
  211.             }
  212.  
  213.          switch (typ)
  214.             {
  215.             case T_CHAR:
  216.                (void)skip (fh, "length");
  217.                (void)skip (fh, "*");
  218.                siz = atoi (getword(fh));
  219.                sprintf (temp, "%s [%s%d]", name, types[(int)typ], siz);
  220.                mb_addfield (data, name, T_CHAR, siz);
  221.                break;
  222.  
  223.             case T_SERIAL:
  224.                sprintf (temp, "%s [%s @%ld]", name, types[(int)typ], nexts);
  225.                mb_addfield (data, name, T_SERIAL, nexts);
  226.                break;
  227.  
  228.             default:
  229.                sprintf (temp, "%s [%s]", name, types[(int)typ]);
  230.                mb_addfield (data, name, typ, 0);
  231.                break;
  232.             }
  233.  
  234.          if (mb_errno)
  235.             fatal();
  236.  
  237.          if ((column = 1-column) == 0)
  238.             { Printf ("%s%-30.30s%s", SUBD, temp, NORM); }
  239.          else
  240.             { Printf ("%s%s%s%s",     SUBD, temp, NORM, SNGCR); }
  241.  
  242.          num_f ++;
  243.  
  244.          comment();
  245.  
  246.          continue;
  247.          }
  248.  
  249.       if (strcmp (temp, "index") == 0)
  250.          {
  251.          if (stage == 1)
  252.             {
  253.             if (column == 0)
  254.                Printf (SNGCR);
  255.  
  256.             if (num_f == 0)
  257.                {
  258.                fflush  (stdout);
  259.                fprintf (stderr, "%sNo fields declared before indices.%s",
  260.                                  qt(SNGCR), SNGCR);
  261.                break;
  262.                }
  263.  
  264.             Printf (lineI, SNGCR);
  265.  
  266.             stage  = 2;
  267.             column = 1;
  268.             }
  269.  
  270.          strlwrcpy (temp, getword (fh));  /* New index?  Get the name (in   */
  271.          strmax (temp, 20);            /* temp first in case it's long) and */
  272.          strcpy (name, temp);          /* make sure it's unique.            */
  273.  
  274.          if (mb_getname (data, name, 1) != -1)
  275.             {
  276.             fflush  (stdout);
  277.             fprintf (stderr, "%sField %s declared twice.%s", qt(cr(column)),
  278.                              name, SNGCR);
  279.             break;
  280.             }
  281.  
  282.          (void)skip (fh, "on");
  283.  
  284.          for (temp[0] = desc[0] = 0; ; )
  285.             {
  286.             strlwrcpy (t2, getword (fh));
  287.  
  288.             if ((i = mb_getname (data, t2, 0)) == -1)
  289.                {
  290.                fflush  (stdout);
  291.                fprintf (stderr, "%sIndex placed on undeclared field %s.%s",
  292.                                 qt(cr(column)), t2, SNGCR);
  293.                exit (1);
  294.                }
  295.  
  296.             strcat  (temp, t2);
  297.             sprintf (t2, "%d", i);
  298.             strcat  (desc, t2);
  299.  
  300.             if (! skip (fh, ","))
  301.                break;
  302.  
  303.             strcat (temp, ",");
  304.             strcat (desc, ",");
  305.             }
  306.  
  307.          Printf ("%s%s", name, repeat ('.', 15-strlen (name)));
  308.          Printf ("%s%s", temp, repeat ('.', 22-strlen (temp)));
  309.  
  310.          typ = (ftype)0;
  311.  
  312.          if (skip (fh, "without"))
  313.             {
  314.             if (skip (fh, "duplicates") || skip (fh, "dups"))
  315.                typ = (ftype)0;
  316.             else
  317.                typ = (ftype)2;
  318.             }
  319.          else if (skip (fh, "with"))
  320.             {
  321.             if (skip (fh, "duplicates") || skip (fh, "dups"))
  322.                typ = (ftype)1;
  323.             else
  324.                typ = (ftype)2;
  325.             }
  326.          if (typ == (ftype)2)
  327.             {
  328.             fflush  (stdout);
  329.             fprintf (stderr, "?%sIncorrect syntax%s", qt(DUBCR), SNGCR);
  330.             exit    (1);
  331.             }
  332.  
  333.          if ((int)typ)  { Printf ("Duplicates allowed%s", SNGCR);     }
  334.          else           { Printf ("Duplicates not allowed%s", SNGCR); }
  335.  
  336.          if (contains_serial (desc))
  337.             typ = (ftype)1;
  338.  
  339.          if (mb_addindex (data, name, (int)typ, desc) != MB_OKAY)
  340.             {
  341.             fatal();
  342.             }
  343.  
  344.          num_i ++;
  345.  
  346.          comment();
  347.  
  348.          continue;
  349.          }
  350.  
  351.       if (strcmp (temp, "end") == 0 || temp[0] == 0)
  352.          {
  353.          Printf ("%s", cr (column));
  354.          endoffile (num_f, num_i);
  355.          stage = 3;
  356.  
  357.          continue;
  358.          }
  359.  
  360.       if (! strcmp (temp, "typedef"))
  361.          {
  362.          strlwrcpy (strname, getword (fh));
  363.          continue;
  364.          }
  365.  
  366.       fflush  (stdout);
  367.       fprintf (stderr, "%sIdentifier %s%s%s not recognized.%s",
  368.                        qt(cr(column)), BOLD, temp, NORM, SNGCR);
  369.       exit    (1);
  370.       }
  371.  
  372.    if (stage != 3)
  373.       {
  374.       exit (1);
  375.       }
  376.  
  377.    write_it (num_i, num_f);
  378.  
  379.    Printf ("Relation created -- zero entries.%s", SNGCR);
  380.  
  381.    exit (0);
  382. }
  383.  
  384. void
  385. write_it (num_i, num_f)
  386. int       num_i, num_f;
  387. {
  388.    char  temp[512], temp2[30];
  389.    int   R, H;
  390.    int   i, j;
  391.  
  392.  
  393.    if ((R = openx (rel, OPENMODE)) != -1)
  394.       {
  395.       if (read (R, temp, 1) != -1)
  396.          {
  397.          if (temp[0] != 50 && temp[0] != 42)  /* Check for 4.1a or 5.0 sig */
  398.             {
  399.             fPrintf (stderr, "%s%s%s%32.32s%-28.28s%s%s", SNGCR, SUBD, INVR,
  400.                              "*** ERR", "OR ***", NORM, SNGCR);
  401.             fprintf (stderr,
  402.                      "%s   This relation is not in MetalBase 5.0 format.%s",
  403.                      qt(SNGCR), DUBCR);
  404.             close (R);
  405.             exit (1);
  406.             }
  407.          }
  408.  
  409.       Printf ("%s%s%32.32s%-28.28s%s%s", SUBD, INVR, "** WARN", "ING **", NORM,
  410.                                          SNGCR);
  411.       Printf ("%s   The file about to be created already exists under the%s",
  412.                SNGCR, SNGCR);
  413.       Printf ("         target directory!  This data will be lost!%s", DUBCR);
  414.  
  415.       close (R);
  416.       }
  417.  
  418. /*
  419.  * That was ugly.  Now make sure they wanna continue first...
  420.  *
  421.  */
  422.  
  423.    if (! quiet)
  424.       {
  425.       Printf ("Continue with the creation of the relation [Y/n] ? ");
  426.       gets(temp);  i = (int)temp[0];
  427.       if (i == 'n' || i == 'N' || i == 'q' || i == 'Q')  exit (0);
  428.       }
  429.  
  430.    if (header || quiet)
  431.       {
  432.       i = (header ? 'y' : 'n');
  433.       }
  434.    else
  435.       {
  436.       Printf ("Create header file for this relation       [y/N] ? ");
  437.       fflush(stdin);  gets(temp);  i = (int)temp[0];
  438.       }
  439.    Printf (SNGCR);
  440.  
  441. /*
  442.  * That was uglier.  At any rate, we now have permission to create the thing:
  443.  *
  444.  */
  445.  
  446.    if (mb_create (data, rel, 0) != MB_OKAY)
  447.       {
  448.       fflush(stdout);
  449.       fprintf (stderr, "Cannot build relation--%s%s.", mb_error, SNGCR);
  450.       return;
  451.       }
  452.  
  453. /*
  454.  * Now if they want the header created, we've gotta do all kindsa special shit:
  455.  *
  456.  */
  457.  
  458.    if (i != 'y' && i != 'Y')
  459.       {
  460.       return;
  461.       }
  462.  
  463.    if ((H = openx (hdr, O_RDWR)) != -1)
  464.       {
  465.       close  (H);
  466.       unlink (hdr);
  467.       }
  468.    if ((H = creatx (hdr)) == -1)
  469.       {
  470.       fprintf (stderr, "%sSorry--cannot create header file%s", qt(DUBCR),
  471.                SNGCR);
  472.       return;
  473.       }
  474.    modex (hdr, 0666);   /* Make the file   -rw-rw-rw-  */
  475.  
  476.    sprintf (temp, "#ifndef %s_H%s", nameb, SNGCR);
  477.    writx   (H, temp, strlen(temp));
  478.    sprintf (temp, "#define %s_H%s", nameb, DUBCR);
  479.    writx   (H, temp, strlen(temp));
  480.    sprintf (temp, DESCLINE, names);
  481.    writx   (H, temp, strlen(temp));
  482.  
  483.    for (j = 0; j < data->num_f; j++)
  484.       {
  485.       switch (data->type[j])
  486.          {
  487.          case T_CHAR:   sprintf (temp, "char     %s[%d];",
  488.                                         data->name[j], data->siz[j]);   break;
  489.          case T_SHORT:  sprintf (temp, "short    %s;", data->name[j]);  break;
  490.          case T_USHORT: sprintf (temp, "ushort   %s;", data->name[j]);  break;
  491.          case T_LONG:   sprintf (temp, "long     %s;", data->name[j]);  break;
  492.          case T_ULONG:  sprintf (temp, "ulong    %s;", data->name[j]);  break;
  493.          case T_FLOAT:  sprintf (temp, "float    %s;", data->name[j]);  break;
  494.          case T_DOUBLE: sprintf (temp, "double   %s;", data->name[j]);  break;
  495.          case T_MONEY:  sprintf (temp, "double   %s;", data->name[j]);  break;
  496.          case T_TIME:   sprintf (temp, "mb_time  %s;", data->name[j]);  break;
  497.          case T_DATE:   sprintf (temp, "mb_date  %s;", data->name[j]);  break;
  498.          case T_PHONE:  sprintf (temp, "mb_phone %s;", data->name[j]);  break;
  499.          default:       sprintf (temp, "long     %s;", data->name[j]);  break;
  500.          }
  501.  
  502.       i = 24;
  503.       if (data->type[j] == T_CHAR)
  504.          i -= 3 +(data->siz[j] >10) +(data->siz[j] >100) +(data->siz[j] >1000);
  505.  
  506.       strcat (temp, repeat (' ', i-strlen(data->name[j])));
  507.  
  508.       strcat (temp, "/");
  509.       strcat (temp, "* field ");
  510.       strcat (temp, data->name[j]);
  511.       strcat (temp, " type ");
  512.  
  513.       if (data->type[j] != T_CHAR)
  514.          {
  515.          strcat (temp, types[(int)data->type[j]]);
  516.          }
  517.       else
  518.          {
  519.          sprintf (nameb, "string length %d", data->siz[j]);
  520.          strcat  (temp, nameb);
  521.          }
  522.       if (data->type[j] == T_SERIAL && data->serial != 0L)
  523.          {
  524.          sprintf (nameb, " start %ld", data->serial);
  525.          strcat  (temp, nameb);
  526.          }
  527.       strcat (temp, repeat (' ', 73-strlen (temp)));
  528.       strcat (temp, " *");
  529.       strcat (temp, "/");
  530.       strcat (temp, SNGCR);
  531.       strcat (temp, "   ");
  532.       writx (H, temp, strlen (temp));
  533.       }
  534.  
  535.    if (strname[0])
  536.       {
  537.       strcpy (temp2, strname);
  538.       }
  539.    else
  540.       {
  541.       strcpy (strname, names);
  542.       strcat (strname, "_str");
  543.       strcpy (temp2,   names);
  544.       }
  545.  
  546.    strcat (temp2, "_rec");
  547.  
  548.    sprintf (temp, "%c %s;%s", RBC, strname, DUBCR);
  549.    writx   (H, temp, strlen (temp));
  550.  
  551.    sprintf (temp, "#ifndef MODULE%s   %s %s;%s",
  552.             SNGCR, strname, temp2, SNGCR);
  553.    writx   (H, temp, strlen (temp));
  554.  
  555.    sprintf (temp, "#else%s   extern %s %s;%s#endif%s#endif%s",
  556.             SNGCR, strname, temp2, SNGCR, DUBCR, DUBCR);
  557.    writx   (H, temp, strlen (temp));
  558.  
  559.    Printf  ("Header file created.%s", SNGCR);
  560.    close   (H);
  561. }
  562.  
  563. void
  564. endoffile (num_f, num_i)
  565. int        num_f, num_i;
  566. {
  567.    if (num_f == 0)
  568.       {
  569.       fprintf (stderr, "No fields declared before end reached%s", SNGCR);
  570.       exit    (1);
  571.       }
  572.    if (num_i == 0)
  573.       {
  574.       fprintf (stderr, "No indices declared before end reached%s", SNGCR);
  575.       exit    (1);
  576.       }
  577. }
  578.  
  579. void
  580. strlwrcpy (new, old)
  581. char      *new,*old;
  582. {
  583.    register char *a,*b;
  584.    if (!new || !old)  return;
  585.    for (a=new,b=old; *b; a++,b++)
  586.       *a = tolower (*b);
  587.    *a=0;
  588. }
  589.  
  590. void
  591. struprcpy (new, old)
  592. char      *new,*old;
  593. {
  594.    register char *a,*b;
  595.    if (!new || !old)  return;
  596.    for (a=new,b=old; *b; a++,b++)
  597.       *a = toupper (*b);
  598.    *a=0;
  599. }
  600.  
  601. void
  602. strmax (str, siz)
  603. char   *str;
  604. int          siz;
  605. {
  606.    register int   i;
  607.    register char *a;
  608.  
  609.    for (i=0, a=str; *a; i++, a++)
  610.       if (i == siz)
  611.          {
  612.          *a = 0;
  613.          break;
  614.          }
  615. }
  616.  
  617. int
  618. get_names (agc, agv)
  619. int        agc;
  620. char          **agv;
  621. {
  622.    char  temp[128];
  623.    int   i, fh;
  624.  
  625.    while (agc > 1 && agv[1][0] == '-')
  626.       {
  627.       switch (agv[1][1])
  628.          {
  629.          case 'q':  quiet  = 1;  break;
  630.          case 'h':  header = 1;  break;
  631.          default:   fprintf (stderr,"unrecognized option '%s'%s",agv[1],SNGCR);
  632.                     usage   ();
  633.                     exit    (1);
  634.                    break;
  635.          }
  636.       switch (agv[1][2])
  637.          {
  638.          case 'q':  quiet  = 1;  break;
  639.          case 'h':  header = 1;  break;
  640.          }
  641.  
  642.       agc--;  agv++;
  643.       }
  644.  
  645.    if (agc != 2)
  646.       {
  647.       usage ();
  648.       exit  (1);
  649.       }
  650.  
  651.    strcpy (temp, agv[1]);
  652.    if (strcmp (&temp[strlen(temp)-2], ".s"))
  653.       strcat (temp, ".s");
  654.  
  655.    strcpy (rel, temp);
  656.  
  657.    for (i = strlen(temp)-1; i > -1 && temp[i] != ':' && temp[i] != DIRSEP; i--)
  658.       ;
  659.    if (i < 0)  i = 0;
  660.  
  661.    rel[i] = 0;
  662.  
  663.    if ((fh = openx (temp, O_RDONLY)) == -1)
  664.       {
  665.       fprintf (stderr, "cannot open %s.%s", temp, SNGCR);
  666.       exit    (1);
  667.       }
  668.  
  669.    comment();
  670.  
  671.    (void)skip (fh, "relation");
  672.  
  673.    strcpy (temp, getword (fh));
  674.  
  675.    if (temp[0] == 0)
  676.       {
  677.       fprintf (stderr, "file holds no schema definition.%s",SNGCR);
  678.       exit    (1);
  679.       }
  680.  
  681.    Printf ("%s", CLS);
  682.    Printf ("Building relation %s under ", temp);
  683.  
  684.    strlwrcpy (names, temp);
  685.    struprcpy (nameb, temp);
  686.  
  687.    if (rel[0] != 0)
  688.       {
  689.       Printf ("directory %s%s",   rel, DUBCR);
  690.       sprintf (hdr, "%s%c%s.h",   rel, DIRSEP, temp);
  691.       sprintf (rel, "%s%c%s.rel", rel, DIRSEP, temp);
  692.       }
  693.    else
  694.       {
  695.       Printf ("current directory%s", DUBCR);
  696.       sprintf (hdr, "%s.h",   temp);
  697.       sprintf (rel, "%s.rel", temp);
  698.       }
  699.  
  700.    Printf (lineF, SNGCR);
  701.  
  702.    comment();
  703.  
  704.    return fh;
  705. }
  706.  
  707. char *
  708. repeat (ch, nm)
  709. char    ch;
  710. int         nm;
  711. {
  712.    static char buf[80];
  713.  
  714.    buf[(nm = (nm < 0) ? 0 : nm)] = 0;
  715.  
  716.    for (nm--; nm >= 0; nm--)  buf[nm] = ch;
  717.  
  718.    return buf;
  719. }
  720.  
  721. int
  722. contains_serial (desc)
  723. char            *desc;
  724. {
  725.    char *line, *pch;
  726.  
  727.    for (line = desc; (pch = strchr (line, ',')) != NULL; line = pch+1)
  728.       {
  729.       *pch = 0;
  730.       if (data->type[atoi(line)] == T_SERIAL)
  731.          return 1;
  732.       }
  733.    if (data->type[atoi(line)] == T_SERIAL)
  734.       return 1;
  735.  
  736.    return 0;
  737. }
  738.  
  739.