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