home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / source / util2src / list2bm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-24  |  26.6 KB  |  710 lines

  1. /*============================================================================*
  2.  * main() module: list2bm.c - Convert list of files to a BookMaster document.
  3.  *
  4.  * (C)Copyright IBM Corporation, 1991, 1992.                     Brian E. Yoder
  5.  *
  6.  * This program reads a list file and writes a BookMaster document to stdout.
  7.  * The list file specifies the document title, author, security classification,
  8.  * and a list of other files to include in the output document.  The output
  9.  * document can be transmitted to host system and processed using SCRIPT and
  10.  * BookMaster.
  11.  *
  12.  * The list file is a text file that is interpreted as follows:  Blank lines
  13.  * are ignored.  Text that follows a pound sign (#) is assumed to be a comment
  14.  * and is ignored.  The remaining non-blank, non-comment lines contain one or
  15.  * two space-delimited tokens.
  16.  *
  17.  * If a token contains embedded blanks, you must enclose it in either double
  18.  * quotes or single quotes:  "This a string"  or 'This is a string'.
  19.  *
  20.  * If a token begins with a $, then it is assumed to be the name of an
  21.  * environment variable.  For example, if the date is stored in the 'DATE'
  22.  * variable, then you can specify $DATE as the token.
  23.  *
  24.  * This program expects the first non-blank, non-comment lines to be formatted
  25.  * as follows (to add more of these, update this comment header, and the
  26.  * tpage() and bmtitle() subroutines):
  27.  *
  28.  *    -sec     "Security Classification"
  29.  *    -date    "Date of Document"
  30.  *    -author  "Author of Document"
  31.  *    -title   "Title of Document"
  32.  *
  33.  * The remaining lines may be zero or more of each of the following, in any
  34.  * order you choose:
  35.  *
  36.  *    -section "Title of Section"
  37.  *    filename
  38.  *
  39.  * The -sec, -date, -author, and -title lines must be the first lines in the
  40.  * input file.  The rest of the lines specify section headings and files to
  41.  * be included in the output document.
  42.  *
  43.  * Each -section line adds a major section (:h0.) heading to the output
  44.  * document.
  45.  *
  46.  * Each 'filename' line adds the named file in its own :h1. heading in the
  47.  * output document -- the heading name is set to 'filename'.  The program
  48.  * converts any special characters to BookMaster symbols, so you can include
  49.  * brackets, braces, box characters, and other special characters in the
  50.  * document.
  51.  *
  52.  * 03/25/91 - Created.
  53.  * 03/25/91 - Initial version: Requires the untab and 't2bm' utilities in the
  54.  *            current path.
  55.  * 03/29/91 - Don't put '.gs tag off/on' in output: we are already changing
  56.  *            periods to '&period'.  The '.gs tag off' was left over from the
  57.  *            AIX shell script version of this program.
  58.  *            Also, support the -n option: 'No title page'.  This allows the
  59.  *            output to contain just the -sections and files in the list,
  60.  *            allowing the output file to be included within another document.
  61.  * 04/04/91 - Ported from AIX to DOS and C/2.  We won't execute untab and t2bm
  62.  *            (too slow on DOS), but instead will call text2bm() directly.
  63.  *            If there is any tab expansion to be done, it's left up to
  64.  *            text2bm().  Also, output is directed to file instead of stdout.
  65.  *            We also use static buffers instead of malloc'd buffers to store
  66.  *            the title page parameter strings.
  67.  * 10/08/91 - If a filename contains a drive specification, we won't write the
  68.  *            'd:' to the heading.  This will make BookMaster happier, since
  69.  *            it complains for certain combinations of 'd:fname'.  Also,
  70.  *            the text2bm() subroutine now expands tabs for us: see the
  71.  *            text2bm.c module!
  72.  * 07/24/92 - Changed "rt" to "r" for fopen(). C Set/2 doesn't allow "rt".
  73.  *============================================================================*/
  74.  
  75. #include <stdio.h>
  76. #include <stdlib.h>
  77. #include <io.h>              /* Required for access(), on DOS */
  78. #include <sys/types.h>
  79.  
  80. #include "util.h"
  81.  
  82. #define MINARGS  2     /* Minimum no. of (non-flag) command line arguments required */
  83.  
  84. #define NO       0
  85. #define YES      1
  86.  
  87. #define TBUFFLEN  64         /* Max. size of title page parm buffers */
  88.  
  89. static char   *ourname;      /* Pointer to our name, for use by all modules */
  90.  
  91. static char sep[]=           /* Separator line, for BookMaster document: */
  92. ".*======================================================================";
  93.  
  94. static int f_bldtp = YES;    /* Do we put the title page in the output? */
  95.  
  96. static FILE   *outfile;      /* Output file, used by output subroutines */
  97.  
  98. /*----------------------------------------------------------------------------*
  99.  * Static buffers used for title page parameters
  100.  *----------------------------------------------------------------------------*/
  101.  
  102. static  char   b_sec[TBUFFLEN+1];
  103. static  char   b_date[TBUFFLEN+1];
  104. static  char   b_author[TBUFFLEN+1];
  105. static  char   b_title[TBUFFLEN+1];
  106.  
  107. /*----------------------------------------------------------------------------*
  108.  * Static line buffer
  109.  *----------------------------------------------------------------------------*/
  110.  
  111. #define LINELEN 1024               /* Maximum input file line length allowed */
  112. static  char line[LINELEN + 1];    /* Input file line buffer */
  113.  
  114. /*============================================================================*
  115.  * Define internal functions to allow forward access
  116.  *============================================================================*/
  117.  
  118. static void       syntax();
  119.  
  120. static int        tpage        ( void );
  121. static int        bmtitle      ( char *, char *, char *, char * );
  122.  
  123. static int        body         ( void );
  124. static int        wrfile       ( char * );
  125.  
  126. static char      *getvalue     ( char * );
  127.  
  128. /*============================================================================*
  129.  * Main Program Entry Point
  130.  *============================================================================*/
  131.  
  132. main(argc, argv)
  133.  
  134. int argc;                           /* arg count */
  135. char *argv[];                       /* arg pointers */
  136.  
  137. {
  138.   int     numargs;                  /* No. of arguments processed, not incl. -flags */
  139.  
  140.   int     rc;                       /* Return code store area */
  141.   char    cf;                       /* Current flag character (if any) */
  142.  
  143.   char   *listname;                 /* Pointer to name of input file */
  144.   char   *outname;                  /* Pointer to name of output file */
  145.  
  146. /*============================================================================*
  147.  * Set initial value of some variables:
  148.  *============================================================================*/
  149.  
  150.   ourname = "list2bm";    /* Hardcode program name */
  151.   numargs = 0;            /* Initialize number of arguments processed = none */
  152.  
  153. /*============================================================================*
  154.  * Process each command line argument:
  155.  *============================================================================*/
  156.  
  157.   argc--;                 /* Ignore 1st argument (program name) */
  158.   argv++;
  159.  
  160.   while (argc > 0)        /* For each command line argument: */
  161.   {
  162.     /*========================================================================*/
  163.     if ((*argv)[0] == '-')    /*   If argument is a -flag: */
  164.     {
  165.        cf = (*argv)[1];       /* Set cf = flag character: */
  166.        switch (cf)
  167.        {
  168.            case 'n':          /* -n */
  169.                 f_bldtp = NO;
  170.                 break;
  171.  
  172.            default:
  173.                 fprintf(stderr, "Unrecognized flag: '-%c'\n",
  174.                    cf);
  175.                 return(1);
  176.                 break; }
  177.     }   /* end if: flag processing */
  178.  
  179.     /*========================================================================*/
  180.  
  181.     else {          /* Argument is NOT a flag: */
  182.        /*
  183.         * The value 'numargs' indicates how many (non-flag) arguments have
  184.         * been processed, and hence, what to do with the current (non-flag)
  185.         * argument:
  186.         * When argument[numargs] (0=first, 1=second, etc.) is processed,
  187.         * be sure to increment 'numargs' so that successive arguments will
  188.         * be processed.
  189.        */
  190.        switch (numargs)
  191.        {
  192.            case 0:                   /* Name of input list file */
  193.                 listname = *argv;
  194.                 numargs++;
  195.                 break;
  196.  
  197.            case 1:                   /* Name of output file */
  198.                 outname = *argv;
  199.                 numargs++;
  200.                 break;
  201.  
  202.            default:
  203.                 fprintf(stderr, "Extra argument: '%s'\n",
  204.                    *argv);
  205.                 return(1);
  206.                 break; }
  207.     }   /* end else: argument processing */
  208.  
  209.     argc--;                     /* Decrement command line argument counter */
  210.     argv++;                     /* Point to next argument */
  211.  
  212.   }   /* end of command line argument processing loop */
  213.  
  214.   if (numargs < MINARGS) syntax(); /* If not enough arguments: Display syntax */
  215.                                    /* Otherwise, continue */
  216.  
  217. /*============================================================================*
  218.  * PROCESS THE LIST FILE AND WRITE THE OUTPUT DOCUMENT TO STDOUT
  219.  *============================================================================*/
  220.  
  221.   rc = cfopen(listname);            /* Open the input list file */
  222.   if (rc != 0)
  223.   {
  224.      fprintf(stderr, "%s: Cannot open file: %s\n",
  225.         ourname, listname);
  226.      return(1);
  227.   }
  228.  
  229.   outfile = fopen(outname, "w");
  230.   if (outfile == NULL)
  231.   {
  232.      fprintf(stderr, "%s: Cannot create output file: %s\n",
  233.         ourname, outfile);
  234.      return(1);
  235.   }
  236.  
  237.   rc = tpage();                     /* Build the title page */
  238.   if (rc != 0)
  239.      return(1);
  240.  
  241.   rc = body();                      /* Build the body of the document */
  242.   if (rc != 0)
  243.      return(1);
  244.  
  245.   cfclose();                        /* Close the list file */
  246.   return(0);                        /* Done with main(): Return */
  247.  
  248. } /* end of main() */
  249.  
  250. /*============================================================================*
  251.  * syntax() - Display command syntax and exit to operating system!
  252.  *============================================================================*/
  253. static void syntax()
  254. {
  255.   fprintf(stderr, "Usage: list2bm [-n] listfile outfile\n");
  256.   fprintf(stderr, "\n");
  257.   fprintf(stderr, "This program reads a list file and writes a BookMaster document\n");
  258.   fprintf(stderr, "to outfile.  The first lines define the title page as follows:\n");
  259.   fprintf(stderr, "   -sec     \"Security Classification\"\n");
  260.   fprintf(stderr, "   -date    \"Date of Document\"\n");
  261.   fprintf(stderr, "   -author  \"Author of Document\"\n");
  262.   fprintf(stderr, "   -title   \"Title of Document\"\n");
  263.   fprintf(stderr, "\n");
  264.   fprintf(stderr, "The remaining lines may be any combination of the following, in any\n");
  265.   fprintf(stderr, "order you choose:\n");
  266.   fprintf(stderr, "   -section \"Title of Section\"\n");
  267.   fprintf(stderr, "   filename\n");
  268.   fprintf(stderr, "\n");
  269.   fprintf(stderr, "For the lines that define the title page, you can specify\n");
  270.   fprintf(stderr, "the name of an environment variable, preceeded by a $.  In this\n");
  271.   fprintf(stderr, "case, the value of the environment variable is used.\n");
  272.   fprintf(stderr, "\n");
  273.   fprintf(stderr, "If -n is specified, then the title page lines are ignored and no\n");
  274.   fprintf(stderr, "title page is written to the output.  In this case, the output file\n");
  275.   fprintf(stderr, "has no :userdoc and :euserdoc tags.\n");
  276.   exit(1);
  277. }
  278.  
  279. /*============================================================================*
  280.  * tpage() - Build title page.
  281.  *
  282.  * PURPOSE:
  283.  *   Reads the first part of the input file and builds the title page for
  284.  *   the output document.
  285.  *
  286.  * RETURNS:
  287.  *   0, if successful.  1, if error.
  288.  *============================================================================*/
  289.  
  290. static int tpage()
  291.  
  292. {
  293.   int     rc;                       /* Return code storage */
  294.  
  295.   int     tokc;                     /* Number of tokens found in a line */
  296.   char  **tokv;                     /* Pointer to array of token pointers */
  297.  
  298.   char   *val;                      /* Pointer to a string */
  299.  
  300.   char   *sec;                      /* Title page values */
  301.   char   *date;
  302.   char   *author;
  303.   char   *title;
  304.  
  305.   short   f_sec;                    /* Flags: 0 == not set yet */
  306.   short   f_date;
  307.   short   f_author;
  308.   short   f_title;
  309.  
  310.   f_sec     = 0;                    /* Set all flags to 0: Value not set yet */
  311.   f_date    = 0;                    /* If a flag is 1, its corresponding value */
  312.   f_author  = 0;                    /* string has been set. */
  313.   f_title   = 0;
  314.  
  315.   if (f_bldtp == NO)                /* If no title page: */
  316.      return(0);                     /* then return immediately! */
  317.  
  318.  /*---------------------------------------------------------------------------*
  319.   * Loop to process the lines that define the title page of the document
  320.   *---------------------------------------------------------------------------*/
  321.  
  322.   for (;;)                          /* For each line in the file: */
  323.   {
  324.      if ((f_sec    &                     /* See if all values have been set */
  325.           f_date   &
  326.           f_author &
  327.           f_title) == 1)
  328.          break;
  329.  
  330.      tokc = cfread(&tokv);               /* Read a line */
  331.      if (tokc == 0)                      /* If no more lines: we found the end */
  332.      {                                   /* of the file before we expected it */
  333.         fprintf(stderr, "%s: End of file encountered before title page was defined.\n",
  334.            ourname);
  335.         return(1);
  336.      }
  337.  
  338.      if (tokc != 2)
  339.      {
  340.         fprintf(stderr, "%s: Line %ld: Two tokens expected.\n",
  341.            ourname, cfline());
  342.         return(1);
  343.      }
  344.  
  345.     /*------------------------------------------------------------------------*
  346.      * The tokv[1] variable points to the 2nd token on the line.  Store in
  347.      * the 'val' variable either a pointer to the token or a pointer to an
  348.      * environment variable.
  349.      *------------------------------------------------------------------------*/
  350.  
  351.      val = getvalue(tokv[1]);       /* Get string's value: See getvalue() */
  352.      if (val == NULL)
  353.      {
  354.         fprintf(stderr, "%s: Line %ld: Cannot find environment variable '%s'.\n",
  355.            ourname, cfline(), tokv[1]);
  356.         return(1);
  357.      }
  358.  
  359.     /*------------------------------------------------------------------------*
  360.      * The tokv[0] variable points to the -sec, -author, etc. token.  The
  361.      * 'val' variable points to its value (string or env. variable contents).
  362.      * Set the correct flag indicating * that the tokv[0] value has been processed.
  363.      * Also, copy string to a static buffer, since the original tokv[] array
  364.      * is overwritten by each call to cfread().
  365.      *------------------------------------------------------------------------*/
  366.  
  367.      if      (strcmp(tokv[0], "-sec") == 0)
  368.      {
  369.         sec = b_sec;
  370.         strncpy(sec, val, TBUFFLEN);
  371.         f_sec = 1;
  372.      }
  373.  
  374.      else if (strcmp(tokv[0], "-date") == 0)
  375.      {
  376.         date = b_date;
  377.         strncpy(date, val, TBUFFLEN);
  378.         f_date = 1;
  379.      }
  380.  
  381.      else if (strcmp(tokv[0], "-author") == 0)
  382.      {
  383.         author = b_author;
  384.         strncpy(author, val, TBUFFLEN);
  385.         f_author = 1;
  386.      }
  387.  
  388.      else if (strcmp(tokv[0], "-title") == 0)
  389.      {
  390.         title = b_title;
  391.         strncpy(title, val, TBUFFLEN);
  392.         f_title = 1;
  393.      }
  394.  
  395.      else
  396.      {
  397.         fprintf(stderr, "%s: Line %ld: Bad token while processing title page: '%s'.\n",
  398.            ourname, cfline(), tokv[0]);
  399.         return(1);
  400.      }
  401.     /*------------------------------------------------------------------------*
  402.      * End of loop to process title page lines.
  403.      *------------------------------------------------------------------------*/
  404.   }
  405.  
  406.  /*---------------------------------------------------------------------------*
  407.   * Title page lines are processed: Build and write the title page itself
  408.   *---------------------------------------------------------------------------*/
  409.  
  410.   rc = bmtitle(sec,
  411.                date,
  412.                author,
  413.                title);
  414.  
  415.   return(0);                        /* Return */
  416. }
  417.  
  418. /*============================================================================*
  419.  * bmtitle() - Build and write the title page.
  420.  *
  421.  * PURPOSE:
  422.  *   Builds the title page and writes it to outfile.  Pass pointers to the
  423.  *   required title page strings:  see the function definition.
  424.  *
  425.  * RETURNS:
  426.  *   0, always.
  427.  *============================================================================*/
  428.  
  429. static int bmtitle(sec, date, author, title)
  430.  
  431. char     *sec;                      /* Title page values */
  432. char     *date;
  433. char     *author;
  434. char     *title;
  435.  
  436. {
  437.   char   *varname;                  /* Pointer to env. var's name */
  438.  
  439.  /*---------------------------------------------------------------------------*
  440.   * Debugging: Comment out if not needed.
  441.   *---------------------------------------------------------------------------*/
  442. /*
  443.   printf("sec       = %s\n", sec         );
  444.   printf("date      = %s\n", date        );
  445.   printf("author    = %s\n", author      );
  446.   printf("title     = %s\n", title       );
  447. */
  448.  
  449.   fprintf(outfile, "%s\n", sep);
  450.  
  451.   fprintf(outfile, ".* Process this file using BookMaster\n");
  452.   fprintf(outfile, ".*\n");
  453.  
  454.   fprintf(outfile, ":userdoc sec='%s'\n", sec);
  455.   fprintf(outfile, ":prolog.\n");
  456.   fprintf(outfile, ".*\n");
  457.   fprintf(outfile, ":docprof\n");
  458.   fprintf(outfile, "    justify=yes\n");
  459.   fprintf(outfile, "    ldrdots=yes\n");
  460.   fprintf(outfile, "    layout=1\n");
  461.   fprintf(outfile, "    duplex=no\n");
  462.   fprintf(outfile, "    xrefpage=no\n");
  463.  
  464.   fprintf(outfile, ".*\n");
  465.   fprintf(outfile, ":title.%s\n", title);
  466.   fprintf(outfile, ":date.%s\n", date);
  467.   fprintf(outfile, ":author.%s\n", author);
  468.  
  469.   fprintf(outfile, ".*\n");
  470.   fprintf(outfile, ":eprolog.\n");
  471.   fprintf(outfile, ":frontm.\n");
  472.   fprintf(outfile, ":tipage.\n");
  473.   fprintf(outfile, ":toc.\n");
  474.   fprintf(outfile, ".*\n");
  475.  
  476.   fprintf(outfile, ":body.\n");
  477.  
  478.   return(0);                        /* Done */
  479. }
  480.  
  481. /*============================================================================*
  482.  * body() - Build the body.
  483.  *
  484.  * PURPOSE:
  485.  *   Reads the rest of the input file and builds the body for the output
  486.  *   document.
  487.  *
  488.  *   If a filename begins with 'd:' (drive specification), then the heading
  489.  *   will contain only the part that follows: the drive portion will be
  490.  *   removed.
  491.  *
  492.  * RETURNS:
  493.  *   0, if successful.  1, if error.
  494.  *============================================================================*/
  495.  
  496. static int body()
  497.  
  498. {
  499.   int     rc;                       /* Return code storage */
  500.  
  501.   int     tokc;                     /* Number of tokens found in a line */
  502.   char  **tokv;                     /* Pointer to array of token pointers */
  503.  
  504.   char   *val;                      /* Pointer to a string */
  505.   char   *fname;                    /* Pointer to a file name */
  506.   char   *fnamehd;                  /* Pointer to file name as shown in heading */
  507.  
  508.  /*---------------------------------------------------------------------------*
  509.   * Loop to process the lines that define the body of the document
  510.   *---------------------------------------------------------------------------*/
  511.  
  512.   for (;;)                          /* For the rest of the lines in the file */
  513.   {
  514.      tokc = cfread(&tokv);               /* Read a line */
  515.      if (tokc == 0)                      /* If no more lines: we're done */
  516.         break;
  517.  
  518.     /*------------------------------------------------------------------------*
  519.      * Look for any -tags that define the body of the document.  If we don't
  520.      * find any, then we will assume that the line defines a filename that
  521.      * should be copied to outfile.
  522.      *------------------------------------------------------------------------*/
  523.  
  524.      if      (strcmp(tokv[0], "-section") == 0)
  525.      {
  526.        /*---------------------------------------------------------------------*
  527.         * Process -section specification:  Must have 2 tokens: -section "title"
  528.         *---------------------------------------------------------------------*/
  529.         if (tokc != 2)
  530.         {
  531.            fprintf(stderr, "%s: Line %ld: Invalid -section specification.\n",
  532.               ourname, cfline());
  533.         }
  534.  
  535.         fprintf(outfile, "%s\n", sep);
  536.         fprintf(outfile, ":h0.%s\n", tokv[1]);
  537.      }
  538.  
  539.      else if (*(tokv[0]) == '-')
  540.      {
  541.        /*---------------------------------------------------------------------*
  542.         * Ignore all other lines whose first token starts with '-'
  543.         *---------------------------------------------------------------------*/
  544.      }
  545.  
  546.      else
  547.      {
  548.        /*---------------------------------------------------------------------*
  549.         * Process filename.  The file needs to have tabs expanded and special
  550.         * characters converted to BookMaster symbols before being copied to
  551.         * outfile.
  552.         *---------------------------------------------------------------------*/
  553.         fname = tokv[0];
  554.         fnamehd = fname;
  555.  
  556.         if ((strlen(fname) >= 3) && (fname[1] == ':'))
  557.            fnamehd += 2;
  558.  
  559.         if (access(fname, R_OK) != 0)
  560.         {
  561.            fprintf(stderr, "%s: Line %ld: Cannot read file '%s'.\n",
  562.               ourname, cfline(), fname);
  563.         }
  564.         else
  565.         {
  566.            fprintf(outfile, "%s\n", sep);
  567.            fprintf(outfile, ":h1.%s\n", fnamehd);
  568.        /*  fprintf(outfile, ":xmp keep=5.\n.gs tag off\n");   3/29/91 */
  569.            fprintf(outfile, ":xmp keep=5.\n");
  570.            fflush(outfile);
  571.  
  572.            rc = wrfile(fname);
  573.            if (rc != 0)
  574.            {
  575.            fprintf(stderr, "%s: Line %ld: Error writing file '%s'.\n",
  576.               ourname, cfline(), fname);
  577.            return(1);
  578.            }
  579.  
  580.        /*  fprintf(outfile, ".gs tag on\n:exmp.\n");          3/29/91 */
  581.            fprintf(outfile, ":exmp.\n");
  582.         } /* end of if we can't access the file */
  583.      } /* end of else: filename processing */
  584.  
  585.   } /* end of for (;;) loop to process each line in the file */
  586.  
  587.  /*---------------------------------------------------------------------------*
  588.   * Add separator line and end-of-document tag (only if there is a title page)
  589.   *---------------------------------------------------------------------------*/
  590.  
  591.   if (f_bldtp == YES)
  592.   {
  593.      fprintf(outfile, "%s\n", sep);
  594.      fprintf(outfile, ":euserdoc.\n");
  595.   }
  596.  
  597.   return(0);                        /* Return */
  598. }
  599.  
  600. /*============================================================================*
  601.  * wrfile() - Write file contents to output file.
  602.  *
  603.  * PURPOSE:
  604.  *   Reads the specified file, converts specical characters using the text2bm()
  605.  *   subroutine, and writes it to the output file specified by the static
  606.  *   'outfile' FILE pointer.
  607.  *
  608.  * RETURNS:
  609.  *   0, if successful.  1, if error.
  610.  *============================================================================*/
  611.  
  612. static int wrfile(fname)
  613.  
  614. char     *fname;                    /* Pointer to name of a text file */
  615.  
  616. {
  617.   int     rc;                       /* Return code storage */
  618.   FILE   *tfile;                    /* Input text file */
  619.   char   *text;                     /* Pointer to text string */
  620.  
  621.   rc = 0;                           /* Initialize return code to: successful */
  622.  
  623.  /*---------------------------------------------------------------------------*
  624.   * Open text file
  625.   *---------------------------------------------------------------------------*/
  626.  
  627.   tfile = fopen(fname, "r");        /* Open the text file for reading */
  628.   if (tfile == NULL)
  629.      return(1);
  630.  
  631.  /*---------------------------------------------------------------------------*
  632.   * Loop to read text file and write it to output file
  633.   *---------------------------------------------------------------------------*/
  634.  
  635.   for (;;)
  636.   {
  637.      text = fgets(line, LINELEN,
  638.                   tfile);
  639.      if (text == NULL)
  640.         break;
  641.  
  642.      rc = text2bm(line, outfile);
  643.      if (rc != 0)
  644.      {
  645.        rc = 1;
  646.        break;
  647.      }
  648.   }
  649.  
  650.  /*---------------------------------------------------------------------------*
  651.   * Close text file and return
  652.   *---------------------------------------------------------------------------*/
  653.  
  654.   fclose(tfile);                    /* Close the text file */
  655.   return(rc);                       /* Return */
  656. }
  657.  
  658. /*============================================================================*
  659.  * getvalue() - Get a string value.
  660.  *
  661.  * PURPOSE:
  662.  *   Gets the value for a given string.
  663.  *
  664.  * RETURNS:
  665.  *   str, if the string 'str' does not begin with $, or:
  666.  *   Pointer to enviroment variable, if 'str' begins with $, or:
  667.  *   NULL, if 'str' begins with $, but the environment variable doesn't exist.
  668.  *
  669.  *   For example, if 'str' is "$VARNAME", then this subroutine returns a pointer
  670.  *   to the value of the environment variable named VARNAME.  If VARNAME doesn't
  671.  *   exist in the environment, then NULL is returned.
  672.  *
  673.  * NOTE:
  674.  *   If not NULL, the pointer returned is either 'str' or a pointer returned
  675.  *   by getenv().
  676.  *============================================================================*/
  677.  
  678. static char *getvalue(str)
  679.  
  680. char    *str;                       /* Pointer to string */
  681.  
  682. {
  683.   char   *varname;                  /* Pointer to env. var's name */
  684.  
  685.  /*---------------------------------------------------------------------------*
  686.   * Ignore NULL pointer, zero-length string, and string that doesn't begin
  687.   * with a '$':
  688.   *---------------------------------------------------------------------------*/
  689.  
  690.   if (str == NULL)                  /* If str is NULL pointer: */
  691.      return(NULL);                  /* Just return the NULL pointer */
  692.  
  693.   if (*str == '\0')                 /* If str points to zero-length string: */
  694.      return(str);                   /* Just return it: it can't be an env var */
  695.  
  696.   if (*str != '$')                  /* If first char of str is NOT a $: */
  697.      return(str);                   /* Then return str */
  698.  
  699.  /*---------------------------------------------------------------------------*
  700.   * 'str' begins with $: it names an environment variable:
  701.   *---------------------------------------------------------------------------*/
  702.  
  703.   varname = str + 1;                /* Point varname past the $ in str */
  704.  
  705.   if (*varname == '\0')             /* If varname is a zero-length string: */
  706.      return(NULL);                  /* Then it can't name an environment var */
  707.  
  708.   return(getenv(varname));          /* Return pointer to variable's value */
  709. }
  710.