1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)pmerge.c 5.1 (Berkeley) 6/5/85"; 15: #endif not lint 16: 17: #include <ctype.h> 18: #include <stdio.h> 19: #include <signal.h> 20: 21: #define PRGFILE 0 22: #define LABELFILE 1 23: #define CONSTFILE 2 24: #define TYPEFILE 3 25: #define VARFILE 4 26: #define RTNFILE 5 27: #define BODYFILE 6 28: #define NUMFILES 7 29: 30: #define TRUE 1 31: #define FALSE 0 32: #define MAXINCL 9 33: #define MAXNAM 75 34: #define TMPNAME "/usr/tmp/MGXXXXXX" 35: 36: FILE *files[NUMFILES]; 37: char *names[NUMFILES]; 38: FILE *curfile; /* current output file */ 39: FILE *fopen(); 40: char labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE; 41: char *mktemp(); 42: char *malloc(); 43: 44: /* 45: * Remove temporary files if interrupted 46: */ 47: onintr() 48: { 49: int i; 50: 51: for (i = 0; i < NUMFILES; i++) 52: if (files[i] != NULL) 53: unlink(names[i]); 54: } 55: 56: /* 57: * Program to merge separately compiled pascal modules into a 58: * single standard Pascal program. 59: */ 60: main(argc, argv) 61: long argc; 62: char **argv; 63: { 64: FILE *incl[MAXINCL]; /* include stack */ 65: long inclcnt = 0; /* incl index */ 66: char *name[MAXNAM]; /* include names seen so far */ 67: long namcnt = 0; /* next name ptr slot available */ 68: char *nambuf; /* string table for names */ 69: char line[BUFSIZ]; /* input line buffer */ 70: char *next; /* next name space available */ 71: FILE *input = stdin; /* current input file */ 72: long ac = 0; /* argv index */ 73: char **cpp, *cp, *fp;/* char ptrs */ 74: char quote; /* include quote character */ 75: int i; /* index var */ 76: 77: for (i = 0; i < MAXNAM ; i++) 78: name[i] = 0; 79: 80: signal(SIGINT, onintr); 81: 82: curfile = files[PRGFILE] = fopen(names[PRGFILE] = mktemp(TMPNAME), "w"); 83: files[LABELFILE] = fopen(names[LABELFILE] = mktemp(TMPNAME), "w"); 84: files[CONSTFILE] = fopen(names[CONSTFILE] = mktemp(TMPNAME), "w"); 85: files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(TMPNAME), "w"); 86: files[VARFILE] = fopen(names[VARFILE] = mktemp(TMPNAME), "w"); 87: files[RTNFILE] = fopen(names[RTNFILE] = mktemp(TMPNAME), "w"); 88: files[BODYFILE] = fopen(names[BODYFILE] = mktemp(TMPNAME), "w"); 89: 90: for (i = 0; i < NUMFILES; i++) 91: if (files[i] == NULL) 92: quit(names[i]); 93: if ((nambuf = malloc(BUFSIZ)) == NULL) { 94: fputs("no space for string table\n", stderr); 95: quit(NULL); 96: } 97: next = nambuf; 98: name[namcnt] = next; 99: for(;;) { 100: if (inclcnt > 0) { 101: inclcnt--; 102: fclose(input); 103: input = incl[inclcnt]; 104: } else if (++ac < argc) { 105: input = freopen(argv[ac], "r", input); 106: if (input == NULL) 107: quit(argv[ac]); 108: } else { 109: printout(); 110: onintr(); 111: exit(0); 112: } 113: fgets(line, BUFSIZ, input); 114: while (!feof(input)) { 115: if (line[0] != '#') { 116: split(line); 117: fgets(line, BUFSIZ, input); 118: continue; 119: } 120: for (cp = &line[1]; isspace(*cp); cp++) 121: /* void */; 122: if (strncmp("include", cp, 7)) 123: goto bad; 124: for (cp += 7; isspace(*cp); cp++) 125: /* void */; 126: if (*cp != '\'' && *cp != '"') 127: goto bad; 128: if (&nambuf[BUFSIZ] < next + strlen(cp)) { 129: if ((nambuf = malloc(BUFSIZ)) == NULL) { 130: fputs("no space for string table\n", 131: stderr); 132: quit(NULL); 133: } 134: next = nambuf; 135: name[namcnt] = next; 136: } 137: for (fp = next, quote = *cp++; 138: *cp != '\0' && *cp != quote; ) 139: *fp++ = *cp++; 140: if (*cp != quote && 141: (fp[-1] != 'i' || fp[-1] != 'h') && 142: (fp[-2] != '.')) 143: goto bad; 144: *fp++ = '\0'; 145: for (cpp = name; *cpp < next && strcmp(*cpp, next); ) 146: cpp++; 147: if (*cpp == next) { 148: if (inclcnt == MAXINCL) { 149: fputs("include table overflow\n", 150: stderr); 151: quit(NULL); 152: } 153: if (++namcnt == MAXNAM) { 154: fputs("include name table overflow\n", 155: stderr); 156: quit(NULL); 157: } 158: incl[inclcnt] = input; 159: inclcnt++; 160: input = fopen(next, "r"); 161: if (input == NULL) 162: quit(next); 163: next = fp; 164: name[namcnt] = next; 165: } 166: fgets(line, BUFSIZ, input); 167: } 168: } 169: bad: 170: fputs("bad include format:", stderr); 171: fputs(line, stderr); 172: quit(NULL); 173: } 174: 175: /* 176: * Split up output into the approprite files 177: */ 178: char incom = FALSE; /* TRUE => in comment */ 179: char incur = FALSE; /* TRUE => in (* *) style comment */ 180: char inbrac = FALSE; /* TRUE => in { } style comment */ 181: char instr = FALSE; /* TRUE => in quoted string */ 182: char inprog = FALSE; /* TRUE => program statement has been found */ 183: int beginnest = 0; /* routine nesting level */ 184: int nest = 0; /* begin block nesting level */ 185: int paren_level = 0; /* nesting level of parentheses */ 186: 187: split(line) 188: char *line; 189: { 190: char ch1, *cp; /* input window */ 191: char *word; /* ptr to current word */ 192: int len; /* length of current word */ 193: char prt = TRUE; /* TRUE => print current word */ 194: 195: ch1 = ' '; 196: cp = line; 197: while (*cp) { 198: switch(*cp) { 199: case '(': 200: if (incom) 201: break; 202: if (*(cp+1) == '*') { 203: fputc(*cp, curfile); 204: cp++; 205: incom = TRUE; 206: incur = TRUE; 207: } else { 208: paren_level++; 209: } 210: break; 211: case ')': 212: if (incur && ch1 == '*') { 213: incom = FALSE; 214: incur = FALSE; 215: } else if (!incom) { 216: paren_level--; 217: } 218: break; 219: case '{': 220: if (!incom) { 221: inbrac = TRUE; 222: incom = TRUE; 223: } 224: break; 225: case '}': 226: if (inbrac) { 227: inbrac = FALSE; 228: incom = FALSE; 229: } 230: break; 231: case '\'': 232: if (!incom) { 233: incom = TRUE; 234: instr = TRUE; 235: } else if (instr) { 236: incom = FALSE; 237: instr = FALSE; 238: } 239: break; 240: } 241: if (incom || !isalpha(*cp)) { 242: fputc(*cp, curfile); 243: ch1 = *cp++; 244: continue; 245: } 246: word = cp; 247: while (isalnum(*cp)) 248: cp++; 249: len = cp - word; 250: switch (*word) { 251: case 'b': 252: if (len == 5 && !strncmp(word, "begin", 5)) { 253: if (nest == 0 && beginnest == 0) { 254: if (inprog != 1) { 255: fprintf(stderr, 256: "improper program body"); 257: quit(NULL); 258: } 259: curfile = files[BODYFILE]; 260: } else { 261: beginnest++; 262: } 263: } 264: break; 265: case 'c': 266: if (len == 4 && !strncmp(word, "case", 4)) { 267: if (beginnest > 0) { 268: beginnest++; 269: } 270: break; 271: } 272: if (len == 5 && !strncmp(word, "const", 5)) { 273: if (nest == 0) { 274: prt = FALSE; 275: if (!constopen) { 276: constopen = TRUE; 277: prt = TRUE; 278: } 279: curfile = files[CONSTFILE]; 280: } 281: } 282: break; 283: case 'e': 284: if (len == 3 && !strncmp(word, "end", 3)) { 285: if (beginnest == 1) { 286: nest--; 287: } 288: if (beginnest > 0) { 289: beginnest--; 290: } 291: if (nest < 0) { 292: if (inprog == 1) { 293: inprog = 0; 294: nest = 0; 295: } else { 296: fprintf(stderr, "too many end statements"); 297: quit(NULL); 298: } 299: } 300: break; 301: } 302: if (len == 8 && !strncmp(word, "external", 8)) { 303: fputs("forward", curfile); 304: prt = FALSE; 305: if (paren_level == 0) { 306: nest--; 307: } 308: } 309: break; 310: case 'f': 311: if (len == 8 && !strncmp(word, "function", 8)) { 312: if (nest == 0) { 313: curfile = files[RTNFILE]; 314: } 315: if (paren_level == 0) { 316: nest++; 317: } 318: break; 319: } 320: if (len == 7 && !strncmp(word, "forward", 7)) { 321: if (paren_level == 0) { 322: nest--; 323: } 324: } 325: break; 326: case 'l': 327: if (len == 5 && !strncmp(word, "label", 5)) { 328: if (nest == 0) { 329: prt = FALSE; 330: if (!labelopen) { 331: labelopen = TRUE; 332: prt = TRUE; 333: } 334: curfile = files[LABELFILE]; 335: } 336: } 337: break; 338: case 'p': 339: if (len == 9 && !strncmp(word, "procedure", 9)) { 340: if (nest == 0) { 341: curfile = files[RTNFILE]; 342: } 343: if (paren_level == 0) { 344: nest++; 345: } 346: break; 347: } 348: if (len == 7 && !strncmp(word, "program", 7)) { 349: if (nest != 0) { 350: fprintf(stderr, "improper program nesting"); 351: quit(NULL); 352: } 353: inprog = 1; 354: curfile = files[PRGFILE]; 355: } 356: break; 357: case 't': 358: if (len == 4 && !strncmp(word, "type", 4)) { 359: if (nest == 0) { 360: prt = FALSE; 361: if (!typeopen) { 362: typeopen = TRUE; 363: prt = TRUE; 364: } 365: curfile = files[TYPEFILE]; 366: } 367: } 368: break; 369: case 'v': 370: if (len == 3 && !strncmp(word, "var", 3)) { 371: if (nest == 0) { 372: prt = FALSE; 373: if (!varopen) { 374: varopen = TRUE; 375: prt = TRUE; 376: } 377: curfile = files[VARFILE]; 378: } 379: } 380: break; 381: } 382: if (prt) 383: fprintf(curfile, "%.*s", len, word); 384: prt = TRUE; 385: ch1 = ' '; 386: } 387: } 388: 389: /* 390: * Print out the merged result 391: */ 392: printout() 393: { 394: FILE *fp; 395: int i; 396: char ch; 397: 398: for(i = 0; i < NUMFILES; i++) { 399: fp = freopen(names[i], "r", files[i]); 400: if (fp == NULL) 401: quit(names[i]); 402: ch = getc(fp); 403: while (!feof(fp)) { 404: putc(ch,stdout); 405: ch = getc(fp); 406: } 407: } 408: } 409: 410: /* 411: * Die gracefully 412: */ 413: quit(fp) 414: char *fp; 415: { 416: if (fp != NULL) 417: perror(fp); 418: onintr(); 419: exit(1); 420: }