em_pc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. /*
  2. * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. *
  4. * This product is part of the Amsterdam Compiler Kit.
  5. *
  6. * Permission to use, sell, duplicate or disclose this software must be
  7. * obtained in writing. Requests for such permissions may be sent to
  8. *
  9. * Dr. Andrew S. Tanenbaum
  10. * Wiskundig Seminarium
  11. * Vrije Universiteit
  12. * Postbox 7161
  13. * 1007 MC Amsterdam
  14. * The Netherlands
  15. *
  16. */
  17. /*
  18. * put all the pieces of the pascal part of the EM project together
  19. * original author: Johan Stevenson, Vrije Universiteit, Amsterdam
  20. * heavily modified by: Ed Keizer, Vrije Universiteit, Amsterdam
  21. */
  22. #include <stdio.h>
  23. #include <signal.h>
  24. #include <sys/types.h>
  25. #include <sys/dir.h>
  26. #include <em_path.h>
  27. #include <pc_size.h>
  28. #include <local.h>
  29. #define MAX_FLAG 40 /* The Max. no of '{' flags allowed */
  30. #define void int
  31. char def_pc_path[200] ;
  32. char def_err_path[200] ;
  33. char *pc_path = def_pc_path ;
  34. char *err_path = def_err_path ;
  35. int toterr;
  36. int parent;
  37. char *eeflag;
  38. char *vvflag = "-V";
  39. int no_pemflag = 0 ;
  40. char *pemflag[MAX_FLAG];
  41. char *eflag;
  42. char *wflag;
  43. int sizes[sz_last+1] = {
  44. 2, /* sz_addr */
  45. 8, /* sz_real */
  46. 0, /* sz_head */
  47. 512, /* sz_buff */
  48. 4096, /* sz_mset */
  49. 2, /* sz_iset */
  50. };
  51. #define CALLSIZE 60
  52. char *callvector[CALLSIZE];
  53. char **av;
  54. int ac;
  55. int fileargs; /* number of recognized, processed args */
  56. int flagargs;
  57. char *progname;
  58. char *source;
  59. #define CHARSIZE 2500
  60. #define CHARMARG 50
  61. char charbuf[CHARSIZE];
  62. char *charp = charbuf;
  63. char *tmp_dir = TMP_DIR;
  64. char *unique = "pcXXXXXX";
  65. char sigs[] = {
  66. SIGHUP,
  67. SIGINT,
  68. SIGTERM,
  69. 0
  70. };
  71. /*
  72. * forward function declarations
  73. */
  74. void finish();
  75. void pem();
  76. int list();
  77. char *flag();
  78. char *tempfile();
  79. char **initvector();
  80. char *basename();
  81. /*
  82. * used library routines and data
  83. */
  84. extern char *sys_errlist[];
  85. extern int errno;
  86. int atoi();
  87. void exit();
  88. void sleep();
  89. void execv();
  90. char *sbrk();
  91. int chdir();
  92. int fork();
  93. int wait();
  94. int getpid();
  95. int open();
  96. int close();
  97. int read();
  98. main(argc,argv) char **argv; {
  99. register char *p;
  100. char *files[3] ;
  101. for (p = sigs; *p; p++)
  102. if (signal(*p,finish) == SIG_IGN)
  103. signal(*p,SIG_IGN);
  104. ac = argc;
  105. av = argv;
  106. progname = *av++;
  107. init();
  108. while ( --ac>0 ) {
  109. p = *av++;
  110. if (*p == '-') {
  111. flagargs++;
  112. p = flag(p);
  113. } else {
  114. if ( fileargs>=3 ) fatal("Too many file arguments") ;
  115. files[fileargs++]= p;
  116. }
  117. }
  118. if ( fileargs!=3 ) fatal("Not enough arguments") ;
  119. source=files[2] ;
  120. pem(files[0],files[1]) ;
  121. finish();
  122. }
  123. char *flag(f) char *f; {
  124. register char *p;
  125. p = f+1;
  126. switch (*p++) {
  127. case 'e':
  128. eflag = f;
  129. break;
  130. case 'E':
  131. eeflag = f;
  132. break;
  133. case 'w':
  134. wflag = f;
  135. break;
  136. case 'V':
  137. vvflag = f;
  138. return(0);
  139. case '{':
  140. if ( no_pemflag>=MAX_FLAG ) {
  141. ermess("too many flags, ignored %s",f) ;
  142. } else {
  143. pemflag[no_pemflag++] = p;
  144. }
  145. return(0);
  146. case 'R':
  147. pc_path= p ;
  148. return 0 ;
  149. case 'r' :
  150. err_path= p ;
  151. return 0 ;
  152. default:
  153. return(f);
  154. }
  155. if (*p)
  156. fatal("bad flag %s",f);
  157. return(0);
  158. }
  159. initsizes(f) FILE *f; {
  160. register c, i;
  161. register char *p;
  162. p = vvflag + 2;
  163. while (c = *p++) {
  164. i = atoi(p);
  165. while (*p >= '0' && *p <= '9')
  166. p++;
  167. switch (c) {
  168. case 'p': sz_addr = i; continue;
  169. case 'f': sz_real = i; continue;
  170. case 'h': sz_head = i; continue;
  171. case 'b': sz_buff = i; continue;
  172. case 'm': sz_mset = i; continue;
  173. case 'j': sz_iset = i; continue;
  174. case 'w':
  175. case 'i': if (i == 2) continue; break;
  176. case 'l': if (i == 4) continue; break;
  177. }
  178. fatal("bad V-flag %s",vvflag);
  179. }
  180. if (sz_head == 0)
  181. sz_head = 6*sz_word + 2*sz_addr;
  182. for (i = 0; i <= sz_last; i++)
  183. fprintf(f, "%d\n",sizes[i]);
  184. }
  185. /* ------------------ calling sequences -------------------- */
  186. pem(p,q) char *p,*q; {
  187. register char **v,*d;
  188. int i;
  189. FILE *erfil;
  190. v = initvector(pc_path);
  191. d = tempfile('d');
  192. if ((erfil = fopen(d,"w")) == NULL)
  193. syserr(d);
  194. initsizes(erfil);
  195. fprintf(erfil,"%s\n",basename(source));
  196. for ( i=0 ; i<no_pemflag ; i++ ) fprintf(erfil,"%s\n",pemflag[i]);
  197. fclose(erfil);
  198. *v++ = q;
  199. *v++ = d;
  200. call(v,p,(char *)0);
  201. if (toterr == 0)
  202. if (list(p,d) < 0)
  203. toterr++;
  204. donewith(d);
  205. }
  206. /* ------------------- miscellaneous routines --------------- */
  207. char *basename(p) char *p; {
  208. register char *q;
  209. q = p;
  210. while (*q)
  211. if (*q++ == '/')
  212. p = q;
  213. return(p);
  214. }
  215. char *tempfile(suf) {
  216. register char *p,*q;
  217. register i;
  218. p = charp; q = tmp_dir;
  219. while (*p = *q++)
  220. p++;
  221. *p++ = '/';
  222. q = unique;
  223. while (*p = *q++)
  224. p++;
  225. i = fileargs;
  226. do
  227. *p++ = i % 10 + '0';
  228. while (i /= 10);
  229. *p++ = '.'; *p++ = suf; *p++ = '\0';
  230. q = charp; charp = p;
  231. return(q);
  232. }
  233. call(v,in,out) char **v,*in,*out; {
  234. register pid;
  235. int status;
  236. while ((parent = fork()) < 0)
  237. sleep(1);
  238. if (parent == 0) {
  239. if (in) {
  240. close(0);
  241. if (open(in,0) != 0)
  242. syserr(in);
  243. }
  244. if (out) {
  245. close(1);
  246. if (creat(out,0666) != 1)
  247. syserr(out);
  248. }
  249. *v = 0;
  250. execv(callvector[0],callvector+1);
  251. syserr(callvector[0]);
  252. }
  253. while ((pid = wait(&status)) != parent) {
  254. if (pid == -1)
  255. fatal("process %d disappeared",parent);
  256. fatal("unknown child %d died",pid);
  257. }
  258. if ((status & 0177) > 3) {
  259. /*
  260. if ((status & 0200) && tflag==0)
  261. unlink("core");
  262. */
  263. fatal("signal %d in %s. Ask an expert for help",
  264. status&0177,callvector[0]);
  265. }
  266. if (status & 0177400)
  267. toterr++;
  268. }
  269. char **initvector(path) char *path; {
  270. register char *p,**v;
  271. v = callvector;
  272. p = path;
  273. *v++ = p;
  274. *v++ = basename(p);
  275. return(v);
  276. }
  277. finish() {
  278. register char *p,*q;
  279. register fd;
  280. struct direct dir;
  281. signal(SIGINT,SIG_IGN);
  282. if (parent != 0) {
  283. chdir(tmp_dir);
  284. fd = open(".",0);
  285. while (read(fd,(char *) &dir,sizeof dir) == sizeof dir) {
  286. if (dir.d_ino == 0)
  287. continue;
  288. p = unique;
  289. q = dir.d_name;
  290. while (*p++ == *q++)
  291. if (*p == '\0') {
  292. unlink(dir.d_name);
  293. break;
  294. }
  295. }
  296. close(fd);
  297. }
  298. exit(toterr ? -1 : 0);
  299. }
  300. donewith(p) char *p; {
  301. if (p >= charbuf && p < &charbuf[CHARSIZE])
  302. unlink(p);
  303. }
  304. init() {
  305. register char *p,*s ;
  306. register i,fd;
  307. if ((fd = open(tmp_dir,0)) < 0)
  308. tmp_dir = ".";
  309. close(fd);
  310. p= def_pc_path ;
  311. s= EM_DIR ; while ( *p++ = *s++ ) ; *p='/' ;
  312. s= PEM_PATH ; while ( *p++ = *s++ ) ;
  313. p= def_err_path ;
  314. s= EM_DIR ; while ( *p++ = *s++ ) ; *p='/' ;
  315. s= ERR_PATH ; while ( *p++ = *s++ ) ;
  316. p = unique+2;
  317. parent = i = getpid();
  318. do
  319. *p++ = i % 10 + '0';
  320. while (i /= 10);
  321. *p++ = '.'; *p = '\0';
  322. }
  323. /* ------------------- pascal listing ----------------------- */
  324. #define MAXERNO 300
  325. #define MAXERRLIST 10
  326. #define IDMAX 8
  327. struct errec {
  328. int erno;
  329. char mess[IDMAX+1];
  330. int mesi;
  331. int chno;
  332. int lino;
  333. };
  334. struct errec curr;
  335. struct errec next;
  336. int *index = 0;
  337. int maxerno;
  338. int errerr;
  339. int errfat;
  340. int listlino;
  341. int listorig;
  342. int listrela;
  343. char *listfnam;
  344. FILE *inpfil;
  345. FILE *mesfil;
  346. FILE *errfil;
  347. int errorline();
  348. int geterrec();
  349. int nexterror();
  350. int list(p,q) char *p,*q; {
  351. if ((errfil = fopen(q,"r")) == NULL)
  352. syserr(q);
  353. if (geterrec() == 0)
  354. if (eeflag==0) {
  355. fclose(errfil);
  356. return(0);
  357. }
  358. if (index == 0) {
  359. index = (int *) sbrk(MAXERNO * sizeof index[0]);
  360. fillindex();
  361. }
  362. if ((inpfil = fopen(p,"r")) == NULL)
  363. syserr(p);
  364. errerr = 0;
  365. errfat = 0;
  366. listlino = 0;
  367. listorig = 0;
  368. listrela = 0;
  369. listfnam = source;
  370. if (eeflag)
  371. listfull();
  372. else if (eflag)
  373. listpartial();
  374. else
  375. listshort();
  376. fclose(errfil);
  377. fclose(inpfil);
  378. fflush(stdout);
  379. return(errfat ? -1 : 1);
  380. }
  381. listshort() {
  382. while (nexterror()) {
  383. while (listlino < curr.lino)
  384. nextline(0);
  385. printf("%s, line %d: ",listfnam,listrela);
  386. string(&curr);
  387. }
  388. }
  389. listfull() {
  390. if (nexterror())
  391. do {
  392. do {
  393. nextline(1);
  394. } while (listlino < curr.lino);
  395. } while (errorline());
  396. while (nextline(1))
  397. ;
  398. }
  399. listpartial() {
  400. if (nexterror())
  401. do {
  402. do {
  403. nextline(listlino >= curr.lino-2);
  404. } while (listlino < curr.lino);
  405. } while (errorline());
  406. }
  407. int nextline(printing) {
  408. register ch;
  409. listlino++;
  410. ch = getc(inpfil);
  411. if (ch == '#') {
  412. if (lineline(printing) == 0)
  413. fatal("bad line directive");
  414. return(1);
  415. }
  416. listrela++;
  417. if (listfnam == source)
  418. listorig++;
  419. if (ch != EOF) {
  420. if (printing)
  421. printf("%5d\t",listorig);
  422. do {
  423. if (printing)
  424. putchar(ch);
  425. if (ch == '\n')
  426. return(1);
  427. } while ((ch = getc(inpfil)) != EOF);
  428. }
  429. return(0);
  430. }
  431. lineline(printing) {
  432. register ch;
  433. register char *p,*q;
  434. static char line[100];
  435. p = line;
  436. while ((ch = getc(inpfil)) != '\n') {
  437. if (ch == EOF || p == &line[100-1])
  438. return(0);
  439. *p++ = ch;
  440. }
  441. *p = '\0'; p = line;
  442. if (printing)
  443. printf("\t#%s\n",p);
  444. if ((listrela = atoi(p)-1) < 0)
  445. return(0);
  446. while ((ch = *p++) != '"')
  447. if (ch == '\0')
  448. return(0);
  449. q = p;
  450. while (ch = *p++) {
  451. if (ch == '"') {
  452. *--p = '\0';
  453. if ( source ) {
  454. listfnam = strcmp(q,source)==0 ? source : q;
  455. return(1);
  456. }
  457. source=q ; listfnam=q ;
  458. return 1 ;
  459. }
  460. if (ch == '/')
  461. q = p;
  462. }
  463. return(0);
  464. }
  465. int errorline() {
  466. register c;
  467. register struct errec *p,*q;
  468. struct errec lerr[MAXERRLIST];
  469. int goon;
  470. printf("*** ***");
  471. p = lerr;
  472. c = 0;
  473. do {
  474. if (c < curr.chno) {
  475. printf("%*c",curr.chno-c,'^');
  476. c = curr.chno;
  477. }
  478. if (p < &lerr[MAXERRLIST])
  479. *p++ = curr;
  480. goon = nexterror();
  481. } while (goon && curr.lino==listlino);
  482. putchar('\n');
  483. for (q = lerr; q < p; q++)
  484. string(q);
  485. putchar('\n');
  486. return(goon);
  487. }
  488. int geterrec() {
  489. register ch;
  490. register char *p;
  491. ch = getc(errfil);
  492. next.erno = 0;
  493. next.mesi = -1;
  494. next.mess[0] = '\0';
  495. if (ch == EOF)
  496. return(0);
  497. if (ch >= '0' && ch <= '9') {
  498. ch = getnum(ch,&next.mesi);
  499. } else if (ch == '\'') {
  500. p = next.mess;
  501. while ((ch = getc(errfil)) != ' ' && ch != EOF)
  502. if (p < &next.mess[IDMAX])
  503. *p++ = ch;
  504. *p = '\0';
  505. }
  506. ch = getnum(ch, &next.erno);
  507. ch = getnum(ch, &next.lino);
  508. ch = getnum(ch, &next.chno);
  509. if (ch != '\n')
  510. fatal("bad error line");
  511. return(1);
  512. }
  513. int getnum(ch, ip) register ch; register *ip; {
  514. register neg;
  515. *ip = 0;
  516. while (ch == ' ')
  517. ch = getc(errfil);
  518. if (neg = ch=='-')
  519. ch = getc(errfil);
  520. while (ch >= '0' && ch <= '9') {
  521. *ip = *ip * 10 - '0' + ch;
  522. ch = getc(errfil);
  523. }
  524. if (neg)
  525. *ip = -(*ip);
  526. return(ch);
  527. }
  528. int nexterror() {
  529. do { /* skip warnings if wflag */
  530. curr = next;
  531. if (curr.erno == 0)
  532. return(0);
  533. for (;;) {
  534. if (geterrec() == 0)
  535. break;
  536. if (next.lino != curr.lino || next.chno != curr.chno)
  537. break;
  538. if (curr.erno < 0 && next.erno > 0)
  539. /* promote warnings if they cause fatals */
  540. curr.erno = -curr.erno;
  541. if (next.mess[0] != '\0' || next.mesi != -1)
  542. /* give all parameterized errors */
  543. break;
  544. if (curr.mess[0] != '\0' || curr.mesi != -1)
  545. /* and at least a non-parameterized one */
  546. break;
  547. }
  548. } while (curr.erno < 0 && wflag != 0);
  549. return(1);
  550. }
  551. fillindex() {
  552. register *ip,n,c;
  553. if ((mesfil = fopen(err_path,"r")) == NULL)
  554. syserr(err_path);
  555. ip = index;
  556. *ip++ = 0;
  557. n = 0;
  558. while ((c = getc(mesfil)) != EOF) {
  559. n++;
  560. if (c == '\n') {
  561. *ip++ = n;
  562. if (ip > &index[MAXERNO])
  563. fatal("too many errors on %s",err_path);
  564. }
  565. }
  566. maxerno = ip - index;
  567. }
  568. string(ep) register struct errec *ep; {
  569. register i,n;
  570. errerr++;
  571. if ((i = ep->erno) < 0) {
  572. i = -i;
  573. printf("Warning: ");
  574. } else
  575. errfat++;
  576. if (i == 0 || i >= maxerno)
  577. fatal("bad error number %d",i);
  578. n = index[i] - index[i-1];
  579. fseek(mesfil,(long)index[i-1],0);
  580. while (--n >= 0) {
  581. i = getc(mesfil);
  582. if (i == '%' && --n>=0) {
  583. i = getc(mesfil);
  584. if (i == 'i')
  585. printf("%d", ep->mesi);
  586. else if (i == 's')
  587. printf("%s", ep->mess);
  588. else
  589. putchar(i);
  590. } else
  591. putchar(i);
  592. }
  593. }
  594. /* ------------------- error routines -------------------------- */
  595. /* VARARGS1 */
  596. void ermess(s,a1,a2,a3,a4) char *s; {
  597. fprintf(stderr,"%s: ",progname);
  598. fprintf(stderr,s,a1,a2,a3,a4);
  599. fprintf(stderr,"\n");
  600. }
  601. syserr(s) char *s; {
  602. fatal("%s: %s",s,sys_errlist[errno]);
  603. }
  604. /* VARARGS1 */
  605. void fatal(s,a1,a2,a3,a4) char *s; {
  606. ermess(s,a1,a2,a3,a4);
  607. toterr++;
  608. finish();
  609. }