13570Smckusick /* Copyright (c) 1979 Regents of the University of California */ 23570Smckusick 3*9577Sgarrison static char sccsid[] = "@(#)pmerge.c 1.3 12/07/82"; 43570Smckusick 53570Smckusick #include <ctype.h> 63570Smckusick #include <stdio.h> 73570Smckusick #include <signal.h> 83570Smckusick 93570Smckusick #define PRGFILE 0 103570Smckusick #define LABELFILE 1 113570Smckusick #define CONSTFILE 2 123570Smckusick #define TYPEFILE 3 133570Smckusick #define VARFILE 4 143570Smckusick #define RTNFILE 5 153570Smckusick #define BODYFILE 6 163570Smckusick #define NUMFILES 7 173570Smckusick 183570Smckusick #define TRUE 1 193570Smckusick #define FALSE 0 203570Smckusick #define MAXINCL 9 213570Smckusick #define MAXNAM 75 223570Smckusick #define TMPNAME "/usr/tmp/MGXXXXXX" 233570Smckusick 243570Smckusick FILE *files[NUMFILES]; 253570Smckusick char *names[NUMFILES]; 263570Smckusick FILE *curfile; /* current output file */ 273570Smckusick FILE *fopen(); 283570Smckusick char labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE; 293570Smckusick char *mktemp(); 30*9577Sgarrison char *malloc(); 313570Smckusick 323570Smckusick /* 333570Smckusick * Remove temporary files if interrupted 343570Smckusick */ 353570Smckusick onintr() 363570Smckusick { 373570Smckusick int i; 383570Smckusick 393570Smckusick for (i = 0; i < NUMFILES; i++) 403570Smckusick if (files[i] != NULL) 413570Smckusick unlink(names[i]); 423570Smckusick } 433570Smckusick 443570Smckusick /* 453570Smckusick * Program to merge separately compiled pascal modules into a 463570Smckusick * single standard Pascal program. 473570Smckusick */ 483570Smckusick main(argc, argv) 493570Smckusick long argc; 503570Smckusick char **argv; 513570Smckusick { 523570Smckusick FILE *incl[MAXINCL]; /* include stack */ 533570Smckusick long inclcnt = 0; /* incl index */ 543570Smckusick char *name[MAXNAM]; /* include names seen so far */ 553570Smckusick long namcnt = 0; /* next name ptr slot available */ 56*9577Sgarrison char *nambuf; /* string table for names */ 573570Smckusick char line[BUFSIZ]; /* input line buffer */ 58*9577Sgarrison char *next; /* next name space available */ 593570Smckusick FILE *input = stdin; /* current input file */ 603570Smckusick long ac = 0; /* argv index */ 613570Smckusick char **cpp, *cp, *fp;/* char ptrs */ 623866Smckusic char quote; /* include quote character */ 633570Smckusick int i; /* index var */ 643570Smckusick 65*9577Sgarrison for (i = 0; i < MAXNAM ; i++) 66*9577Sgarrison name[i] = 0; 67*9577Sgarrison 683570Smckusick signal(SIGINT, onintr); 69*9577Sgarrison 703570Smckusick curfile = files[PRGFILE] = fopen(names[PRGFILE] = mktemp(TMPNAME), "w"); 713570Smckusick files[LABELFILE] = fopen(names[LABELFILE] = mktemp(TMPNAME), "w"); 723570Smckusick files[CONSTFILE] = fopen(names[CONSTFILE] = mktemp(TMPNAME), "w"); 733570Smckusick files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(TMPNAME), "w"); 743570Smckusick files[VARFILE] = fopen(names[VARFILE] = mktemp(TMPNAME), "w"); 753570Smckusick files[RTNFILE] = fopen(names[RTNFILE] = mktemp(TMPNAME), "w"); 763570Smckusick files[BODYFILE] = fopen(names[BODYFILE] = mktemp(TMPNAME), "w"); 77*9577Sgarrison 783570Smckusick for (i = 0; i < NUMFILES; i++) 793570Smckusick if (files[i] == NULL) 803570Smckusick quit(names[i]); 81*9577Sgarrison if ((nambuf = malloc(BUFSIZ)) == NULL) { 82*9577Sgarrison fputs("no space for string table\n", stderr); 83*9577Sgarrison quit(NULL); 84*9577Sgarrison } 85*9577Sgarrison next = nambuf; 863570Smckusick name[namcnt] = next; 873570Smckusick for(;;) { 883570Smckusick if (inclcnt > 0) { 893570Smckusick inclcnt--; 903570Smckusick fclose(input); 913570Smckusick input = incl[inclcnt]; 923570Smckusick } else if (++ac < argc) { 933570Smckusick input = freopen(argv[ac], "r", input); 943570Smckusick if (input == NULL) 953570Smckusick quit(argv[ac]); 963570Smckusick } else { 973570Smckusick printout(); 983570Smckusick onintr(); 993570Smckusick exit(0); 1003570Smckusick } 1013570Smckusick fgets(line, BUFSIZ, input); 1023570Smckusick while (!feof(input)) { 1033570Smckusick if (line[0] != '#') { 1043570Smckusick split(line); 1053570Smckusick fgets(line, BUFSIZ, input); 1063570Smckusick continue; 1073570Smckusick } 1083570Smckusick for (cp = &line[1]; isspace(*cp); cp++) 1093570Smckusick /* void */; 1103570Smckusick if (strcmpn("include", cp, 7)) 1113570Smckusick goto bad; 1123570Smckusick for (cp += 7; isspace(*cp); cp++) 1133570Smckusick /* void */; 1143570Smckusick if (*cp != '\'' && *cp != '"') 1153570Smckusick goto bad; 116*9577Sgarrison if (&nambuf[BUFSIZ] < next + strlen(cp)) { 117*9577Sgarrison if ((nambuf = malloc(BUFSIZ)) == NULL) { 118*9577Sgarrison fputs("no space for string table\n", 119*9577Sgarrison stderr); 120*9577Sgarrison quit(NULL); 121*9577Sgarrison } 122*9577Sgarrison next = nambuf; 123*9577Sgarrison name[namcnt] = next; 124*9577Sgarrison } 1253866Smckusic for (fp = next, quote = *cp++; 1263866Smckusic *cp != '\0' && *cp != quote; ) 1273570Smckusick *fp++ = *cp++; 1283866Smckusic if (*cp != quote && 1293570Smckusick (fp[-1] != 'i' || fp[-1] != 'h') && 1303570Smckusick (fp[-2] != '.')) 1313570Smckusick goto bad; 1323570Smckusick *fp++ = '\0'; 1333570Smckusick for (cpp = name; *cpp < next && strcmp(*cpp, next); ) 1343570Smckusick cpp++; 1353570Smckusick if (*cpp == next) { 1363570Smckusick if (inclcnt == MAXINCL) { 1373570Smckusick fputs("include table overflow\n", 1383570Smckusick stderr); 1393570Smckusick quit(NULL); 1403570Smckusick } 141*9577Sgarrison if (++namcnt == MAXNAM) { 1423570Smckusick fputs("include name table overflow\n", 1433570Smckusick stderr); 1443570Smckusick quit(NULL); 1453570Smckusick } 1463570Smckusick incl[inclcnt] = input; 1473570Smckusick inclcnt++; 1483570Smckusick input = fopen(next, "r"); 1493570Smckusick if (input == NULL) 1503570Smckusick quit(next); 1513570Smckusick next = fp; 1523570Smckusick name[namcnt] = next; 1533570Smckusick } 1543570Smckusick fgets(line, BUFSIZ, input); 1553570Smckusick } 1563570Smckusick } 1573570Smckusick bad: 1583570Smckusick fputs("bad include format:", stderr); 1593570Smckusick fputs(line, stderr); 1603570Smckusick quit(NULL); 1613570Smckusick } 1623570Smckusick 1633570Smckusick /* 1643570Smckusick * Split up output into the approprite files 1653570Smckusick */ 1663570Smckusick char incom = FALSE; /* TRUE => in comment */ 1673570Smckusick char incur = FALSE; /* TRUE => in (* *) style comment */ 1683570Smckusick char inbrac = FALSE; /* TRUE => in { } style comment */ 1693570Smckusick char instr = FALSE; /* TRUE => in quoted string */ 1703570Smckusick char inprog = FALSE; /* TRUE => program statement has been found */ 1713570Smckusick int beginnest = 0; /* routine nesting level */ 1723570Smckusick int nest = 0; /* begin block nesting level */ 173*9577Sgarrison int paren_level = 0; /* nesting level of parentheses */ 1743570Smckusick 1753570Smckusick split(line) 1763570Smckusick char *line; 1773570Smckusick { 1783570Smckusick char ch1, *cp; /* input window */ 1793570Smckusick char *word; /* ptr to current word */ 1803570Smckusick int len; /* length of current word */ 1813570Smckusick char prt = TRUE; /* TRUE => print current word */ 1823570Smckusick 1833570Smckusick ch1 = ' '; 1843570Smckusick cp = line; 1853570Smckusick while (*cp) { 1863570Smckusick switch(*cp) { 187*9577Sgarrison case '(': 188*9577Sgarrison if (incom) 189*9577Sgarrison break; 190*9577Sgarrison if (*(cp+1) == '*') { 191*9577Sgarrison fputc(*cp, curfile); 192*9577Sgarrison cp++; 1933570Smckusick incom = TRUE; 1943570Smckusick incur = TRUE; 195*9577Sgarrison } else { 196*9577Sgarrison paren_level++; 1973570Smckusick } 1983570Smckusick break; 1993570Smckusick case ')': 2003570Smckusick if (incur && ch1 == '*') { 2013570Smckusick incom = FALSE; 2023570Smckusick incur = FALSE; 203*9577Sgarrison } else if (!incom) { 204*9577Sgarrison paren_level--; 2053570Smckusick } 2063570Smckusick break; 2073570Smckusick case '{': 2083570Smckusick if (!incom) { 2093570Smckusick inbrac = TRUE; 2103570Smckusick incom = TRUE; 2113570Smckusick } 2123570Smckusick break; 2133570Smckusick case '}': 2143570Smckusick if (inbrac) { 2153570Smckusick inbrac = FALSE; 2163570Smckusick incom = FALSE; 2173570Smckusick } 2183570Smckusick break; 2193570Smckusick case '\'': 2203570Smckusick if (!incom) { 2213570Smckusick incom = TRUE; 2223570Smckusick instr = TRUE; 2233570Smckusick } else if (instr) { 2243570Smckusick incom = FALSE; 2253570Smckusick instr = FALSE; 2263570Smckusick } 2273570Smckusick break; 2283570Smckusick } 2293570Smckusick if (incom || !isalpha(*cp)) { 2303570Smckusick fputc(*cp, curfile); 2313570Smckusick ch1 = *cp++; 2323570Smckusick continue; 2333570Smckusick } 2343570Smckusick word = cp; 235*9577Sgarrison while (isalnum(*cp)) 2363570Smckusick cp++; 2373570Smckusick len = cp - word; 2383570Smckusick switch (*word) { 2393570Smckusick case 'b': 2403570Smckusick if (len == 5 && !strcmpn(word, "begin", 5)) { 2413570Smckusick if (nest == 0 && beginnest == 0) { 2423570Smckusick if (inprog != 1) { 2433570Smckusick fprintf(stderr, 2443570Smckusick "improper program body"); 2453570Smckusick quit(NULL); 2463570Smckusick } 2473570Smckusick curfile = files[BODYFILE]; 2483570Smckusick } else { 2493570Smckusick beginnest++; 2503570Smckusick } 2513570Smckusick } 2523570Smckusick break; 2533570Smckusick case 'c': 2543570Smckusick if (len == 4 && !strcmpn(word, "case", 4)) { 2553570Smckusick if (beginnest > 0) { 2563570Smckusick beginnest++; 2573570Smckusick } 2583570Smckusick break; 2593570Smckusick } 2603570Smckusick if (len == 5 && !strcmpn(word, "const", 5)) { 2613570Smckusick if (nest == 0) { 2623570Smckusick prt = FALSE; 2633570Smckusick if (!constopen) { 2643570Smckusick constopen = TRUE; 2653570Smckusick prt = TRUE; 2663570Smckusick } 2673570Smckusick curfile = files[CONSTFILE]; 2683570Smckusick } 2693570Smckusick } 2703570Smckusick break; 2713570Smckusick case 'e': 2723570Smckusick if (len == 3 && !strcmpn(word, "end", 3)) { 2733570Smckusick if (beginnest == 1) { 2743570Smckusick nest--; 2753570Smckusick } 2763570Smckusick if (beginnest > 0) { 2773570Smckusick beginnest--; 2783570Smckusick } 2793570Smckusick if (nest < 0) { 2803570Smckusick if (inprog == 1) { 2813570Smckusick inprog = 0; 2823570Smckusick nest = 0; 2833570Smckusick } else { 2843570Smckusick fprintf(stderr, "too many end statements"); 2853570Smckusick quit(NULL); 2863570Smckusick } 2873570Smckusick } 2883570Smckusick break; 2893570Smckusick } 2903570Smckusick if (len == 8 && !strcmpn(word, "external", 8)) { 2913570Smckusick fputs("forward", curfile); 2923570Smckusick prt = FALSE; 293*9577Sgarrison if (paren_level == 0) { 294*9577Sgarrison nest--; 295*9577Sgarrison } 2963570Smckusick } 2973570Smckusick break; 2983570Smckusick case 'f': 2993570Smckusick if (len == 8 && !strcmpn(word, "function", 8)) { 3003570Smckusick if (nest == 0) { 3013570Smckusick curfile = files[RTNFILE]; 3023570Smckusick } 303*9577Sgarrison if (paren_level == 0) { 304*9577Sgarrison nest++; 305*9577Sgarrison } 3063570Smckusick break; 3073570Smckusick } 3083570Smckusick if (len == 7 && !strcmpn(word, "forward", 7)) { 309*9577Sgarrison if (paren_level == 0) { 310*9577Sgarrison nest--; 311*9577Sgarrison } 3123570Smckusick } 3133570Smckusick break; 3143570Smckusick case 'l': 3153570Smckusick if (len == 5 && !strcmpn(word, "label", 5)) { 3163570Smckusick if (nest == 0) { 3173570Smckusick prt = FALSE; 3183570Smckusick if (!labelopen) { 3193570Smckusick labelopen = TRUE; 3203570Smckusick prt = TRUE; 3213570Smckusick } 3223570Smckusick curfile = files[LABELFILE]; 3233570Smckusick } 3243570Smckusick } 3253570Smckusick break; 3263570Smckusick case 'p': 3273570Smckusick if (len == 9 && !strcmpn(word, "procedure", 9)) { 3283570Smckusick if (nest == 0) { 3293570Smckusick curfile = files[RTNFILE]; 3303570Smckusick } 331*9577Sgarrison if (paren_level == 0) { 332*9577Sgarrison nest++; 333*9577Sgarrison } 3343570Smckusick break; 3353570Smckusick } 3363570Smckusick if (len == 7 && !strcmpn(word, "program", 7)) { 3373570Smckusick if (nest != 0) { 3383570Smckusick fprintf(stderr, "improper program nesting"); 3393570Smckusick quit(NULL); 3403570Smckusick } 3413570Smckusick inprog = 1; 3423570Smckusick curfile = files[PRGFILE]; 3433570Smckusick } 3443570Smckusick break; 3453570Smckusick case 't': 3463570Smckusick if (len == 4 && !strcmpn(word, "type", 4)) { 3473570Smckusick if (nest == 0) { 3483570Smckusick prt = FALSE; 3493570Smckusick if (!typeopen) { 3503570Smckusick typeopen = TRUE; 3513570Smckusick prt = TRUE; 3523570Smckusick } 3533570Smckusick curfile = files[TYPEFILE]; 3543570Smckusick } 3553570Smckusick } 3563570Smckusick break; 3573570Smckusick case 'v': 3583570Smckusick if (len == 3 && !strcmpn(word, "var", 3)) { 3593570Smckusick if (nest == 0) { 3603570Smckusick prt = FALSE; 3613570Smckusick if (!varopen) { 3623570Smckusick varopen = TRUE; 3633570Smckusick prt = TRUE; 3643570Smckusick } 3653570Smckusick curfile = files[VARFILE]; 3663570Smckusick } 3673570Smckusick } 3683570Smckusick break; 3693570Smckusick } 3703570Smckusick if (prt) 3713570Smckusick fprintf(curfile, "%.*s", len, word); 3723570Smckusick prt = TRUE; 3733570Smckusick ch1 = ' '; 3743570Smckusick } 3753570Smckusick } 3763570Smckusick 3773570Smckusick /* 3783570Smckusick * Print out the merged result 3793570Smckusick */ 3803570Smckusick printout() 3813570Smckusick { 3823570Smckusick FILE *fp; 3833570Smckusick int i; 3843570Smckusick char ch; 3853570Smckusick 3863570Smckusick for(i = 0; i < NUMFILES; i++) { 3873570Smckusick fp = freopen(names[i], "r", files[i]); 3883570Smckusick if (fp == NULL) 3893570Smckusick quit(names[i]); 3903570Smckusick ch = getc(fp); 3913570Smckusick while (!feof(fp)) { 3923570Smckusick putc(ch,stdout); 3933570Smckusick ch = getc(fp); 3943570Smckusick } 3953570Smckusick } 3963570Smckusick } 3973570Smckusick 3983570Smckusick /* 3993570Smckusick * Die gracefully 4003570Smckusick */ 4013570Smckusick quit(fp) 4023570Smckusick char *fp; 4033570Smckusick { 4043570Smckusick if (fp != NULL) 4053570Smckusick perror(fp); 4063570Smckusick onintr(); 4073570Smckusick exit(1); 4083570Smckusick } 409