1*22263Sdist /* 2*22263Sdist * Copyright (c) 1980 Regents of the University of California. 3*22263Sdist * All rights reserved. The Berkeley software License Agreement 4*22263Sdist * specifies the terms and conditions for redistribution. 5*22263Sdist */ 63570Smckusick 7*22263Sdist #ifndef lint 8*22263Sdist char copyright[] = 9*22263Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10*22263Sdist All rights reserved.\n"; 11*22263Sdist #endif not lint 123570Smckusick 13*22263Sdist #ifndef lint 14*22263Sdist static char sccsid[] = "@(#)pmerge.c 5.1 (Berkeley) 06/05/85"; 15*22263Sdist #endif not lint 16*22263Sdist 173570Smckusick #include <ctype.h> 183570Smckusick #include <stdio.h> 193570Smckusick #include <signal.h> 203570Smckusick 213570Smckusick #define PRGFILE 0 223570Smckusick #define LABELFILE 1 233570Smckusick #define CONSTFILE 2 243570Smckusick #define TYPEFILE 3 253570Smckusick #define VARFILE 4 263570Smckusick #define RTNFILE 5 273570Smckusick #define BODYFILE 6 283570Smckusick #define NUMFILES 7 293570Smckusick 303570Smckusick #define TRUE 1 313570Smckusick #define FALSE 0 323570Smckusick #define MAXINCL 9 333570Smckusick #define MAXNAM 75 343570Smckusick #define TMPNAME "/usr/tmp/MGXXXXXX" 353570Smckusick 363570Smckusick FILE *files[NUMFILES]; 373570Smckusick char *names[NUMFILES]; 383570Smckusick FILE *curfile; /* current output file */ 393570Smckusick FILE *fopen(); 403570Smckusick char labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE; 413570Smckusick char *mktemp(); 429577Sgarrison char *malloc(); 433570Smckusick 443570Smckusick /* 453570Smckusick * Remove temporary files if interrupted 463570Smckusick */ 473570Smckusick onintr() 483570Smckusick { 493570Smckusick int i; 503570Smckusick 513570Smckusick for (i = 0; i < NUMFILES; i++) 523570Smckusick if (files[i] != NULL) 533570Smckusick unlink(names[i]); 543570Smckusick } 553570Smckusick 563570Smckusick /* 573570Smckusick * Program to merge separately compiled pascal modules into a 583570Smckusick * single standard Pascal program. 593570Smckusick */ 603570Smckusick main(argc, argv) 613570Smckusick long argc; 623570Smckusick char **argv; 633570Smckusick { 643570Smckusick FILE *incl[MAXINCL]; /* include stack */ 653570Smckusick long inclcnt = 0; /* incl index */ 663570Smckusick char *name[MAXNAM]; /* include names seen so far */ 673570Smckusick long namcnt = 0; /* next name ptr slot available */ 689577Sgarrison char *nambuf; /* string table for names */ 693570Smckusick char line[BUFSIZ]; /* input line buffer */ 709577Sgarrison char *next; /* next name space available */ 713570Smckusick FILE *input = stdin; /* current input file */ 723570Smckusick long ac = 0; /* argv index */ 733570Smckusick char **cpp, *cp, *fp;/* char ptrs */ 743866Smckusic char quote; /* include quote character */ 753570Smckusick int i; /* index var */ 763570Smckusick 779577Sgarrison for (i = 0; i < MAXNAM ; i++) 789577Sgarrison name[i] = 0; 799577Sgarrison 803570Smckusick signal(SIGINT, onintr); 819577Sgarrison 823570Smckusick curfile = files[PRGFILE] = fopen(names[PRGFILE] = mktemp(TMPNAME), "w"); 833570Smckusick files[LABELFILE] = fopen(names[LABELFILE] = mktemp(TMPNAME), "w"); 843570Smckusick files[CONSTFILE] = fopen(names[CONSTFILE] = mktemp(TMPNAME), "w"); 853570Smckusick files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(TMPNAME), "w"); 863570Smckusick files[VARFILE] = fopen(names[VARFILE] = mktemp(TMPNAME), "w"); 873570Smckusick files[RTNFILE] = fopen(names[RTNFILE] = mktemp(TMPNAME), "w"); 883570Smckusick files[BODYFILE] = fopen(names[BODYFILE] = mktemp(TMPNAME), "w"); 899577Sgarrison 903570Smckusick for (i = 0; i < NUMFILES; i++) 913570Smckusick if (files[i] == NULL) 923570Smckusick quit(names[i]); 939577Sgarrison if ((nambuf = malloc(BUFSIZ)) == NULL) { 949577Sgarrison fputs("no space for string table\n", stderr); 959577Sgarrison quit(NULL); 969577Sgarrison } 979577Sgarrison next = nambuf; 983570Smckusick name[namcnt] = next; 993570Smckusick for(;;) { 1003570Smckusick if (inclcnt > 0) { 1013570Smckusick inclcnt--; 1023570Smckusick fclose(input); 1033570Smckusick input = incl[inclcnt]; 1043570Smckusick } else if (++ac < argc) { 1053570Smckusick input = freopen(argv[ac], "r", input); 1063570Smckusick if (input == NULL) 1073570Smckusick quit(argv[ac]); 1083570Smckusick } else { 1093570Smckusick printout(); 1103570Smckusick onintr(); 1113570Smckusick exit(0); 1123570Smckusick } 1133570Smckusick fgets(line, BUFSIZ, input); 1143570Smckusick while (!feof(input)) { 1153570Smckusick if (line[0] != '#') { 1163570Smckusick split(line); 1173570Smckusick fgets(line, BUFSIZ, input); 1183570Smckusick continue; 1193570Smckusick } 1203570Smckusick for (cp = &line[1]; isspace(*cp); cp++) 1213570Smckusick /* void */; 12215685Speter if (strncmp("include", cp, 7)) 1233570Smckusick goto bad; 1243570Smckusick for (cp += 7; isspace(*cp); cp++) 1253570Smckusick /* void */; 1263570Smckusick if (*cp != '\'' && *cp != '"') 1273570Smckusick goto bad; 1289577Sgarrison if (&nambuf[BUFSIZ] < next + strlen(cp)) { 1299577Sgarrison if ((nambuf = malloc(BUFSIZ)) == NULL) { 1309577Sgarrison fputs("no space for string table\n", 1319577Sgarrison stderr); 1329577Sgarrison quit(NULL); 1339577Sgarrison } 1349577Sgarrison next = nambuf; 1359577Sgarrison name[namcnt] = next; 1369577Sgarrison } 1373866Smckusic for (fp = next, quote = *cp++; 1383866Smckusic *cp != '\0' && *cp != quote; ) 1393570Smckusick *fp++ = *cp++; 1403866Smckusic if (*cp != quote && 1413570Smckusick (fp[-1] != 'i' || fp[-1] != 'h') && 1423570Smckusick (fp[-2] != '.')) 1433570Smckusick goto bad; 1443570Smckusick *fp++ = '\0'; 1453570Smckusick for (cpp = name; *cpp < next && strcmp(*cpp, next); ) 1463570Smckusick cpp++; 1473570Smckusick if (*cpp == next) { 1483570Smckusick if (inclcnt == MAXINCL) { 1493570Smckusick fputs("include table overflow\n", 1503570Smckusick stderr); 1513570Smckusick quit(NULL); 1523570Smckusick } 1539577Sgarrison if (++namcnt == MAXNAM) { 1543570Smckusick fputs("include name table overflow\n", 1553570Smckusick stderr); 1563570Smckusick quit(NULL); 1573570Smckusick } 1583570Smckusick incl[inclcnt] = input; 1593570Smckusick inclcnt++; 1603570Smckusick input = fopen(next, "r"); 1613570Smckusick if (input == NULL) 1623570Smckusick quit(next); 1633570Smckusick next = fp; 1643570Smckusick name[namcnt] = next; 1653570Smckusick } 1663570Smckusick fgets(line, BUFSIZ, input); 1673570Smckusick } 1683570Smckusick } 1693570Smckusick bad: 1703570Smckusick fputs("bad include format:", stderr); 1713570Smckusick fputs(line, stderr); 1723570Smckusick quit(NULL); 1733570Smckusick } 1743570Smckusick 1753570Smckusick /* 1763570Smckusick * Split up output into the approprite files 1773570Smckusick */ 1783570Smckusick char incom = FALSE; /* TRUE => in comment */ 1793570Smckusick char incur = FALSE; /* TRUE => in (* *) style comment */ 1803570Smckusick char inbrac = FALSE; /* TRUE => in { } style comment */ 1813570Smckusick char instr = FALSE; /* TRUE => in quoted string */ 1823570Smckusick char inprog = FALSE; /* TRUE => program statement has been found */ 1833570Smckusick int beginnest = 0; /* routine nesting level */ 1843570Smckusick int nest = 0; /* begin block nesting level */ 1859577Sgarrison int paren_level = 0; /* nesting level of parentheses */ 1863570Smckusick 1873570Smckusick split(line) 1883570Smckusick char *line; 1893570Smckusick { 1903570Smckusick char ch1, *cp; /* input window */ 1913570Smckusick char *word; /* ptr to current word */ 1923570Smckusick int len; /* length of current word */ 1933570Smckusick char prt = TRUE; /* TRUE => print current word */ 1943570Smckusick 1953570Smckusick ch1 = ' '; 1963570Smckusick cp = line; 1973570Smckusick while (*cp) { 1983570Smckusick switch(*cp) { 1999577Sgarrison case '(': 2009577Sgarrison if (incom) 2019577Sgarrison break; 2029577Sgarrison if (*(cp+1) == '*') { 2039577Sgarrison fputc(*cp, curfile); 2049577Sgarrison cp++; 2053570Smckusick incom = TRUE; 2063570Smckusick incur = TRUE; 2079577Sgarrison } else { 2089577Sgarrison paren_level++; 2093570Smckusick } 2103570Smckusick break; 2113570Smckusick case ')': 2123570Smckusick if (incur && ch1 == '*') { 2133570Smckusick incom = FALSE; 2143570Smckusick incur = FALSE; 2159577Sgarrison } else if (!incom) { 2169577Sgarrison paren_level--; 2173570Smckusick } 2183570Smckusick break; 2193570Smckusick case '{': 2203570Smckusick if (!incom) { 2213570Smckusick inbrac = TRUE; 2223570Smckusick incom = TRUE; 2233570Smckusick } 2243570Smckusick break; 2253570Smckusick case '}': 2263570Smckusick if (inbrac) { 2273570Smckusick inbrac = FALSE; 2283570Smckusick incom = FALSE; 2293570Smckusick } 2303570Smckusick break; 2313570Smckusick case '\'': 2323570Smckusick if (!incom) { 2333570Smckusick incom = TRUE; 2343570Smckusick instr = TRUE; 2353570Smckusick } else if (instr) { 2363570Smckusick incom = FALSE; 2373570Smckusick instr = FALSE; 2383570Smckusick } 2393570Smckusick break; 2403570Smckusick } 2413570Smckusick if (incom || !isalpha(*cp)) { 2423570Smckusick fputc(*cp, curfile); 2433570Smckusick ch1 = *cp++; 2443570Smckusick continue; 2453570Smckusick } 2463570Smckusick word = cp; 2479577Sgarrison while (isalnum(*cp)) 2483570Smckusick cp++; 2493570Smckusick len = cp - word; 2503570Smckusick switch (*word) { 2513570Smckusick case 'b': 25215685Speter if (len == 5 && !strncmp(word, "begin", 5)) { 2533570Smckusick if (nest == 0 && beginnest == 0) { 2543570Smckusick if (inprog != 1) { 2553570Smckusick fprintf(stderr, 2563570Smckusick "improper program body"); 2573570Smckusick quit(NULL); 2583570Smckusick } 2593570Smckusick curfile = files[BODYFILE]; 2603570Smckusick } else { 2613570Smckusick beginnest++; 2623570Smckusick } 2633570Smckusick } 2643570Smckusick break; 2653570Smckusick case 'c': 26615685Speter if (len == 4 && !strncmp(word, "case", 4)) { 2673570Smckusick if (beginnest > 0) { 2683570Smckusick beginnest++; 2693570Smckusick } 2703570Smckusick break; 2713570Smckusick } 27215685Speter if (len == 5 && !strncmp(word, "const", 5)) { 2733570Smckusick if (nest == 0) { 2743570Smckusick prt = FALSE; 2753570Smckusick if (!constopen) { 2763570Smckusick constopen = TRUE; 2773570Smckusick prt = TRUE; 2783570Smckusick } 2793570Smckusick curfile = files[CONSTFILE]; 2803570Smckusick } 2813570Smckusick } 2823570Smckusick break; 2833570Smckusick case 'e': 28415685Speter if (len == 3 && !strncmp(word, "end", 3)) { 2853570Smckusick if (beginnest == 1) { 2863570Smckusick nest--; 2873570Smckusick } 2883570Smckusick if (beginnest > 0) { 2893570Smckusick beginnest--; 2903570Smckusick } 2913570Smckusick if (nest < 0) { 2923570Smckusick if (inprog == 1) { 2933570Smckusick inprog = 0; 2943570Smckusick nest = 0; 2953570Smckusick } else { 2963570Smckusick fprintf(stderr, "too many end statements"); 2973570Smckusick quit(NULL); 2983570Smckusick } 2993570Smckusick } 3003570Smckusick break; 3013570Smckusick } 30215685Speter if (len == 8 && !strncmp(word, "external", 8)) { 3033570Smckusick fputs("forward", curfile); 3043570Smckusick prt = FALSE; 3059577Sgarrison if (paren_level == 0) { 3069577Sgarrison nest--; 3079577Sgarrison } 3083570Smckusick } 3093570Smckusick break; 3103570Smckusick case 'f': 31115685Speter if (len == 8 && !strncmp(word, "function", 8)) { 3123570Smckusick if (nest == 0) { 3133570Smckusick curfile = files[RTNFILE]; 3143570Smckusick } 3159577Sgarrison if (paren_level == 0) { 3169577Sgarrison nest++; 3179577Sgarrison } 3183570Smckusick break; 3193570Smckusick } 32015685Speter if (len == 7 && !strncmp(word, "forward", 7)) { 3219577Sgarrison if (paren_level == 0) { 3229577Sgarrison nest--; 3239577Sgarrison } 3243570Smckusick } 3253570Smckusick break; 3263570Smckusick case 'l': 32715685Speter if (len == 5 && !strncmp(word, "label", 5)) { 3283570Smckusick if (nest == 0) { 3293570Smckusick prt = FALSE; 3303570Smckusick if (!labelopen) { 3313570Smckusick labelopen = TRUE; 3323570Smckusick prt = TRUE; 3333570Smckusick } 3343570Smckusick curfile = files[LABELFILE]; 3353570Smckusick } 3363570Smckusick } 3373570Smckusick break; 3383570Smckusick case 'p': 33915685Speter if (len == 9 && !strncmp(word, "procedure", 9)) { 3403570Smckusick if (nest == 0) { 3413570Smckusick curfile = files[RTNFILE]; 3423570Smckusick } 3439577Sgarrison if (paren_level == 0) { 3449577Sgarrison nest++; 3459577Sgarrison } 3463570Smckusick break; 3473570Smckusick } 34815685Speter if (len == 7 && !strncmp(word, "program", 7)) { 3493570Smckusick if (nest != 0) { 3503570Smckusick fprintf(stderr, "improper program nesting"); 3513570Smckusick quit(NULL); 3523570Smckusick } 3533570Smckusick inprog = 1; 3543570Smckusick curfile = files[PRGFILE]; 3553570Smckusick } 3563570Smckusick break; 3573570Smckusick case 't': 35815685Speter if (len == 4 && !strncmp(word, "type", 4)) { 3593570Smckusick if (nest == 0) { 3603570Smckusick prt = FALSE; 3613570Smckusick if (!typeopen) { 3623570Smckusick typeopen = TRUE; 3633570Smckusick prt = TRUE; 3643570Smckusick } 3653570Smckusick curfile = files[TYPEFILE]; 3663570Smckusick } 3673570Smckusick } 3683570Smckusick break; 3693570Smckusick case 'v': 37015685Speter if (len == 3 && !strncmp(word, "var", 3)) { 3713570Smckusick if (nest == 0) { 3723570Smckusick prt = FALSE; 3733570Smckusick if (!varopen) { 3743570Smckusick varopen = TRUE; 3753570Smckusick prt = TRUE; 3763570Smckusick } 3773570Smckusick curfile = files[VARFILE]; 3783570Smckusick } 3793570Smckusick } 3803570Smckusick break; 3813570Smckusick } 3823570Smckusick if (prt) 3833570Smckusick fprintf(curfile, "%.*s", len, word); 3843570Smckusick prt = TRUE; 3853570Smckusick ch1 = ' '; 3863570Smckusick } 3873570Smckusick } 3883570Smckusick 3893570Smckusick /* 3903570Smckusick * Print out the merged result 3913570Smckusick */ 3923570Smckusick printout() 3933570Smckusick { 3943570Smckusick FILE *fp; 3953570Smckusick int i; 3963570Smckusick char ch; 3973570Smckusick 3983570Smckusick for(i = 0; i < NUMFILES; i++) { 3993570Smckusick fp = freopen(names[i], "r", files[i]); 4003570Smckusick if (fp == NULL) 4013570Smckusick quit(names[i]); 4023570Smckusick ch = getc(fp); 4033570Smckusick while (!feof(fp)) { 4043570Smckusick putc(ch,stdout); 4053570Smckusick ch = getc(fp); 4063570Smckusick } 4073570Smckusick } 4083570Smckusick } 4093570Smckusick 4103570Smckusick /* 4113570Smckusick * Die gracefully 4123570Smckusick */ 4133570Smckusick quit(fp) 4143570Smckusick char *fp; 4153570Smckusick { 4163570Smckusick if (fp != NULL) 4173570Smckusick perror(fp); 4183570Smckusick onintr(); 4193570Smckusick exit(1); 4203570Smckusick } 421