122263Sdist /* 222263Sdist * Copyright (c) 1980 Regents of the University of California. 322263Sdist * All rights reserved. The Berkeley software License Agreement 422263Sdist * specifies the terms and conditions for redistribution. 522263Sdist */ 63570Smckusick 722263Sdist #ifndef lint 822263Sdist char copyright[] = 922263Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1022263Sdist All rights reserved.\n"; 1122263Sdist #endif not lint 123570Smckusick 1322263Sdist #ifndef lint 14*47032Sdonn static char sccsid[] = "@(#)pmerge.c 5.2 (Berkeley) 03/06/91"; 1522263Sdist #endif not lint 1622263Sdist 173570Smckusick #include <ctype.h> 183570Smckusick #include <stdio.h> 19*47032Sdonn #include <string.h> 20*47032Sdonn #include <stdlib.h> 21*47032Sdonn #include <unistd.h> 223570Smckusick #include <signal.h> 233570Smckusick 243570Smckusick #define PRGFILE 0 253570Smckusick #define LABELFILE 1 263570Smckusick #define CONSTFILE 2 273570Smckusick #define TYPEFILE 3 283570Smckusick #define VARFILE 4 293570Smckusick #define RTNFILE 5 303570Smckusick #define BODYFILE 6 313570Smckusick #define NUMFILES 7 323570Smckusick 333570Smckusick #define TRUE 1 343570Smckusick #define FALSE 0 353570Smckusick #define MAXINCL 9 363570Smckusick #define MAXNAM 75 373570Smckusick #define TMPNAME "/usr/tmp/MGXXXXXX" 383570Smckusick 393570Smckusick FILE *files[NUMFILES]; 403570Smckusick char *names[NUMFILES]; 413570Smckusick FILE *curfile; /* current output file */ 423570Smckusick char labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE; 433570Smckusick 443570Smckusick /* 453570Smckusick * Remove temporary files if interrupted 463570Smckusick */ 47*47032Sdonn void 48*47032Sdonn onintr(unused) 493570Smckusick { 503570Smckusick int i; 513570Smckusick 523570Smckusick for (i = 0; i < NUMFILES; i++) 533570Smckusick if (files[i] != NULL) 543570Smckusick unlink(names[i]); 553570Smckusick } 563570Smckusick 573570Smckusick /* 583570Smckusick * Program to merge separately compiled pascal modules into a 593570Smckusick * single standard Pascal program. 603570Smckusick */ 613570Smckusick main(argc, argv) 623570Smckusick long argc; 633570Smckusick char **argv; 643570Smckusick { 653570Smckusick FILE *incl[MAXINCL]; /* include stack */ 663570Smckusick long inclcnt = 0; /* incl index */ 673570Smckusick char *name[MAXNAM]; /* include names seen so far */ 683570Smckusick long namcnt = 0; /* next name ptr slot available */ 699577Sgarrison char *nambuf; /* string table for names */ 703570Smckusick char line[BUFSIZ]; /* input line buffer */ 719577Sgarrison char *next; /* next name space available */ 723570Smckusick FILE *input = stdin; /* current input file */ 733570Smckusick long ac = 0; /* argv index */ 743570Smckusick char **cpp, *cp, *fp;/* char ptrs */ 753866Smckusic char quote; /* include quote character */ 763570Smckusick int i; /* index var */ 773570Smckusick 789577Sgarrison for (i = 0; i < MAXNAM ; i++) 799577Sgarrison name[i] = 0; 809577Sgarrison 813570Smckusick signal(SIGINT, onintr); 829577Sgarrison 83*47032Sdonn curfile = files[PRGFILE] = 84*47032Sdonn fopen(names[PRGFILE] = mktemp(strdup(TMPNAME)), "w"); 85*47032Sdonn files[LABELFILE] = 86*47032Sdonn fopen(names[LABELFILE] = mktemp(strdup(TMPNAME)), "w"); 87*47032Sdonn files[CONSTFILE] = 88*47032Sdonn fopen(names[CONSTFILE] = mktemp(strdup(TMPNAME)), "w"); 89*47032Sdonn files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(strdup(TMPNAME)), "w"); 90*47032Sdonn files[VARFILE] = fopen(names[VARFILE] = mktemp(strdup(TMPNAME)), "w"); 91*47032Sdonn files[RTNFILE] = fopen(names[RTNFILE] = mktemp(strdup(TMPNAME)), "w"); 92*47032Sdonn files[BODYFILE] = fopen(names[BODYFILE] = mktemp(strdup(TMPNAME)), "w"); 939577Sgarrison 943570Smckusick for (i = 0; i < NUMFILES; i++) 953570Smckusick if (files[i] == NULL) 963570Smckusick quit(names[i]); 979577Sgarrison if ((nambuf = malloc(BUFSIZ)) == NULL) { 989577Sgarrison fputs("no space for string table\n", stderr); 999577Sgarrison quit(NULL); 1009577Sgarrison } 1019577Sgarrison next = nambuf; 1023570Smckusick name[namcnt] = next; 1033570Smckusick for(;;) { 1043570Smckusick if (inclcnt > 0) { 1053570Smckusick inclcnt--; 1063570Smckusick fclose(input); 1073570Smckusick input = incl[inclcnt]; 1083570Smckusick } else if (++ac < argc) { 1093570Smckusick input = freopen(argv[ac], "r", input); 1103570Smckusick if (input == NULL) 1113570Smckusick quit(argv[ac]); 1123570Smckusick } else { 1133570Smckusick printout(); 114*47032Sdonn onintr(0); 1153570Smckusick exit(0); 1163570Smckusick } 1173570Smckusick fgets(line, BUFSIZ, input); 1183570Smckusick while (!feof(input)) { 1193570Smckusick if (line[0] != '#') { 1203570Smckusick split(line); 1213570Smckusick fgets(line, BUFSIZ, input); 1223570Smckusick continue; 1233570Smckusick } 1243570Smckusick for (cp = &line[1]; isspace(*cp); cp++) 1253570Smckusick /* void */; 12615685Speter if (strncmp("include", cp, 7)) 1273570Smckusick goto bad; 1283570Smckusick for (cp += 7; isspace(*cp); cp++) 1293570Smckusick /* void */; 1303570Smckusick if (*cp != '\'' && *cp != '"') 1313570Smckusick goto bad; 1329577Sgarrison if (&nambuf[BUFSIZ] < next + strlen(cp)) { 1339577Sgarrison if ((nambuf = malloc(BUFSIZ)) == NULL) { 1349577Sgarrison fputs("no space for string table\n", 1359577Sgarrison stderr); 1369577Sgarrison quit(NULL); 1379577Sgarrison } 1389577Sgarrison next = nambuf; 1399577Sgarrison name[namcnt] = next; 1409577Sgarrison } 1413866Smckusic for (fp = next, quote = *cp++; 1423866Smckusic *cp != '\0' && *cp != quote; ) 1433570Smckusick *fp++ = *cp++; 1443866Smckusic if (*cp != quote && 1453570Smckusick (fp[-1] != 'i' || fp[-1] != 'h') && 1463570Smckusick (fp[-2] != '.')) 1473570Smckusick goto bad; 1483570Smckusick *fp++ = '\0'; 1493570Smckusick for (cpp = name; *cpp < next && strcmp(*cpp, next); ) 1503570Smckusick cpp++; 1513570Smckusick if (*cpp == next) { 1523570Smckusick if (inclcnt == MAXINCL) { 1533570Smckusick fputs("include table overflow\n", 1543570Smckusick stderr); 1553570Smckusick quit(NULL); 1563570Smckusick } 1579577Sgarrison if (++namcnt == MAXNAM) { 1583570Smckusick fputs("include name table overflow\n", 1593570Smckusick stderr); 1603570Smckusick quit(NULL); 1613570Smckusick } 1623570Smckusick incl[inclcnt] = input; 1633570Smckusick inclcnt++; 1643570Smckusick input = fopen(next, "r"); 1653570Smckusick if (input == NULL) 1663570Smckusick quit(next); 1673570Smckusick next = fp; 1683570Smckusick name[namcnt] = next; 1693570Smckusick } 1703570Smckusick fgets(line, BUFSIZ, input); 1713570Smckusick } 1723570Smckusick } 1733570Smckusick bad: 1743570Smckusick fputs("bad include format:", stderr); 1753570Smckusick fputs(line, stderr); 1763570Smckusick quit(NULL); 1773570Smckusick } 1783570Smckusick 1793570Smckusick /* 1803570Smckusick * Split up output into the approprite files 1813570Smckusick */ 1823570Smckusick char incom = FALSE; /* TRUE => in comment */ 1833570Smckusick char incur = FALSE; /* TRUE => in (* *) style comment */ 1843570Smckusick char inbrac = FALSE; /* TRUE => in { } style comment */ 1853570Smckusick char instr = FALSE; /* TRUE => in quoted string */ 1863570Smckusick char inprog = FALSE; /* TRUE => program statement has been found */ 1873570Smckusick int beginnest = 0; /* routine nesting level */ 1883570Smckusick int nest = 0; /* begin block nesting level */ 1899577Sgarrison int paren_level = 0; /* nesting level of parentheses */ 1903570Smckusick 1913570Smckusick split(line) 1923570Smckusick char *line; 1933570Smckusick { 1943570Smckusick char ch1, *cp; /* input window */ 1953570Smckusick char *word; /* ptr to current word */ 1963570Smckusick int len; /* length of current word */ 1973570Smckusick char prt = TRUE; /* TRUE => print current word */ 1983570Smckusick 1993570Smckusick ch1 = ' '; 2003570Smckusick cp = line; 2013570Smckusick while (*cp) { 2023570Smckusick switch(*cp) { 2039577Sgarrison case '(': 2049577Sgarrison if (incom) 2059577Sgarrison break; 2069577Sgarrison if (*(cp+1) == '*') { 2079577Sgarrison fputc(*cp, curfile); 2089577Sgarrison cp++; 2093570Smckusick incom = TRUE; 2103570Smckusick incur = TRUE; 2119577Sgarrison } else { 2129577Sgarrison paren_level++; 2133570Smckusick } 2143570Smckusick break; 2153570Smckusick case ')': 2163570Smckusick if (incur && ch1 == '*') { 2173570Smckusick incom = FALSE; 2183570Smckusick incur = FALSE; 2199577Sgarrison } else if (!incom) { 2209577Sgarrison paren_level--; 2213570Smckusick } 2223570Smckusick break; 2233570Smckusick case '{': 2243570Smckusick if (!incom) { 2253570Smckusick inbrac = TRUE; 2263570Smckusick incom = TRUE; 2273570Smckusick } 2283570Smckusick break; 2293570Smckusick case '}': 2303570Smckusick if (inbrac) { 2313570Smckusick inbrac = FALSE; 2323570Smckusick incom = FALSE; 2333570Smckusick } 2343570Smckusick break; 2353570Smckusick case '\'': 2363570Smckusick if (!incom) { 2373570Smckusick incom = TRUE; 2383570Smckusick instr = TRUE; 2393570Smckusick } else if (instr) { 2403570Smckusick incom = FALSE; 2413570Smckusick instr = FALSE; 2423570Smckusick } 2433570Smckusick break; 2443570Smckusick } 2453570Smckusick if (incom || !isalpha(*cp)) { 2463570Smckusick fputc(*cp, curfile); 2473570Smckusick ch1 = *cp++; 2483570Smckusick continue; 2493570Smckusick } 2503570Smckusick word = cp; 2519577Sgarrison while (isalnum(*cp)) 2523570Smckusick cp++; 2533570Smckusick len = cp - word; 2543570Smckusick switch (*word) { 2553570Smckusick case 'b': 25615685Speter if (len == 5 && !strncmp(word, "begin", 5)) { 2573570Smckusick if (nest == 0 && beginnest == 0) { 2583570Smckusick if (inprog != 1) { 2593570Smckusick fprintf(stderr, 2603570Smckusick "improper program body"); 2613570Smckusick quit(NULL); 2623570Smckusick } 2633570Smckusick curfile = files[BODYFILE]; 2643570Smckusick } else { 2653570Smckusick beginnest++; 2663570Smckusick } 2673570Smckusick } 2683570Smckusick break; 2693570Smckusick case 'c': 27015685Speter if (len == 4 && !strncmp(word, "case", 4)) { 2713570Smckusick if (beginnest > 0) { 2723570Smckusick beginnest++; 2733570Smckusick } 2743570Smckusick break; 2753570Smckusick } 27615685Speter if (len == 5 && !strncmp(word, "const", 5)) { 2773570Smckusick if (nest == 0) { 2783570Smckusick prt = FALSE; 2793570Smckusick if (!constopen) { 2803570Smckusick constopen = TRUE; 2813570Smckusick prt = TRUE; 2823570Smckusick } 2833570Smckusick curfile = files[CONSTFILE]; 2843570Smckusick } 2853570Smckusick } 2863570Smckusick break; 2873570Smckusick case 'e': 28815685Speter if (len == 3 && !strncmp(word, "end", 3)) { 2893570Smckusick if (beginnest == 1) { 2903570Smckusick nest--; 2913570Smckusick } 2923570Smckusick if (beginnest > 0) { 2933570Smckusick beginnest--; 2943570Smckusick } 2953570Smckusick if (nest < 0) { 2963570Smckusick if (inprog == 1) { 2973570Smckusick inprog = 0; 2983570Smckusick nest = 0; 2993570Smckusick } else { 3003570Smckusick fprintf(stderr, "too many end statements"); 3013570Smckusick quit(NULL); 3023570Smckusick } 3033570Smckusick } 3043570Smckusick break; 3053570Smckusick } 30615685Speter if (len == 8 && !strncmp(word, "external", 8)) { 3073570Smckusick fputs("forward", curfile); 3083570Smckusick prt = FALSE; 3099577Sgarrison if (paren_level == 0) { 3109577Sgarrison nest--; 3119577Sgarrison } 3123570Smckusick } 3133570Smckusick break; 3143570Smckusick case 'f': 31515685Speter if (len == 8 && !strncmp(word, "function", 8)) { 3163570Smckusick if (nest == 0) { 3173570Smckusick curfile = files[RTNFILE]; 3183570Smckusick } 3199577Sgarrison if (paren_level == 0) { 3209577Sgarrison nest++; 3219577Sgarrison } 3223570Smckusick break; 3233570Smckusick } 32415685Speter if (len == 7 && !strncmp(word, "forward", 7)) { 3259577Sgarrison if (paren_level == 0) { 3269577Sgarrison nest--; 3279577Sgarrison } 3283570Smckusick } 3293570Smckusick break; 3303570Smckusick case 'l': 33115685Speter if (len == 5 && !strncmp(word, "label", 5)) { 3323570Smckusick if (nest == 0) { 3333570Smckusick prt = FALSE; 3343570Smckusick if (!labelopen) { 3353570Smckusick labelopen = TRUE; 3363570Smckusick prt = TRUE; 3373570Smckusick } 3383570Smckusick curfile = files[LABELFILE]; 3393570Smckusick } 3403570Smckusick } 3413570Smckusick break; 3423570Smckusick case 'p': 34315685Speter if (len == 9 && !strncmp(word, "procedure", 9)) { 3443570Smckusick if (nest == 0) { 3453570Smckusick curfile = files[RTNFILE]; 3463570Smckusick } 3479577Sgarrison if (paren_level == 0) { 3489577Sgarrison nest++; 3499577Sgarrison } 3503570Smckusick break; 3513570Smckusick } 35215685Speter if (len == 7 && !strncmp(word, "program", 7)) { 3533570Smckusick if (nest != 0) { 3543570Smckusick fprintf(stderr, "improper program nesting"); 3553570Smckusick quit(NULL); 3563570Smckusick } 3573570Smckusick inprog = 1; 3583570Smckusick curfile = files[PRGFILE]; 3593570Smckusick } 3603570Smckusick break; 3613570Smckusick case 't': 36215685Speter if (len == 4 && !strncmp(word, "type", 4)) { 3633570Smckusick if (nest == 0) { 3643570Smckusick prt = FALSE; 3653570Smckusick if (!typeopen) { 3663570Smckusick typeopen = TRUE; 3673570Smckusick prt = TRUE; 3683570Smckusick } 3693570Smckusick curfile = files[TYPEFILE]; 3703570Smckusick } 3713570Smckusick } 3723570Smckusick break; 3733570Smckusick case 'v': 37415685Speter if (len == 3 && !strncmp(word, "var", 3)) { 3753570Smckusick if (nest == 0) { 3763570Smckusick prt = FALSE; 3773570Smckusick if (!varopen) { 3783570Smckusick varopen = TRUE; 3793570Smckusick prt = TRUE; 3803570Smckusick } 3813570Smckusick curfile = files[VARFILE]; 3823570Smckusick } 3833570Smckusick } 3843570Smckusick break; 3853570Smckusick } 3863570Smckusick if (prt) 3873570Smckusick fprintf(curfile, "%.*s", len, word); 3883570Smckusick prt = TRUE; 3893570Smckusick ch1 = ' '; 3903570Smckusick } 3913570Smckusick } 3923570Smckusick 3933570Smckusick /* 3943570Smckusick * Print out the merged result 3953570Smckusick */ 3963570Smckusick printout() 3973570Smckusick { 3983570Smckusick FILE *fp; 3993570Smckusick int i; 4003570Smckusick char ch; 4013570Smckusick 4023570Smckusick for(i = 0; i < NUMFILES; i++) { 4033570Smckusick fp = freopen(names[i], "r", files[i]); 4043570Smckusick if (fp == NULL) 4053570Smckusick quit(names[i]); 4063570Smckusick ch = getc(fp); 4073570Smckusick while (!feof(fp)) { 4083570Smckusick putc(ch,stdout); 4093570Smckusick ch = getc(fp); 4103570Smckusick } 4113570Smckusick } 4123570Smckusick } 4133570Smckusick 4143570Smckusick /* 4153570Smckusick * Die gracefully 4163570Smckusick */ 4173570Smckusick quit(fp) 4183570Smckusick char *fp; 4193570Smckusick { 4203570Smckusick if (fp != NULL) 4213570Smckusick perror(fp); 422*47032Sdonn onintr(0); 4233570Smckusick exit(1); 4243570Smckusick } 425