home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / TEXT / UTILITY / CAWF2.ZIP / CAWF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-04  |  9.3 KB  |  408 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. #ifdef    USG
  39. #include <string.h>
  40. #else
  41. #include <strings.h>
  42. #endif
  43. #include <sys/stat.h>
  44. #else
  45. #include <io.h>
  46. #include <process.h>
  47. #include <string.h>
  48. #include <sys\types.h>
  49. #include <sys\stat.h>
  50. #endif
  51.  
  52.  
  53. main(argc, argv)
  54.     int     argc;
  55.     char    *argv[];
  56. {
  57.     char buf[MAXLINE];        /* character buffer */
  58.     char *ep;                   /* environment pointer */
  59.     int f = 0;            /* -f option count */
  60.     char *files[MAXFILES];      /* file names */
  61.     int i;                           /* temporary index */
  62.     size_t l;                       /* length */
  63.     char *lib = CAWFLIB;            /* library path */
  64.     int libl;            /* library path length */
  65.     int mac = 0;            /* macro specification status */
  66.     int nf = 0;                 /* number of files */
  67.     char *np;                   /* name pointer */
  68.     int pc;                     /* prolog count */
  69.     struct stat sbuf;               /* stat buffer */
  70. /*
  71.  * Save program name.
  72.  */
  73.     if ((Pname = strrchr(argv[0], '\\')) != NULL)
  74.         Pname++;
  75.     else if ((Pname = strrchr(argv[0], '/')) != NULL)
  76.         Pname++;
  77.     else
  78.         Pname = argv[0];
  79. /*
  80.  * Set error file stream pointer.
  81.  */
  82.     Efs = stderr;
  83. /*
  84.  * Get library name.
  85.  */
  86.     if ((np = getenv("CAWFLIB")) != NULL)
  87.         lib = np;
  88.     libl = strlen(lib);
  89. /*
  90.  * Get device file name.
  91.  */
  92.     if ((ep = getenv("TERM")) == NULL || *ep == '\0')
  93.         ep = "dumb";
  94.     l = libl + 1 + strlen(ep) + strlen(".dev") + 1;
  95.     if ((np = malloc(l)) == NULL)
  96.         Error(FATAL, NOLINE, " no string space for device file name",
  97.             NULL);
  98.     (void) sprintf(np, "%s/%s.dev", lib, ep);
  99.     files[nf++] = np;
  100. /*
  101.  * Get common text file name.
  102.  */
  103.     l = libl + 1 + strlen("common") + 1;
  104.     if ((np = malloc(l)) == NULL)
  105.         Error(FATAL, NOLINE, " no string space for common file name",
  106.             NULL);
  107.     (void) sprintf(np, "%s/common", lib);
  108.     files[nf++] = np;
  109. /*
  110.  * Process options.
  111.  */
  112.     while ((i = getopt(argc, argv, "f:m:")) != EOF) {
  113.         switch (i) {
  114.     /*
  115.      * -f<font_switch>: n = none
  116.      *            b = use backspaces and underlines (default)
  117.      *            e = use ESC<font_code>
  118.      */
  119.         case 'f':
  120.             switch(*optarg) {
  121.             case 'n':
  122.             case 'b':
  123.             case 'e':
  124.                 Fontout = *optarg;
  125.                 f++;
  126.                 break;
  127.             default:
  128.                 Error(WARN, NOLINE, "illegal -f option: ",
  129.                     optarg);
  130.             }
  131.             break;
  132.     /*
  133.      * -m<macro_file_name>
  134.      */
  135.         case 'm':
  136.             if (mac) {
  137.                 Error(WARN, NOLINE,
  138.                     "multiple macro file declaration",
  139.                     NULL);
  140.                 break;
  141.             }
  142.             l = libl + 2 + strlen(optarg) + strlen(".mac") + 1;
  143.             if ((np = malloc(l)) == NULL)
  144.                 Error(FATAL, NOLINE, " no string space for ",
  145.                     argv[1]);
  146.             (void) sprintf(np, "%s/m%s.mac", lib, optarg);
  147.             files[nf++] = np;
  148.             if (strcmp(optarg, "an") == 0)
  149.                 Marg = MANMACROS;
  150.             else if (strcmp(optarg, "s") == 0)
  151.                 Marg = MSMACROS;
  152.             mac++;
  153.             break;
  154.         case '?':
  155.             Err = 1;
  156.         }
  157.     }
  158.     if (f > 1)
  159.         Error(WARN, NOLINE, " conflicting font (-f) specifications");
  160.     if (Err) {
  161.         (void) fprintf(stderr,
  162.             "%s usage: -f[n|b|e] -m[macro_file] file . . .\n",
  163.             Pname);
  164.         exit(1);
  165.     }
  166.     if (mac == 0) {
  167.  
  168.         /*
  169.          * No macroes - enable Bold, Italic and Roman fonts.
  170.          */
  171.         for (i = 0; Fcode[i].nm; i++) {
  172.             switch (Fcode[i].nm) {
  173.             case 'B':
  174.             case 'I':
  175.             case 'R':
  176.                 Fcode[i].status = '1';
  177.             }
  178.         }
  179.     }
  180. /*
  181.  * Add user-supplied file names.
  182.  */
  183.     pc = nf;
  184.     if (optind >= argc) {
  185.         files[nf++] = NULL;       /* STDIN */
  186.     } else {
  187.         while (optind < argc) {
  188.             if (nf >= MAXFILES)
  189.                 Error(WARN, NOLINE, " too many files at ",
  190.                     argv[optind]);
  191.             files[nf++] = argv[optind++];
  192.         }
  193.     }
  194. /*
  195.  * Make sure all input files are accessible.
  196.  */
  197.     for (i = 0; i < nf; i++) {
  198.         if (files[i] != NULL) {
  199.             if (stat(files[i], &sbuf) != 0)
  200.                 Error(WARN, NOLINE, " can't find ", files[i]);
  201.         }
  202.     }
  203.     if (Err)
  204.         exit(1);
  205. /*
  206.  * Miscellaneous initialization.
  207.  */
  208.  
  209.     for (i = 0; ; i++) {
  210.         if (Pat[i].re == NULL)
  211.             break;
  212.         if ((Pat[i].pat = regcomp(Pat[i].re, 0)) == NULL)
  213.             Error(WARN, NOLINE, Pat[i].re, " regcomp failure");
  214.     }
  215.     if ((i = Findscale('n', 0.0, 0)) < 0)
  216.         Error(WARN, NOLINE, " can't find Scale['n']", NULL);
  217.     Scalen = Scale[i].val;
  218.     if ((i = Findscale('u', 0.0, 0)) < 0)
  219.         Error(WARN, NOLINE, " can't find Scale['u']", NULL);
  220.     Scaleu = Scale[i].val;
  221.     if ((i = Findscale('v', 0.0, 0)) < 0)
  222.         Error(WARN, NOLINE, " can't find Scale['v']", NULL);
  223.     Scalev = Scale[i].val;
  224.     (void) Findstr("CH", "= % -", 1);
  225.     Cont = Newstr(" ");
  226.     Contlen = 1;
  227.     if ((Trtbl = (char *)malloc(256)) == NULL)
  228.         Error(WARN, NOLINE, " can't allocate translate table space",
  229.             NULL);
  230.     else {
  231.         *Trtbl = ' ';
  232.         for (i = 1; i < 256; i++)
  233.             Trtbl[i] = (char) i;
  234.     }
  235.     if (Err)
  236.         exit(1);
  237. /*
  238.  * Here begins pass1 of awf - reading input lines and expanding macros.
  239.  */
  240.  
  241. /*
  242.  * Output prolog.
  243.  */
  244.     Macro(".^x");
  245.     Macro(".^b");
  246.     Macro(".^# 1 <prolog>");
  247. /*
  248.  * Read input files.
  249.  */
  250.     for (i = 0; i < nf; i++) {
  251.         if (files[i] == NULL) {
  252.             np = "stdin";
  253.             Ifs = stdin;
  254.         } else {
  255. #ifdef    UNIX
  256.             if ((Ifs = fopen(files[i], "r")) == NULL)
  257. #else
  258.             if ((Ifs = fopen(files[i], "rt")) == NULL)
  259. #endif
  260.                 Error(FATAL, NOLINE, " can't open ", files[i]);
  261.             np = files[i];
  262.         }
  263.         if (i >= pc) {
  264.             (void) sprintf(Line, ".^# 1 %s", np);
  265.             Macro(Line);
  266.             NR = 0;
  267.         }
  268.         Fsp = 0;
  269.         do {
  270.             while (fgets(Line, MAXLINE, Ifs) != NULL) {
  271.                 NR++;
  272.                 if ((np = strrchr(Line, '\n')) != NULL)
  273.                     *np = '\0';
  274.                 else
  275.                     Line[MAXLINE-1] = '\0';
  276.                 Macro(Line);
  277.             }
  278.             if (i >= pc)
  279.                 Macro(".^e");
  280.             if (Ifs != stdin)
  281.                 (void) fclose(Ifs);
  282.             if (Fsp > 0) {
  283.                 Free(&Inname);
  284.                 Inname = Inn_stk[Fsp-1];
  285.                 NR = NR_stk[Fsp-1];
  286.                 Ifs = Ifs_stk[Fsp-1];
  287.             }
  288.         } while (Fsp-- > 0);
  289.     }
  290.     Macro(NULL);
  291.     exit(Err);
  292. }
  293.  
  294.  
  295. /*
  296.  * Macro(inp) - process a possible macro statement
  297.  *        pass non-macros and macros alike to pass 2
  298.  */
  299.  
  300. void
  301. Macro(inp)
  302.     char *inp;               /* possible macro statement pointer */
  303. {
  304.     char c[2];            /* characters */
  305.     FILE *fs;            /* temporary file stream */
  306.     int i, j, k;                    /* temporary indexes */
  307.     int mx;                         /* Macrotab[] index */
  308.     char *s1, *s2;                  /* temporary string pointers */
  309.  
  310.     if (inp == NULL) {
  311.         Pass2(NULL);
  312.         return;
  313.     }
  314. /*
  315.  * Check for file name designator.
  316.  */
  317.     if (strncmp(inp, ".^#", 3) == 0) {
  318.         Free(&Inname);
  319.         Inname = Field(3, inp, 1);
  320.         F = NULL;
  321.         Pass2(inp);
  322.         return;
  323.     }
  324. /*
  325.  * Check for source command - "^\.so".
  326.  */
  327.     if (strncmp(inp, ".so", 3) == 0) {
  328.         if ((s1 = Field(2, inp, 1)) == NULL) {
  329.             Error(WARN, LINE, " no file specified", NULL);
  330.             return;
  331.         }
  332.         if ((fs = fopen(s1, "r")) == NULL) {
  333.             Error(WARN, LINE, " can't open", NULL);
  334.             return;
  335.         }
  336.         if (Fsp >= MAXFSTK) {
  337.             (void) fclose(fs);
  338.             Error(WARN, LINE, " nesting too deep", NULL);
  339.             return;
  340.         }
  341.         Ifs_stk[Fsp] = Ifs;
  342.         Ifs = fs;
  343.         Inn_stk[Fsp] = Inname;
  344.         Inname = F;
  345.         F = NULL;
  346.         NR_stk[Fsp++] = NR;
  347.         NR = 0;
  348.         return;
  349.     }
  350.  /*
  351.   * Check for start of macro definition.
  352.   */
  353.     if (strncmp(inp, ".de", 3) == 0) {
  354.         if (inp[3] != ' ' || inp[4] == '\0') {
  355.             Error(WARN, LINE, " illegal macro definition", NULL);
  356.             return;
  357.         }
  358.         c[0] = inp[4];
  359.         c[1] = inp[5];
  360.         Curmx = Findmacro(c, 1);
  361.         return;
  362.     }
  363. /*
  364.  * Check for macro text.  Remove double backslashes.
  365.  */
  366.     if (Curmx >= 0 && strcmp(inp, "..") != 0) {
  367.         if (Mtx >= MAXMTXT)
  368.             Error(FATAL, LINE, " out of macro text space", NULL);
  369.         if ((s1 = strchr(inp, '\\')) == NULL)
  370.             Macrotxt[Mtx] = Newstr(inp);
  371.         else {
  372.             for (s1 = Pass1ln, s2 = inp;; s1++) {
  373.                 if ((*s1 = *s2++) == '\0')
  374.                     break;
  375.                 if (*s1 == '\\' && *s2 == '\\')
  376.                     s2++;
  377.             }
  378.             Macrotxt[Mtx] = Newstr(Pass1ln);
  379.         }
  380.         if (Macrotab[Curmx].bx == -1)
  381.             Macrotab[Curmx].bx = Mtx;
  382.         Mtx++;
  383.         Macrotab[Curmx].ct++;
  384.         return;
  385.     }
  386. /*
  387.  * Check for end of macro.
  388.  */
  389.     if (Curmx >= 0 && strcmp(inp, "..") == 0) {
  390.         Curmx = -1;
  391.         (void) sprintf(Pass1ln, ".^# %d %s", NR, Inname);
  392.         Pass2(Pass1ln);
  393.         return;
  394.     }
  395.  /*
  396.   * Check for conditionals and macro expansions.
  397.   */
  398.     if (*inp == '.'
  399.     &&  (((mx = Findmacro(inp+1, 0)) != -1) || regexec(Pat[0].pat, inp))) {
  400.         Expand(inp);
  401.         return;
  402.     }
  403. /*
  404.  * None of the above: forward the line.
  405.  */
  406.     Pass2(inp);
  407. }
  408.