home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / pascal / pmerge / pmerge.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  10.1 KB  |  452 lines

  1. /*-
  2.  * Copyright (c) 1980 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)pmerge.c    5.3 (Berkeley) 4/16/91";
  42. #endif /* not lint */
  43.  
  44. #include <ctype.h>
  45. #include <stdio.h>
  46. #include <string.h>
  47. #include <stdlib.h>
  48. #include <unistd.h>
  49. #include <signal.h>
  50.  
  51. #define PRGFILE 0
  52. #define LABELFILE 1
  53. #define CONSTFILE 2
  54. #define TYPEFILE 3
  55. #define VARFILE 4
  56. #define RTNFILE 5
  57. #define BODYFILE 6
  58. #define NUMFILES 7
  59.  
  60. #define TRUE 1
  61. #define FALSE 0
  62. #define MAXINCL 9
  63. #define MAXNAM 75
  64. #define TMPNAME "/usr/tmp/MGXXXXXX"
  65.  
  66. FILE    *files[NUMFILES];
  67. char    *names[NUMFILES];
  68. FILE    *curfile;        /* current output file */
  69. char    labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE;
  70.  
  71. /*
  72.  * Remove temporary files if interrupted
  73.  */
  74. void
  75. onintr(unused)
  76. {
  77.     int i;
  78.  
  79.     for (i = 0; i < NUMFILES; i++)
  80.         if (files[i] != NULL)
  81.             unlink(names[i]);
  82. }
  83.  
  84. /*
  85.  * Program to merge separately compiled pascal modules into a
  86.  * single standard Pascal program.
  87.  */
  88. main(argc, argv)
  89.     long argc;
  90.     char **argv;
  91. {
  92.     FILE    *incl[MAXINCL];    /* include stack */
  93.     long    inclcnt = 0;    /* incl index */
  94.     char    *name[MAXNAM];    /* include names seen so far */
  95.     long    namcnt = 0;    /* next name ptr slot available */
  96.     char    *nambuf;    /* string table for names */
  97.     char    line[BUFSIZ];    /* input line buffer */
  98.     char    *next;        /* next name space available */
  99.     FILE    *input = stdin;    /* current input file */
  100.     long    ac = 0;        /* argv index */
  101.     char    **cpp, *cp, *fp;/* char ptrs */
  102.     char    quote;        /* include quote character */
  103.     int    i;        /* index var */
  104.  
  105.     for (i = 0; i < MAXNAM ; i++)
  106.         name[i] = 0;
  107.  
  108.     signal(SIGINT, onintr);
  109.  
  110.     curfile = files[PRGFILE] =
  111.         fopen(names[PRGFILE] = mktemp(strdup(TMPNAME)), "w");
  112.     files[LABELFILE] =
  113.         fopen(names[LABELFILE] = mktemp(strdup(TMPNAME)), "w");
  114.     files[CONSTFILE] =
  115.         fopen(names[CONSTFILE] = mktemp(strdup(TMPNAME)), "w");
  116.     files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(strdup(TMPNAME)), "w");
  117.     files[VARFILE] = fopen(names[VARFILE] = mktemp(strdup(TMPNAME)), "w");
  118.     files[RTNFILE] = fopen(names[RTNFILE] = mktemp(strdup(TMPNAME)), "w");
  119.     files[BODYFILE] = fopen(names[BODYFILE] = mktemp(strdup(TMPNAME)), "w");
  120.  
  121.     for (i = 0; i < NUMFILES; i++)
  122.         if (files[i] == NULL)
  123.             quit(names[i]);
  124.     if ((nambuf = malloc(BUFSIZ)) == NULL) {
  125.         fputs("no space for string table\n", stderr);
  126.         quit(NULL);
  127.     }
  128.     next = nambuf;
  129.     name[namcnt] = next;
  130.     for(;;) {
  131.         if (inclcnt > 0) {
  132.             inclcnt--;
  133.             fclose(input);
  134.             input = incl[inclcnt];
  135.         } else if (++ac < argc) {
  136.             input = freopen(argv[ac], "r", input);
  137.             if (input == NULL)
  138.                 quit(argv[ac]);
  139.         } else {
  140.             printout();
  141.             onintr(0);
  142.             exit(0);
  143.         }
  144.         fgets(line, BUFSIZ, input);
  145.         while (!feof(input)) {
  146.             if (line[0] != '#') {
  147.                 split(line);
  148.                 fgets(line, BUFSIZ, input);
  149.                 continue;
  150.             }
  151.             for (cp = &line[1]; isspace(*cp); cp++)
  152.                 /* void */;
  153.             if (strncmp("include", cp, 7))
  154.                 goto bad;
  155.             for (cp += 7; isspace(*cp); cp++)
  156.                 /* void */;
  157.             if (*cp != '\'' && *cp != '"')
  158.                 goto bad;
  159.             if (&nambuf[BUFSIZ] < next + strlen(cp)) {
  160.                 if ((nambuf = malloc(BUFSIZ)) == NULL) {
  161.                     fputs("no space for string table\n",
  162.                         stderr);
  163.                     quit(NULL);
  164.                 }
  165.                 next = nambuf;
  166.                 name[namcnt] = next;
  167.             }
  168.             for (fp = next, quote = *cp++;
  169.                  *cp != '\0' && *cp != quote; )
  170.                 *fp++ = *cp++;
  171.             if (*cp != quote &&
  172.                 (fp[-1] != 'i' || fp[-1] != 'h') &&
  173.                 (fp[-2] != '.'))
  174.                 goto bad;
  175.             *fp++ = '\0';
  176.             for (cpp = name; *cpp < next && strcmp(*cpp, next); )
  177.                 cpp++;
  178.             if (*cpp == next) {
  179.                 if (inclcnt == MAXINCL) {
  180.                     fputs("include table overflow\n",
  181.                         stderr);
  182.                     quit(NULL);
  183.                 }
  184.                 if (++namcnt == MAXNAM) {
  185.                     fputs("include name table overflow\n",
  186.                         stderr);
  187.                     quit(NULL);
  188.                 }
  189.                 incl[inclcnt] = input;
  190.                 inclcnt++;
  191.                 input = fopen(next, "r");
  192.                 if (input == NULL)
  193.                     quit(next);
  194.                 next = fp;
  195.                 name[namcnt] = next;
  196.             }
  197.             fgets(line, BUFSIZ, input);
  198.         }
  199.     }
  200. bad:
  201.     fputs("bad include format:", stderr);
  202.     fputs(line, stderr);
  203.     quit(NULL);
  204. }
  205.  
  206. /*
  207.  * Split up output into the approprite files
  208.  */
  209. char incom = FALSE;    /* TRUE => in comment */
  210. char incur = FALSE;    /* TRUE => in (* *) style comment */
  211. char inbrac = FALSE;    /* TRUE => in { } style comment */
  212. char instr = FALSE;    /* TRUE => in quoted string */
  213. char inprog = FALSE;    /* TRUE => program statement has been found */
  214. int  beginnest = 0;    /* routine nesting level */
  215. int  nest = 0;        /* begin block nesting level */
  216. int  paren_level = 0;    /* nesting level of parentheses */
  217.  
  218. split(line)
  219.     char *line;
  220. {
  221.     char ch1, *cp;        /* input window */
  222.     char *word;        /* ptr to current word */
  223.     int len;        /* length of current word */
  224.     char prt = TRUE;    /* TRUE => print current word */
  225.  
  226.     ch1 = ' ';
  227.     cp = line;
  228.     while (*cp) {
  229.         switch(*cp) {
  230.         case '(':
  231.             if (incom)
  232.                 break;
  233.             if (*(cp+1) == '*') {
  234.                 fputc(*cp, curfile);
  235.                 cp++;
  236.                 incom = TRUE;
  237.                 incur = TRUE;
  238.             } else {
  239.                 paren_level++;
  240.             }
  241.             break;
  242.         case ')':
  243.             if (incur && ch1 == '*') {
  244.                 incom = FALSE;
  245.                 incur = FALSE;
  246.             } else if (!incom) {
  247.                 paren_level--;
  248.             }
  249.             break;
  250.         case '{':
  251.             if (!incom) {
  252.                 inbrac = TRUE;
  253.                 incom = TRUE;
  254.             }
  255.             break;
  256.         case '}':
  257.             if (inbrac) {
  258.                 inbrac = FALSE;
  259.                 incom = FALSE;
  260.             }
  261.             break;
  262.         case '\'':
  263.             if (!incom) {
  264.                 incom = TRUE;
  265.                 instr = TRUE;
  266.             } else if (instr) {
  267.                 incom = FALSE;
  268.                 instr = FALSE;
  269.             }
  270.             break;
  271.         }
  272.         if (incom || !isalpha(*cp)) {
  273.             fputc(*cp, curfile);
  274.             ch1 = *cp++;
  275.             continue;
  276.         }
  277.         word = cp;
  278.         while (isalnum(*cp))
  279.             cp++;
  280.         len = cp - word;
  281.         switch (*word) {
  282.         case 'b':
  283.             if (len == 5 && !strncmp(word, "begin", 5)) {
  284.                 if (nest == 0 && beginnest == 0) {
  285.                     if (inprog != 1) {
  286.                         fprintf(stderr,
  287.                             "improper program body");
  288.                         quit(NULL);
  289.                     }
  290.                     curfile = files[BODYFILE];
  291.                 } else {
  292.                     beginnest++;
  293.                 }
  294.             }
  295.             break;
  296.         case 'c':
  297.             if (len == 4 && !strncmp(word, "case", 4)) {
  298.                 if (beginnest > 0) {
  299.                     beginnest++;
  300.                 }
  301.                 break;
  302.             }
  303.             if (len == 5 && !strncmp(word, "const", 5)) {
  304.                 if (nest == 0) {
  305.                     prt = FALSE;
  306.                     if (!constopen) {
  307.                         constopen = TRUE;
  308.                         prt = TRUE;
  309.                     }
  310.                     curfile = files[CONSTFILE];
  311.                 }
  312.             }
  313.             break;
  314.         case 'e':
  315.             if (len == 3 && !strncmp(word, "end", 3)) {
  316.                 if (beginnest == 1) {
  317.                     nest--;
  318.                 }
  319.                 if (beginnest > 0) {
  320.                     beginnest--;
  321.                 }
  322.                 if (nest < 0) {
  323.                     if (inprog == 1) {
  324.                         inprog = 0;
  325.                         nest = 0;
  326.                     } else {
  327.                         fprintf(stderr, "too many end statements");
  328.                         quit(NULL);
  329.                     }
  330.                 }
  331.                 break;
  332.             }
  333.             if (len == 8 && !strncmp(word, "external", 8)) {
  334.                 fputs("forward", curfile);
  335.                 prt = FALSE;
  336.                 if (paren_level == 0) {
  337.                     nest--;
  338.                 }
  339.             }
  340.             break;
  341.         case 'f':
  342.             if (len == 8 && !strncmp(word, "function", 8)) {
  343.                 if (nest == 0) {
  344.                     curfile = files[RTNFILE];
  345.                 }
  346.                 if (paren_level == 0) {
  347.                     nest++;
  348.                 }
  349.                 break;
  350.             }
  351.             if (len == 7 && !strncmp(word, "forward", 7)) {
  352.                 if (paren_level == 0) {
  353.                     nest--;
  354.                 }
  355.             }
  356.             break;
  357.         case 'l':
  358.             if (len == 5 && !strncmp(word, "label", 5)) {
  359.                 if (nest == 0) {
  360.                     prt = FALSE;
  361.                     if (!labelopen) {
  362.                         labelopen = TRUE;
  363.                         prt = TRUE;
  364.                     }
  365.                     curfile = files[LABELFILE];
  366.                 }
  367.             }
  368.             break;
  369.         case 'p':
  370.             if (len == 9 && !strncmp(word, "procedure", 9)) {
  371.                 if (nest == 0) {
  372.                     curfile = files[RTNFILE];
  373.                 }
  374.                 if (paren_level == 0) {
  375.                     nest++;
  376.                 }
  377.                 break;
  378.             }
  379.             if (len == 7 && !strncmp(word, "program", 7)) {
  380.                 if (nest != 0) {
  381.                     fprintf(stderr, "improper program nesting");
  382.                     quit(NULL);
  383.                 }
  384.                 inprog = 1;
  385.                 curfile = files[PRGFILE];
  386.             }
  387.             break;
  388.         case 't':
  389.             if (len == 4 && !strncmp(word, "type", 4)) {
  390.                 if (nest == 0) {
  391.                     prt = FALSE;
  392.                     if (!typeopen) {
  393.                         typeopen = TRUE;
  394.                         prt = TRUE;
  395.                     }
  396.                     curfile = files[TYPEFILE];
  397.                 }
  398.             }
  399.             break;
  400.         case 'v':
  401.             if (len == 3 && !strncmp(word, "var", 3)) {
  402.                 if (nest == 0) {
  403.                     prt = FALSE;
  404.                     if (!varopen) {
  405.                         varopen = TRUE;
  406.                         prt = TRUE;
  407.                     }
  408.                     curfile = files[VARFILE];
  409.                 }
  410.             }
  411.             break;
  412.         }
  413.         if (prt)
  414.             fprintf(curfile, "%.*s", len, word);
  415.         prt = TRUE;
  416.         ch1 = ' ';
  417.     }
  418. }
  419.  
  420. /*
  421.  * Print out the merged result
  422.  */
  423. printout()
  424. {
  425.     FILE *fp;
  426.     int i;
  427.     char ch;
  428.  
  429.     for(i = 0; i < NUMFILES; i++) {
  430.         fp = freopen(names[i], "r", files[i]);
  431.         if (fp == NULL)
  432.             quit(names[i]);
  433.         ch = getc(fp);
  434.         while (!feof(fp)) {
  435.             putc(ch,stdout);
  436.             ch = getc(fp);
  437.         }
  438.     }
  439. }
  440.  
  441. /*
  442.  * Die gracefully
  443.  */
  444. quit(fp)
  445.     char *fp;
  446. {
  447.     if (fp != NULL)
  448.         perror(fp);
  449.     onintr(0);
  450.     exit(1);
  451. }
  452.