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