1*48107Sbostic /*- 2*48107Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48107Sbostic * All rights reserved. 4*48107Sbostic * 5*48107Sbostic * %sccs.include.redist.c% 622263Sdist */ 73570Smckusick 822263Sdist #ifndef lint 922263Sdist char copyright[] = 10*48107Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 1122263Sdist All rights reserved.\n"; 12*48107Sbostic #endif /* not lint */ 133570Smckusick 1422263Sdist #ifndef lint 15*48107Sbostic static char sccsid[] = "@(#)pmerge.c 5.3 (Berkeley) 04/16/91"; 16*48107Sbostic #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 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 */ 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 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 */ 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 */ 4183570Smckusick quit(fp) 4193570Smckusick char *fp; 4203570Smckusick { 4213570Smckusick if (fp != NULL) 4223570Smckusick perror(fp); 42347032Sdonn onintr(0); 4243570Smckusick exit(1); 4253570Smckusick } 426