home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 08 / generate.asc < prev    next >
Text File  |  1991-07-23  |  29KB  |  1,266 lines

  1. _A SOURCE CODE GENERATOR FOR C_
  2. by Karl Vogel
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /* File "new.h" */
  8.  
  9. #ifndef    lint
  10. static char    *new_h_rcsid =
  11. "$Header: new.h,v 1.5 91/03/29 19:23:08 vogel Exp $";
  12.  
  13. static char    *new_h_source =
  14. "$Source: /d/cdc/vogel/source/new/RCS/new.h,v $";
  15.  
  16. #endif
  17.  
  18. /*
  19.  * NAME:
  20.  *    new.h
  21.  *
  22.  * SYNOPSIS:
  23.  *    #include "new.h"
  24.  *
  25.  * DESCRIPTION:
  26.  *    Holds the data structure for the command line options, plus
  27.  *    general definitions.
  28.  *    
  29.  * AUTHOR:
  30.  *    Karl Vogel
  31.  *
  32.  * BUGS:
  33.  *    None noticed.
  34.  *
  35.  * REVISIONS:
  36.  *
  37.  * $Log:    new.h,v $
  38.  * Revision 1.5  91/03/29  19:23:08  vogel
  39.  * 1.  Renamed the directory holding the templates.
  40.  * 
  41.  * Revision 1.4  91/03/15  16:56:33  vogel
  42.  * 1.  Ran indent on the code and reformatted the comment header.
  43.  * 
  44.  * Revision 1.3  90/07/03  14:21:20  vogel
  45.  * 1.  Added a new field:  extension of the program to be created.  This is also
  46.  *     in "macro.h", but it can be most easily set from examining the command
  47.  *     line options.
  48.  * 
  49.  * Revision 1.2  90/07/03  12:07:06  vogel
  50.  * 1.  Added a flag to the OPTIONS structure which is TRUE if the created file
  51.  *     is to be edited, FALSE otherwise.
  52.  * 
  53.  * Revision 1.1  90/06/29  15:32:04  vogel
  54.  * Initial revision
  55.  * 
  56.  */
  57.  
  58. #include    <stdio.h>
  59.  
  60. #define        YES        1
  61. #define        NO        0
  62.  
  63. /* Error codes.  */
  64. #define        OK        0
  65. #define        EMALLOC        1
  66.  
  67. /* Set directory holding templates, and prefix of each template file.  */
  68. #define        DIRECTORY    "/d/cdc/vogel/source/new/"
  69. #define        PREFIX        "template."
  70.  
  71. /* Set up the options structure.  */
  72. struct options_data
  73. {
  74.     char          **files;        /* NULL-terminated array of C files
  75.                      * to be created. */
  76.     char           *template;    /* Full name of the desired   
  77.                      * template file. */
  78.     char            exten[5];    /* Extension of the program to be
  79.                      * created.  */
  80.     int             edit;        /* True if the created program is to
  81.                      * be edited. */
  82.     int             help;        /* True if help is needed. */
  83. };
  84.  
  85. typedef struct options_data OPTIONS;
  86.  
  87.  
  88.  
  89. [LISTING TWO]
  90.  
  91.  
  92. /* File "macro.h" */
  93.  
  94. #ifndef    lint
  95. static char    *macro_h_rcsid =
  96. "$Header: macro.h,v 1.2 91/03/15 16:56:28 vogel Exp $";
  97.  
  98. static char    *macro_h_source =
  99. "$Source: /d/cdc/vogel/source/new/RCS/macro.h,v $";
  100.  
  101. #endif
  102.  
  103. /*
  104.  * NAME:
  105.  *    macro.h
  106.  *
  107.  * SYNOPSIS:
  108.  *    #include "macro.h"
  109.  *
  110.  * DESCRIPTION:
  111.  *    Header file for macro substitutions.
  112.  *    
  113.  * AUTHOR:
  114.  *    Karl Vogel
  115.  *
  116.  * BUGS:
  117.  *    Any problems or suggestions. 
  118.  *
  119.  * REVISIONS:
  120.  *
  121.  * $Log:    macro.h,v $
  122.  * Revision 1.2  91/03/15  16:56:28  vogel
  123.  * 1.  Ran indent on the code and reformatted the comment header.
  124.  * 
  125.  * Revision 1.1  90/06/29  17:40:15  vogel
  126.  * Initial revision
  127.  * 
  128.  */
  129.  
  130. #define        BUFFER        512
  131.  
  132. struct macro_data
  133. {
  134.     char            args[BUFFER];    /* Arguments for the function: full
  135.                      * declarations separated by
  136.                      * semicolons and newlines. Replaces
  137.                      * $a in a template.  */
  138.     char            body[BUFFER];    /* Body of the function.  Comes under
  139.                      * the first comment after the
  140.                      * variable declarations. Includes
  141.                      * tabs and newlines. Replaces $b in
  142.                      * a template.  */
  143.     char            exten[5];    /* Extension of the created file,
  144.                      * usually ".c".  Replaces $e in a
  145.                      * template. */
  146.     char            functions[BUFFER];    /* Internal function
  147.                          * declarations. Comes just
  148.                          * after the start of the
  149.                          * function itself.  Includes
  150.                          * tabs and newlines. 
  151.                          * Replaces $f in a template. */
  152.     char            globals[BUFFER];/* External global variables. Comes
  153.                      * just before the start of the
  154.                      * function itself.  Includes tabs
  155.                      * and newlines.  Replaces $g in a
  156.                      * template. */
  157.     char            include[BUFFER];/* External include files.  Comes
  158.                      * just before the start of the
  159.                      * function itself.  Includes tabs
  160.                      * and newlines.  Replaces $i in a
  161.                      * template.  */
  162.     char            alist[BUFFER];    /* Short form of the argument list,
  163.                      * consisting of just the variable
  164.                      * names separated by commas. 
  165.                      * Replaces $l in a template. */
  166.     char            name[64];    /* Name of the function being
  167.                      * created.  May or may not be the
  168.                      * same as the filename. Replaces $n
  169.                      * in a template.  */
  170.     char            define[BUFFER];    /* Holds preprocessor #define
  171.                      * statements separated by newlines. 
  172.                      * Replaces $p in a template. */
  173.     char            rev[16];    /* Current revision level of the
  174.                      * created function.  Replaces $r in
  175.                      * a template. */
  176.     char            type[32];    /* Type of function created, i.e.
  177.                      * char * or int.  Replaces $t in a
  178.                      * template.  */
  179.     char            usage[BUFFER];    /* Comes right after the first use of
  180.                      * the function name, and tells you
  181.                      * what the function is supposed to
  182.                      * do.  Just above the Usage section
  183.                      * in the intro comments.  This is
  184.                      * the only "smart" macro: won't let
  185.                      * you put too many words on a line,
  186.                      * and starts each line with a
  187.                      * comment indicator.  Replaces $u in
  188.                      * a template. */
  189.     char            vars[BUFFER];    /* Holds internally-declared
  190.                      * variables, separated by tabs,
  191.                      * semicolons, and newlines. Replaces
  192.                      * $v in a template.  */
  193.     char            userid[16];    /* Holds the author's userid.
  194.                      * Replaces $w in a template.  */
  195.     char            username[BUFFER];    /* Holds the author's full
  196.                          * name. Replaces $x in a
  197.                          * template.  */
  198.     char            token;        /* Holds the character to be used as
  199.                      * a token indicator.  Shown as a
  200.                      * dollar sign in this file.  */
  201.     int             year;        /* Current year.  Replaces $y in a
  202.                      * template. */
  203.     int             month;        /* Current month.  Replaces $c in a
  204.                      * template. */
  205.     int             day;        /* Current day.  Replaces $d in a
  206.                      * template. */
  207.     int             hour;        /* Current hour.  Replaces $h in a
  208.                      * template. */
  209.     int             minute;        /* Current minute.  Replaces $m in a
  210.                      * template.  */
  211.     int             second;        /* Current second.  Replaces $s in a
  212.                      * template.  */
  213. };
  214. typedef struct macro_data MACRO;
  215.  
  216.  
  217.  
  218.  
  219. [LISTING THREE]
  220.  
  221. /* File "new.c" */
  222.  
  223. #ifndef    lint
  224. static char    *new_c_rcsid =
  225. "$Header: new.c,v 1.6 91/03/15 16:55:42 vogel Exp $";
  226.  
  227. static char    *new_c_source =
  228. "$Source: /d/cdc/vogel/source/new/RCS/new.c,v $";
  229.  
  230. #endif
  231.  
  232. /*
  233.  * NAME:
  234.  *    new
  235.  *
  236.  * SYNOPSIS:
  237.  *    new [-c] [-h] [-mx] file [file ...]
  238.  *
  239.  * DESCRIPTION:
  240.  *    Creates and optionally edits one or more new C programs.
  241.  *
  242.  *    "new" makes extensive use of templates to create new C files.
  243.  *    A template file has the name "template.x", where 'x' is the string
  244.  *    which follows '-m' in the program arguments.
  245.  *
  246.  *    You can create other templates by adding template files to the
  247.  *    template directory specified in the header file "new.h".
  248.  *    
  249.  * OPTIONS:
  250.  *    "-c"    creates a new program but does NOT edit it.
  251.  *
  252.  *    "-h"    prints help information if improper or no arguments at all
  253.  *        are given.
  254.  *
  255.  *    "-mx"    creates a program of type 'x', where x is one of the following:
  256.  *        d - function driver.
  257.  *        f - normal function (default).
  258.  *        h - header file.
  259.  *        i - program to handle simple I/O.
  260.  *        m - main routine with arguments.
  261.  *        o - function to handle command line arguments.
  262.  *        s - stub (placeholder) function.
  263.  *
  264.  *    "file"    is one or more C files to be created.  A suffix of ".c" will
  265.  *        be appended if it isn't there already.  If the file already
  266.  *        exists, you will be asked if you want to overwrite it.
  267.  *
  268.  * AUTHOR:
  269.  *    Karl Vogel
  270.  *
  271.  * BUGS:
  272.  *    None noticed.
  273.  *
  274.  * REVISIONS:
  275.  *
  276.  * $Log:    new.c,v $
  277.  * Revision 1.6  91/03/15  16:55:42  vogel
  278.  * 1.  Ran indent on the code and reformatted the comment header.
  279.  * 
  280.  * Revision 1.5  90/09/24  16:42:03  vogel
  281.  * 1.  Corrected a typo in the comments.
  282.  * 
  283.  * Revision 1.4  90/07/03  14:20:23  vogel
  284.  * 1.  Copied the desired file extension into the MACRO structure.
  285.  * 
  286.  * Revision 1.3  90/07/03  12:05:23  vogel
  287.  * 1.  Added "nextfile" variable, to hold the next file to be created.
  288.  * 2.  Got rid of debugging print statements for the macros structure.
  289.  * 3.  Added code to create and optionally edit each file in turn.
  290.  * 
  291.  * Revision 1.2  90/06/29  17:40:04  vogel
  292.  * 1.  Added header file and definitions for the macro substitution strings.
  293.  * 2.  Added code to print help if needed.
  294.  * 
  295.  * Revision 1.1  90/06/29  15:27:52  vogel
  296.  * Initial revision
  297.  * 
  298.  */
  299.  
  300. #include    "new.h"
  301. #include    "macro.h"
  302. #include    <strings.h>
  303. #include    <sys/param.h>
  304.  
  305. main (argc, argv)
  306. int             argc;
  307. char          **argv;
  308. {
  309.  
  310. /* Variables. */
  311.     MACRO          *macros;
  312.     MACRO           macbuffer;
  313.  
  314.     OPTIONS        *options;
  315.     OPTIONS         opbuffer;
  316.  
  317.     char            nextfile[MAXPATHLEN];
  318.  
  319.     int             k;
  320.     int             status;
  321.  
  322. /* Process command line options. If they aren't OK, offer help and exit. */
  323.     options = &opbuffer;
  324.     status = GetOptions (argc, argv, options);
  325.  
  326.     if (status == EMALLOC)
  327.     {
  328.         fprintf (stderr, "Severe memory error -- please call the ");
  329.         fprintf (stderr, "System Administrator.\n");
  330.         exit (1);
  331.     }
  332.  
  333.     if (options->help)
  334.     {
  335.         (void) Help ();
  336.         exit (1);
  337.     }
  338.  
  339. /* Set up the substitution macros.  */
  340.     macros = &macbuffer;
  341.     SetMacros (macros);
  342.     (void) strcpy (macros->exten, options->exten);
  343.  
  344. /* Create and optionally edit each file in turn.  */
  345.     for (k = 0; options->files[k]; ++k)
  346.     {
  347.         (void) strcpy (nextfile, options->files[k]);
  348.  
  349.         if (CreateCode (macros, options->template, nextfile) == 0)
  350.             if (options->edit)
  351.                 EditCode (nextfile);
  352.     }
  353.  
  354.     exit (0);
  355. }
  356.  
  357.  
  358.  
  359.  
  360. [LISTING FOUR]
  361.  
  362. /* File "CreateCode.c" */
  363.  
  364. #ifndef    lint
  365. static char    *CreateCode_c_rcsid =
  366. "$Header: CreateCode.c,v 1.2 91/03/15 16:55:25 vogel Exp $";
  367.  
  368. static char    *CreateCode_c_source =
  369. "$Source: /d/cdc/vogel/source/new/RCS/CreateCode.c,v $";
  370.  
  371. #endif
  372.  
  373. /*
  374.  * NAME:
  375.  *    CreateCode
  376.  *
  377.  * SYNOPSIS:
  378.  *    #include "macro.h"
  379.  *
  380.  *    int CreateCode (macros, template, nextfile)
  381.  *    MACRO * macros;
  382.  *    char * template;
  383.  *    char * nextfile;
  384.  *
  385.  * DESCRIPTION:
  386.  *    Accepts the substitution structure, the input file, and the new C
  387.  *    file to be created.  Reads the template file, fills it in with the
  388.  *    contents of the substitution structure, and writes the results to
  389.  *    the new C file.
  390.  *
  391.  *    A function value of 0 is returned if everything is OK.
  392.  *    A function value of 1 is returned if the template could not be read.
  393.  *    A function value of 2 is returned if the output could not be written.
  394.  *
  395.  * ARGUMENTS:
  396.  *    "macros" is the structure holding the macro substitution values.
  397.  *    "template" is the name of the input template file.
  398.  *    "nextfile" is the name of the next output file.
  399.  *
  400.  * AUTHOR:
  401.  *    Karl Vogel
  402.  *
  403.  * BUGS:
  404.  *    None noticed.
  405.  *
  406.  * REVISIONS:
  407.  *
  408.  * $Log:    CreateCode.c,v $
  409.  * Revision 1.2  91/03/15  16:55:25  vogel
  410.  * 1.  Ran indent on the code and reformatted the comment header.
  411.  * 
  412.  * Revision 1.1  90/07/03  11:59:45  vogel
  413.  * Initial revision
  414.  * 
  415.  */
  416.  
  417. #include    "macro.h"
  418. #include    <stdio.h>
  419. #include    <strings.h>
  420. #include    <sys/file.h>
  421.  
  422. #define        SMALLBUF    20
  423.  
  424. int             CreateCode (macros, template, nextfile)
  425. MACRO          *macros;
  426. char           *template;
  427. char           *nextfile;
  428. {
  429.  
  430. /* Variables. */
  431.  
  432.     FILE           *in;
  433.     FILE           *out;
  434.  
  435.     char           *base;
  436.     char           *dot;
  437.     char            last[SMALLBUF];
  438.     char            prompt[SMALLBUF];
  439.  
  440.     int             length;
  441.     int             status;
  442.  
  443. /* If filename already has default extension specified in MACRO structure, zap
  444.  * it so we can store the function name in the MACRO structure. */
  445.     status = 0;
  446.     in = (FILE *) NULL;
  447.     out = (FILE *) NULL;
  448.  
  449.     last[0] = '.';
  450.     last[1] = '\0';
  451.  
  452.     (void) strcat (last, macros->exten);
  453.     length = strlen (last);
  454.  
  455.     if (dot = rindex (nextfile, '.'))
  456.         if (strcmp (dot, last) == 0)
  457.             *dot = '\0';
  458.  
  459.     if (base = rindex (nextfile, '/'))
  460.         base++;
  461.     else
  462.         base = nextfile;
  463.  
  464.     (void) strcpy (macros->name, base);
  465.     (void) strcat (nextfile, last);
  466.  
  467. /* If output file already exists, make sure that user wants to overwrite it. */
  468.     if (access (nextfile, F_OK) == 0)
  469.     {
  470.         printf ("File \"%s\" exists.  Overwrite?  ", nextfile);
  471.         fflush (stdout);
  472.         fgets (prompt, SMALLBUF, stdin);
  473.  
  474.         if (prompt[0] != 'y' && prompt[0] != 'Y')
  475.         {
  476.             printf ("\"%s\" not overwritten.\n", nextfile);
  477.             goto done;
  478.         }
  479.     }
  480.  
  481. /* Open the input template file. */
  482.     if ((in = fopen (template, "r")) == (FILE *) NULL)
  483.     {
  484.         printf ("Unable to open template file \"%s\"\n", template);
  485.         status = 1;
  486.         goto done;
  487.     }
  488.  
  489. /* Open the output C file. */
  490.     if ((out = fopen (nextfile, "w")) == (FILE *) NULL)
  491.     {
  492.         printf ("Unable to open C file \"%s\"\n", nextfile);
  493.         status = 2;
  494.         goto done;
  495.     }
  496.  
  497. /* Do the macro substitution, clean up, and return. */
  498.     ReplaceMacros (in, macros, out);
  499. done:
  500.     if (in)
  501.         (void) fclose (in);
  502.     if (out)
  503.         (void) fclose (out);
  504.     return (status);
  505. }
  506.  
  507.  
  508. [LISTING FIVE]
  509.  
  510. /* File "EditCode.c" */
  511.  
  512. #ifndef    lint
  513. static char    *EditCode_c_rcsid =
  514. "$Header: EditCode.c,v 1.2 91/03/15 16:55:28 vogel Exp $";
  515.  
  516. static char    *EditCode_c_source =
  517. "$Source: /d/cdc/vogel/source/new/RCS/EditCode.c,v $";
  518.  
  519. #endif
  520.  
  521. /*
  522.  * NAME:
  523.  *    EditCode
  524.  *
  525.  * SYNOPSIS:
  526.  *    int EditCode (nextfile)
  527.  *    char * nextfile;
  528.  *
  529.  * DESCRIPTION:
  530.  *    Edits the new C file using either "cvi" or whatever the user has in
  531.  *    his "EDITOR" environment variable.
  532.  *
  533.  * ARGUMENTS:
  534.  *    "nextfile" is the new C file.
  535.  *
  536.  * AUTHOR:
  537.  *    Karl Vogel
  538.  *
  539.  * BUGS:
  540.  *    None noticed.
  541.  *
  542.  * REVISIONS:
  543.  *
  544.  * $Log:    EditCode.c,v $
  545.  * Revision 1.2  91/03/15  16:55:28  vogel
  546.  * 1.  Ran indent on the code and reformatted the comment header.
  547.  * 
  548.  * Revision 1.1  90/07/03  12:00:13  vogel
  549.  * Initial revision
  550.  */
  551.  
  552. #include    <stdio.h>
  553.  
  554. int             EditCode (nextfile)
  555. char           *nextfile;
  556. {
  557.  
  558. /* Functions.  */
  559.     char           *getenv ();
  560.  
  561. /* Variables.  */
  562.     char           *editor;
  563.     char            cmd[BUFSIZ];
  564.  
  565.     int             status;
  566.  
  567. /* Create and execute the edit command.  */
  568.     if (editor = getenv ("EDITOR"))
  569.         (void) strcpy (cmd, editor);
  570.     else
  571.         (void) strcpy (cmd, "cvi");
  572.     (void) strcat (cmd, " ");
  573.     (void) strcat (cmd, nextfile);
  574.     (void) system (cmd);
  575.  
  576.     return (0);
  577. }
  578.  
  579.  
  580. [LISTING SIX]
  581.  
  582. /* File "GetOptions.c" */
  583.  
  584. #ifndef    lint
  585. static char    *GetOptions_c_rcsid =
  586. "$Header: GetOptions.c,v 1.4 91/03/15 16:55:31 vogel Exp $";
  587.  
  588. static char    *GetOptions_c_source =
  589. "$Source: /d/cdc/vogel/source/new/RCS/GetOptions.c,v $";
  590.  
  591. #endif
  592.  
  593. /*
  594.  * NAME:
  595.  *    GetOptions
  596.  *
  597.  * SYNOPSIS:
  598.  *    #include "new.h"
  599.  *
  600.  *    int GetOptions (argc, argv, options)
  601.  *    int argc;
  602.  *    char ** argv;
  603.  *    OPTIONS * options;
  604.  *
  605.  * DESCRIPTION:
  606.  *    Accepts the command line arguments and a pointer to a structure which
  607.  *    holds the options, and parses the arguments into the structure.
  608.  *
  609.  * ARGUMENTS:
  610.  *    "argc" and "argv" are the normal C program variables holding the
  611.  *    argument list.
  612.  *
  613.  *    "options" is the structure meant to hold the options.
  614.  *
  615.  * AUTHOR:
  616.  *    Karl Vogel
  617.  *
  618.  * BUGS:
  619.  *    Any problems or suggestions. 
  620.  *
  621.  * REVISIONS:
  622.  *
  623.  * $Log:    GetOptions.c,v $
  624.  * Revision 1.4  91/03/15  16:55:31  vogel
  625.  * 1.  Ran indent on the code and reformatted the comment header.
  626.  * 
  627.  * Revision 1.3  90/07/03  14:19:49  vogel
  628.  * 1.  Added code to set up the file extension based on the command line options.
  629.  *     "new -mh" gives you a file with name ending in ".h", anything else gives
  630.  *     you a file with name ending in ".c".
  631.  * 
  632.  * Revision 1.2  90/07/03  12:01:01  vogel
  633.  * 1.  Added new option '-c'.
  634.  * 2.  Added code to make sure that default template is properly set up.
  635.  * 
  636.  * Revision 1.1  90/06/29  15:28:13  vogel
  637.  * Initial revision
  638.  * 
  639.  */
  640.  
  641. #include    "new.h"
  642. #include    <strings.h>
  643.  
  644. #define        SMALL        10
  645.  
  646. int             GetOptions (argc, argv, options)
  647. int             argc;
  648. char          **argv;
  649. OPTIONS        *options;
  650. {
  651.  
  652. /* Functions. */
  653.     char           *malloc ();
  654.  
  655. /* Variables. */
  656.     char           *next;
  657.     char            extension[SMALL + 1];
  658.  
  659.     int             count;
  660.     int             flags;
  661.     int             k;
  662.     int             status;
  663.  
  664.     unsigned int    length;
  665.  
  666. /* Initialize options to defaults.  */
  667.     options->files = (char **) NULL;
  668.     options->template = (char *) NULL;
  669.     options->edit = YES;
  670.     options->help = NO;
  671.  
  672.     (void) strcpy (extension, "f");
  673.  
  674.     count = 0;
  675.     status = OK;
  676.  
  677. /* Handle the flags, and count the files. */
  678.     for (k = 1; k < argc; ++k)
  679.     {
  680.         next = argv[k];
  681.  
  682.         if (*next == '-')
  683.         {
  684.             next++;
  685.  
  686.             if (*next == 'm')
  687.             {
  688.                 (void) strncpy (extension, next + 1, SMALL);
  689.                 extension[SMALL] = '\0';
  690.             }
  691.  
  692.             else
  693.             if (*next == 'c')
  694.                 options->edit = NO;
  695.  
  696.             else
  697.             {
  698.                 options->help = YES;
  699.                 goto done;
  700.             }
  701.         }
  702.  
  703.         else        /* option does not start with a dash  */
  704.             count++;
  705.     }
  706.  
  707. /* If no files were specified, set help flag. Otherwise, store filenames. */
  708.     if (count)
  709.     {
  710.         length = (unsigned) ((count + 1) * (sizeof (char *)));
  711.         if (options->files = (char **) malloc (length))
  712.         {
  713.             for (k = 1, count = 0; k < argc; ++k)
  714.                 if (*argv[k] != '-')
  715.                     options->files[count++] = argv[k];
  716.             options->files[count] = (char *) NULL;
  717.         }
  718.         else
  719.         {
  720.             status = EMALLOC;
  721.             goto done;
  722.         }
  723.     }
  724.     else
  725.     {
  726.         options->help = YES;
  727.         goto done;
  728.     }
  729.  
  730. /* Set up the file extension. */
  731.     if (strcmp (extension, "h") == 0)
  732.         options->exten[0] = 'h';
  733.     else
  734.         options->exten[0] = 'c';
  735.  
  736.     options->exten[1] = '\0';
  737.  
  738. /* Set up the template pathname.  */
  739.     length = (unsigned) (strlen (DIRECTORY) + strlen (PREFIX) +
  740.                  strlen (extension) + 1);
  741.     if (options->template = malloc (length))
  742.         (void) sprintf (options->template, "%s%s%s", DIRECTORY,
  743.                 PREFIX, extension);
  744.     else
  745.         status = EMALLOC;
  746. done:
  747.     return (status);
  748. }
  749.  
  750.  
  751.  
  752.  
  753. [LISTING SEVEN]
  754.  
  755. /* File "Help.c" */
  756.  
  757. #ifndef    lint
  758. static char    *Help_c_rcsid =
  759. "$Header: Help.c,v 1.4 91/03/15 16:55:33 vogel Exp $";
  760.  
  761. static char    *Help_c_source =
  762. "$Source: /d/cdc/vogel/source/new/RCS/Help.c,v $";
  763.  
  764. #endif
  765.  
  766. /*
  767.  * NAME:
  768.  *    Help
  769.  *
  770.  * SYNOPSIS:
  771.  *    int Help ()
  772.  *
  773.  * DESCRIPTION:
  774.  *    Prints help information to stdout.
  775.  *
  776.  * ARGUMENTS:
  777.  *    None.
  778.  *
  779.  * AUTHOR:
  780.  *    Karl Vogel
  781.  *
  782.  * BUGS:
  783.  *    None noticed.
  784.  *
  785.  * REVISIONS:
  786.  *
  787.  * $Log:    Help.c,v $
  788.  * Revision 1.4  91/03/15  16:55:33  vogel
  789.  * 1.  Ran indent on the code and reformatted the comment header.
  790.  * 
  791.  * Revision 1.3  90/09/24  16:40:47  vogel
  792.  * 1.  Corrected a typo.
  793.  * 
  794.  * Revision 1.2  90/07/03  12:01:42  vogel
  795.  * 1.  Changed print strings to reflect new '-c' option.
  796.  * 
  797.  * Revision 1.1  90/06/29  17:40:46  vogel
  798.  * Initial revision
  799.  * 
  800.  */
  801.  
  802. #include    <stdio.h>
  803.  
  804. int             Help ()
  805. {
  806.  
  807. /* Variables.  */
  808.     int             k;
  809.  
  810.     static char    *array[] =
  811.     {
  812.      "",
  813.      "\tnew:\t\tcreates and optionally edits one or more new C",
  814.      "\t\t\tprograms.",
  815.      "",
  816.      "\t\tUsage:\tnew [-c] [-h] [-mx] file [file ...]",
  817.      "",
  818.      "\t\tWhere:\t\"-c\"\tcreates a new program but does NOT edit it.",
  819.      "",
  820.      "\t\t\t\"-h\"\tprints a help file.  Help is also given if",
  821.      "\t\t\t\tno arguments at all are given.",
  822.      "",
  823.      "\t\t\t\"-mx\"\tcreates a program of type 'x', where x is",
  824.      "\t\t\t\tone of the following:",
  825.      "\t",
  826.      "\t\t\t\td - function driver.",
  827.      "\t\t\t\tf - normal function (default).",
  828.      "\t\t\t\th - header file.",
  829.      "\t\t\t\ti - program to handle simple I/O.",
  830.      "\t\t\t\tm - main routine with arguments.",
  831.      "\t\t\t\to - function to handle command line arguments.",
  832.      "\t\t\t\ts - stub (placeholder) function.",
  833.      "",
  834.      "\t\t\t\"file\"\tis one or more C files to be created.  A",
  835.      "\t\t\t\tsuffix of \".c\" will be appended if it isn't",
  836.      "\t\t\t\tthere already.",
  837.      "\t",
  838.      "\t\t\t\tIf the file already exists, you will be asked",
  839.      "\t\t\t\tif you want to overwrite it.",
  840.      "",
  841.      "",
  842.      "\t\t\"new\" makes extensive use of templates to create new C files.",
  843.      "\t\tA template file has the name \"template.x\", where 'x' is the",
  844.      "\t\tstring which follows '-m' in the program arguments.",
  845.      "\t",
  846.      "\t\tYou can create other templates by adding template files to",
  847.     "\t\tthe template directory specified in the header file \"new.h\".",
  848.      (char *) NULL
  849.     };
  850.  
  851. /* Write the help information. */
  852.     for (k = 0; array[k]; ++k)
  853.         puts (array[k]);
  854.     return (0);
  855. }
  856.  
  857.  
  858.  
  859. [LISTING EIGHT]
  860.  
  861. /* File "OutString.c" */
  862.  
  863. #ifndef    lint
  864. static char    *OutString_c_rcsid =
  865. "$Header: OutString.c,v 1.2 91/03/15 16:55:35 vogel Exp $";
  866.  
  867. static char    *OutString_c_source =
  868. "$Source: /d/cdc/vogel/source/new/RCS/OutString.c,v $";
  869.  
  870. #endif
  871.  
  872. /*
  873.  * NAME:
  874.  *    OutString
  875.  *
  876.  * SYNOPSIS:
  877.  *    #include "new.h"
  878.  *    #include "macro.h"
  879.  *
  880.  *    int OutString (macros, current, string)
  881.  *    MACRO * macros;
  882.  *    char current;
  883.  *    char * string;
  884.  *
  885.  * DESCRIPTION:
  886.  *    Decides which macro string to return based on the current token
  887.  *    character.
  888.  *    
  889.  *
  890.  * ARGUMENTS:
  891.  *    "macros" holds the current macro replacement values.
  892.  *
  893.  *    "current" is the value of the token character following a dollar sign.
  894.  *
  895.  *    "string" is the replacement value of that token.
  896.  *
  897.  * AUTHOR:
  898.  *    Karl Vogel
  899.  *
  900.  * BUGS:
  901.  *    None noticed.
  902.  *
  903.  * REVISIONS:
  904.  *
  905.  * $Log:    OutString.c,v $
  906.  * Revision 1.2  91/03/15  16:55:35  vogel
  907.  * 1.  Ran indent on the code and reformatted the comment header.
  908.  * 
  909.  * Revision 1.1  90/07/03  12:02:28  vogel
  910.  * Initial revision
  911.  * 
  912.  */
  913.  
  914. #include    "new.h"
  915. #include    "macro.h"
  916. #include    <stdio.h>
  917. #include    <ctype.h>
  918. #include    <strings.h>
  919.  
  920. int             OutString (macros, current, string)
  921. MACRO          *macros;
  922. char            current;
  923. char           *string;
  924. {
  925.  
  926. /* Variables.  */
  927.     char           *blank;
  928.     char           *s;
  929.     char           *t;
  930.     char            temp[BUFFER];
  931.  
  932.     int             col;
  933.     int             first;
  934.     int             length;
  935.     int             status;
  936.  
  937. /* Do the simple string replacements, and numeric conversion.  */
  938.     switch (current)
  939.     {
  940.         case 'a':
  941.             (void) strcpy (string, macros->args);
  942.             break;
  943.         case 'b':
  944.             (void) strcpy (string, macros->body);
  945.             break;
  946.         case 'c':
  947.             (void) sprintf (string, "%2.2d", macros->month);
  948.             break;
  949.         case 'd':
  950.             (void) sprintf (string, "%2.2d", macros->day);
  951.             break;
  952.         case 'e':
  953.             (void) strcpy (string, macros->exten);
  954.             break;
  955.         case 'f':
  956.             (void) strcpy (string, macros->functions);
  957.             break;
  958.         case 'g':
  959.             (void) strcpy (string, macros->globals);
  960.             break;
  961.         case 'h':
  962.             (void) sprintf (string, "%2.2d", macros->hour);
  963.             break;
  964.         case 'i':
  965.             break;
  966.         case 'l':
  967.             (void) strcpy (string, macros->alist);
  968.             break;
  969.         case 'm':
  970.             (void) sprintf (string, "%2.2d", macros->minute);
  971.             break;
  972.         case 'n':
  973.             (void) strcpy (string, macros->name);
  974.             break;
  975.         case 'p':
  976.             (void) strcpy (string, macros->define);
  977.             break;
  978.         case 'r':
  979.             (void) strcpy (string, macros->rev);
  980.             break;
  981.         case 's':
  982.             (void) sprintf (string, "%2.2d", macros->second);
  983.             break;
  984.         case 't':
  985.             (void) strcpy (string, macros->type);
  986.             break;
  987.         case 'u':
  988.             break;
  989.         case 'v':
  990.             (void) strcpy (string, macros->vars);
  991.             break;
  992.         case 'w':
  993.             (void) strcpy (string, macros->userid);
  994.             break;
  995.         case 'x':
  996.             (void) strcpy (string, macros->username);
  997.             break;
  998.         case 'y':
  999.             (void) sprintf (string, "%2.2d", macros->year);
  1000.             break;
  1001.         default:
  1002.             *string = '\0';
  1003.             break;
  1004.     }
  1005.  
  1006. /* Handle "Usage" string. Write no more than 50 characters/line, indented 
  1007.  *3 tab spaces in. */
  1008.     if (current == 'u')
  1009.     {
  1010.         (void) strcpy (temp, macros->usage);
  1011.         t = temp;
  1012.         *string = '\0';
  1013.         first = YES;
  1014.         while (length = strlen (t))
  1015.         {
  1016.             if (!first)
  1017.                 (void) strcat (string, "\n * \t\t\t");
  1018.  
  1019.             first = NO;
  1020.             if (length <= 50)
  1021.             {
  1022.                 (void) strcat (string, t);
  1023.                 break;
  1024.             }
  1025.             else
  1026.             {
  1027.                 blank = (char *) NULL;
  1028.                 col = 25;
  1029.                 for (s = t; *s && col < 75; ++s, ++col)
  1030.                     if (isspace (*s))
  1031.                         blank = s;
  1032.                 if (blank)
  1033.                 {
  1034.                     *blank = '\0';
  1035.                     (void) strcat (string, t);
  1036.                     t = blank + 1;
  1037.                 }
  1038.                 else
  1039.                 {
  1040.                     (void) strcat (string, t);
  1041.                     break;
  1042.                 }
  1043.             }
  1044.         }
  1045.     }
  1046.  
  1047. /* Handle the "include" strings. */
  1048.     if (current == 'i')
  1049.     {
  1050.         for (s = string, t = macros->include; *t; ++s, ++t)
  1051.         {
  1052.             if (*t == ' ')
  1053.                 *s = '\t';
  1054.             else
  1055.                 *s = *t;
  1056.         }
  1057.         *s = '\0';
  1058.     }
  1059.     return (0);
  1060. }
  1061.  
  1062.  
  1063.  
  1064. [LISTING NINE]
  1065.  
  1066. /* File "ReplaceMacros.c" */
  1067.  
  1068. #ifndef    lint
  1069. static char    *ReplaceMacros_c_rcsid =
  1070. "$Header: ReplaceMacros.c,v 1.2 91/03/15 16:55:37 vogel Exp $";
  1071.  
  1072. static char    *ReplaceMacros_c_source =
  1073. "$Source: /d/cdc/vogel/source/new/RCS/ReplaceMacros.c,v $";
  1074.  
  1075. #endif
  1076.  
  1077. /*
  1078.  * NAME:
  1079.  *    ReplaceMacros
  1080.  *
  1081.  * SYNOPSIS:
  1082.  *    #include "macro.h"
  1083.  *
  1084.  *    int ReplaceMacros (in, macros, out)
  1085.  *    FILE * in;
  1086.  *    MACRO * macros;
  1087.  *    FILE * out;
  1088.  *
  1089.  * DESCRIPTION:
  1090.  *    Accepts the macro structure holding the variables to be replaced,
  1091.  *    an input filepointer, and an output filepointer.  Does token
  1092.  *    substitution from input to output.
  1093.  *
  1094.  * ARGUMENTS:
  1095.  *    Described above.
  1096.  *
  1097.  * AUTHOR:
  1098.  *    Karl Vogel
  1099.  *
  1100.  * BUGS:
  1101.  *    None noticed.
  1102.  *
  1103.  * REVISIONS:
  1104.  *
  1105.  * $Log:    ReplaceMacros.c,v $
  1106.  * Revision 1.2  91/03/15  16:55:37  vogel
  1107.  * 1.  Ran indent on the code and reformatted the comment header.
  1108.  * 
  1109.  * Revision 1.1  90/07/03  12:02:42  vogel
  1110.  * Initial revision
  1111.  * 
  1112.  */
  1113.  
  1114. #include    "macro.h"
  1115. #include    <stdio.h>
  1116. #include    <ctype.h>
  1117. #include    <strings.h>
  1118.  
  1119. int             ReplaceMacros (in, macros, out)
  1120. FILE           *in;
  1121. MACRO          *macros;
  1122. FILE           *out;
  1123. {
  1124.  
  1125. /* Variables. */
  1126.     char           *s;
  1127.     char            string[BUFFER];
  1128.     char            current;
  1129.     char            previous;
  1130.  
  1131. /* Start the main loop which looks ahead one character. */
  1132.     previous = getc (in);
  1133.     if (previous == EOF)
  1134.         return (0);
  1135.  
  1136. /* Decide what to do if we get a token character. */
  1137.     while ((current = getc (in)) != EOF)
  1138.     {
  1139.         if (previous == macros->token)
  1140.         {
  1141.             if (index ("abcdefghilmnprstuvwxy", current))
  1142.             {
  1143.                 OutString (macros, current, string);
  1144.                 for (s = string; *s; ++s)
  1145.                     putc (*s, out);
  1146.                 previous = getc (in);
  1147.             }
  1148.             else
  1149.             {
  1150.                 putc (previous, out);
  1151.                 previous = current;
  1152.             }
  1153.         }
  1154.         else
  1155.         {
  1156.             putc (previous, out);
  1157.             previous = current;
  1158.         }
  1159.     }
  1160.  
  1161. /* Don't forget to write the last character. */
  1162.     putc (previous, out);
  1163.     return (0);
  1164. }
  1165.  
  1166.  
  1167.  
  1168. [LISTING TEN]
  1169.  
  1170. /* File "SetMacros.c" */
  1171.  
  1172. #ifndef    lint
  1173. static char    *SetMacros_c_rcsid =
  1174. "$Header: SetMacros.c,v 1.4 91/03/15 16:55:40 vogel Exp $";
  1175.  
  1176. static char    *SetMacros_c_source =
  1177. "$Source: /d/cdc/vogel/source/new/RCS/SetMacros.c,v $";
  1178.  
  1179. #endif
  1180.  
  1181. #include    "macro.h"
  1182. #include    <stdio.h>
  1183. #include    <strings.h>
  1184. #include    <pwd.h>
  1185. #include    <sys/time.h>
  1186.  
  1187. int             SetMacros (macros)
  1188. MACRO          *macros;
  1189. {
  1190.  
  1191. /* Functions. */
  1192.     char           *getenv ();
  1193.     struct passwd  *getpwuid ();
  1194.  
  1195. /* Variables. */
  1196.     char           *s;
  1197.     int             offset;
  1198.     long            clock;
  1199.     struct passwd  *ptr;
  1200.     struct tm      *now;
  1201.  
  1202. /* Set up the internal C stuff.  The "name" entry will be set later. */
  1203.     macros->args[0] = '\0';
  1204.     macros->body[0] = '\0';
  1205.     macros->functions[0] = '\0';
  1206.     macros->globals[0] = '\0';
  1207.     macros->alist[0] = '\0';
  1208.     macros->name[0] = '\0';
  1209.     macros->define[0] = '\0';
  1210.     macros->usage[0] = '\0';
  1211.     macros->vars[0] = '\0';
  1212.  
  1213.     (void) strcpy (macros->exten, "c");
  1214.     (void) strcpy (macros->rev, "1.1");
  1215.     (void) strcpy (macros->type, "int");
  1216.  
  1217.     (void) strcpy (macros->include,
  1218.                "#include <stdio.h>\n#include <ctype.h>");
  1219.  
  1220. /* Set up userid and full name of program author. See if we can get the 
  1221.  * information from the environment. If that fails, look it up from userid 
  1222.  * and passwd file. */
  1223.     macros->userid[0] = '\0';
  1224.     macros->username[0] = '\0';
  1225.  
  1226.     if (s = getenv ("USER"))
  1227.         (void) strcpy (macros->userid, s);
  1228.     if (s = getenv ("USERNAME"))
  1229.         (void) strcpy (macros->username, s);
  1230.     if (strlen (macros->userid) == 0 || strlen (macros->username) == 0)
  1231.     {
  1232.         if (ptr = getpwuid (getuid ()))
  1233.         {
  1234.             (void) strcpy (macros->userid, ptr->pw_name);
  1235.             if (strncmp (ptr->pw_gecos, "Civ ", 4) == 0)
  1236.                 offset = 4;
  1237.             else
  1238.                 offset = 0;
  1239.             (void) strcpy (macros->username,
  1240.                        ptr->pw_gecos + offset);
  1241.             if (s = index (macros->username, ';'))
  1242.                 *s = '\0';
  1243.         }
  1244.         else
  1245.         {
  1246.             (void) strcpy (macros->userid, "unknown");
  1247.             (void) strcpy (macros->username, "unknown");
  1248.         }
  1249.     }
  1250.  
  1251. /* Set the character which we will recognize as the start of a token.  */
  1252.     macros->token = '$';
  1253.  
  1254. /* Set up the current date and time.  */
  1255.     (void) time (&clock);
  1256.     now = localtime (&clock);
  1257.     macros->second = now->tm_sec;
  1258.     macros->minute = now->tm_min;
  1259.     macros->hour = now->tm_hour;
  1260.     macros->day = now->tm_mday;
  1261.     macros->month = now->tm_mon + 1;
  1262.     macros->year = now->tm_year;
  1263.  
  1264.     return (0);
  1265. }
  1266.