home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / fileutil / cawf / cawf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-26  |  9.0 KB  |  377 lines

  1. /*
  2.  *    cawf - a C version of Henry Spencer's awf(1), the Amazingly
  3.  *           Workable (text) Formatter
  4.  *
  5.  *    V. Abell, Purdue University Computing Center
  6.  *    Version 1.0, February, 1991
  7.  */
  8.  
  9. /*
  10.  *    Copyright (c) 1991 Purdue University Research Foundation,
  11.  *    West Lafayette, Indiana 47907.  All rights reserved.
  12.  *
  13.  *    Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
  14.  *    University Computing Center.  Not derived from licensed software;
  15.  *    derived from awf(1) by Henry Spencer of the University of Toronto.
  16.  *
  17.  *    Permission is granted to anyone to use this software for any
  18.  *    purpose on any computer system, and to alter it and redistribute
  19.  *    it freely, subject to the following restrictions:
  20.  *
  21.  *    1. The author is not responsible for any consequences of use of
  22.  *       this software, even if they arise from flaws in it.
  23.  *
  24.  *    2. The origin of this software must not be misrepresented, either
  25.  *       by explicit claim or by omission.  Credits must appear in the
  26.  *       documentation.
  27.  *
  28.  *    3. Altered versions must be plainly marked as such, and must not
  29.  *       be misrepresented as being the original software.  Credits must
  30.  *       appear in the documentation.
  31.  *
  32.  *    4. This notice may not be removed or altered.
  33.  */
  34.  
  35. #include "cawf.h"
  36.  
  37. #ifdef    UNIX
  38. #include <strings.h>
  39. #include <sys/stat.h>
  40. #else
  41. #include <io.h>
  42. #include <process.h>
  43. #include <string.h>
  44. #include <sys\types.h>
  45. #include <sys\stat.h>
  46. #endif
  47.  
  48.  
  49. main(argc, argv)
  50.     int     argc;
  51.     char    *argv[];
  52. {
  53.     int ax = 1;                 /* argument index */
  54.     char buf[MAXLINE];        /* character buffer */
  55.     char *ep;                   /* environment pointer */
  56.     int err = 0;                /* error count */
  57.     char *files[MAXFILES];      /* file names */
  58.     int i;                           /* temporary indexes */
  59.     size_t l;                       /* length */
  60.     char *lib = CAWFLIB;            /* library path */
  61.     int libl;            /* library path length */
  62.     int nf = 0;                 /* number of files */
  63.     char *np;                   /* name pointer */
  64.     int pc;                     /* prolog count */
  65.     struct stat sbuf;               /* stat buffer */
  66. /*
  67.  * Save program name.
  68.  */
  69.     if ((Pname = strrchr(argv[0], '\\')) != NULL)
  70.         Pname++;
  71.     else if ((Pname = strrchr(argv[0], '/')) != NULL)
  72.         Pname++;
  73.     else
  74.         Pname = argv[0];
  75. /*
  76.  * Set error file stream pointer.
  77.  */
  78.     Efs = stderr;
  79. /*
  80.  * Get library name.
  81.  */
  82.     if ((np = getenv("CAWFLIB")) != NULL)
  83.         lib = np;
  84.     libl = strlen(lib);
  85. /*
  86.  * Get device file name.
  87.  */
  88.     if ((ep = getenv("TERM")) == NULL || *ep == '\0')
  89.         ep = "dumb";
  90.     l = libl + 1 + strlen(ep) + strlen(".dev") + 1;
  91.     if ((np = malloc(l)) == NULL)
  92.         Error(FATAL, NOLINE, " no string space for device file name",
  93.             NULL);
  94.     (void) sprintf(np, "%s/%s.dev", lib, ep);
  95.         if ( access(np, 0) )
  96.         {
  97.                 free(np);
  98.             l = libl + 1 + strlen("dumb") + strlen(".dev") + 1;
  99.             if ((np = malloc(l)) == NULL)
  100.                 Error(FATAL, NOLINE, " no string space for device file name",
  101.                     NULL);
  102.               (void) sprintf(np, "%s/dumb.dev", lib, ep);
  103.         }
  104.     files[nf++] = np;
  105. /*
  106.  * Get common text file name.
  107.  */
  108.     l = libl + 1 + strlen("common") + 1;
  109.     if ((np = malloc(l)) == NULL)
  110.         Error(FATAL, NOLINE, " no string space for common file name",
  111.             NULL);
  112.     (void) sprintf(np, "%s/common", lib);
  113.     files[nf++] = np;
  114. /*
  115.  * Get macro text file name.
  116.  */
  117.     if (argc > 1) {
  118.         if (strncmp(argv[1], "-m", 2) == 0) {
  119.             l = libl + 1 + strlen(argv[1]+1) + strlen(".mac") + 1;
  120.             if ((np = malloc(l)) == NULL)
  121.                 Error(FATAL, NOLINE, " no string space for ",
  122.                     argv[1]);
  123.             (void) sprintf(np, "%s/%s.mac", lib, argv[1]+1);
  124.             files[nf++] = np;
  125.             if (strcmp(argv[1], "-man") == 0)
  126.                 Marg = MANMACROS;
  127.             else if (strcmp(argv[1], "-ms") == 0)
  128.                 Marg = MSMACROS;
  129.             ax = 2;
  130.         } else {
  131.             /*
  132.              * No macroes - enable Bold, Italic and Roman fonts.
  133.              */
  134.             for (i = 0; Fcode[i].nm; i++) {
  135.                 switch (Fcode[i].nm) {
  136.                 case 'B':
  137.                 case 'I':
  138.                 case 'R':
  139.                     Fcode[i].status = '1';
  140.                 }
  141.             }
  142.         }
  143.     }
  144. /*
  145.  * Add user-supplied file names.
  146.  */
  147.     pc = nf;
  148.     if (ax >= argc) {
  149.                 if ( isatty(1) )
  150.                         usage(argv[0]);
  151.         files[nf++] = NULL;       /* STDIN */
  152.     } else {
  153.         while (ax < argc) {
  154.             if (nf >= MAXFILES)
  155.                 Error(WARN, NOLINE, " too many files at ",
  156.                     argv[ax]);
  157.             files[nf++] = argv[ax++];
  158.         }
  159.     }
  160. /*
  161.  * Make sure all input files are accessible.
  162.  */
  163.     for (i = 0; i < nf; i++) {
  164.         if (files[i] != NULL) {
  165.             if (stat(files[i], &sbuf) != 0)
  166.                 Error(WARN, NOLINE, " can't find ", files[i]);
  167.         }
  168.     }
  169.     if (Err)
  170.         exit(1);
  171. /*
  172.  * Miscellaneous initialization.
  173.  */
  174.  
  175.     for (i = 0; ; i++) {
  176.         if (Pat[i].re == NULL)
  177.             break;
  178.         if ((Pat[i].pat = regcomp(Pat[i].re, 0)) == NULL)
  179.             Error(WARN, NOLINE, Pat[i].re, " regcomp failure");
  180.     }
  181.     if ((i = Findscale('n', 0.0, 0)) < 0)
  182.         Error(WARN, NOLINE, " can't find Scale['n']", NULL);
  183.     Scalen = Scale[i].val;
  184.     if ((i = Findscale('u', 0.0, 0)) < 0)
  185.         Error(WARN, NOLINE, " can't find Scale['u']", NULL);
  186.     Scaleu = Scale[i].val;
  187.     if ((i = Findscale('v', 0.0, 0)) < 0)
  188.         Error(WARN, NOLINE, " can't find Scale['v']", NULL);
  189.     Scalev = Scale[i].val;
  190.     (void) Findstr("CH", "= % -", 1);
  191.     Cont = Newstr(" ");
  192.     Contlen = 1;
  193.     if (Err)
  194.         exit(1);
  195. /*
  196.  * Here begins pass1 of awf - reading input lines and expanding macros.
  197.  */
  198.  
  199. /*
  200.  * Output prolog.
  201.  */
  202.     Macro(".^x");
  203.     Macro(".^b");
  204.     Macro(".^# 1 <prolog>");
  205. /*
  206.  * Read input files.
  207.  */
  208.     for (i = 0; i < nf; i++) {
  209.         if (files[i] == NULL) {
  210.             np = "stdin";
  211.             Ifs = stdin;
  212.         } else {
  213. #ifdef    UNIX
  214.             if ((Ifs = fopen(files[i], "r")) == NULL)
  215. #else
  216.             if ((Ifs = fopen(files[i], "rt")) == NULL)
  217. #endif
  218.                 Error(FATAL, NOLINE, " can't open ", files[i]);
  219.             np = files[i];
  220.         }
  221.         if (i >= pc) {
  222.             (void) sprintf(Line, ".^# 1 %s", np);
  223.             Macro(Line);
  224.             NR = 0;
  225.         }
  226.         Fsp = 0;
  227.         do {
  228.             while (fgets(Line, MAXLINE, Ifs) != NULL) {
  229.                 NR++;
  230.                 if ((np = strrchr(Line, '\n')) != NULL)
  231.                     *np = '\0';
  232.                 else
  233.                     Line[MAXLINE-1] = '\0';
  234.                 Macro(Line);
  235.             }
  236.             if (i >= pc)
  237.                 Macro(".^e");
  238.             if (Ifs != stdin)
  239.                 (void) fclose(Ifs);
  240.             if (Fsp > 0) {
  241.                 Free(&Inname);
  242.                 Inname = Inn_stk[Fsp-1];
  243.                 NR = NR_stk[Fsp-1];
  244.                 Ifs = Ifs_stk[Fsp-1];
  245.             }
  246.         } while (Fsp-- > 0);
  247.     }
  248.     Macro(NULL);
  249.     exit(Err);
  250. }
  251.  
  252.  
  253. usage(name)
  254. char *name;
  255. {
  256.         printf("\nCAWF - C version of the nroff-like, Amazingly Workable (text) Formatter\n"
  257.                "\nUsage: %s [ -macros ] [ file ... ]\n"
  258.                "\n       -macros may be -man or -ms, for example\n", name);
  259.         exit(1);
  260. }
  261.  
  262.  
  263. /*
  264.  * Macro(inp) - process a possible macro statement
  265.  *        pass non-macros and macros alike to pass 2
  266.  */
  267.  
  268. void
  269. Macro(inp)
  270.     char *inp;               /* possible macro statement pointer */
  271. {
  272.     char c[2];            /* characters */
  273.     FILE *fs;            /* temporary file stream */
  274.     int i, j, k;                    /* temporary indexes */
  275.     int mx;                         /* Macrotab[] index */
  276.     char *s1, *s2;                  /* temporary string pointers */
  277.  
  278.     if (inp == NULL) {
  279.         Pass2(NULL);
  280.         return;
  281.     }
  282. /*
  283.  * Check for file name designator.
  284.  */
  285.     if (strncmp(inp, ".^#", 3) == 0) {
  286.         Free(&Inname);
  287.         Inname = Field(3, inp, 1);
  288.         F = NULL;
  289.         Pass2(inp);
  290.         return;
  291.     }
  292. /*
  293.  * Check for source command - "^\.so".
  294.  */
  295.     if (strncmp(inp, ".so", 3) == 0) {
  296.         if ((s1 = Field(2, inp, 1)) == NULL) {
  297.             Error(WARN, LINE, " no file specified", NULL);
  298.             return;
  299.         }
  300.         if ((fs = fopen(s1, "r")) == NULL) {
  301.             Error(WARN, LINE, " can't open", NULL);
  302.             return;
  303.         }
  304.         if (Fsp >= MAXFSTK) {
  305.             (void) fclose(fs);
  306.             Error(WARN, LINE, " nesting too deep", NULL);
  307.             return;
  308.         }
  309.         Ifs_stk[Fsp] = Ifs;
  310.         Ifs = fs;
  311.         Inn_stk[Fsp] = Inname;
  312.         Inname = F;
  313.         F = NULL;
  314.         NR_stk[Fsp++] = NR;
  315.         NR = 0;
  316.         return;
  317.     }
  318.  /*
  319.   * Check for start of macro definition.
  320.   */
  321.     if (strncmp(inp, ".de", 3) == 0) {
  322.         if (inp[3] != ' ' || inp[4] == '\0') {
  323.             Error(WARN, LINE, " illegal macro definition", NULL);
  324.             return;
  325.         }
  326.         c[0] = inp[4];
  327.         c[1] = inp[5];
  328.         Curmx = Findmacro(c, 1);
  329.         return;
  330.     }
  331. /*
  332.  * Check for macro text.  Remove double backslashes.
  333.  */
  334.     if (Curmx >= 0 && strcmp(inp, "..") != 0) {
  335.         if (Mtx >= MAXMTXT)
  336.             Error(FATAL, LINE, " out of macro text space", NULL);
  337.         if ((s1 = strchr(inp, '\\')) == NULL)
  338.             Macrotxt[Mtx] = Newstr(inp);
  339.         else {
  340.             for (s1 = Pass1ln, s2 = inp;; s1++) {
  341.                 if ((*s1 = *s2++) == '\0')
  342.                     break;
  343.                 if (*s1 == '\\' && *s2 == '\\')
  344.                     s2++;
  345.             }
  346.             Macrotxt[Mtx] = Newstr(Pass1ln);
  347.         }
  348.         if (Macrotab[Curmx].bx == -1)
  349.             Macrotab[Curmx].bx = Mtx;
  350.         Mtx++;
  351.         Macrotab[Curmx].ct++;
  352.         return;
  353.     }
  354. /*
  355.  * Check for end of macro.
  356.  */
  357.     if (Curmx >= 0 && strcmp(inp, "..") == 0) {
  358.         Curmx = -1;
  359.         (void) sprintf(Pass1ln, ".^# %d %s", NR, Inname);
  360.         Pass2(Pass1ln);
  361.         return;
  362.     }
  363.  /*
  364.   * Check for conditionals and macro expansions.
  365.   */
  366.     if (*inp == '.'
  367.     &&  (((mx = Findmacro(inp+1, 0)) != -1) || regexec(Pat[0].pat, inp))) {
  368.         Expand(inp);
  369.         return;
  370.     }
  371. /*
  372.  * None of the above: forward the line.
  373.  */
  374.     Pass2(inp);
  375. }
  376. 
  377.