comm4.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /* $Id$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. */
  6. /* @(#)comm4.c 1.6 */
  7. /*
  8. * Micro processor assembler framework written by
  9. * Johan Stevenson, Vrije Universiteit, Amsterdam
  10. * modified by
  11. * Johan Stevenson, Han Schaminee and Hans de Vries
  12. * Philips S&I, T&M, PMDS, Eindhoven
  13. */
  14. #include "comm0.h"
  15. #include "comm1.h"
  16. #include "y.tab.h"
  17. extern YYSTYPE yylval;
  18. /* ========== Machine independent C routines ========== */
  19. void stop(int signal)
  20. {
  21. #if DEBUG < 2
  22. unlink(temppath);
  23. #ifdef LISTING
  24. unlink(listpath);
  25. #endif
  26. #endif
  27. exit(nerrors != 0);
  28. }
  29. int main(int argc, char *argv[])
  30. {
  31. char *p;
  32. int i;
  33. static char sigs[] = {
  34. SIGHUP, SIGINT, SIGQUIT, SIGTERM, 0
  35. };
  36. /* the next test should be performed by the
  37. * preprocessor, but it cannot, so it is performed by the compiler.
  38. */
  39. switch(0) {
  40. case 1: break;
  41. case (S_ETC|S_COM|S_VAR|S_DOT) != S_ETC : break;
  42. }
  43. progname = *argv++; argc--;
  44. for (p = sigs; (i = *p++); )
  45. if (signal(i, SIG_IGN) != SIG_IGN)
  46. signal(i, stop);
  47. for (i = 0; i < argc; i++) {
  48. p = argv[i];
  49. if (*p++ != '-')
  50. continue;
  51. switch (*p++) {
  52. case 'o':
  53. if (*p != '\0') {
  54. aoutpath = p;
  55. break;
  56. }
  57. argv[i] = 0;
  58. if (++i >= argc)
  59. fatal("-o needs filename");
  60. aoutpath = argv[i];
  61. break;
  62. case 'T':
  63. if (*p != '\0') {
  64. extern char *tmp_dir;
  65. tmp_dir = p;
  66. }
  67. break;
  68. case 'd':
  69. #ifdef LISTING
  70. dflag = 0;
  71. while (*p >= '0' && *p <= '7')
  72. dflag = (dflag << 3) + *p++ - '0';
  73. if ((dflag & 0777) == 0)
  74. dflag |= 0700;
  75. dflag &= ~4;
  76. #endif
  77. break;
  78. case 's':
  79. sflag = 0;
  80. while (*p >= '0' && *p <= '7')
  81. sflag = (sflag << 3) + *p++ - '0';
  82. break;
  83. case 'r':
  84. #ifdef RELOCATION
  85. #ifdef ASLD
  86. rflag = 1;
  87. #endif /* ASLD */
  88. #endif /* RELOCATION */
  89. break;
  90. case 'b':
  91. #ifdef THREE_PASS
  92. bflag = 1;
  93. #endif
  94. break;
  95. #ifndef ASLD
  96. case 'u':
  97. case '\0':
  98. uflag = 1;
  99. break;
  100. #endif
  101. default:
  102. continue;
  103. }
  104. argv[i] = 0;
  105. }
  106. #ifdef RELOCATION
  107. if (rflag)
  108. sflag |= SYM_SCT;
  109. #endif /* RELOCATION */
  110. pass_1(argc, argv);
  111. #ifdef THREE_PASS
  112. pass_23(PASS_2);
  113. #endif
  114. pass_23(PASS_3);
  115. wr_close();
  116. stop(0);
  117. return 0;
  118. }
  119. /* ---------- pass 1: arguments, modules, archives ---------- */
  120. int pass_1(int argc, char *argv[])
  121. {
  122. char *p;
  123. item_t *ip;
  124. #ifdef ASLD
  125. char armagic[2];
  126. #else
  127. int nfile = 0;
  128. #endif
  129. #ifdef THREE_PASS
  130. bitindex = -1;
  131. nbits = BITCHUNK;
  132. #endif
  133. tempfile = fftemp(temppath, "asTXXXXXX");
  134. #ifdef LISTING
  135. listmode = dflag;
  136. if (listmode & 0440)
  137. listfile = fftemp(listpath, "asLXXXXXX");
  138. #endif
  139. for (ip = keytab; ip->i_type; ip++)
  140. item_insert(ip, H_KEY+hash(ip->i_name));
  141. machstart(PASS_1);
  142. while (--argc >= 0) {
  143. p = *argv++;
  144. if (p == 0)
  145. continue;
  146. #ifndef ASLD
  147. if (nfile != 0)
  148. fatal("second source file %s", p);
  149. nfile++;
  150. #else
  151. if (p[0] == '-' && p[1] == '\0') {
  152. input = stdin;
  153. parse("STDIN");
  154. continue;
  155. }
  156. #endif
  157. if ((input = fopen(p, "r")) == NULL)
  158. fatal("can't open %s", p);
  159. #ifdef ASLD
  160. if (
  161. fread(armagic, 2, 1, input) == 1
  162. &&
  163. ((armagic[0]&0377) |
  164. ((unsigned)(armagic[1]&0377)<<8)) == ARMAG
  165. ) {
  166. archive();
  167. fclose(input);
  168. continue;
  169. }
  170. rewind(input);
  171. #endif
  172. parse(p);
  173. fclose(input);
  174. }
  175. #ifndef ASLD
  176. if (nfile == 0) {
  177. input = stdin;
  178. parse("STDIN");
  179. }
  180. #endif
  181. commfinish();
  182. machfinish(PASS_1);
  183. #ifdef ASLD
  184. if (unresolved) {
  185. int i;
  186. nerrors++;
  187. fflush(stdout);
  188. fprintf(stderr, "unresolved references:\n");
  189. for (i = 0; i < H_SIZE; i++) {
  190. ip = hashtab[H_GLOBAL+i];
  191. while (ip != 0) {
  192. if ((ip->i_type & (S_EXT|S_TYP)) == (S_EXT|S_UND))
  193. fprintf(stderr, "\t%s\n", ip->i_name);
  194. ip = ip->i_next;
  195. }
  196. }
  197. }
  198. #else
  199. if (unresolved)
  200. outhead.oh_flags |= HF_LINK;
  201. /*
  202. if (nfile == 0)
  203. fatal("no source file");
  204. */
  205. #endif
  206. return 0;
  207. }
  208. #ifdef ASLD
  209. void archive()
  210. {
  211. long offset;
  212. struct ar_hdr header;
  213. char getsize[AR_TOTAL];
  214. archmode++;
  215. offset = 2;
  216. for (;;) {
  217. if (unresolved == 0)
  218. break;
  219. fseek(input,offset,0);
  220. if (fread(getsize,AR_TOTAL,1,input) != 1)
  221. break;
  222. offset += AR_TOTAL;
  223. strncpy(header.ar_name,getsize,sizeof header.ar_name) ;
  224. header.ar_size= (((((long) (getsize[AR_SIZE+1]&0377))<<8)+
  225. ((long) (getsize[AR_SIZE ]&0377))<<8)+
  226. ((long) (getsize[AR_SIZE+3]&0377))<<8)+
  227. ((long) (getsize[AR_SIZE+2]&0377)) ;
  228. archsize = header.ar_size;
  229. if (needed()) {
  230. fseek(input,offset,0);
  231. archsize = header.ar_size;
  232. header.ar_name[14] = '\0';
  233. parse(remember(header.ar_name));
  234. }
  235. offset += header.ar_size;
  236. while (offset % 2)
  237. offset++;
  238. }
  239. archmode = 0;
  240. }
  241. int needed()
  242. {
  243. c, first;
  244. item_t *ip;
  245. int need;
  246. #ifdef LISTING
  247. int save;
  248. save = listflag; listflag = 0;
  249. #endif
  250. need = 0;
  251. peekc = -1;
  252. first = 1;
  253. for (;;) {
  254. c = nextchar();
  255. if (c == '\n') {
  256. first = 1;
  257. continue;
  258. }
  259. if (c == ' ' || c == '\t' || c == ',')
  260. continue;
  261. if (ISALPHA(c) == 0)
  262. break;
  263. if ((ip = item_search(readident(c))) == 0) {
  264. if (first)
  265. break;
  266. continue;
  267. }
  268. if (first) {
  269. if (ip == &keytab[KEYSECT]) {
  270. while ((c = nextchar()) != '\n')
  271. ;
  272. continue;
  273. }
  274. if (ip != &keytab[KEYDEFINE])
  275. break;
  276. first = 0;
  277. }
  278. if ((ip->i_type & S_TYP) == S_UND) {
  279. need++;
  280. break;
  281. }
  282. }
  283. #ifdef LISTING
  284. listflag = save;
  285. #endif
  286. return(need);
  287. }
  288. #endif /* ASLD */
  289. void parse(char *s)
  290. {
  291. int i;
  292. item_t *ip;
  293. char *p;
  294. for (p = s; *p; )
  295. if (*p++ == '/')
  296. s = p;
  297. #ifdef ASLD
  298. yylval.y_strp = s;
  299. putval(MODULE);
  300. #endif
  301. for (i = 0; i < FB_SIZE; i++)
  302. fb_ptr[FB_BACK+i] = 0;
  303. newmodule(s);
  304. peekc = -1;
  305. yyparse();
  306. /*
  307. * Check for undefined symbols
  308. */
  309. #ifdef ASLD
  310. for (i = 0; i < H_SIZE; i++) {
  311. while (ip = hashtab[H_LOCAL+i]) {
  312. /*
  313. * cleanup local queue
  314. */
  315. hashtab[H_LOCAL+i] = ip->i_next;
  316. /*
  317. * make undefined references extern
  318. */
  319. if ((ip->i_type & (S_VAR|S_TYP)) == S_UND)
  320. ip->i_type |= S_EXT;
  321. /*
  322. * relink externals in global queue
  323. */
  324. if (ip->i_type & S_EXT)
  325. item_insert(ip, H_GLOBAL+i);
  326. }
  327. }
  328. #else
  329. for (i = 0; i < H_SIZE; i++) {
  330. for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) {
  331. if (ip->i_type & S_EXT)
  332. continue;
  333. if (ip->i_type != S_UND)
  334. continue;
  335. if (uflag == 0)
  336. serror("undefined symbol %s", ip->i_name);
  337. ip->i_type |= S_EXT;
  338. }
  339. }
  340. #endif
  341. /*
  342. * Check for undefined numeric labels
  343. */
  344. for (i = 0; i < FB_SIZE; i++) {
  345. if ((ip = fb_ptr[FB_FORW+i]) == 0)
  346. continue;
  347. serror("undefined label %d", i);
  348. fb_ptr[FB_FORW+i] = 0;
  349. }
  350. }
  351. void pass_23(int n)
  352. {
  353. int i;
  354. #ifdef ASLD
  355. ADDR_T base = 0;
  356. #endif
  357. sect_t *sp;
  358. if (nerrors)
  359. stop(0);
  360. pass = n;
  361. #ifdef LISTING
  362. listmode >>= 3;
  363. if (listmode & 4)
  364. ffreopen(listpath, listfile);
  365. listeoln = 1;
  366. #endif
  367. #ifdef THREE_PASS
  368. bitindex = -1;
  369. nbits = BITCHUNK;
  370. #endif
  371. for (i = 0; i < FB_SIZE; i++)
  372. fb_ptr[FB_FORW+i] = fb_ptr[FB_HEAD+i];
  373. outhead.oh_nemit = 0;
  374. for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
  375. #ifdef ASLD
  376. if (sp->s_flag & BASED) {
  377. base = sp->s_base;
  378. if (base % sp->s_lign)
  379. fatal("base not aligned");
  380. } else {
  381. base += (sp->s_lign - 1);
  382. base -= (base % sp->s_lign);
  383. sp->s_base = base;
  384. }
  385. base += sp->s_size;
  386. base += sp->s_comm;
  387. #endif
  388. outhead.oh_nemit += sp->s_size - sp->s_zero;
  389. }
  390. if (pass == PASS_3)
  391. setupoutput();
  392. for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
  393. sp->s_size = 0;
  394. sp->s_zero = 0;
  395. #ifdef THREE_PASS
  396. sp->s_gain = 0;
  397. #endif
  398. }
  399. machstart(n);
  400. #ifndef ASLD
  401. newmodule(modulename);
  402. #endif /* ASLD */
  403. ffreopen(temppath, tempfile);
  404. yyparse();
  405. commfinish();
  406. machfinish(n);
  407. }
  408. void newmodule(char *s)
  409. {
  410. static char nmbuf[STRINGMAX];
  411. switchsect(S_UND);
  412. if (s && s != modulename) {
  413. strncpy(nmbuf, s, STRINGMAX-1);
  414. modulename = nmbuf;
  415. }
  416. else modulename = s;
  417. lineno = 1;
  418. #ifdef NEEDED
  419. /*
  420. * problem: it shows the name of the tempfile, not any name
  421. * the user is familiar with. Moreover, it is not reproducable.
  422. */
  423. if ((sflag & (SYM_EXT|SYM_LOC|SYM_LAB)) && PASS_SYMB)
  424. newsymb(s, S_MOD, 0, (valu_t)0);
  425. #endif
  426. #ifdef LISTING
  427. listtemp = 0;
  428. if (dflag & 01000)
  429. listtemp = listmode;
  430. listflag = listtemp;
  431. #endif
  432. }
  433. void setupoutput()
  434. {
  435. sect_t *sp;
  436. long off;
  437. struct outsect outsect;
  438. struct outsect *pos = &outsect;
  439. if (! wr_open(aoutpath)) {
  440. fatal("can't create %s", aoutpath);
  441. }
  442. wr_ohead(&outhead);
  443. /*
  444. * section table generation
  445. */
  446. off = SZ_HEAD;
  447. off += (long)outhead.oh_nsect * SZ_SECT;
  448. for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
  449. sp->s_foff = off;
  450. pos->os_base = SETBASE(sp);
  451. pos->os_size = sp->s_size + sp->s_comm;
  452. pos->os_foff = sp->s_foff;
  453. pos->os_flen = sp->s_size - sp->s_zero;
  454. pos->os_lign = sp->s_lign;
  455. off += pos->os_flen;
  456. wr_sect(pos, 1);
  457. }
  458. #ifdef RELOCATION
  459. off += (long)outhead.oh_nrelo * SZ_RELO;
  460. #endif
  461. if (sflag == 0)
  462. return;
  463. off += (long)outhead.oh_nname * SZ_NAME;
  464. outhead.oh_nchar = off; /* see newsymb() */
  465. }
  466. void commfinish()
  467. {
  468. #ifndef ASLD
  469. int i;
  470. #endif
  471. struct common_t *cp;
  472. item_t *ip;
  473. sect_t *sp;
  474. valu_t addr;
  475. switchsect(S_UND);
  476. /*
  477. * assign .comm labels and produce .comm symbol table entries
  478. */
  479. for (cp = commons; cp; cp = cp->c_next) {
  480. ip = cp->c_it;
  481. #ifndef ASLD
  482. if (!( ip->i_type & S_EXT)) {
  483. #endif
  484. sp = &sect[(ip->i_type & S_TYP) - S_MIN];
  485. if (pass == PASS_1) {
  486. addr = sp->s_size + sp->s_comm;
  487. sp->s_comm += ip->i_valu;
  488. ip->i_valu = addr;
  489. #ifndef ASLD
  490. ip->i_type &= ~S_COM;
  491. #endif
  492. }
  493. #ifdef ASLD
  494. #ifdef THREE_PASS
  495. if (pass == PASS_2) {
  496. ip->i_valu -= sp->s_gain;
  497. }
  498. #endif
  499. if ((sflag & SYM_EXT) && PASS_SYMB)
  500. newsymb(
  501. ip->i_name,
  502. ip->i_type & (S_EXT|S_TYP),
  503. 0,
  504. load(ip)
  505. );
  506. #else /* not ASLD */
  507. #ifdef THREE_PASS
  508. if (pass == PASS_2) {
  509. cp->c_size -= sp->s_gain;
  510. }
  511. #endif /* THREE_PASS */
  512. }
  513. if (pass == PASS_1) cp->c_size = ip->i_valu;
  514. if (PASS_SYMB) {
  515. if (pass != PASS_3 && (ip->i_type & S_EXT)) {
  516. ip->i_valu = outhead.oh_nname;
  517. }
  518. newsymb(
  519. ip->i_name,
  520. ip->i_type,
  521. 0,
  522. cp->c_size
  523. );
  524. }
  525. #endif /* not ASLD */
  526. }
  527. if (PASS_SYMB == 0)
  528. return;
  529. #ifndef ASLD
  530. /*
  531. * produce symbol table entries for undefined's
  532. */
  533. for (i = 0; i<H_SIZE; i++)
  534. for (ip = hashtab[H_LOCAL+i]; ip; ip = ip->i_next) {
  535. if (ip->i_type != (S_EXT|S_UND))
  536. continue;
  537. if (pass != PASS_3)
  538. /*
  539. * save symbol table index
  540. * for possible relocation
  541. */
  542. ip->i_valu = outhead.oh_nname;
  543. newsymb(
  544. ip->i_name,
  545. S_EXT|S_UND,
  546. 0,
  547. (valu_t)0
  548. );
  549. }
  550. #endif /* not ASLD */
  551. /*
  552. * produce symbol table entries for sections
  553. */
  554. if (sflag & SYM_SCT)
  555. for (sp = sect; sp < &sect[outhead.oh_nsect]; sp++) {
  556. ip = sp->s_item;
  557. newsymb(
  558. ip->i_name,
  559. (ip->i_type | S_SCT),
  560. 0,
  561. load(ip)
  562. );
  563. }
  564. }