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