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