148107Sbostic /*-
2*62176Sbostic * Copyright (c) 1980, 1993
3*62176Sbostic * The Regents of the University of California. All rights reserved.
448107Sbostic *
548107Sbostic * %sccs.include.redist.c%
622263Sdist */
73570Smckusick
822263Sdist #ifndef lint
9*62176Sbostic static char copyright[] =
10*62176Sbostic "@(#) Copyright (c) 1980, 1993\n\
11*62176Sbostic The Regents of the University of California. All rights reserved.\n";
1248107Sbostic #endif /* not lint */
133570Smckusick
1422263Sdist #ifndef lint
15*62176Sbostic static char sccsid[] = "@(#)pmerge.c 8.1 (Berkeley) 06/06/93";
1648107Sbostic #endif /* not lint */
1722263Sdist
183570Smckusick #include <ctype.h>
193570Smckusick #include <stdio.h>
2047032Sdonn #include <string.h>
2147032Sdonn #include <stdlib.h>
2247032Sdonn #include <unistd.h>
233570Smckusick #include <signal.h>
243570Smckusick
253570Smckusick #define PRGFILE 0
263570Smckusick #define LABELFILE 1
273570Smckusick #define CONSTFILE 2
283570Smckusick #define TYPEFILE 3
293570Smckusick #define VARFILE 4
303570Smckusick #define RTNFILE 5
313570Smckusick #define BODYFILE 6
323570Smckusick #define NUMFILES 7
333570Smckusick
343570Smckusick #define TRUE 1
353570Smckusick #define FALSE 0
363570Smckusick #define MAXINCL 9
373570Smckusick #define MAXNAM 75
383570Smckusick #define TMPNAME "/usr/tmp/MGXXXXXX"
393570Smckusick
403570Smckusick FILE *files[NUMFILES];
413570Smckusick char *names[NUMFILES];
423570Smckusick FILE *curfile; /* current output file */
433570Smckusick char labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE;
443570Smckusick
453570Smckusick /*
463570Smckusick * Remove temporary files if interrupted
473570Smckusick */
4847032Sdonn void
onintr(unused)4947032Sdonn onintr(unused)
503570Smckusick {
513570Smckusick int i;
523570Smckusick
533570Smckusick for (i = 0; i < NUMFILES; i++)
543570Smckusick if (files[i] != NULL)
553570Smckusick unlink(names[i]);
563570Smckusick }
573570Smckusick
583570Smckusick /*
593570Smckusick * Program to merge separately compiled pascal modules into a
603570Smckusick * single standard Pascal program.
613570Smckusick */
main(argc,argv)623570Smckusick main(argc, argv)
633570Smckusick long argc;
643570Smckusick char **argv;
653570Smckusick {
663570Smckusick FILE *incl[MAXINCL]; /* include stack */
673570Smckusick long inclcnt = 0; /* incl index */
683570Smckusick char *name[MAXNAM]; /* include names seen so far */
693570Smckusick long namcnt = 0; /* next name ptr slot available */
709577Sgarrison char *nambuf; /* string table for names */
713570Smckusick char line[BUFSIZ]; /* input line buffer */
729577Sgarrison char *next; /* next name space available */
733570Smckusick FILE *input = stdin; /* current input file */
743570Smckusick long ac = 0; /* argv index */
753570Smckusick char **cpp, *cp, *fp;/* char ptrs */
763866Smckusic char quote; /* include quote character */
773570Smckusick int i; /* index var */
783570Smckusick
799577Sgarrison for (i = 0; i < MAXNAM ; i++)
809577Sgarrison name[i] = 0;
819577Sgarrison
823570Smckusick signal(SIGINT, onintr);
839577Sgarrison
8447032Sdonn curfile = files[PRGFILE] =
8547032Sdonn fopen(names[PRGFILE] = mktemp(strdup(TMPNAME)), "w");
8647032Sdonn files[LABELFILE] =
8747032Sdonn fopen(names[LABELFILE] = mktemp(strdup(TMPNAME)), "w");
8847032Sdonn files[CONSTFILE] =
8947032Sdonn fopen(names[CONSTFILE] = mktemp(strdup(TMPNAME)), "w");
9047032Sdonn files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(strdup(TMPNAME)), "w");
9147032Sdonn files[VARFILE] = fopen(names[VARFILE] = mktemp(strdup(TMPNAME)), "w");
9247032Sdonn files[RTNFILE] = fopen(names[RTNFILE] = mktemp(strdup(TMPNAME)), "w");
9347032Sdonn files[BODYFILE] = fopen(names[BODYFILE] = mktemp(strdup(TMPNAME)), "w");
949577Sgarrison
953570Smckusick for (i = 0; i < NUMFILES; i++)
963570Smckusick if (files[i] == NULL)
973570Smckusick quit(names[i]);
989577Sgarrison if ((nambuf = malloc(BUFSIZ)) == NULL) {
999577Sgarrison fputs("no space for string table\n", stderr);
1009577Sgarrison quit(NULL);
1019577Sgarrison }
1029577Sgarrison next = nambuf;
1033570Smckusick name[namcnt] = next;
1043570Smckusick for(;;) {
1053570Smckusick if (inclcnt > 0) {
1063570Smckusick inclcnt--;
1073570Smckusick fclose(input);
1083570Smckusick input = incl[inclcnt];
1093570Smckusick } else if (++ac < argc) {
1103570Smckusick input = freopen(argv[ac], "r", input);
1113570Smckusick if (input == NULL)
1123570Smckusick quit(argv[ac]);
1133570Smckusick } else {
1143570Smckusick printout();
11547032Sdonn onintr(0);
1163570Smckusick exit(0);
1173570Smckusick }
1183570Smckusick fgets(line, BUFSIZ, input);
1193570Smckusick while (!feof(input)) {
1203570Smckusick if (line[0] != '#') {
1213570Smckusick split(line);
1223570Smckusick fgets(line, BUFSIZ, input);
1233570Smckusick continue;
1243570Smckusick }
1253570Smckusick for (cp = &line[1]; isspace(*cp); cp++)
1263570Smckusick /* void */;
12715685Speter if (strncmp("include", cp, 7))
1283570Smckusick goto bad;
1293570Smckusick for (cp += 7; isspace(*cp); cp++)
1303570Smckusick /* void */;
1313570Smckusick if (*cp != '\'' && *cp != '"')
1323570Smckusick goto bad;
1339577Sgarrison if (&nambuf[BUFSIZ] < next + strlen(cp)) {
1349577Sgarrison if ((nambuf = malloc(BUFSIZ)) == NULL) {
1359577Sgarrison fputs("no space for string table\n",
1369577Sgarrison stderr);
1379577Sgarrison quit(NULL);
1389577Sgarrison }
1399577Sgarrison next = nambuf;
1409577Sgarrison name[namcnt] = next;
1419577Sgarrison }
1423866Smckusic for (fp = next, quote = *cp++;
1433866Smckusic *cp != '\0' && *cp != quote; )
1443570Smckusick *fp++ = *cp++;
1453866Smckusic if (*cp != quote &&
1463570Smckusick (fp[-1] != 'i' || fp[-1] != 'h') &&
1473570Smckusick (fp[-2] != '.'))
1483570Smckusick goto bad;
1493570Smckusick *fp++ = '\0';
1503570Smckusick for (cpp = name; *cpp < next && strcmp(*cpp, next); )
1513570Smckusick cpp++;
1523570Smckusick if (*cpp == next) {
1533570Smckusick if (inclcnt == MAXINCL) {
1543570Smckusick fputs("include table overflow\n",
1553570Smckusick stderr);
1563570Smckusick quit(NULL);
1573570Smckusick }
1589577Sgarrison if (++namcnt == MAXNAM) {
1593570Smckusick fputs("include name table overflow\n",
1603570Smckusick stderr);
1613570Smckusick quit(NULL);
1623570Smckusick }
1633570Smckusick incl[inclcnt] = input;
1643570Smckusick inclcnt++;
1653570Smckusick input = fopen(next, "r");
1663570Smckusick if (input == NULL)
1673570Smckusick quit(next);
1683570Smckusick next = fp;
1693570Smckusick name[namcnt] = next;
1703570Smckusick }
1713570Smckusick fgets(line, BUFSIZ, input);
1723570Smckusick }
1733570Smckusick }
1743570Smckusick bad:
1753570Smckusick fputs("bad include format:", stderr);
1763570Smckusick fputs(line, stderr);
1773570Smckusick quit(NULL);
1783570Smckusick }
1793570Smckusick
1803570Smckusick /*
1813570Smckusick * Split up output into the approprite files
1823570Smckusick */
1833570Smckusick char incom = FALSE; /* TRUE => in comment */
1843570Smckusick char incur = FALSE; /* TRUE => in (* *) style comment */
1853570Smckusick char inbrac = FALSE; /* TRUE => in { } style comment */
1863570Smckusick char instr = FALSE; /* TRUE => in quoted string */
1873570Smckusick char inprog = FALSE; /* TRUE => program statement has been found */
1883570Smckusick int beginnest = 0; /* routine nesting level */
1893570Smckusick int nest = 0; /* begin block nesting level */
1909577Sgarrison int paren_level = 0; /* nesting level of parentheses */
1913570Smckusick
split(line)1923570Smckusick split(line)
1933570Smckusick char *line;
1943570Smckusick {
1953570Smckusick char ch1, *cp; /* input window */
1963570Smckusick char *word; /* ptr to current word */
1973570Smckusick int len; /* length of current word */
1983570Smckusick char prt = TRUE; /* TRUE => print current word */
1993570Smckusick
2003570Smckusick ch1 = ' ';
2013570Smckusick cp = line;
2023570Smckusick while (*cp) {
2033570Smckusick switch(*cp) {
2049577Sgarrison case '(':
2059577Sgarrison if (incom)
2069577Sgarrison break;
2079577Sgarrison if (*(cp+1) == '*') {
2089577Sgarrison fputc(*cp, curfile);
2099577Sgarrison cp++;
2103570Smckusick incom = TRUE;
2113570Smckusick incur = TRUE;
2129577Sgarrison } else {
2139577Sgarrison paren_level++;
2143570Smckusick }
2153570Smckusick break;
2163570Smckusick case ')':
2173570Smckusick if (incur && ch1 == '*') {
2183570Smckusick incom = FALSE;
2193570Smckusick incur = FALSE;
2209577Sgarrison } else if (!incom) {
2219577Sgarrison paren_level--;
2223570Smckusick }
2233570Smckusick break;
2243570Smckusick case '{':
2253570Smckusick if (!incom) {
2263570Smckusick inbrac = TRUE;
2273570Smckusick incom = TRUE;
2283570Smckusick }
2293570Smckusick break;
2303570Smckusick case '}':
2313570Smckusick if (inbrac) {
2323570Smckusick inbrac = FALSE;
2333570Smckusick incom = FALSE;
2343570Smckusick }
2353570Smckusick break;
2363570Smckusick case '\'':
2373570Smckusick if (!incom) {
2383570Smckusick incom = TRUE;
2393570Smckusick instr = TRUE;
2403570Smckusick } else if (instr) {
2413570Smckusick incom = FALSE;
2423570Smckusick instr = FALSE;
2433570Smckusick }
2443570Smckusick break;
2453570Smckusick }
2463570Smckusick if (incom || !isalpha(*cp)) {
2473570Smckusick fputc(*cp, curfile);
2483570Smckusick ch1 = *cp++;
2493570Smckusick continue;
2503570Smckusick }
2513570Smckusick word = cp;
2529577Sgarrison while (isalnum(*cp))
2533570Smckusick cp++;
2543570Smckusick len = cp - word;
2553570Smckusick switch (*word) {
2563570Smckusick case 'b':
25715685Speter if (len == 5 && !strncmp(word, "begin", 5)) {
2583570Smckusick if (nest == 0 && beginnest == 0) {
2593570Smckusick if (inprog != 1) {
2603570Smckusick fprintf(stderr,
2613570Smckusick "improper program body");
2623570Smckusick quit(NULL);
2633570Smckusick }
2643570Smckusick curfile = files[BODYFILE];
2653570Smckusick } else {
2663570Smckusick beginnest++;
2673570Smckusick }
2683570Smckusick }
2693570Smckusick break;
2703570Smckusick case 'c':
27115685Speter if (len == 4 && !strncmp(word, "case", 4)) {
2723570Smckusick if (beginnest > 0) {
2733570Smckusick beginnest++;
2743570Smckusick }
2753570Smckusick break;
2763570Smckusick }
27715685Speter if (len == 5 && !strncmp(word, "const", 5)) {
2783570Smckusick if (nest == 0) {
2793570Smckusick prt = FALSE;
2803570Smckusick if (!constopen) {
2813570Smckusick constopen = TRUE;
2823570Smckusick prt = TRUE;
2833570Smckusick }
2843570Smckusick curfile = files[CONSTFILE];
2853570Smckusick }
2863570Smckusick }
2873570Smckusick break;
2883570Smckusick case 'e':
28915685Speter if (len == 3 && !strncmp(word, "end", 3)) {
2903570Smckusick if (beginnest == 1) {
2913570Smckusick nest--;
2923570Smckusick }
2933570Smckusick if (beginnest > 0) {
2943570Smckusick beginnest--;
2953570Smckusick }
2963570Smckusick if (nest < 0) {
2973570Smckusick if (inprog == 1) {
2983570Smckusick inprog = 0;
2993570Smckusick nest = 0;
3003570Smckusick } else {
3013570Smckusick fprintf(stderr, "too many end statements");
3023570Smckusick quit(NULL);
3033570Smckusick }
3043570Smckusick }
3053570Smckusick break;
3063570Smckusick }
30715685Speter if (len == 8 && !strncmp(word, "external", 8)) {
3083570Smckusick fputs("forward", curfile);
3093570Smckusick prt = FALSE;
3109577Sgarrison if (paren_level == 0) {
3119577Sgarrison nest--;
3129577Sgarrison }
3133570Smckusick }
3143570Smckusick break;
3153570Smckusick case 'f':
31615685Speter if (len == 8 && !strncmp(word, "function", 8)) {
3173570Smckusick if (nest == 0) {
3183570Smckusick curfile = files[RTNFILE];
3193570Smckusick }
3209577Sgarrison if (paren_level == 0) {
3219577Sgarrison nest++;
3229577Sgarrison }
3233570Smckusick break;
3243570Smckusick }
32515685Speter if (len == 7 && !strncmp(word, "forward", 7)) {
3269577Sgarrison if (paren_level == 0) {
3279577Sgarrison nest--;
3289577Sgarrison }
3293570Smckusick }
3303570Smckusick break;
3313570Smckusick case 'l':
33215685Speter if (len == 5 && !strncmp(word, "label", 5)) {
3333570Smckusick if (nest == 0) {
3343570Smckusick prt = FALSE;
3353570Smckusick if (!labelopen) {
3363570Smckusick labelopen = TRUE;
3373570Smckusick prt = TRUE;
3383570Smckusick }
3393570Smckusick curfile = files[LABELFILE];
3403570Smckusick }
3413570Smckusick }
3423570Smckusick break;
3433570Smckusick case 'p':
34415685Speter if (len == 9 && !strncmp(word, "procedure", 9)) {
3453570Smckusick if (nest == 0) {
3463570Smckusick curfile = files[RTNFILE];
3473570Smckusick }
3489577Sgarrison if (paren_level == 0) {
3499577Sgarrison nest++;
3509577Sgarrison }
3513570Smckusick break;
3523570Smckusick }
35315685Speter if (len == 7 && !strncmp(word, "program", 7)) {
3543570Smckusick if (nest != 0) {
3553570Smckusick fprintf(stderr, "improper program nesting");
3563570Smckusick quit(NULL);
3573570Smckusick }
3583570Smckusick inprog = 1;
3593570Smckusick curfile = files[PRGFILE];
3603570Smckusick }
3613570Smckusick break;
3623570Smckusick case 't':
36315685Speter if (len == 4 && !strncmp(word, "type", 4)) {
3643570Smckusick if (nest == 0) {
3653570Smckusick prt = FALSE;
3663570Smckusick if (!typeopen) {
3673570Smckusick typeopen = TRUE;
3683570Smckusick prt = TRUE;
3693570Smckusick }
3703570Smckusick curfile = files[TYPEFILE];
3713570Smckusick }
3723570Smckusick }
3733570Smckusick break;
3743570Smckusick case 'v':
37515685Speter if (len == 3 && !strncmp(word, "var", 3)) {
3763570Smckusick if (nest == 0) {
3773570Smckusick prt = FALSE;
3783570Smckusick if (!varopen) {
3793570Smckusick varopen = TRUE;
3803570Smckusick prt = TRUE;
3813570Smckusick }
3823570Smckusick curfile = files[VARFILE];
3833570Smckusick }
3843570Smckusick }
3853570Smckusick break;
3863570Smckusick }
3873570Smckusick if (prt)
3883570Smckusick fprintf(curfile, "%.*s", len, word);
3893570Smckusick prt = TRUE;
3903570Smckusick ch1 = ' ';
3913570Smckusick }
3923570Smckusick }
3933570Smckusick
3943570Smckusick /*
3953570Smckusick * Print out the merged result
3963570Smckusick */
printout()3973570Smckusick printout()
3983570Smckusick {
3993570Smckusick FILE *fp;
4003570Smckusick int i;
4013570Smckusick char ch;
4023570Smckusick
4033570Smckusick for(i = 0; i < NUMFILES; i++) {
4043570Smckusick fp = freopen(names[i], "r", files[i]);
4053570Smckusick if (fp == NULL)
4063570Smckusick quit(names[i]);
4073570Smckusick ch = getc(fp);
4083570Smckusick while (!feof(fp)) {
4093570Smckusick putc(ch,stdout);
4103570Smckusick ch = getc(fp);
4113570Smckusick }
4123570Smckusick }
4133570Smckusick }
4143570Smckusick
4153570Smckusick /*
4163570Smckusick * Die gracefully
4173570Smckusick */
quit(fp)4183570Smckusick quit(fp)
4193570Smckusick char *fp;
4203570Smckusick {
4213570Smckusick if (fp != NULL)
4223570Smckusick perror(fp);
42347032Sdonn onintr(0);
4243570Smckusick exit(1);
4253570Smckusick }
426