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