/* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)pmerge.c 5.1 (Berkeley) 6/5/85"; #endif not lint #include #include #include #define PRGFILE 0 #define LABELFILE 1 #define CONSTFILE 2 #define TYPEFILE 3 #define VARFILE 4 #define RTNFILE 5 #define BODYFILE 6 #define NUMFILES 7 #define TRUE 1 #define FALSE 0 #define MAXINCL 9 #define MAXNAM 75 #define TMPNAME "/usr/tmp/MGXXXXXX" FILE *files[NUMFILES]; char *names[NUMFILES]; FILE *curfile; /* current output file */ FILE *fopen(); char labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE; char *mktemp(); char *malloc(); /* * Remove temporary files if interrupted */ onintr() { int i; for (i = 0; i < NUMFILES; i++) if (files[i] != NULL) unlink(names[i]); } /* * Program to merge separately compiled pascal modules into a * single standard Pascal program. */ main(argc, argv) long argc; char **argv; { FILE *incl[MAXINCL]; /* include stack */ long inclcnt = 0; /* incl index */ char *name[MAXNAM]; /* include names seen so far */ long namcnt = 0; /* next name ptr slot available */ char *nambuf; /* string table for names */ char line[BUFSIZ]; /* input line buffer */ char *next; /* next name space available */ FILE *input = stdin; /* current input file */ long ac = 0; /* argv index */ char **cpp, *cp, *fp;/* char ptrs */ char quote; /* include quote character */ int i; /* index var */ for (i = 0; i < MAXNAM ; i++) name[i] = 0; signal(SIGINT, onintr); curfile = files[PRGFILE] = fopen(names[PRGFILE] = mktemp(TMPNAME), "w"); files[LABELFILE] = fopen(names[LABELFILE] = mktemp(TMPNAME), "w"); files[CONSTFILE] = fopen(names[CONSTFILE] = mktemp(TMPNAME), "w"); files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(TMPNAME), "w"); files[VARFILE] = fopen(names[VARFILE] = mktemp(TMPNAME), "w"); files[RTNFILE] = fopen(names[RTNFILE] = mktemp(TMPNAME), "w"); files[BODYFILE] = fopen(names[BODYFILE] = mktemp(TMPNAME), "w"); for (i = 0; i < NUMFILES; i++) if (files[i] == NULL) quit(names[i]); if ((nambuf = malloc(BUFSIZ)) == NULL) { fputs("no space for string table\n", stderr); quit(NULL); } next = nambuf; name[namcnt] = next; for(;;) { if (inclcnt > 0) { inclcnt--; fclose(input); input = incl[inclcnt]; } else if (++ac < argc) { input = freopen(argv[ac], "r", input); if (input == NULL) quit(argv[ac]); } else { printout(); onintr(); exit(0); } fgets(line, BUFSIZ, input); while (!feof(input)) { if (line[0] != '#') { split(line); fgets(line, BUFSIZ, input); continue; } for (cp = &line[1]; isspace(*cp); cp++) /* void */; if (strncmp("include", cp, 7)) goto bad; for (cp += 7; isspace(*cp); cp++) /* void */; if (*cp != '\'' && *cp != '"') goto bad; if (&nambuf[BUFSIZ] < next + strlen(cp)) { if ((nambuf = malloc(BUFSIZ)) == NULL) { fputs("no space for string table\n", stderr); quit(NULL); } next = nambuf; name[namcnt] = next; } for (fp = next, quote = *cp++; *cp != '\0' && *cp != quote; ) *fp++ = *cp++; if (*cp != quote && (fp[-1] != 'i' || fp[-1] != 'h') && (fp[-2] != '.')) goto bad; *fp++ = '\0'; for (cpp = name; *cpp < next && strcmp(*cpp, next); ) cpp++; if (*cpp == next) { if (inclcnt == MAXINCL) { fputs("include table overflow\n", stderr); quit(NULL); } if (++namcnt == MAXNAM) { fputs("include name table overflow\n", stderr); quit(NULL); } incl[inclcnt] = input; inclcnt++; input = fopen(next, "r"); if (input == NULL) quit(next); next = fp; name[namcnt] = next; } fgets(line, BUFSIZ, input); } } bad: fputs("bad include format:", stderr); fputs(line, stderr); quit(NULL); } /* * Split up output into the approprite files */ char incom = FALSE; /* TRUE => in comment */ char incur = FALSE; /* TRUE => in (* *) style comment */ char inbrac = FALSE; /* TRUE => in { } style comment */ char instr = FALSE; /* TRUE => in quoted string */ char inprog = FALSE; /* TRUE => program statement has been found */ int beginnest = 0; /* routine nesting level */ int nest = 0; /* begin block nesting level */ int paren_level = 0; /* nesting level of parentheses */ split(line) char *line; { char ch1, *cp; /* input window */ char *word; /* ptr to current word */ int len; /* length of current word */ char prt = TRUE; /* TRUE => print current word */ ch1 = ' '; cp = line; while (*cp) { switch(*cp) { case '(': if (incom) break; if (*(cp+1) == '*') { fputc(*cp, curfile); cp++; incom = TRUE; incur = TRUE; } else { paren_level++; } break; case ')': if (incur && ch1 == '*') { incom = FALSE; incur = FALSE; } else if (!incom) { paren_level--; } break; case '{': if (!incom) { inbrac = TRUE; incom = TRUE; } break; case '}': if (inbrac) { inbrac = FALSE; incom = FALSE; } break; case '\'': if (!incom) { incom = TRUE; instr = TRUE; } else if (instr) { incom = FALSE; instr = FALSE; } break; } if (incom || !isalpha(*cp)) { fputc(*cp, curfile); ch1 = *cp++; continue; } word = cp; while (isalnum(*cp)) cp++; len = cp - word; switch (*word) { case 'b': if (len == 5 && !strncmp(word, "begin", 5)) { if (nest == 0 && beginnest == 0) { if (inprog != 1) { fprintf(stderr, "improper program body"); quit(NULL); } curfile = files[BODYFILE]; } else { beginnest++; } } break; case 'c': if (len == 4 && !strncmp(word, "case", 4)) { if (beginnest > 0) { beginnest++; } break; } if (len == 5 && !strncmp(word, "const", 5)) { if (nest == 0) { prt = FALSE; if (!constopen) { constopen = TRUE; prt = TRUE; } curfile = files[CONSTFILE]; } } break; case 'e': if (len == 3 && !strncmp(word, "end", 3)) { if (beginnest == 1) { nest--; } if (beginnest > 0) { beginnest--; } if (nest < 0) { if (inprog == 1) { inprog = 0; nest = 0; } else { fprintf(stderr, "too many end statements"); quit(NULL); } } break; } if (len == 8 && !strncmp(word, "external", 8)) { fputs("forward", curfile); prt = FALSE; if (paren_level == 0) { nest--; } } break; case 'f': if (len == 8 && !strncmp(word, "function", 8)) { if (nest == 0) { curfile = files[RTNFILE]; } if (paren_level == 0) { nest++; } break; } if (len == 7 && !strncmp(word, "forward", 7)) { if (paren_level == 0) { nest--; } } break; case 'l': if (len == 5 && !strncmp(word, "label", 5)) { if (nest == 0) { prt = FALSE; if (!labelopen) { labelopen = TRUE; prt = TRUE; } curfile = files[LABELFILE]; } } break; case 'p': if (len == 9 && !strncmp(word, "procedure", 9)) { if (nest == 0) { curfile = files[RTNFILE]; } if (paren_level == 0) { nest++; } break; } if (len == 7 && !strncmp(word, "program", 7)) { if (nest != 0) { fprintf(stderr, "improper program nesting"); quit(NULL); } inprog = 1; curfile = files[PRGFILE]; } break; case 't': if (len == 4 && !strncmp(word, "type", 4)) { if (nest == 0) { prt = FALSE; if (!typeopen) { typeopen = TRUE; prt = TRUE; } curfile = files[TYPEFILE]; } } break; case 'v': if (len == 3 && !strncmp(word, "var", 3)) { if (nest == 0) { prt = FALSE; if (!varopen) { varopen = TRUE; prt = TRUE; } curfile = files[VARFILE]; } } break; } if (prt) fprintf(curfile, "%.*s", len, word); prt = TRUE; ch1 = ' '; } } /* * Print out the merged result */ printout() { FILE *fp; int i; char ch; for(i = 0; i < NUMFILES; i++) { fp = freopen(names[i], "r", files[i]); if (fp == NULL) quit(names[i]); ch = getc(fp); while (!feof(fp)) { putc(ch,stdout); ch = getc(fp); } } } /* * Die gracefully */ quit(fp) char *fp; { if (fp != NULL) perror(fp); onintr(); exit(1); }