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