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