PageRenderTime 76ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/zmac/zmac.y

https://bitbucket.org/sgraham/sayyoho
Happy | 3886 lines | 3489 code | 397 blank | 0 comment | 0 complexity | f0d98eb2827095270fc65d3e7d32019e MD5 | raw file
  1. %{
  2. /*
  3. * zmac -- macro cross-assembler for the Zilog Z80 microprocessor
  4. *
  5. * Bruce Norskog 4/78
  6. *
  7. * Last modification 2000-07-01 by mgr
  8. *
  9. * This assembler is modeled after the Intel 8080 macro cross-assembler
  10. * for the Intel 8080 by Ken Borgendale. The major features are:
  11. * 1. Full macro capabilities
  12. * 2. Conditional assembly
  13. * 3. A very flexible set of listing options and pseudo-ops
  14. * 4. Symbol table output
  15. * 5. Error report
  16. * 6. Elimination of sequential searching
  17. * 7. Commenting of source
  18. * 8. Facilities for system definiton files
  19. *
  20. * (Revision history is now in ChangeLog. -rjm)
  21. */
  22. #define ZMAC_VERSION "1.3"
  23. /* #define ZMAC_BETA "b4" */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <stdarg.h>
  28. #include <time.h>
  29. #include "mio.h"
  30. #include "getoptn.h"
  31. #define UNUSED(var) ((void) var)
  32. #if defined (__riscos__) && !defined (__riscos)
  33. #define __riscos
  34. #endif
  35. #ifdef __riscos
  36. #include "swis.h"
  37. #define DDEUtils_Prefix 0x42580
  38. #define DDEUtils_ThrowbackStart 0x42587
  39. #define DDEUtils_ThrowbackSend 0x42588
  40. #define DDEUtils_ThrowbackEnd 0x42589
  41. #endif
  42. #ifndef OS_DIR_SEP
  43. #if defined (MSDOS)
  44. #define OS_DIR_SEP '\\'
  45. #elif defined (__riscos)
  46. #define OS_DIR_SEP '.'
  47. #else
  48. #define OS_DIR_SEP '/'
  49. #endif
  50. #endif
  51. #ifndef OS_EXT_SEP
  52. #if defined (__riscos)
  53. #define OS_EXT_SEP '/'
  54. #else
  55. #define OS_EXT_SEP '.'
  56. #endif
  57. #endif
  58. /*
  59. * DEBUG turns on pass reporting.
  60. * Macro debug and Token debug enables.
  61. #define DEBUG
  62. #define M_DEBUG
  63. #define T_DEBUG
  64. */
  65. #define ITEMTABLESIZE 2000
  66. #define TEMPBUFSIZE 200
  67. #define LINEBUFFERSIZE 200
  68. #define EMITBUFFERSIZE 200
  69. #define MAXSYMBOLSIZE 40
  70. #define IFSTACKSIZE 20
  71. #define MAXIFS 1024
  72. #define TITLELEN 50
  73. #define BINPERLINE 16
  74. #define PARMMAX 25
  75. #define MAXEXP 25
  76. #define SYMMAJIC 07203
  77. #define NEST_IN 8
  78. #define loop for(;;)
  79. void yyerror(char *err)
  80. {
  81. UNUSED (err); /* we will do our own error printing */
  82. /* printf ("Oops! %s\n", err); */
  83. }
  84. struct item {
  85. char *i_string;
  86. int i_value;
  87. int i_token;
  88. int i_uses;
  89. int i_equbad;
  90. };
  91. FILE *fout,
  92. *fbuf,
  93. *fin[NEST_IN],
  94. *now_file ;
  95. int pass2; /* set when pass one completed */
  96. int dollarsign ; /* location counter */
  97. int olddollar ; /* kept to put out binary */
  98. /* program counter save for PHASE/DEPHASE */
  99. int phdollar, phbegin, phaseflag ;
  100. char *src_name[NEST_IN] ;
  101. int linein[NEST_IN] ;
  102. int now_in ;
  103. #define bflag 0 /* balance error */
  104. #define eflag 1 /* expression error */
  105. #define fflag 2 /* syntax error */
  106. #define iflag 3 /* bad digits */
  107. #define mflag 4 /* multiply defined */
  108. #define pflag 5 /* phase error */
  109. #define uflag 6 /* undeclared used */
  110. #define vflag 7 /* value out of range */
  111. #define oflag 8 /* phase/dephase error */
  112. #define frflag 9 /* double forward ref. via equ error */
  113. #define zflag 10 /* Z80-only instruction (when `-z' option in use) */
  114. #define orgflag 11 /* retrograde org error (when `-h' option not in use) */
  115. #define FLAGS 12 /* number of flags */
  116. char err[FLAGS];
  117. int keeperr[FLAGS];
  118. char errlet[FLAGS]="BEFIMPUVORZG";
  119. char *errname[FLAGS]={
  120. "Balance",
  121. "Expression",
  122. "Syntax",
  123. "Digit",
  124. "Mult. def.",
  125. "Phase",
  126. "Undeclared",
  127. "Value",
  128. "Phase/Dephase",
  129. "Forward ref. to EQU with forward ref.",
  130. "Z80-specific instruction",
  131. "Retrograde ORG"
  132. };
  133. char *warnname[]={
  134. "Symbol length exceeded",
  135. "Non-standard syntax",
  136. "Could replace JP with JR",
  137. "Could replace LD A, 0 with XOR A if flags unimportant",
  138. "Could replace RLC A with RLCA if S, Z and P/V flags unimportant",
  139. "Could replace RRC A with RRCA if S, Z and P/V flags unimportant",
  140. "Could replace RL A with RLA if S, Z and P/V flags unimportant",
  141. "Could replace RR A with RRA if S, Z and P/V flags unimportant",
  142. "Could replace SLA A with ADD A, A if H and P/V flags unimportant"
  143. };
  144. /* for "0 symbols", "1 symbol", "2 symbols", etc. */
  145. #define DO_PLURAL(x) (x),((x)==1)?"":"s"
  146. char linebuf[LINEBUFFERSIZE];
  147. char *lineptr;
  148. char *linemax = linebuf+LINEBUFFERSIZE;
  149. char outbin[BINPERLINE];
  150. char *outbinp = outbin;
  151. char *outbinm = outbin+BINPERLINE;
  152. char emitbuf[EMITBUFFERSIZE];
  153. char *emitptr;
  154. char ifstack[IFSTACKSIZE];
  155. char *ifptr;
  156. char *ifstmax = ifstack+IFSTACKSIZE-1;
  157. char expif[MAXIFS];
  158. char *expifp;
  159. char *expifmax = expif+MAXIFS;
  160. char hexadec[] = "0123456789ABCDEF" ;
  161. char *expstack[MAXEXP];
  162. int expptr;
  163. int nitems;
  164. int linecnt;
  165. int nbytes;
  166. int invented;
  167. char tempbuf[TEMPBUFSIZE];
  168. char *tempmax = tempbuf+TEMPBUFSIZE-1;
  169. char inmlex;
  170. char arg_flag;
  171. char quoteflag;
  172. int parm_number;
  173. int exp_number;
  174. char symlong[] = "Symbol too long";
  175. int disp;
  176. #define FLOC PARMMAX
  177. #define TEMPNUM PARMMAX+1
  178. char **est;
  179. char **est2;
  180. char *floc;
  181. int mfptr;
  182. FILE *mfile;
  183. char *title;
  184. char titlespace[TITLELEN];
  185. char *timp;
  186. char *sourcef;
  187. /* changed to cope with filenames longer than 14 chars -rjm 1998-12-15 */
  188. char src[1024];
  189. char bin[1024];
  190. char mtmp[1024];
  191. char listf[1024];
  192. char writesyms[1024];
  193. #ifdef __riscos
  194. char riscos_thbkf[1024];
  195. #endif
  196. char bopt = 1,
  197. edef = 1,
  198. eopt = 1,
  199. fdef = 0,
  200. fopt = 0,
  201. gdef = 1,
  202. gopt = 1,
  203. iopt = 0 , /* list include files */
  204. lstoff = 0,
  205. lston = 0, /* flag to force listing on */
  206. lopt = 0,
  207. mdef = 0,
  208. mopt = 0,
  209. nopt = 1, /* line numbers on as default */
  210. oldoopt = 0,
  211. popt = 1, /* form feed as default page eject */
  212. sopt = 0, /* turn on symbol table listing */
  213. output_hex = 0, /* `-h', output .hex rather than .bin -rjm */
  214. output_8080_only = 0, /* `-z', output 8080-compat. ops only -rjm */
  215. show_error_line = 0, /* `-S', show line which caused error -rjm */
  216. terse_lst_errors = 0, /* `-t', terse errors in listing -rjm */
  217. continuous_listing = 1, /* `-d', discontinuous - with page breaks */
  218. suggest_optimise = 0, /* `-O', suggest optimisations -mgr */
  219. #ifdef __riscos
  220. riscos_thbk = 0, /* `-T', RISC OS throwback -mep */
  221. #endif
  222. output_amsdos = 0, /* `-A', AMSDOS binary file output -mep */
  223. saveopt;
  224. char xeq_flag = 0;
  225. int xeq;
  226. time_t now;
  227. int line;
  228. int page = 1;
  229. int had_errors = 0; /* if program had errors, do exit(1) */
  230. #ifdef __riscos
  231. int riscos_throwback_started = 0;
  232. #endif
  233. int not_seen_org = 1;
  234. int first_org_store = 0;
  235. struct stab {
  236. char t_name[MAXSYMBOLSIZE+1];
  237. int t_value;
  238. int t_token;
  239. };
  240. /*
  241. * push back character
  242. */
  243. int peekc;
  244. /* function prototypes */
  245. int addtoline(int ac);
  246. int iflist(void);
  247. int yylex(void);
  248. int tokenofitem(int deftoken);
  249. int nextchar(void);
  250. int skipline(int ac);
  251. void usage(void);
  252. int main(int argc, char *argv[]);
  253. int getarg(void);
  254. int getm(void);
  255. void yyerror(char *err);
  256. void emit(int num, ...);
  257. void emit1(int opcode,int regvalh,int data16,int type);
  258. void emitdad(int rp1,int rp2);
  259. void emitjr(int opcode,int expr);
  260. void emitjp(int opcode,int expr);
  261. void putbin(int v);
  262. void flushbin(void);
  263. void puthex(char byte, FILE *buf);
  264. void list(int optarg);
  265. void lineout(void);
  266. void eject(void);
  267. void space(int n);
  268. void lsterr1(void);
  269. void lsterr2(int lst);
  270. void errorprt(int errnum);
  271. void warnprt(int warnnum, int warnoff);
  272. void list1(void);
  273. void interchange(int i, int j);
  274. void custom_qsort(int m, int n);
  275. void setvars(void);
  276. void error(char *as);
  277. void fileerror(char *as,char *filename);
  278. void justerror(char *as);
  279. void putsymtab(void);
  280. void erreport(void);
  281. void mlex(void);
  282. void suffix_if_none(char *str,char *suff);
  283. void suffix(char *str,char *suff);
  284. void decanonicalise(char *str);
  285. void putm(char c);
  286. void popsi(void);
  287. char *getlocal(int c, int n);
  288. void insymtab(char *name);
  289. void outsymtab(char *name);
  290. void copyname(char *st1, char *st2);
  291. void next_source(char *sp);
  292. void doatexit (void);
  293. #ifdef __riscos
  294. void riscos_set_csd(char *sp);
  295. void riscos_throwback(int severity, char *file, int line, char *error);
  296. #endif
  297. /*
  298. * add a character to the output line buffer
  299. */
  300. int addtoline(int ac)
  301. {
  302. /* check for EOF from stdio */
  303. if (ac == -1)
  304. ac = 0 ;
  305. if (inmlex)
  306. return(ac);
  307. if (lineptr >= linemax)
  308. error("line buffer overflow");
  309. *lineptr++ = ac;
  310. return(ac);
  311. }
  312. /*
  313. * put values in buffer for outputing
  314. */
  315. void emit(int bytes, ...)
  316. {
  317. va_list ap;
  318. unsigned char *oldemitptr=(unsigned char *)emitptr;
  319. int c;
  320. va_start(ap,bytes);
  321. while (--bytes >= 0)
  322. if (emitptr >= &emitbuf[EMITBUFFERSIZE])
  323. error("emit buffer overflow");
  324. else {
  325. *emitptr++ = va_arg(ap,int);
  326. }
  327. if (output_8080_only) {
  328. /* test for Z80-specific ops. These start with one of
  329. * sixteen byte values, listed below. The values were
  330. * taken from "A Z80 Workshop Manual" by E. A. Parr. -rjm
  331. */
  332. /* As far as I can tell from my own literature
  333. * review, 0x02, 0x0a, 0x12 and 0x1a are valid
  334. * 8080 opcodes (LDAX/STAX B/D) -mgr
  335. */
  336. c=*oldemitptr;
  337. if (/* c==0x02 || */ c==0x08 || /* c==0x0a || */ c==0x10 ||
  338. /* c==0x12 || */ c==0x18 || /* c==0x1a || */ c==0x20 ||
  339. c==0x28 || c==0x30 || c==0x38 || c==0xcb ||
  340. c==0xd9 || c==0xdd || c==0xed || c==0xfd)
  341. err[zflag]++;
  342. }
  343. va_end(ap);
  344. }
  345. /* for emitted data - as above, without 8080 test.
  346. * Duplicating the code was easier than putting an extra arg in all
  347. * those emit()s. :-} Hopefully this isn't too unbearably nasty. -rjm
  348. */
  349. void dataemit(int bytes, ...)
  350. {
  351. va_list ap;
  352. va_start(ap,bytes);
  353. while (--bytes >= 0)
  354. if (emitptr >= &emitbuf[EMITBUFFERSIZE])
  355. error("emit buffer overflow");
  356. else {
  357. *emitptr++ = va_arg(ap,int);
  358. }
  359. va_end(ap);
  360. }
  361. void emit1(int opcode,int regvalh,int data16,int type)
  362. {
  363. if ((regvalh & 0x8000)) { /* extra brackets to silence -Wall */
  364. if ((type & 1) == 0 && (disp > 127 || disp < -128))
  365. err[vflag]++;
  366. switch(type) {
  367. case 0:
  368. if (opcode & 0x8000)
  369. emit(4, regvalh >> 8, opcode >> 8, disp, opcode);
  370. else
  371. emit(3, regvalh >> 8, opcode, disp);
  372. break;
  373. case 1:
  374. emit(2, regvalh >> 8, opcode);
  375. break;
  376. case 2:
  377. if (data16 > 255 || data16 < -128)
  378. err[vflag]++;
  379. emit(4, regvalh >> 8, opcode, disp, data16);
  380. break;
  381. case 5:
  382. emit(4, regvalh >> 8, opcode, data16, data16 >> 8);
  383. }
  384. } else
  385. switch(type) {
  386. case 0:
  387. if (opcode & 0100000)
  388. emit(2, opcode >> 8, opcode);
  389. else
  390. emit(1, opcode);
  391. break;
  392. case 1:
  393. if (opcode & 0100000)
  394. emit(2, opcode >> 8, opcode);
  395. else
  396. emit(1, opcode);
  397. break;
  398. case 2:
  399. if (data16 > 255 || data16 < -128)
  400. err[vflag]++;
  401. emit(2, opcode, data16);
  402. break;
  403. case 3:
  404. if (data16 >255 || data16 < -128)
  405. err[vflag]++;
  406. emit(2, opcode, data16);
  407. break;
  408. case 5:
  409. if (opcode & 0100000)
  410. emit(4, opcode >> 8, opcode, data16, data16 >> 8);
  411. else
  412. emit(3, opcode, data16, data16 >> 8);
  413. }
  414. }
  415. void emitdad(int rp1,int rp2)
  416. {
  417. if (rp1 & 0x8000)
  418. emit(2,rp1 >> 8, rp2 + 9);
  419. else
  420. emit(1,rp2 + 9);
  421. }
  422. void emitjr(int opcode,int expr)
  423. {
  424. disp = expr - dollarsign - 2;
  425. if (disp > 127 || disp < -128)
  426. err[vflag]++;
  427. emit(2, opcode, disp);
  428. }
  429. void emitjp(int opcode,int expr)
  430. {
  431. if (suggest_optimise && pass2 && opcode <= 0xda && !output_8080_only) {
  432. disp = expr - dollarsign - 2;
  433. if (disp <= 127 && disp >= -128)
  434. warnprt (2, 0);
  435. }
  436. emit(3, opcode, expr, expr >> 8);
  437. }
  438. /*
  439. * put out a byte of binary
  440. */
  441. void putbin(int v)
  442. {
  443. if(!pass2 || !bopt) return;
  444. *outbinp++ = v;
  445. if (outbinp >= outbinm) flushbin();
  446. }
  447. /*
  448. * output one line of binary in INTEL standard form
  449. */
  450. void flushbin()
  451. {
  452. char *p;
  453. int check=outbinp-outbin;
  454. if (!pass2 || !bopt)
  455. return;
  456. nbytes += check;
  457. if (check) {
  458. if (output_hex) {
  459. putc(':', fbuf);
  460. puthex(check, fbuf);
  461. puthex(olddollar>>8, fbuf);
  462. puthex(olddollar, fbuf);
  463. puthex(0, fbuf);
  464. }
  465. check += (olddollar >> 8) + olddollar;
  466. olddollar += (outbinp-outbin);
  467. for (p=outbin; p<outbinp; p++) {
  468. if (output_hex)
  469. puthex(*p, fbuf);
  470. else
  471. fputc(*p, fbuf);
  472. check += *p;
  473. }
  474. if (output_hex) {
  475. puthex(256-check, fbuf);
  476. putc('\n', fbuf);
  477. }
  478. outbinp = outbin;
  479. }
  480. }
  481. /*
  482. * put out one byte of hex
  483. */
  484. void puthex(char byte, FILE *buf)
  485. {
  486. putc(hexadec[(byte >> 4) & 017], buf);
  487. putc(hexadec[byte & 017], buf);
  488. }
  489. /*
  490. * put out a line of output -- also put out binary
  491. */
  492. void list(int optarg)
  493. {
  494. char * p;
  495. int i;
  496. int lst;
  497. if (!expptr)
  498. linecnt++;
  499. addtoline('\0');
  500. if (pass2) {
  501. lst = iflist();
  502. if (lst) {
  503. lineout();
  504. if (nopt)
  505. fprintf(fout, "%4d:\t", linein[now_in]);
  506. puthex(optarg >> 8, fout);
  507. puthex(optarg, fout);
  508. fputs(" ", fout);
  509. for (p = emitbuf; (p < emitptr) && (p - emitbuf < 4); p++) {
  510. puthex(*p, fout);
  511. }
  512. for (i = 4 - (p-emitbuf); i > 0; i--)
  513. fputs(" ", fout);
  514. putc('\t', fout);
  515. fputs(linebuf, fout);
  516. }
  517. if (bopt) {
  518. for (p = emitbuf; p < emitptr; p++)
  519. putbin(*p);
  520. }
  521. p = emitbuf+4;
  522. while (lst && gopt && p < emitptr) {
  523. lineout();
  524. if (nopt) putc('\t', fout);
  525. fputs(" ", fout);
  526. for (i = 0; (i < 4) && (p < emitptr);i++) {
  527. puthex(*p, fout);
  528. p++;
  529. }
  530. putc('\n', fout);
  531. }
  532. lsterr2(lst);
  533. } else
  534. lsterr1();
  535. dollarsign += emitptr - emitbuf;
  536. emitptr = emitbuf;
  537. lineptr = linebuf;
  538. }
  539. /*
  540. * keep track of line numbers and put out headers as necessary
  541. */
  542. void lineout()
  543. {
  544. if (continuous_listing) {
  545. line = 1;
  546. return;
  547. }
  548. if (line == 60) {
  549. if (popt)
  550. putc('\014', fout); /* send the form feed */
  551. else
  552. fputs("\n\n\n\n\n", fout);
  553. line = 0;
  554. }
  555. if (line == 0) {
  556. fprintf(fout, "\n\n%s %s\t%s\t Page %d\n\n\n",
  557. &timp[4], &timp[20], title, page++);
  558. line = 4;
  559. }
  560. line++;
  561. }
  562. /*
  563. * cause a page eject
  564. */
  565. void eject()
  566. {
  567. if (pass2 && !continuous_listing && iflist()) {
  568. if (popt) {
  569. putc('\014', fout); /* send the form feed */
  570. } else {
  571. while (line < 65) {
  572. line++;
  573. putc('\n', fout);
  574. }
  575. }
  576. }
  577. line = 0;
  578. }
  579. /*
  580. * space n lines on the list file
  581. */
  582. void space(int n)
  583. {
  584. int i ;
  585. if (pass2 && iflist())
  586. for (i = 0; i<n; i++) {
  587. lineout();
  588. putc('\n', fout);
  589. }
  590. }
  591. /*
  592. * Error handling - pass 1
  593. */
  594. void lsterr1()
  595. {
  596. int i;
  597. for (i = 0; i <= 4; i++)
  598. if (err[i]) {
  599. errorprt(i);
  600. err[i] = 0;
  601. }
  602. }
  603. /*
  604. * Error handling - pass 2.
  605. */
  606. void lsterr2(int lst)
  607. {
  608. int i;
  609. for (i=0; i<FLAGS; i++)
  610. if (err[i]) {
  611. if (lst) {
  612. lineout();
  613. /* verbose inline error messages now,
  614. * must override with `-t' to get old
  615. * behaviour. -rjm
  616. */
  617. if (terse_lst_errors)
  618. putc(errlet[i], fout);
  619. else
  620. fprintf(fout,"*** %s error ***",
  621. errname[i]);
  622. putc('\n', fout);
  623. }
  624. err[i] = 0;
  625. keeperr[i]++;
  626. if (i > 4)
  627. errorprt(i);
  628. }
  629. fflush(fout); /* to avoid putc(har) mix bug */
  630. }
  631. /*
  632. * print diagnostic to error terminal
  633. */
  634. void errorprt(int errnum)
  635. {
  636. had_errors=1;
  637. fprintf(stderr,"%s:%d: %s error\n",
  638. src_name[now_in], linein[now_in], errname[errnum]);
  639. if(show_error_line)
  640. fprintf(stderr, "%s\n", linebuf);
  641. #ifdef __riscos
  642. if (riscos_thbk)
  643. riscos_throwback (1, src_name[now_in], linein[now_in], errname[errnum]);
  644. #endif
  645. }
  646. /*
  647. * print warning to error terminal
  648. */
  649. void warnprt(int warnnum, int warnoff)
  650. {
  651. fprintf(stderr,"%s:%d: warning: %s\n",
  652. src_name[now_in], linein[now_in] + warnoff, warnname[warnnum]);
  653. /* Offset needed if warning issued while line is being parsed */
  654. #ifdef __riscos
  655. if (riscos_thbk)
  656. riscos_throwback (0, src_name[now_in], linein[now_in] + warnoff, warnname[warnnum]);
  657. #endif
  658. /* if(show_error_line)
  659. Can't show line because it isn't necessarily complete
  660. fprintf(stderr, "%s\n", linebuf); */
  661. }
  662. /*
  663. * list without address -- for comments and if skipped lines
  664. */
  665. void list1()
  666. {
  667. int lst;
  668. addtoline('\0');
  669. lineptr = linebuf;
  670. if (!expptr) linecnt++;
  671. if (pass2)
  672. {
  673. if ((lst = iflist())) {
  674. lineout();
  675. if (nopt)
  676. fprintf(fout, "%4d:\t", linein[now_in]);
  677. fprintf(fout, "\t\t%s", linebuf);
  678. lsterr2(lst);
  679. }
  680. } else
  681. lsterr1();
  682. }
  683. /*
  684. * see if listing is desired
  685. */
  686. int iflist()
  687. {
  688. int i, j;
  689. if (lston)
  690. return(1) ;
  691. if (lopt)
  692. return(0);
  693. if (*ifptr && !fopt)
  694. return(0);
  695. if (!lstoff && !expptr)
  696. return(1);
  697. j = 0;
  698. for (i=0; i<FLAGS; i++)
  699. if (err[i])
  700. j++;
  701. if (expptr)
  702. return(mopt || j);
  703. if (eopt && j)
  704. return(1);
  705. return(0);
  706. }
  707. /* moved out of %{..%} bit in parse routine because `bison -y'
  708. * didn't like it... -rjm
  709. */
  710. char *cp;
  711. int list_tmp1,list_tmp2;
  712. int equ_bad_label=0;
  713. %}
  714. %union {
  715. struct item *itemptr;
  716. int ival;
  717. char *cval;
  718. }
  719. %token <cval> STRING
  720. %token <itemptr> NOOPERAND
  721. %token <itemptr> ARITHC
  722. %token ADD
  723. %token <itemptr> LOGICAL
  724. %token <itemptr> AND
  725. %token <itemptr> OR
  726. %token <itemptr> XOR
  727. %token <itemptr> BIT
  728. %token CALL
  729. %token <itemptr> INCDEC
  730. %token <itemptr> DJNZ
  731. %token EX
  732. %token <itemptr> IM
  733. %token PHASE
  734. %token DEPHASE
  735. %token <itemptr> IN
  736. %token JP
  737. %token <itemptr> JR
  738. %token LD
  739. %token <itemptr> OUT
  740. %token <itemptr> PUSHPOP
  741. %token <itemptr> RET
  742. %token <itemptr> SHIFT
  743. %token <itemptr> RST
  744. %token <itemptr> REGNAME
  745. %token <itemptr> ACC
  746. %token <itemptr> C
  747. %token <itemptr> RP
  748. %token <itemptr> HL
  749. %token <itemptr> INDEX
  750. %token <itemptr> AF
  751. %token <itemptr> SP
  752. %token <itemptr> MISCREG
  753. %token F
  754. %token <itemptr> COND
  755. %token <itemptr> SPCOND
  756. %token <ival> NUMBER
  757. %token <itemptr> UNDECLARED
  758. %token END
  759. %token ORG
  760. %token DEFB
  761. %token DEFS
  762. %token DEFW
  763. %token EQU
  764. %token DEFL
  765. %token <itemptr> LABEL
  766. %token <itemptr> EQUATED
  767. %token <itemptr> WASEQUATED
  768. %token <itemptr> DEFLED
  769. %token <itemptr> MULTDEF
  770. %token <ival> MOD
  771. %token <ival> SHL
  772. %token <ival> SHR
  773. %token <ival> NOT
  774. %token <ival> LT
  775. %token <ival> GT
  776. %token <ival> EQ
  777. %token <ival> LE
  778. %token <ival> GE
  779. %token <ival> NE
  780. %token IF
  781. %token ELSE
  782. %token ENDIF
  783. %token <itemptr> ARGPSEUDO
  784. %token <itemptr> LIST
  785. %token <itemptr> MINMAX
  786. %token MACRO
  787. %token <itemptr> MNAME
  788. %token <itemptr> OLDMNAME
  789. %token ARG
  790. %token ENDM
  791. %token MPARM
  792. %token <ival> ONECHAR
  793. %token <ival> TWOCHAR
  794. %type <itemptr> label.part symbol
  795. %type <ival> reg evenreg realreg mem pushable bcdesp bcdehlsp mar condition
  796. %type <ival> spcondition noparenexpr parenexpr expression lxexpression
  797. %left '|' OR
  798. %left '^' XOR
  799. %left '&' AND
  800. %left '=' EQ NE
  801. %left '<' '>' LT GT LE GE
  802. %left SHL SHR
  803. %left '+' '-'
  804. %left '*' '/' '%' MOD
  805. %right '!' '~' NOT UNARY
  806. %%
  807. statements:
  808. /* Empty file! */
  809. |
  810. statements statement
  811. ;
  812. statement:
  813. label.part '\n' {
  814. if ($1) list(dollarsign);
  815. else list1();
  816. }
  817. |
  818. label.part operation '\n' {
  819. list(dollarsign);
  820. }
  821. |
  822. symbol EQU expression '\n' {
  823. /* a forward reference to a label in the expression cannot
  824. * be fixed in a forward reference to the EQU;
  825. * it would need three passes. -rjm
  826. */
  827. if(!pass2 && equ_bad_label) {
  828. /* this indicates that the equ has an incorrect
  829. * (i.e. pass 1) value.
  830. */
  831. $1->i_equbad = 1;
  832. } else {
  833. /* but if 2nd pass or no forward reference, it's ok. */
  834. $1->i_equbad = 0;
  835. }
  836. equ_bad_label=0;
  837. switch($1->i_token) {
  838. case UNDECLARED: case WASEQUATED:
  839. $1->i_token = EQUATED;
  840. $1->i_value = $3;
  841. break;
  842. case EQUATED:
  843. if ($1->i_value == $3)
  844. break; /* Allow benign redefinition -mgr */
  845. /* Drop-through intentional */
  846. default:
  847. err[mflag]++;
  848. $1->i_token = MULTDEF;
  849. }
  850. list($3);
  851. }
  852. |
  853. symbol DEFL expression '\n' {
  854. switch($1->i_token) {
  855. case UNDECLARED: case DEFLED:
  856. $1->i_token = DEFLED;
  857. $1->i_value = $3;
  858. break;
  859. default:
  860. err[mflag]++;
  861. $1->i_token = MULTDEF;
  862. }
  863. list($3);
  864. }
  865. |
  866. symbol MINMAX expression ',' expression '\n' {
  867. switch ($1->i_token) {
  868. case UNDECLARED: case DEFLED:
  869. $1->i_token = DEFLED;
  870. if ($2->i_value) /* max */
  871. list($1->i_value = ($3 > $5? $3:$5));
  872. else list($1->i_value = ($3 < $5? $3:$5));
  873. break;
  874. default:
  875. err[mflag]++;
  876. $1->i_token = MULTDEF;
  877. list($1->i_value);
  878. }
  879. }
  880. |
  881. IF expression '\n' {
  882. /* all $2's here were yypc[2].ival before.
  883. * I think the idea was perhaps to allow constants
  884. * only...? Anyway, it now allows any expression -
  885. * which would seem to make sense given the definition
  886. * above, right? :-) -rjm
  887. */
  888. if (ifptr >= ifstmax)
  889. error("Too many ifs");
  890. else {
  891. if (pass2) {
  892. *++ifptr = *expifp++;
  893. if (*ifptr != !($2)) err[pflag]++;
  894. } else {
  895. if (expifp >= expifmax)
  896. error("Too many ifs!");
  897. *expifp++ = !($2);
  898. *++ifptr = !($2);
  899. }
  900. }
  901. saveopt = fopt;
  902. fopt = 1;
  903. list($2);
  904. fopt = saveopt;
  905. }
  906. |
  907. ELSE '\n' {
  908. /* FIXME: it would be nice to spot repeated ELSEs, but how? */
  909. *ifptr = !*ifptr;
  910. saveopt = fopt;
  911. fopt = 1;
  912. list1();
  913. fopt = saveopt;
  914. }
  915. |
  916. ENDIF '\n' {
  917. if (ifptr == ifstack) err[bflag]++;
  918. else --ifptr;
  919. list1();
  920. }
  921. |
  922. label.part END '\n' {
  923. list(dollarsign);
  924. peekc = 0;
  925. }
  926. |
  927. label.part END expression '\n' {
  928. xeq_flag++;
  929. xeq = $3;
  930. list($3);
  931. peekc = 0;
  932. }
  933. |
  934. label.part DEFS expression '\n' {
  935. if ($3 < 0) err[vflag]++;
  936. list(dollarsign);
  937. if ($3) {
  938. flushbin();
  939. dollarsign += $3;
  940. olddollar = dollarsign;
  941. /* if it's not hex output though, we also need
  942. * to output zeroes as appropriate. -rjm
  943. */
  944. if(!output_hex && pass2) {
  945. int f;
  946. for (f=0;f<($3);f++)
  947. fputc(0, fbuf);
  948. }
  949. }
  950. }
  951. |
  952. ARGPSEUDO arg_on ARG arg_off '\n' {
  953. list1();
  954. switch ($1->i_value) {
  955. case 0: /* title */
  956. lineptr = linebuf;
  957. cp = tempbuf;
  958. title = titlespace;
  959. while ((*title++ = *cp++) && (title < &titlespace[TITLELEN]));
  960. *title = 0;
  961. title = titlespace;
  962. break;
  963. case 1: /* rsym */
  964. if (pass2) break;
  965. insymtab(tempbuf);
  966. break;
  967. case 2: /* wsym */
  968. strcpy(writesyms, tempbuf);
  969. break;
  970. case 3: /* include file */
  971. if (*tempbuf == '"' || *tempbuf == '\'')
  972. {
  973. if (tempbuf[strlen (tempbuf) - 1] == '"' || tempbuf[strlen (tempbuf) - 1] == '\'')
  974. tempbuf[strlen (tempbuf) - 1] = 0;
  975. next_source(tempbuf + 1) ;
  976. }
  977. else
  978. {
  979. next_source(tempbuf) ;
  980. }
  981. break ;
  982. }
  983. }
  984. |
  985. ARGPSEUDO arg_on arg_off '\n' {
  986. fprintf(stderr,"ARGPSEUDO error\n");
  987. err[fflag]++;
  988. list(dollarsign);
  989. }
  990. |
  991. LIST '\n' {
  992. list_tmp1=$1->i_value;
  993. list_tmp2=1;
  994. goto dolopt;
  995. }
  996. |
  997. LIST expression '\n' {
  998. list_tmp1=$1->i_value;
  999. list_tmp2=$2;
  1000. dolopt:
  1001. linecnt++;
  1002. if (pass2) {
  1003. lineptr = linebuf;
  1004. switch (list_tmp1) {
  1005. case 0: /* list */
  1006. if (list_tmp2 < 0) lstoff = 1;
  1007. if (list_tmp2 > 0) lstoff = 0;
  1008. break;
  1009. case 1: /* eject */
  1010. if (list_tmp2) eject();
  1011. break;
  1012. case 2: /* space */
  1013. if ((line + list_tmp2) > 60) eject();
  1014. else space(list_tmp2);
  1015. break;
  1016. case 3: /* elist */
  1017. eopt = edef;
  1018. if (list_tmp2 < 0) eopt = 0;
  1019. if (list_tmp2 > 0) eopt = 1;
  1020. break;
  1021. case 4: /* fopt */
  1022. fopt = fdef;
  1023. if (list_tmp2 < 0) fopt = 0;
  1024. if (list_tmp2 > 0) fopt = 1;
  1025. break;
  1026. case 5: /* gopt */
  1027. gopt = gdef;
  1028. if (list_tmp2 < 0) gopt = 1;
  1029. if (list_tmp2 > 0) gopt = 0;
  1030. break;
  1031. case 6: /* mopt */
  1032. mopt = mdef;
  1033. if (list_tmp2 < 0) mopt = 0;
  1034. if (list_tmp2 > 0) mopt = 1;
  1035. }
  1036. }
  1037. }
  1038. |
  1039. UNDECLARED MACRO parm.list '\n' {
  1040. $1->i_token = MNAME;
  1041. $1->i_value = mfptr;
  1042. #ifdef M_DEBUG
  1043. fprintf (stderr, "[UNDECLARED MACRO %s]\n", $1->i_string);
  1044. #endif
  1045. mfseek(mfile, (long)mfptr, 0);
  1046. list1();
  1047. mlex() ;
  1048. parm_number = 0;
  1049. }
  1050. |
  1051. OLDMNAME MACRO {
  1052. $1->i_token = MNAME;
  1053. #ifdef M_DEBUG
  1054. fprintf (stderr, "[OLDNAME MACRO %s]\n", $1->i_string);
  1055. #endif
  1056. while (yychar != ENDM && yychar) {
  1057. while (yychar != '\n' && yychar)
  1058. yychar = yylex();
  1059. list1();
  1060. yychar = yylex();
  1061. }
  1062. while (yychar != '\n' && yychar) yychar = yylex();
  1063. list1();
  1064. yychar = yylex();
  1065. }
  1066. |
  1067. label.part MNAME al arg.list '\n' {
  1068. #ifdef M_DEBUG
  1069. fprintf (stderr, "[MNAME %s]\n", $2->i_string);
  1070. #endif
  1071. $2->i_uses++ ;
  1072. arg_flag = 0;
  1073. parm_number = 0;
  1074. list(dollarsign);
  1075. expptr++;
  1076. est = est2;
  1077. est2 = NULL;
  1078. est[FLOC] = floc;
  1079. est[TEMPNUM] = (char *)(long)exp_number++;
  1080. floc = (char *)(long)($2->i_value);
  1081. mfseek(mfile, (long)floc, 0);
  1082. }
  1083. |
  1084. error {
  1085. err[fflag]++;
  1086. quoteflag = 0;
  1087. arg_flag = 0;
  1088. parm_number = 0;
  1089. if (est2)
  1090. {
  1091. int i;
  1092. for (i=0; i<PARMMAX; i++) {
  1093. if (est2[i])
  1094. #ifdef M_DEBUG
  1095. fprintf (stderr, "[Freeing2 arg%u(%p)]\n", i, est2[i]),
  1096. #endif
  1097. free(est2[i]);
  1098. }
  1099. free(est2);
  1100. est2 = NULL;
  1101. }
  1102. while(yychar != '\n' && yychar != '\0') yychar = yylex();
  1103. list(dollarsign);
  1104. yyclearin;yyerrok;
  1105. }
  1106. ;
  1107. colonordot:
  1108. ':'
  1109. |
  1110. '.'
  1111. ;
  1112. maybecolon:
  1113. /* empty */
  1114. |
  1115. ':'
  1116. ;
  1117. label.part:
  1118. /* empty */
  1119. { $$ = NULL; }
  1120. |
  1121. colonordot symbol {
  1122. switch($2->i_token) {
  1123. case UNDECLARED:
  1124. if (pass2)
  1125. err[pflag]++;
  1126. else {
  1127. $2->i_token = LABEL;
  1128. $2->i_value = dollarsign;
  1129. }
  1130. break;
  1131. case LABEL:
  1132. if (!pass2) {
  1133. $2->i_token = MULTDEF;
  1134. err[mflag]++;
  1135. } else if ($2->i_value != dollarsign)
  1136. err[pflag]++;
  1137. break;
  1138. default:
  1139. err[mflag]++;
  1140. $2->i_token = MULTDEF;
  1141. }
  1142. }
  1143. |
  1144. symbol maybecolon {
  1145. switch($1->i_token) {
  1146. case UNDECLARED:
  1147. if (pass2)
  1148. err[pflag]++;
  1149. else {
  1150. $1->i_token = LABEL;
  1151. $1->i_value = dollarsign;
  1152. }
  1153. break;
  1154. case LABEL:
  1155. if (!pass2) {
  1156. $1->i_token = MULTDEF;
  1157. err[mflag]++;
  1158. } else if ($1->i_value != dollarsign)
  1159. err[pflag]++;
  1160. break;
  1161. default:
  1162. err[mflag]++;
  1163. $1->i_token = MULTDEF;
  1164. }
  1165. }
  1166. ;
  1167. operation:
  1168. NOOPERAND
  1169. { emit1($1->i_value, 0, 0, 1); }
  1170. |
  1171. JP expression
  1172. { emitjp(0303, $2); }
  1173. |
  1174. CALL expression
  1175. { emit(3, 0315, $2, $2 >> 8); }
  1176. |
  1177. RST expression
  1178. { int a = $2, doneerr=0;
  1179. /* added support for normal RST form -rjm */
  1180. if (a >= 8) {
  1181. if ((a&7)!=0) doneerr=1,err[vflag]++;
  1182. a >>= 3;
  1183. }
  1184. if ((a > 7 || a < 0) && !doneerr) /* don't give two errs... */
  1185. err[vflag]++;
  1186. emit(1, $1->i_value + (a << 3));
  1187. }
  1188. |
  1189. ADD expression
  1190. { emit1(0306, 0, $2, 3); if (pass2) warnprt (1, 0); }
  1191. |
  1192. ADD ACC ',' expression
  1193. { emit1(0306, 0, $4, 3); }
  1194. |
  1195. ARITHC expression
  1196. { emit1(0306 + ($1->i_value << 3), 0, $2, 3); if (pass2) warnprt (1, 0); }
  1197. |
  1198. ARITHC ACC ',' expression
  1199. { emit1(0306 + ($1->i_value << 3), 0, $4, 3); }
  1200. |
  1201. LOGICAL expression
  1202. { emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
  1203. |
  1204. AND expression
  1205. { emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
  1206. |
  1207. OR expression
  1208. { emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
  1209. |
  1210. XOR expression
  1211. { emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
  1212. |
  1213. LOGICAL ACC ',' expression /* -cdk */
  1214. { emit1(0306 | ($1->i_value << 3), 0, $4, 3); if (pass2) warnprt (1, 0); }
  1215. |
  1216. AND ACC ',' expression /* -cdk */
  1217. { emit1(0306 | ($1->i_value << 3), 0, $4, 3); if (pass2) warnprt (1, 0); }
  1218. |
  1219. OR ACC ',' expression /* -cdk */
  1220. { emit1(0306 | ($1->i_value << 3), 0, $4, 3); if (pass2) warnprt (1, 0); }
  1221. |
  1222. XOR ACC ',' expression /* -cdk */
  1223. { emit1(0306 | ($1->i_value << 3), 0, $4, 3); if (pass2) warnprt (1, 0); }
  1224. |
  1225. ADD reg
  1226. { emit1(0200 + ($2 & 0377), $2, 0, 0); if (pass2) warnprt (1, 0); }
  1227. |
  1228. ADD ACC ',' reg
  1229. { emit1(0200 + ($4 & 0377), $4, 0, 0); }
  1230. |
  1231. ARITHC reg
  1232. { emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); if (pass2) warnprt (1, 0); }
  1233. |
  1234. ARITHC ACC ',' reg
  1235. { emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); }
  1236. |
  1237. LOGICAL reg
  1238. { emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
  1239. |
  1240. AND reg
  1241. { emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
  1242. |
  1243. OR reg
  1244. { emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
  1245. |
  1246. XOR reg
  1247. { emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
  1248. |
  1249. LOGICAL ACC ',' reg /* -cdk */
  1250. { emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); if (pass2) warnprt (1, 0); }
  1251. |
  1252. AND ACC ',' reg /* -cdk */
  1253. { emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); if (pass2) warnprt (1, 0); }
  1254. |
  1255. OR ACC ',' reg /* -cdk */
  1256. { emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); if (pass2) warnprt (1, 0); }
  1257. |
  1258. XOR ACC ',' reg /* -cdk */
  1259. { emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); if (pass2) warnprt (1, 0); }
  1260. |
  1261. SHIFT reg
  1262. {
  1263. if (suggest_optimise && pass2 && ($2 & 0377) == 7 && $1->i_value <= 4)
  1264. warnprt ($1->i_value + 4, 0);
  1265. if (pass2 && $1->i_value == 6)
  1266. warnprt (1, 0);
  1267. emit1(0145400 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0);
  1268. }
  1269. |
  1270. INCDEC reg
  1271. { emit1($1->i_value + (($2 & 0377) << 3) + 4, $2, 0, 0); }
  1272. |
  1273. ARITHC HL ',' bcdehlsp
  1274. { if ($1->i_value == 1)
  1275. emit(2,0355,0112+$4);
  1276. else
  1277. emit(2,0355,0102+$4);
  1278. }
  1279. |
  1280. ADD mar ',' bcdesp
  1281. { emitdad($2,$4); }
  1282. |
  1283. ADD mar ',' mar
  1284. {
  1285. if ($2 != $4) {
  1286. fprintf(stderr,"ADD mar, mar error\n");
  1287. err[fflag]++;
  1288. }
  1289. emitdad($2,$4);
  1290. }
  1291. |
  1292. INCDEC evenreg
  1293. { emit1(($1->i_value << 3) + ($2 & 0377) + 3, $2, 0, 1); }
  1294. |
  1295. PUSHPOP pushable
  1296. { emit1($1->i_value + ($2 & 0377), $2, 0, 1); }
  1297. |
  1298. BIT expression ',' reg
  1299. {
  1300. if ($2 < 0 || $2 > 7)
  1301. err[vflag]++;
  1302. emit1($1->i_value + (($2 & 7) << 3) + ($4 & 0377), $4, 0, 0);
  1303. }
  1304. |
  1305. JP condition ',' expression
  1306. { emitjp(0302 + $2, $4); }
  1307. |
  1308. JP '(' mar ')'
  1309. { emit1(0351, $3, 0, 1); }
  1310. |
  1311. JP mar
  1312. { emit1(0351, $2, 0, 1); if (pass2) warnprt (1, 0); }
  1313. |
  1314. CALL condition ',' expression
  1315. { emit(3, 0304 + $2, $4, $4 >> 8); }
  1316. |
  1317. JR expression
  1318. { emitjr(030,$2); }
  1319. |
  1320. JR spcondition ',' expression
  1321. { emitjr($1->i_value + $2, $4); }
  1322. |
  1323. DJNZ expression
  1324. { emitjr($1->i_value, $2); }
  1325. |
  1326. RET
  1327. { emit(1, $1->i_value); }
  1328. |
  1329. RET condition
  1330. { emit(1, 0300 + $2); }
  1331. |
  1332. LD reg ',' reg
  1333. {
  1334. if (($2 & 0377) == 6 && ($4 & 0377) == 6) {
  1335. fprintf(stderr,"LD reg, reg error\n");
  1336. err[fflag]++;
  1337. }
  1338. emit1(0100 + (($2 & 7) << 3) + ($4 & 7),$2 | $4, 0, 0);
  1339. }
  1340. |
  1341. LD reg ',' noparenexpr
  1342. {
  1343. if (suggest_optimise && pass2 && $4 == 0 && ($2 & 0377) == 7)
  1344. warnprt (3, 0);
  1345. emit1(6 + (($2 & 0377) << 3), $2, $4, 2);
  1346. }
  1347. |
  1348. LD reg ',' '(' RP ')'
  1349. { if ($2 != 7) {
  1350. fprintf(stderr,"LD reg, (RP) error\n");
  1351. err[fflag]++;
  1352. }
  1353. else emit(1, 012 + $5->i_value);
  1354. }
  1355. |
  1356. LD reg ',' parenexpr
  1357. {
  1358. if ($2 != 7) {
  1359. fprintf(stderr,"LD reg, (expr) error\n");
  1360. err[fflag]++;
  1361. }
  1362. else emit(3, 072, $4, $4 >> 8);
  1363. }
  1364. |
  1365. LD '(' RP ')' ',' ACC
  1366. { emit(1, 2 + $3->i_value); }
  1367. |
  1368. LD parenexpr ',' ACC
  1369. { emit(3, 062, $2, $2 >> 8); }
  1370. |
  1371. LD reg ',' MISCREG
  1372. {
  1373. if ($2 != 7) {
  1374. fprintf(stderr,"LD reg, MISCREG error\n");
  1375. err[fflag]++;
  1376. }
  1377. else emit(2, 0355, 0127 + $4->i_value);
  1378. }
  1379. |
  1380. LD MISCREG ',' ACC
  1381. { emit(2, 0355, 0107 + $2->i_value); }
  1382. |
  1383. LD evenreg ',' lxexpression
  1384. { emit1(1 + ($2 & 060), $2, $4, 5); }
  1385. |
  1386. LD evenreg ',' parenexpr
  1387. {
  1388. if (($2 & 060) == 040)
  1389. emit1(052, $2, $4, 5);
  1390. else
  1391. emit(4, 0355, 0113 + $2, $4, $4 >> 8);
  1392. }
  1393. |
  1394. LD parenexpr ',' evenreg
  1395. {
  1396. if (($4 & 060) == 040)
  1397. emit1(042, $4, $2, 5);
  1398. else
  1399. emit(4, 0355, 0103 + $4, $2, $2 >> 8);
  1400. }
  1401. |
  1402. LD evenreg ',' mar
  1403. {
  1404. if ($2 != 060) {
  1405. fprintf(stderr,"LD evenreg error\n");
  1406. err[fflag]++;
  1407. }
  1408. else
  1409. emit1(0371, $4, 0, 1);
  1410. }
  1411. |
  1412. EX RP ',' HL
  1413. {
  1414. if ($2->i_value != 020) {
  1415. fprintf(stderr,"EX RP, HL error\n");
  1416. err[fflag]++;
  1417. }
  1418. else
  1419. emit(1, 0353);
  1420. }
  1421. |
  1422. EX AF ',' AF setqf '\'' clrqf
  1423. { emit(1, 010); }
  1424. |
  1425. EX '(' SP ')' ',' mar
  1426. { emit1(0343, $6, 0, 1); }
  1427. |
  1428. IN realreg ',' parenexpr
  1429. {
  1430. if ($2 != 7) {
  1431. fprintf(stderr,"IN reg, (expr) error\n");
  1432. err[fflag]++;
  1433. }
  1434. else {
  1435. if ($4 < 0 || $4 > 255)
  1436. err[vflag]++;
  1437. emit(2, $1->i_value, $4);
  1438. }
  1439. }
  1440. |
  1441. IN realreg ',' '(' C ')'
  1442. { emit(2, 0355, 0100 + ($2 << 3)); }
  1443. |
  1444. IN F ',' '(' C ')'
  1445. { emit(2, 0355, 0160); }
  1446. |
  1447. OUT parenexpr ',' ACC
  1448. {
  1449. if ($2 < 0 || $2 > 255)
  1450. err[vflag]++;
  1451. emit(2, $1->i_value, $2);
  1452. }
  1453. |
  1454. OUT '(' C ')' ',' realreg
  1455. { emit(2, 0355, 0101 + ($6 << 3)); }
  1456. |
  1457. IM expression
  1458. {
  1459. if ($2 > 2 || $2 < 0)
  1460. err[vflag]++;
  1461. else
  1462. emit(2, $1->i_value >> 8, $1->i_value + (($2 + ($2 > 0)) << 3));
  1463. }
  1464. |
  1465. PHASE expression
  1466. {
  1467. if (phaseflag) {
  1468. err[oflag]++;
  1469. } else {
  1470. phaseflag = 1;
  1471. phdollar = dollarsign;
  1472. dollarsign = $2;
  1473. phbegin = dollarsign;
  1474. }
  1475. }
  1476. |
  1477. DEPHASE
  1478. {
  1479. if (!phaseflag) {
  1480. err[oflag]++;
  1481. } else {
  1482. phaseflag = 0;
  1483. dollarsign = phdollar + dollarsign - phbegin;
  1484. }
  1485. }
  1486. |
  1487. ORG expression
  1488. {
  1489. if (not_seen_org)
  1490. first_org_store=yyvsp[0].ival;
  1491. not_seen_org=0;
  1492. if (phaseflag) {
  1493. err[oflag]++;
  1494. dollarsign = phdollar + dollarsign - phbegin;
  1495. phaseflag = 0;
  1496. }
  1497. if ($2-dollarsign) {
  1498. flushbin();
  1499. if (pass2 && !output_hex && dollarsign != 0) {
  1500. if (yyvsp[0].ival < dollarsign) {
  1501. err[orgflag]++;
  1502. } else {
  1503. int f;
  1504. for (f=0;f<(yyvsp[0].ival - dollarsign);f++)
  1505. fputc(0, fbuf);
  1506. }
  1507. }
  1508. olddollar = $2;
  1509. dollarsign = $2;
  1510. }
  1511. }
  1512. |
  1513. DEFB db.list
  1514. |
  1515. DEFW dw.list
  1516. |
  1517. ENDM
  1518. ;
  1519. parm.list:
  1520. |
  1521. parm.element
  1522. |
  1523. parm.list ',' parm.element
  1524. ;
  1525. parm.element:
  1526. UNDECLARED
  1527. {
  1528. $1->i_token = MPARM;
  1529. if (parm_number >= PARMMAX)
  1530. error("Too many parameters");
  1531. $1->i_value = parm_number++;
  1532. }
  1533. ;
  1534. arg.list:
  1535. /* empty */
  1536. |
  1537. arg.element
  1538. |
  1539. arg.list ',' arg.element
  1540. ;
  1541. arg.element:
  1542. ARG
  1543. {
  1544. cp = malloc(strlen(tempbuf)+1);
  1545. #ifdef M_DEBUG
  1546. fprintf (stderr, "[Arg%u(%p): %s]\n", parm_number, cp, tempbuf);
  1547. #endif
  1548. est2[parm_number++] = cp;
  1549. strcpy(cp, tempbuf);
  1550. }
  1551. ;
  1552. reg:
  1553. realreg
  1554. |
  1555. mem
  1556. ;
  1557. realreg:
  1558. REGNAME
  1559. {
  1560. $$ = $1->i_value;
  1561. }
  1562. |
  1563. ACC
  1564. {
  1565. $$ = $1->i_value;
  1566. }
  1567. |
  1568. C
  1569. {
  1570. $$ = $1->i_value;
  1571. }
  1572. ;
  1573. mem:
  1574. '(' HL ')'
  1575. {
  1576. $$ = 6;
  1577. }
  1578. |
  1579. '(' INDEX expression ')'
  1580. {
  1581. disp = $3;
  1582. $$ = ($2->i_value & 0177400) | 6;
  1583. }
  1584. |
  1585. '(' INDEX ')'
  1586. {
  1587. disp = 0;
  1588. $$ = ($2->i_value & 0177400) | 6;
  1589. }
  1590. ;
  1591. evenreg:
  1592. bcdesp
  1593. |
  1594. mar
  1595. ;
  1596. pushable:
  1597. RP
  1598. {
  1599. $$ = $1->i_value;
  1600. }
  1601. |
  1602. AF
  1603. {
  1604. $$ = $1->i_value;
  1605. }
  1606. |
  1607. mar
  1608. ;
  1609. bcdesp:
  1610. RP
  1611. {
  1612. $$ = $1->i_value;
  1613. }
  1614. |
  1615. SP
  1616. {
  1617. $$ = $1->i_value;
  1618. }
  1619. ;
  1620. bcdehlsp:
  1621. bcdesp
  1622. |
  1623. HL
  1624. {
  1625. $$ = $1->i_value;
  1626. }
  1627. ;
  1628. mar:
  1629. HL
  1630. {
  1631. $$ = $1->i_value;
  1632. }
  1633. |
  1634. INDEX
  1635. {
  1636. $$ = $1->i_value;
  1637. }
  1638. ;
  1639. condition:
  1640. spcondition
  1641. |
  1642. COND
  1643. {
  1644. $$ = $1->i_value;
  1645. }
  1646. ;
  1647. spcondition:
  1648. SPCOND
  1649. {
  1650. $$ = $1->i_value;
  1651. }
  1652. |
  1653. C
  1654. { $$ = 030; }
  1655. ;
  1656. db.list:
  1657. db.list.element
  1658. |
  1659. db.list ',' db.list.element
  1660. ;
  1661. db.list.element:
  1662. TWOCHAR
  1663. {
  1664. dataemit(2, $1, $1>>8);
  1665. }
  1666. |
  1667. STRING
  1668. {
  1669. cp = $1;
  1670. while (*cp != '\0')
  1671. dataemit(1,*cp++);
  1672. }
  1673. |
  1674. expression
  1675. {
  1676. if ($1 < -128 || $1 > 255)
  1677. err[vflag]++;
  1678. dataemit(1, $1 & 0377);
  1679. }
  1680. ;
  1681. dw.list:
  1682. dw.list.element
  1683. |
  1684. dw.list ',' dw.list.element
  1685. ;
  1686. dw.list.element:
  1687. expression
  1688. {
  1689. dataemit(2, $1, $1>>8);
  1690. }
  1691. ;
  1692. lxexpression:
  1693. noparenexpr
  1694. |
  1695. TWOCHAR
  1696. ;
  1697. expression:
  1698. parenexpr
  1699. |
  1700. noparenexpr
  1701. ;
  1702. parenexpr:
  1703. '(' expression ')'
  1704. { $$ = $2; }
  1705. ;
  1706. noparenexpr:
  1707. LABEL
  1708. { $$ = $1->i_value; $1->i_uses++ ; }
  1709. |
  1710. NUMBER
  1711. |
  1712. ONECHAR
  1713. |
  1714. EQUATED
  1715. { $$ = $1->i_value; $1->i_uses++ ; }
  1716. |
  1717. WASEQUATED
  1718. {
  1719. $$ = $1->i_value; $1->i_uses++ ;
  1720. if ($1->i_equbad) {
  1721. /* forward reference to equ with a forward
  1722. * reference of its own cannot be resolved
  1723. * in two passes. -rjm
  1724. */
  1725. err[frflag]++;
  1726. }
  1727. }
  1728. |
  1729. DEFLED
  1730. { $$ = $1->i_value; $1->i_uses++ ; }
  1731. |
  1732. '$'
  1733. { $$ = dollarsign; }
  1734. |
  1735. UNDECLARED
  1736. {
  1737. err[uflag]++;
  1738. equ_bad_label=1;
  1739. $$ = 0;
  1740. }
  1741. |
  1742. MULTDEF
  1743. { $$ = $1->i_value; }
  1744. |
  1745. expression '+' expression
  1746. { $$ = $1 + $3; }
  1747. |
  1748. expression '-' expression
  1749. { $$ = $1 - $3; }
  1750. |
  1751. expression '/' expression
  1752. { if ($3 == 0) err[eflag]++; else $$ = $1 / $3; }
  1753. |
  1754. expression '*' expression
  1755. { $$ = $1 * $3; }
  1756. |
  1757. expression '%' expression
  1758. { if ($3 == 0) err[eflag]++; else $$ = $1 % $3; }
  1759. |
  1760. expression MOD expression
  1761. { if ($3 == 0) err[eflag]++; else $$ = $1 % $3; }
  1762. |
  1763. expression '&' expression
  1764. { $$ = $1 & $3; }
  1765. |
  1766. expression AND expression
  1767. { $$ = $1 & $3; }
  1768. |
  1769. expression '|' expression
  1770. { $$ = $1 | $3; }
  1771. |
  1772. expression OR expression
  1773. { $$ = $1 | $3; }
  1774. |
  1775. expression '^' expression
  1776. { $$ = $1 ^ $3; }
  1777. |
  1778. expression XOR expression
  1779. { $$ = $1 ^ $3; }
  1780. |
  1781. expression SHL expression
  1782. { $$ = $1 << $3; }
  1783. |
  1784. expression SHR expression
  1785. { $$ = (($1 >> 1) & 077777) >> ($3 - 1); }
  1786. |
  1787. expression '<' expression
  1788. { $$ = $1 < $3; }
  1789. |
  1790. expression '=' expression
  1791. { $$ = $1 == $3; }
  1792. |
  1793. expression '>' expression
  1794. { $$ = $1 > $3; }
  1795. |
  1796. expression LT expression
  1797. { $$ = $1 < $3; }
  1798. |
  1799. expression EQ expression
  1800. { $$ = $1 == $3; }
  1801. |
  1802. expression GT expression
  1803. { $$ = $1 > $3; }
  1804. |
  1805. expression LE expression
  1806. { $$ = $1 <= $3; }
  1807. |
  1808. expression GE expression
  1809. { $$ = $1 >= $3; }
  1810. |
  1811. expression NE expression
  1812. { $$ = $1 != $3; }
  1813. |
  1814. '[' expression ']'
  1815. { $$ = $2; }
  1816. |
  1817. NOT expression
  1818. { $$ = ~$2; }
  1819. |
  1820. '~' expression
  1821. { $$ = ~$2; }
  1822. |
  1823. '!' expression
  1824. { $$ = !$2; }
  1825. |
  1826. '+' expression %prec UNARY
  1827. { $$ = $2; }
  1828. |
  1829. '-' expression %prec UNARY
  1830. { $$ = -$2; }
  1831. ;
  1832. symbol:
  1833. UNDECLARED
  1834. |
  1835. LABEL
  1836. |
  1837. MULTDEF
  1838. |
  1839. EQUATED
  1840. |
  1841. WASEQUATED
  1842. |
  1843. DEFLED
  1844. ;
  1845. al:
  1846. { int i;
  1847. if (expptr >= MAXEXP)
  1848. error("Macro expansion level");
  1849. est2 = (char **) malloc((PARMMAX +4) * sizeof(char *));
  1850. expstack[expptr] = (char *)est2 ;
  1851. for (i=0; i<PARMMAX; i++)
  1852. est2[i] = 0;
  1853. arg_flag++;
  1854. }
  1855. ;
  1856. arg_on:
  1857. { arg_flag++; }
  1858. ;
  1859. arg_off:
  1860. { arg_flag = 0; }
  1861. ;
  1862. setqf:
  1863. { quoteflag++; }
  1864. ;
  1865. clrqf:
  1866. { quoteflag = 0; }
  1867. ;
  1868. %%
  1869. #define F_END 0
  1870. #define OTHER 1
  1871. #define SPACE 2
  1872. #define DIGIT 3
  1873. #define LETTER 4
  1874. #define STARTER 5
  1875. #define HEXIN 6
  1876. /*
  1877. * This is the table of character classes. It is used by the lexical
  1878. * analyser. (yylex())
  1879. */
  1880. char charclass[] = {
  1881. F_END, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
  1882. OTHER, SPACE, OTHER, OTHER, OTHER, SPACE, OTHER, OTHER,
  1883. OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
  1884. OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
  1885. SPACE, OTHER, OTHER, HEXIN, HEXIN, OTHER, HEXIN, OTHER,
  1886. OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
  1887. DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
  1888. DIGIT, DIGIT, OTHER, OTHER, OTHER, OTHER, OTHER, STARTER,
  1889. STARTER,LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1890. LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1891. LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1892. LETTER, LETTER, LETTER, OTHER, OTHER, OTHER, OTHER, LETTER,
  1893. OTHER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1894. LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1895. LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1896. LETTER, LETTER, LETTER, OTHER, OTHER, OTHER, OTHER, OTHER,
  1897. };
  1898. /*
  1899. * the following table tells which characters are parts of numbers.
  1900. * The entry is non-zero for characters which can be parts of numbers.
  1901. */
  1902. char numpart[] = {
  1903. 0, 0, 0, 0, 0, 0, 0, 0,
  1904. 0, 0, 0, 0, 0, 0, 0, 0,
  1905. 0, 0, 0, 0, 0, 0, 0, 0,
  1906. 0, 0, 0, 0, 0, 0, 0, 0,
  1907. 0, 0, 0, 0, 0, 0, 0, 0,
  1908. 0, 0, 0, 0, 0, 0, 0, 0,
  1909. '0', '1', '2', '3', '4', '5', '6', '7',
  1910. '8', '9', 0, 0, 0, 0, 0, 0,
  1911. 0, 'A', 'B', 'C', 'D', 'E', 'F', 0,
  1912. 'H', 0, 0, 0, 0, 0, 0, 'O',
  1913. 0, 'Q', 0, 0, 0, 0, 0, 0,
  1914. 0, 0, 0, 0, 0, 0, 0, 0,
  1915. 0, 'a', 'b', 'c', 'd', 'e', 'f', 0,
  1916. 'h', 0, 0, 0, 0, 0, 0, 'o',
  1917. 0, 'q', 0, 0, 0, 0, 0, 0,
  1918. 0, 0, 0, 0, 0, 0, 0, 0,
  1919. 0};
  1920. /*
  1921. * the following table is a list of assembler mnemonics;
  1922. * for each mnemonic the associated machine-code bit pattern
  1923. * and symbol type are given.
  1924. */
  1925. struct item keytab[] = {
  1926. {"a", 7, ACC, 0},
  1927. {"adc", 1, ARITHC, 0},
  1928. {"add", 0, ADD, 0},
  1929. {"af", 060, AF, 0},
  1930. {"and", 4, AND, 0},
  1931. {"ascii",0, DEFB, 0},
  1932. {"b", 0, REGNAME, 0},
  1933. {"bc", 0, RP, 0},
  1934. {"bit", 0145500,BIT, 0},
  1935. {"block",0, DEFS, 0},
  1936. {"byte",0, DEFB, 0},
  1937. {"c", 1, C, 0},
  1938. {"call",0315, CALL, 0},
  1939. {"ccf", 077, NOOPERAND, 0},
  1940. {"cmp", 7, LOGICAL, 0}, /* -cdk */
  1941. {"cond",0, IF, 0},
  1942. {"cp", 7, LOGICAL, 0},
  1943. {"cpd", 0166651,NOOPERAND, 0},
  1944. {"cpdr",0166671,NOOPERAND, 0},
  1945. {"cpi", 0166641,NOOPERAND, 0},
  1946. {"cpir",0166661,NOOPERAND, 0},
  1947. {"cpl", 057, NOOPERAND, 0},
  1948. {"d", 2, REGNAME, 0},
  1949. {"daa", 0047, NOOPERAND, 0},
  1950. {"db", 0, DEFB, 0},
  1951. {"de", 020, RP, 0},
  1952. {"dec", 1, INCDEC, 0},
  1953. {"defb",0, DEFB, 0},
  1954. {"defl",0, DEFL, 0},
  1955. {"defm",0, DEFB, 0},
  1956. {"defs",0, DEFS, 0},
  1957. {"defw",0, DEFW, 0},
  1958. {"dephase",0, DEPHASE, 0},
  1959. {"di", 0363, NOOPERAND, 0},
  1960. {"djnz",020, DJNZ, 0},
  1961. {"ds", 0, DEFS, 0},
  1962. {"dw", 0, DEFW, 0},
  1963. {"e", 3, REGNAME, 0},
  1964. {"ei", 0373, NOOPERAND, 0},
  1965. {"eject",1, LIST, 0},
  1966. {"elist",3, LIST, 0},
  1967. {"else",0, ELSE, 0},
  1968. {"end", 0, END, 0},
  1969. {"endc",0, ENDIF, 0},
  1970. {"endif",0, ENDIF, 0},
  1971. {"endm", 0, ENDM, 0},
  1972. {"eq", 0, EQ, 0},
  1973. {"equ", 0, EQU, 0},
  1974. {"ex", 0, EX, 0},
  1975. {"exx", 0331, NOOPERAND, 0},
  1976. {"f", 0, F, 0},
  1977. {"flist",4, LIST, 0},
  1978. {"ge", 0, GE, 0},
  1979. {"glist",5, LIST, 0},
  1980. {"gt", 0, GT, 0},
  1981. {"h", 4, REGNAME, 0},
  1982. {"halt",0166, NOOPERAND, 0},
  1983. {"hl", 040, HL, 0},
  1984. {"i", 0, MISCREG, 0},
  1985. {"if", 0, IF, 0},
  1986. {"im", 0166506,IM, 0},
  1987. {"in", 0333, IN, 0},
  1988. {"inc", 0, INCDEC, 0},
  1989. {"include", 3, ARGPSEUDO, 0},
  1990. {"ind", 0166652,NOOPERAND, 0},
  1991. {"indr",0166672,NOOPERAND, 0},
  1992. {"ini", 0166642,NOOPERAND, 0},
  1993. {"inir",0166662,NOOPERAND, 0},
  1994. {"ix", 0156440,INDEX, 0},
  1995. {"iy", 0176440,INDEX, 0},
  1996. {"jmp", 0303, JP, 0}, /* -cdk */
  1997. {"jp", 0303, JP, 0},
  1998. {"jr", 040, JR, 0},
  1999. {"l", 5, REGNAME, 0},
  2000. {"ld", 0, LD, 0},
  2001. {"ldd", 0166650,NOOPERAND, 0},
  2002. {"lddr",0166670,NOOPERAND, 0},
  2003. {"ldi", 0166640,NOOPERAND, 0},
  2004. {"ldir",0166660,NOOPERAND, 0},
  2005. {"le", 0, LE, 0},
  2006. {"list",0, LIST, 0},
  2007. {"lt", 0, LT, 0},
  2008. {"m", 070, COND, 0},
  2009. {"macro",0, MACRO, 0},
  2010. {"max", 1, MINMAX, 0},
  2011. {"min", 0, MINMAX, 0},
  2012. {"mlist",6, LIST, 0},
  2013. {"mod", 0, MOD, 0},
  2014. {"nc", 020, SPCOND, 0},
  2015. {"ne", 0, NE, 0},
  2016. {"neg", 0166504,NOOPERAND, 0},
  2017. {"nolist",-1, LIST, 0},
  2018. {"nop", 0, NOOPERAND, 0},
  2019. {"not", 0, NOT, 0},
  2020. {"nv", 040, COND, 0},
  2021. {"nz", 0, SPCOND, 0},
  2022. {"or", 6, OR, 0},
  2023. {"org", 0, ORG, 0},
  2024. {"otdr",0166673,NOOPERAND, 0},
  2025. {"otir",0166663,NOOPERAND, 0},
  2026. {"out", 0323, OUT, 0},
  2027. {"outd",0166653,NOOPERAND, 0},
  2028. {"outi",0166643,NOOPERAND, 0},
  2029. {"p", 060, COND, 0},
  2030. {"pe", 050, COND, 0},
  2031. {"phase",0, PHASE, 0},
  2032. {"po", 040, COND, 0},
  2033. {"pop", 0301, PUSHPOP, 0},
  2034. {"push", 0305, PUSHPOP, 0},
  2035. {"r", 010, MISCREG, 0},
  2036. {"read", 3, ARGPSEUDO, 0},
  2037. {"res", 0145600,BIT, 0},
  2038. {"ret", 0311, RET, 0},
  2039. {"reti",0166515,NOOPERAND, 0},
  2040. {"retn",0166505,NOOPERAND, 0},
  2041. {"rl", 2, SHIFT, 0},
  2042. {"rla", 027, NOOPERAND, 0},
  2043. {"rlc", 0, SHIFT, 0},
  2044. {"rlca",07, NOOPERAND, 0},
  2045. {"rld", 0166557,NOOPERAND, 0},
  2046. {"rmem",0, DEFS, 0},
  2047. {"rr", 3, SHIFT, 0},
  2048. {"rra", 037, NOOPERAND, 0},
  2049. {"rrc", 1, SHIFT, 0},
  2050. {"rrca",017, NOOPERAND, 0},
  2051. {"rrd", 0166547,NOOPERAND, 0},
  2052. {"rst", 0307, RST, 0},
  2053. {"rsym",1, ARGPSEUDO, 0},
  2054. {"sbc", 3, ARITHC, 0},
  2055. {"scf", 067, NOOPERAND, 0},
  2056. {"set", 0145700,BIT, 0},
  2057. {"shl", 0, SHL, 0},
  2058. {"shr", 0, SHR, 0},
  2059. {"sla", 4, SHIFT, 0},
  2060. {"sll", 6, SHIFT, 0}, /* Undocumented */
  2061. {"sp", 060, SP, 0},
  2062. {"space",2, LIST, 0},
  2063. {"sra", 5, SHIFT, 0},
  2064. {"srl", 7, SHIFT, 0},
  2065. {"sub", 2, LOGICAL, 0},
  2066. {"text",0, DEFB, 0},
  2067. {"title",0, ARGPSEUDO, 0},
  2068. {"v", 050, COND, 0},
  2069. {"word",0, DEFW, 0},
  2070. {"wsym",2, ARGPSEUDO, 0},
  2071. {"xor", 5, XOR, 0},
  2072. {"z", 010, SPCOND, 0}
  2073. };
  2074. /*
  2075. * user-defined items are tabulated in the following table.
  2076. */
  2077. struct item itemtab[ITEMTABLESIZE];
  2078. struct item *itemmax = itemtab+ITEMTABLESIZE;
  2079. /*
  2080. * lexical analyser, called by yyparse.
  2081. */
  2082. int yylex()
  2083. {
  2084. int c;
  2085. char *p;
  2086. int radix;
  2087. int limit;
  2088. int leadinghex = 0;
  2089. if (arg_flag)
  2090. return(getarg());
  2091. loop switch(charclass[c = nextchar()]) {
  2092. case F_END:
  2093. if (expptr) {
  2094. popsi();
  2095. continue;
  2096. } else return(0);
  2097. case SPACE:
  2098. break;
  2099. case LETTER:
  2100. case STARTER:
  2101. p = tempbuf;
  2102. do {
  2103. if (p >= tempmax)
  2104. error(symlong);
  2105. *p++ = (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
  2106. while ((c = nextchar()) == '$')
  2107. ;
  2108. } while (charclass[c]==LETTER || charclass[c]==DIGIT);
  2109. if (p - tempbuf > MAXSYMBOLSIZE)
  2110. {
  2111. if (pass2) warnprt (0, 1);
  2112. p = tempbuf + MAXSYMBOLSIZE;
  2113. }
  2114. *p++ = '\0';
  2115. peekc = c;
  2116. return(tokenofitem(UNDECLARED));
  2117. case HEXIN:
  2118. {
  2119. int corig = c;
  2120. if (*ifptr) return (skipline(c));
  2121. while ((c = nextchar ()) == '$');
  2122. if (!numpart[c])
  2123. {
  2124. peekc = c;
  2125. return (corig);
  2126. }
  2127. leadinghex = 1;
  2128. /* fall through */
  2129. }
  2130. case DIGIT:
  2131. if (*ifptr) return (skipline(c));
  2132. p = tempbuf;
  2133. do {
  2134. if (p >= tempmax)
  2135. error(symlong);
  2136. *p++ = (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
  2137. while ((c = nextchar()) == '$');
  2138. }
  2139. while(numpart[c]);
  2140. peekc = c;
  2141. if (leadinghex)
  2142. {
  2143. *p++ = 'h';
  2144. }
  2145. *p-- = '\0';
  2146. switch(*p) {
  2147. case 'o':
  2148. case 'q':
  2149. radix = 8;
  2150. limit = 020000;
  2151. *p = '\0';
  2152. break;
  2153. case 'd':
  2154. radix = 10;
  2155. limit = 6553;
  2156. *p = '\0';
  2157. break;
  2158. case 'h':
  2159. radix = 16;
  2160. limit = 010000;
  2161. *p = '\0';
  2162. break;
  2163. case 'b':
  2164. radix = 2;
  2165. limit = 077777;
  2166. *p = '\0';
  2167. break;
  2168. default:
  2169. radix = 10;
  2170. limit = 6553;
  2171. p++;
  2172. break;
  2173. }
  2174. /*
  2175. * tempbuf now points to the number, null terminated
  2176. * with radix 'radix'.
  2177. */
  2178. yylval.ival = 0;
  2179. p = tempbuf;
  2180. do {
  2181. c = *p - (*p > '9' ? ('a' - 10) : '0');
  2182. if (c >= radix)
  2183. {
  2184. err[iflag]++;
  2185. yylval.ival = 0;
  2186. break;
  2187. }
  2188. if (yylval.ival < limit ||
  2189. (radix == 10 && yylval.ival == 6553 && c < 6) ||
  2190. (radix == 2 && yylval.ival == limit))
  2191. yylval.ival = yylval.ival * radix + c;
  2192. else {
  2193. err[vflag]++;
  2194. yylval.ival = 0;
  2195. break;
  2196. }
  2197. }
  2198. while(*++p != '\0');
  2199. return(NUMBER);
  2200. default:
  2201. if (*ifptr)
  2202. return(skipline(c));
  2203. switch(c) {
  2204. int corig;
  2205. case ';':
  2206. return(skipline(c));
  2207. case '\'':
  2208. if (quoteflag) return('\'');
  2209. case '"':
  2210. corig = c;
  2211. p = tempbuf;
  2212. p[1] = 0;
  2213. do switch(c = nextchar()) {
  2214. case '\0':
  2215. case '\n':
  2216. err[bflag]++;
  2217. goto retstring;
  2218. case '\'':
  2219. case '"':
  2220. if (c == corig && (c = nextchar()) != corig) {
  2221. retstring:
  2222. peekc = c;
  2223. *p = '\0';
  2224. if ((p-tempbuf) >2) {
  2225. yylval.cval = tempbuf;
  2226. return(STRING);
  2227. } else if (p-tempbuf == 2) {
  2228. p = tempbuf;
  2229. yylval.ival = *p++ ;
  2230. yylval.ival |= *p<<8;
  2231. return(TWOCHAR);
  2232. } else {
  2233. p = tempbuf;
  2234. yylval.ival = *p++;
  2235. return(ONECHAR);
  2236. }
  2237. }
  2238. default:
  2239. *p++ = c;
  2240. } while (p < tempmax);
  2241. /*
  2242. * if we break out here, our string is longer than
  2243. * our input line
  2244. */
  2245. error("string buffer overflow");
  2246. case '<':
  2247. corig = c;
  2248. switch (c = nextchar ()) {
  2249. case '=':
  2250. return LE;
  2251. case '<':
  2252. return SHL;
  2253. case '>':
  2254. return NE;
  2255. default:
  2256. peekc = c;
  2257. return corig;
  2258. }
  2259. /* break; suppress "unreachable" warning for tcc */
  2260. case '>':
  2261. corig = c;
  2262. switch (c = nextchar ()) {
  2263. case '=':
  2264. return GE;
  2265. case '>':
  2266. return SHR;
  2267. default:
  2268. peekc = c;
  2269. return corig;
  2270. }
  2271. /* break; suppress "unreachable" warning for tcc */
  2272. case '!':
  2273. corig = c;
  2274. switch (c = nextchar ()) {
  2275. case '=':
  2276. return NE;
  2277. default:
  2278. peekc = c;
  2279. return corig;
  2280. }
  2281. /* break; suppress "unreachable" warning for tcc */
  2282. case '=':
  2283. corig = c;
  2284. switch (c = nextchar ()) {
  2285. case '=':
  2286. return EQ;
  2287. default:
  2288. peekc = c;
  2289. return corig;
  2290. }
  2291. /* break; suppress "unreachable" warning for tcc */
  2292. default:
  2293. return(c);
  2294. }
  2295. }
  2296. }
  2297. /*
  2298. * return the token associated with the string pointed to by
  2299. * tempbuf. if no token is associated with the string, associate
  2300. * deftoken with the string and return deftoken.
  2301. * in either case, cause yylval to point to the relevant
  2302. * symbol table entry.
  2303. */
  2304. int tokenofitem(int deftoken)
  2305. {
  2306. char *p;
  2307. struct item * ip;
  2308. int i;
  2309. int r, l, u, hash;
  2310. #ifdef T_DEBUG
  2311. fputs("'tokenofitem entry' ", stderr) ;
  2312. fputs(tempbuf, stderr) ;
  2313. #endif
  2314. if (strcmp (tempbuf, "cmp") == 0 ||
  2315. strcmp (tempbuf, "jmp") == 0 ||
  2316. strcmp (tempbuf, "v") == 0 ||
  2317. strcmp (tempbuf, "nv") == 0)
  2318. if (pass2) warnprt (1, 1);
  2319. /*
  2320. * binary search
  2321. */
  2322. l = 0;
  2323. u = (sizeof keytab/sizeof keytab[0])-1;
  2324. while (l <= u) {
  2325. i = (l+u)/2;
  2326. ip = &keytab[i];
  2327. if ((r = strcmp(tempbuf, ip->i_string)) == 0)
  2328. goto found;
  2329. if (r < 0)
  2330. u = i-1;
  2331. else
  2332. l = i+1;
  2333. }
  2334. /*
  2335. * hash into item table
  2336. */
  2337. hash = 0;
  2338. p = tempbuf;
  2339. while (*p) hash += *p++;
  2340. hash %= ITEMTABLESIZE;
  2341. ip = &itemtab[hash];
  2342. loop {
  2343. if (ip->i_token == 0)
  2344. break;
  2345. if (strcmp(tempbuf, ip->i_string) == 0)
  2346. goto found;
  2347. if (++ip >= itemmax)
  2348. ip = itemtab;
  2349. }
  2350. if (!deftoken) {
  2351. i = 0 ;
  2352. goto token_done ;
  2353. }
  2354. if (++nitems > ITEMTABLESIZE-20)
  2355. error("item table overflow");
  2356. ip->i_string = malloc(strlen(tempbuf)+1);
  2357. ip->i_token = deftoken;
  2358. ip->i_uses = 0;
  2359. ip->i_equbad = 0;
  2360. strcpy(ip->i_string, tempbuf);
  2361. found:
  2362. if (*ifptr) {
  2363. if (ip->i_token == ENDIF) {
  2364. i = ENDIF ;
  2365. goto token_done ;
  2366. }
  2367. if (ip->i_token == ELSE) {
  2368. /* We must only honour the ELSE if it is not
  2369. in a nested failed IF/ELSE */
  2370. char forbid = 0;
  2371. char *ifstackptr;
  2372. for (ifstackptr = ifstack; ifstackptr != ifptr; ++ifstackptr) {
  2373. if (*ifstackptr) {
  2374. forbid = 1;
  2375. break;
  2376. }
  2377. }
  2378. if (!forbid) {
  2379. i = ELSE;
  2380. goto token_done;
  2381. }
  2382. }
  2383. if (ip->i_token == IF) {
  2384. if (ifptr >= ifstmax)
  2385. error("Too many ifs");
  2386. else *++ifptr = 1;
  2387. }
  2388. i = skipline(' ');
  2389. goto token_done ;
  2390. }
  2391. yylval.itemptr = ip;
  2392. i = ip->i_token;
  2393. if (i == EQU) equ_bad_label=0;
  2394. token_done:
  2395. #ifdef T_DEBUG
  2396. fputs("\t'tokenofitem exit'\n", stderr) ;
  2397. #endif
  2398. return(i) ;
  2399. }
  2400. /*
  2401. * interchange two entries in the item table -- used by custom_qsort
  2402. */
  2403. void interchange(int i, int j)
  2404. {
  2405. struct item *fp, *tp;
  2406. struct item temp;
  2407. fp = &itemtab[i];
  2408. tp = &itemtab[j];
  2409. temp.i_string = fp->i_string;
  2410. temp.i_value = fp->i_value;
  2411. temp.i_token = fp->i_token;
  2412. temp.i_uses = fp->i_uses;
  2413. temp.i_equbad = fp->i_equbad;
  2414. fp->i_string = tp->i_string;
  2415. fp->i_value = tp->i_value;
  2416. fp->i_token = tp->i_token;
  2417. fp->i_uses = tp->i_uses;
  2418. fp->i_equbad = tp->i_equbad;
  2419. tp->i_string = temp.i_string;
  2420. tp->i_value = temp.i_value;
  2421. tp->i_token = temp.i_token;
  2422. tp->i_uses = temp.i_uses;
  2423. tp->i_equbad = temp.i_equbad;
  2424. }
  2425. /*
  2426. * quick sort -- used by putsymtab to sort the symbol table
  2427. */
  2428. void custom_qsort(int m, int n)
  2429. {
  2430. int i, j;
  2431. if (m < n) {
  2432. i = m;
  2433. j = n+1;
  2434. loop {
  2435. do i++; while(strcmp(itemtab[i].i_string,
  2436. itemtab[m].i_string) < 0);
  2437. do j--; while(strcmp(itemtab[j].i_string,
  2438. itemtab[m].i_string) > 0);
  2439. if (i < j) interchange(i, j); else break;
  2440. }
  2441. interchange(m, j);
  2442. custom_qsort(m, j-1);
  2443. custom_qsort(j+1, n);
  2444. }
  2445. }
  2446. /*
  2447. * get the next character
  2448. */
  2449. int nextchar()
  2450. {
  2451. int c, ch;
  2452. static char *earg;
  2453. if (peekc != -1) {
  2454. c = peekc;
  2455. peekc = -1;
  2456. return(c);
  2457. }
  2458. start:
  2459. if (earg) {
  2460. if (*earg)
  2461. return(addtoline(*earg++));
  2462. earg = 0;
  2463. }
  2464. if (expptr) {
  2465. if ((ch = getm()) == '\1') { /* expand argument */
  2466. ch = getm() - 'A';
  2467. if (ch >= 0 && ch < PARMMAX && est[ch])
  2468. earg = est[ch];
  2469. goto start;
  2470. }
  2471. if (ch == '\2') { /* local symbol */
  2472. ch = getm() - 'A';
  2473. if (ch >= 0 && ch < PARMMAX && est[ch]) {
  2474. earg = est[ch];
  2475. goto start;
  2476. }
  2477. earg = getlocal(ch, (int)(long)est[TEMPNUM]);
  2478. goto start;
  2479. }
  2480. return(addtoline(ch));
  2481. }
  2482. ch = getc(now_file) ;
  2483. /* if EOF, check for include file */
  2484. if (ch == EOF) {
  2485. while (ch == EOF && now_in) {
  2486. fclose(fin[now_in]) ;
  2487. free(src_name[now_in]) ;
  2488. now_file = fin[--now_in] ;
  2489. ch = getc(now_file) ;
  2490. }
  2491. if (linein[now_in] < 0) {
  2492. lstoff = 1 ;
  2493. linein[now_in] = -linein[now_in] ;
  2494. } else {
  2495. lstoff = 0 ;
  2496. }
  2497. if (pass2 && iflist()) {
  2498. lineout() ;
  2499. fprintf(fout, "**** %s ****\n", src_name[now_in]) ;
  2500. }
  2501. }
  2502. if (ch == '\n')
  2503. {
  2504. linein[now_in]++ ;
  2505. }
  2506. return(addtoline(ch)) ;
  2507. }
  2508. /*
  2509. * skip to rest of the line -- comments and if skipped lines
  2510. */
  2511. int skipline(int ac)
  2512. {
  2513. int c;
  2514. c = ac;
  2515. while (c != '\n' && c != '\0')
  2516. c = nextchar();
  2517. return('\n');
  2518. }
  2519. void usage()
  2520. {
  2521. printf(
  2522. "zmac " ZMAC_VERSION
  2523. #ifdef ZMAC_BETA
  2524. ZMAC_BETA
  2525. #endif
  2526. ", a Z80 macro cross-assembler.\n"
  2527. "Public domain by Bruce Norskog and others.\n"
  2528. "\n"
  2529. #ifdef __riscos
  2530. "usage: zmac [--help] [--version] [-AbcdefghilLmnOpsStTz]\n"
  2531. #else
  2532. "usage: zmac [--help] [--version] [-AbcdefghilLmnOpsStz]\n"
  2533. #endif
  2534. " [-o outfile] [-x listfile] [filename]\n"
  2535. "\n"
  2536. " --help give this usage help.\n"
  2537. " --version report version number.\n"
  2538. " -A output AMSDOS binary file rather than default binary file.\n"
  2539. " -b don't generate the m/c output at all.\n"
  2540. " -c make the listing continuous, i.e. don't generate any\n"
  2541. " page breaks or page headers. (This is the default.)\n"
  2542. " -d make the listing discontinuous.\n"
  2543. " -e omit the `error report' section in the listing.\n"
  2544. " -f list instructions not assembled due to `if' expressions being\n"
  2545. " false. (Normally these are not shown in the listing.)\n"
  2546. " -g list only the first line of equivalent hex for a source line.\n"
  2547. " -h output CP/M-ish Intel hex format (using extension `.hex')\n"
  2548. " rather than default binary file (extension `.bin').\n"
  2549. " -i don't list files included with `include'.\n"
  2550. " -l don't generate a listing at all.\n"
  2551. " -L generate listing; overrides any conflicting options.\n"
  2552. " -m list macro expansions.\n"
  2553. " -n omit line numbers from listing.\n"
  2554. " -o assemble output to `outfile'.\n"
  2555. " -O suggest possible optimisations (as warnings).\n"
  2556. " -p use linefeeds for page break in listing rather than ^L.\n"
  2557. " -s omit the symbol table from the listing.\n"
  2558. " -S show relevant line when reporting errors.\n"
  2559. " -t give terse (single-letter) error codes in listing.\n"
  2560. #ifdef __riscos
  2561. " -T enable DDE throwback for reporting warnings and errors.\n"
  2562. #endif
  2563. " -x generate listing to `listfile' (`-' for stdout).\n"
  2564. " -z accept 8080-compatible instructions only; flag any\n"
  2565. " Z80-specific ones as errors.\n");
  2566. }
  2567. int main(int argc, char *argv[])
  2568. {
  2569. struct item *ip;
  2570. int i, c;
  2571. #ifdef ZMAC_BETA
  2572. printf ("*** THIS IS A BETA VERSION; NOT FOR GENERAL DISTRIBUTION ***\n");
  2573. #endif
  2574. if(argc==1)
  2575. usage(),exit(0);
  2576. if(argc>=2) {
  2577. if(strcmp(argv[1],"--help")==0)
  2578. usage(),exit(0);
  2579. else if(strcmp(argv[1],"--version")==0)
  2580. puts("zmac " ZMAC_VERSION
  2581. #ifdef ZMAC_BETA
  2582. ZMAC_BETA
  2583. #endif
  2584. ),exit(0);
  2585. }
  2586. fout = stdout ;
  2587. fin[0] = stdin ;
  2588. now_file = stdin ;
  2589. *bin = *listf = 0;
  2590. optnerr = 0;
  2591. while((c = getoptn(argc,argv,
  2592. #ifdef __riscos
  2593. "AbcdefghilLmno:OpsStTx:z"
  2594. #else
  2595. "AbcdefghilLmno:OpsStx:z"
  2596. #endif
  2597. )) != EOF) {
  2598. switch(c) {
  2599. case 'A': /* AMSDOS binary -mep */
  2600. output_amsdos = 1;
  2601. output_hex = 0;
  2602. break;
  2603. case 'b': /* no binary */
  2604. bopt = 0;
  2605. break;
  2606. case 'c': /* continuous listing */
  2607. continuous_listing = 1;
  2608. break;
  2609. case 'd': /* discontinuous listing */
  2610. continuous_listing = 0;
  2611. break;
  2612. case 'e': /* error list only */
  2613. eopt = 0;
  2614. edef = 0;
  2615. break;
  2616. case 'f': /* print if skipped lines */
  2617. fopt++;
  2618. fdef++;
  2619. break;
  2620. case 'g': /* do not list extra code */
  2621. gopt = 0;
  2622. gdef = 0;
  2623. break;
  2624. case 'h': /* output .hex not .bin -rjm */
  2625. output_hex = 1;
  2626. output_amsdos = 0;
  2627. break;
  2628. case 'i': /* do not list include files */
  2629. iopt = 1 ;
  2630. break;
  2631. case 'l': /* no list */
  2632. lopt++;
  2633. break;
  2634. case 'L': /* force listing of everything */
  2635. lston++;
  2636. break;
  2637. case 'm': /* print macro expansions */
  2638. mdef++;
  2639. mopt++;
  2640. break;
  2641. case 'n': /* put line numbers off */
  2642. nopt-- ;
  2643. break;
  2644. case 'o': /* specify m/c output file */
  2645. strcpy(bin, optnarg);
  2646. break;
  2647. case 'O': /* suggest optimisations */
  2648. suggest_optimise = 1;
  2649. break;
  2650. case 'p': /* put out four \n's for eject */
  2651. popt-- ;
  2652. break;
  2653. case 's': /* don't produce a symbol list */
  2654. sopt++;
  2655. break;
  2656. case 'S': /* show line which caused error */
  2657. show_error_line = 1;
  2658. break;
  2659. case 't': /* terse error messages in listing */
  2660. terse_lst_errors = 1;
  2661. break;
  2662. #ifdef __riscos
  2663. case 'T': /* RISC OS throwback -mep */
  2664. riscos_thbk = 1;
  2665. break;
  2666. #endif
  2667. case 'x': /* specify listing file */
  2668. if(strcmp(optnarg, "-") == 0)
  2669. oldoopt++; /* list to stdout (old `-o') */
  2670. else
  2671. strcpy(listf, optnarg);
  2672. break;
  2673. case 'z': /* 8080-compatible ops only */
  2674. output_8080_only = 1;
  2675. break;
  2676. case '?':
  2677. default: /* error */
  2678. justerror("Unknown option or missing argument");
  2679. break;
  2680. }
  2681. }
  2682. if(optnind != argc-1) justerror("Missing, extra or mispositioned argument");
  2683. atexit (doatexit);
  2684. sourcef = argv[optnind];
  2685. strcpy(src, sourcef);
  2686. if ((now_file = fopen(src, "r")) == NULL)
  2687. {
  2688. /* If filename has no pre-existing suffix, then try .z */
  2689. suffix_if_none (src, "z");
  2690. if ((now_file = fopen(src, "r")) == NULL)
  2691. fileerror("Cannot open source file", src);
  2692. }
  2693. now_in = 0 ;
  2694. fin[now_in] = now_file ;
  2695. src_name[now_in] = src ;
  2696. #ifdef __riscos
  2697. riscos_set_csd(src); /* -mep */
  2698. #endif
  2699. /* If we haven't got a bin file filename, then create one from the
  2700. * source filename (.hex extension if option -h is specified).
  2701. */
  2702. if (*bin == 0) {
  2703. strcpy(bin, sourcef);
  2704. if (output_hex)
  2705. suffix(bin,"hex");
  2706. else
  2707. suffix(bin,"bin");
  2708. }
  2709. if (bopt)
  2710. if (( fbuf = fopen(bin, output_hex ? "w" : "wb")) == NULL)
  2711. fileerror("Cannot create binary file", bin);
  2712. if (output_amsdos)
  2713. for(i=0; i<128; i++)
  2714. putc(0,fbuf); /* -mep */
  2715. if (!lopt && !oldoopt) {
  2716. /* If we've not got a filename for the listing file
  2717. * (-x option) then create one from the source filename
  2718. * (.lst extension)
  2719. */
  2720. if( *listf == 0 ) {
  2721. strcpy(listf, sourcef);
  2722. suffix(listf,"lst");
  2723. }
  2724. if ((fout = fopen(listf, "w")) == NULL)
  2725. fileerror("Cannot create list file", listf);
  2726. } else
  2727. fout = stdout ;
  2728. strcpy(mtmp, sourcef);
  2729. suffix(mtmp,"tmp");
  2730. mfile = mfopen(mtmp,"w+b") ;
  2731. if (mfile == NULL) {
  2732. fileerror("Cannot create temp file", mtmp);
  2733. }
  2734. /*
  2735. * get the time
  2736. */
  2737. time(&now);
  2738. timp = ctime(&now);
  2739. timp[16] = 0;
  2740. timp[24] = 0;
  2741. title = sourcef;
  2742. /*
  2743. * pass 1
  2744. */
  2745. #ifdef DEBUG
  2746. fputs("DEBUG-pass 1\n", stderr) ;
  2747. #endif
  2748. setvars();
  2749. yyparse();
  2750. pass2++;
  2751. ip = &itemtab[-1];
  2752. while (++ip < itemmax) {
  2753. /* reset use count */
  2754. ip->i_uses = 0 ;
  2755. /* set macro names, equated and defined names */
  2756. switch (ip->i_token) {
  2757. case MNAME:
  2758. ip->i_token = OLDMNAME;
  2759. break;
  2760. case EQUATED:
  2761. ip->i_token = WASEQUATED;
  2762. break;
  2763. case DEFLED:
  2764. ip->i_token = UNDECLARED;
  2765. break;
  2766. }
  2767. }
  2768. setvars();
  2769. fseek(now_file, (long)0, 0);
  2770. #ifdef DEBUG
  2771. fputs("DEBUG- pass 2\n", stderr) ;
  2772. #endif
  2773. yyparse();
  2774. if (bopt) {
  2775. flushbin();
  2776. if (output_hex) {
  2777. putc(':', fbuf);
  2778. if (xeq_flag) {
  2779. puthex(0, fbuf);
  2780. puthex(xeq >> 8, fbuf);
  2781. puthex(xeq, fbuf);
  2782. puthex(1, fbuf);
  2783. puthex(255-(xeq >> 8)-xeq, fbuf);
  2784. } else
  2785. for (i = 0; i < 10; i++)
  2786. putc('0', fbuf);
  2787. putc('\n', fbuf);
  2788. }
  2789. if (output_amsdos) {
  2790. char leafname[] = "FILENAMEBIN";
  2791. unsigned int chk;
  2792. unsigned int filelen = dollarsign - first_org_store;
  2793. if (filelen & 0x7f)
  2794. {
  2795. putc (0x1a, fbuf); /* CP/M EOF char */
  2796. }
  2797. rewind(fbuf);
  2798. chk=0;
  2799. putc(0,fbuf);
  2800. for(i=0;i<11;i++) {
  2801. putc(leafname[i],fbuf);
  2802. chk+=leafname[i];
  2803. }
  2804. for(i=0;i<6;i++)
  2805. putc(0,fbuf);
  2806. putc(2,fbuf); /* Unprotected binary */
  2807. chk+=2;
  2808. putc(0,fbuf);
  2809. putc(0,fbuf);
  2810. putc(first_org_store & 0xFF,fbuf);
  2811. chk+=first_org_store & 0xFF;
  2812. putc(first_org_store >> 8,fbuf);
  2813. chk+=first_org_store >> 8;
  2814. putc(0,fbuf);
  2815. putc(filelen & 0xFF,fbuf);
  2816. chk+=filelen & 0xFF;
  2817. putc(filelen >> 8,fbuf);
  2818. chk+=filelen >> 8;
  2819. /* Next bit should be entry address really */
  2820. putc(first_org_store & 0xFF,fbuf);
  2821. chk+=first_org_store & 0xFF;
  2822. putc(first_org_store >> 8,fbuf);
  2823. chk+=first_org_store >> 8;
  2824. for(i=28;i<64;i++)
  2825. putc(0,fbuf);
  2826. putc(filelen & 0xFF,fbuf);
  2827. chk+=filelen & 0xFF;
  2828. putc(filelen >> 8,fbuf);
  2829. chk+=filelen >> 8;
  2830. putc(0,fbuf); /* this would be used if length>64K */
  2831. putc(chk & 0xFF,fbuf);
  2832. putc(chk >> 8,fbuf);
  2833. }
  2834. fflush(fbuf);
  2835. }
  2836. if (!lopt)
  2837. fflush(fout);
  2838. if (*writesyms)
  2839. outsymtab(writesyms);
  2840. if (eopt)
  2841. erreport();
  2842. if (!lopt && !sopt)
  2843. putsymtab();
  2844. if (!lopt) {
  2845. eject();
  2846. fflush(fout);
  2847. }
  2848. exit(had_errors);
  2849. return(had_errors); /* main () does return int, after all... */
  2850. }
  2851. void doatexit (void)
  2852. {
  2853. #ifdef __riscos
  2854. if (riscos_throwback_started)
  2855. {
  2856. _swix(DDEUtils_ThrowbackEnd,0);
  2857. }
  2858. _swix(DDEUtils_Prefix,1,0); /* Unset CSD */
  2859. #endif
  2860. }
  2861. /*
  2862. * set some data values before each pass
  2863. */
  2864. void setvars()
  2865. {
  2866. int i;
  2867. peekc = -1;
  2868. linein[now_in] = linecnt = 0;
  2869. exp_number = 0;
  2870. emitptr = emitbuf;
  2871. lineptr = linebuf;
  2872. ifptr = ifstack;
  2873. expifp = expif;
  2874. *ifptr = 0;
  2875. dollarsign = 0;
  2876. olddollar = 0;
  2877. phaseflag = 0;
  2878. for (i=0; i<FLAGS; i++) err[i] = 0;
  2879. }
  2880. /*
  2881. * print out an error message and die
  2882. */
  2883. void error(char *as)
  2884. {
  2885. *linemax = 0;
  2886. fprintf(fout, "%s\n", linebuf);
  2887. fflush(fout);
  2888. fprintf(stderr, "%s\n", as) ;
  2889. exit(1);
  2890. }
  2891. /*
  2892. * alternate version
  2893. */
  2894. void fileerror(char *as,char *filename)
  2895. {
  2896. *linemax = 0;
  2897. if (fout != NULL && fout != stdout)
  2898. fprintf(fout, "%s\n", linebuf);
  2899. fflush(fout);
  2900. fprintf(stderr, "%s `%s'\n", as, filename) ;
  2901. exit(1);
  2902. }
  2903. /*
  2904. * alternate alternate version
  2905. */
  2906. void justerror(char *as)
  2907. {
  2908. fprintf(stderr, "%s\n", as) ;
  2909. exit(1);
  2910. }
  2911. /*
  2912. * output the symbol table
  2913. */
  2914. void putsymtab()
  2915. {
  2916. struct item *tp, *fp;
  2917. int i, j, k, t, rows;
  2918. char c, c1 ;
  2919. if (!nitems)
  2920. return;
  2921. /* compact the table so unused and UNDECLARED entries are removed */
  2922. tp = &itemtab[-1];
  2923. for (fp = itemtab; fp<itemmax; fp++) {
  2924. if (fp->i_token == UNDECLARED) {
  2925. nitems--;
  2926. continue;
  2927. }
  2928. if (fp->i_token == 0)
  2929. continue;
  2930. tp++;
  2931. if (tp != fp) {
  2932. tp->i_string = fp->i_string;
  2933. tp->i_value = fp->i_value;
  2934. tp->i_token = fp->i_token;
  2935. tp->i_uses = fp->i_uses ;
  2936. tp->i_equbad = fp->i_equbad ;
  2937. }
  2938. }
  2939. tp++;
  2940. tp->i_string = "{";
  2941. /* sort the table */
  2942. custom_qsort(0, nitems-1);
  2943. title = "** Symbol Table **";
  2944. rows = (nitems+3) / 3;
  2945. if (rows+5+line > 60)
  2946. eject();
  2947. lineout();
  2948. fprintf(fout,"\n\n\nSymbol Table:\n\n");
  2949. line += 4;
  2950. for (i=0; i<rows; i++) {
  2951. for(j=0; j<3; j++) {
  2952. k = rows*j+i;
  2953. if (k < nitems) {
  2954. tp = &itemtab[k];
  2955. t = tp->i_token;
  2956. c = ' ' ;
  2957. if (t == EQUATED || t == DEFLED)
  2958. c = '=' ;
  2959. if (tp->i_uses == 0)
  2960. c1 = '+' ;
  2961. else
  2962. c1 = ' ' ;
  2963. fprintf(fout, "%-15s%c%4x%c ",
  2964. tp->i_string, c, tp->i_value & 0xffff, c1);
  2965. }
  2966. }
  2967. lineout();
  2968. putc('\n', fout);
  2969. }
  2970. }
  2971. /*
  2972. * put out error report
  2973. */
  2974. void erreport()
  2975. {
  2976. int i, numerr;
  2977. if (line > 50) eject();
  2978. lineout();
  2979. numerr = 0;
  2980. for (i=0; i<FLAGS; i++) numerr += keeperr[i];
  2981. if (numerr) {
  2982. fputs("\n\n\nError report:\n\n", fout);
  2983. fprintf(fout, "%6d error%s\n", DO_PLURAL(numerr));
  2984. line += 5;
  2985. } else {
  2986. fputs("\n\n\nStatistics:\n", fout);
  2987. line += 3;
  2988. }
  2989. for (i=0; i<FLAGS; i++)
  2990. if (keeperr[i]) {
  2991. lineout();
  2992. if (terse_lst_errors)
  2993. /* no plural on this because it would
  2994. * odd, I think. -rjm
  2995. */
  2996. fprintf(fout, "%6d %c -- %s error\n",
  2997. keeperr[i], errlet[i], errname[i]);
  2998. else
  2999. /* can't use DO_PLURAL for this due to
  3000. * the %s in the middle... -rjm
  3001. */
  3002. fprintf(fout, "%6d %s error%s\n",
  3003. keeperr[i], errname[i],
  3004. (keeperr[i]==1)?"":"s");
  3005. }
  3006. if (line > 55) eject();
  3007. lineout();
  3008. fprintf(fout, "\n%6d\tsymbol%s\n", DO_PLURAL(nitems));
  3009. fprintf(fout, "%6d\tbyte%s\n", DO_PLURAL(nbytes));
  3010. line += 2;
  3011. if (mfptr) {
  3012. if (line > 53) eject();
  3013. lineout();
  3014. fprintf(fout, "\n%6d\tmacro call%s\n", DO_PLURAL(exp_number));
  3015. fprintf(fout, "%6d\tmacro byte%s\n", DO_PLURAL(mfptr));
  3016. fprintf(fout, "%6d\tinvented symbol%s\n",
  3017. DO_PLURAL(invented/2));
  3018. line += 3;
  3019. }
  3020. }
  3021. /*
  3022. * lexical analyser for macro definition
  3023. */
  3024. void mlex()
  3025. {
  3026. char *p;
  3027. int c;
  3028. int t;
  3029. /*
  3030. * move text onto macro file, changing formal parameters
  3031. */
  3032. #ifdef M_DEBUG
  3033. fprintf(stderr,"enter 'mlex'\n") ;
  3034. #endif
  3035. inmlex++;
  3036. c = nextchar();
  3037. loop {
  3038. switch(charclass[c]) {
  3039. case DIGIT:
  3040. while (numpart[c]) {
  3041. putm(c);
  3042. c = nextchar();
  3043. }
  3044. continue;
  3045. case STARTER:
  3046. case LETTER:
  3047. t = 0;
  3048. p = tempbuf+MAXSYMBOLSIZE+2;
  3049. do {
  3050. if (p >= tempmax)
  3051. error(symlong);
  3052. *p++ = c;
  3053. if (t < MAXSYMBOLSIZE)
  3054. tempbuf[t++] = (c >= 'A' && c <= 'Z') ?
  3055. c+'a'-'A' : c;
  3056. else
  3057. if (pass2) warnprt (0, 1);
  3058. c = nextchar();
  3059. } while (charclass[c]==LETTER || charclass[c]==DIGIT);
  3060. tempbuf[t] = 0;
  3061. *p++ = '\0';
  3062. p = tempbuf+MAXSYMBOLSIZE+2;
  3063. t = tokenofitem(0);
  3064. if (t != MPARM) while (*p) putm(*p++);
  3065. else {
  3066. if (*(yylval.itemptr->i_string) == '?') putm('\2');
  3067. else putm('\1');
  3068. putm(yylval.itemptr->i_value + 'A');
  3069. }
  3070. if (t == ENDM) goto done;
  3071. continue;
  3072. case F_END:
  3073. if (expptr) {
  3074. popsi();
  3075. c = nextchar();
  3076. continue;
  3077. }
  3078. goto done;
  3079. default:
  3080. if (c == '\n') {
  3081. linecnt++;
  3082. }
  3083. if (c != '\1') putm(c);
  3084. c = nextchar();
  3085. }
  3086. }
  3087. /*
  3088. * finish off the file entry
  3089. */
  3090. done:
  3091. while(c != EOF && c != '\n' && c != '\0') c = nextchar();
  3092. linecnt++;
  3093. putm('\n');
  3094. putm('\n');
  3095. putm(0);
  3096. for (c=0; c<ITEMTABLESIZE; c++)
  3097. if (itemtab[c].i_token == MPARM) {
  3098. itemtab[c].i_token = UNDECLARED;
  3099. }
  3100. inmlex = 0;
  3101. #ifdef M_DEBUG
  3102. fprintf(stderr,"exit 'mlex'\n") ;
  3103. #endif
  3104. }
  3105. /*
  3106. * lexical analyser for the arguments of a macro call
  3107. */
  3108. int getarg()
  3109. {
  3110. int c;
  3111. char *p;
  3112. static int comma;
  3113. *tempbuf = 0;
  3114. yylval.cval = tempbuf;
  3115. while(charclass[c = nextchar()] == SPACE);
  3116. switch(c) {
  3117. case '\0':
  3118. popsi();
  3119. case '\n':
  3120. case ';':
  3121. comma = 0;
  3122. return(skipline(c));
  3123. case ',':
  3124. if (comma) {
  3125. comma = 0;
  3126. return(',');
  3127. }
  3128. else {
  3129. comma++;
  3130. return(ARG);
  3131. }
  3132. case '\'':
  3133. p = tempbuf;
  3134. do switch (c = nextchar()) {
  3135. case '\0':
  3136. case '\n':
  3137. peekc = c;
  3138. *p = 0;
  3139. err[bflag]++;
  3140. return(ARG);
  3141. case '\'':
  3142. if ((c = nextchar()) != '\'') {
  3143. peekc = c;
  3144. *p = '\0';
  3145. comma++;
  3146. return(ARG);
  3147. }
  3148. default:
  3149. *p++ = c;
  3150. } while (p < tempmax);
  3151. error(symlong); /* doesn't return */
  3152. default: /* unquoted string */
  3153. p = tempbuf;
  3154. peekc = c;
  3155. do switch(c = nextchar()) {
  3156. case '\0':
  3157. case '\n':
  3158. case '\t':
  3159. case ' ':
  3160. case ',':
  3161. peekc = c;
  3162. *p = '\0';
  3163. comma++;
  3164. return(ARG);
  3165. default:
  3166. *p++ = c;
  3167. } while (p < tempmax);
  3168. }
  3169. /* in practice it can't get here, but FWIW and to satisfy
  3170. * -Wall... -rjm */
  3171. error("can't happen - in zmac.y:getarg(), infinite unquoted string!?");
  3172. return(0);
  3173. }
  3174. /*
  3175. * Add suffix to pathname if leafname doesn't already have a suffix.
  3176. * The suffix passed should not include an extension separator.
  3177. * The pathname passed should be in local format.
  3178. */
  3179. void suffix_if_none (char *str, char *suff)
  3180. {
  3181. char *leafname, *extension;
  3182. leafname = strrchr (str, OS_DIR_SEP);
  3183. if (leafname == NULL)
  3184. {
  3185. leafname = str;
  3186. }
  3187. extension = strchr (leafname, OS_EXT_SEP);
  3188. if (extension == NULL)
  3189. {
  3190. size_t leafsize = strlen (leafname);
  3191. leafname[leafsize] = OS_EXT_SEP;
  3192. strcpy (leafname + leafsize + 1, suff);
  3193. }
  3194. }
  3195. /*
  3196. * Add or change pathname suffix.
  3197. * The suffix passed should not include an extension separator.
  3198. * The pathname passed should be in local format.
  3199. * If the leafname passed has more than one extension, the last is changed.
  3200. */
  3201. void suffix (char *str, char *suff)
  3202. {
  3203. char *leafname, *extension;
  3204. leafname = strrchr (str, OS_DIR_SEP);
  3205. if (leafname == NULL)
  3206. {
  3207. leafname = str;
  3208. }
  3209. extension = strrchr (leafname, OS_EXT_SEP);
  3210. if (extension == NULL)
  3211. {
  3212. extension = leafname + strlen (leafname);
  3213. }
  3214. *extension = OS_EXT_SEP;
  3215. strcpy (extension + 1, suff);
  3216. }
  3217. /*
  3218. * Decanonicalise a canonical pathname.
  3219. * A canonical pathname uses '/' as the directory separator,
  3220. * '.' as the extension separator, ".." as the parent directory,
  3221. * "." as the current directory, and a leading '/' as the root
  3222. * directory (it would be more user-friendly not to use this!).
  3223. */
  3224. void decanonicalise (char *pathname)
  3225. {
  3226. #if defined (MSDOS)
  3227. char *directory = pathname;
  3228. /* Just need to change all '/'s to '\'s */
  3229. while ((directory = strchr (directory, '/')) != NULL)
  3230. {
  3231. *directory = OS_DIR_SEP;
  3232. }
  3233. #elif defined (__riscos)
  3234. char *directory = pathname, *dirend;
  3235. /* First deal with leading '/' */
  3236. if (*directory == '/')
  3237. {
  3238. memmove (directory + 1, directory, strlen (directory) + 1);
  3239. *directory = '$';
  3240. ++directory;
  3241. }
  3242. /* Then deal with non-leaf ".."s and "."s */
  3243. while (1)
  3244. {
  3245. dirend = strchr (directory, '/');
  3246. if (dirend == NULL)
  3247. {
  3248. break;
  3249. }
  3250. *dirend = '\0';
  3251. if (strcmp (directory, "..") == 0)
  3252. {
  3253. *directory = '^';
  3254. memmove (directory + 2, directory + 3, strlen (directory + 3) + 1);
  3255. dirend = directory + 1;
  3256. }
  3257. else if (strcmp (directory, ".") == 0)
  3258. {
  3259. memmove (directory, directory + 2, strlen (directory + 2) + 1);
  3260. continue;
  3261. }
  3262. *dirend = '/';
  3263. directory = dirend + 1;
  3264. }
  3265. directory = pathname;
  3266. /* Finally, swap '/' and '.' */
  3267. while ((directory = strpbrk (directory, "/.")) != NULL)
  3268. {
  3269. if (*directory == '/')
  3270. {
  3271. *directory = OS_DIR_SEP;
  3272. }
  3273. else
  3274. {
  3275. *directory = OS_EXT_SEP;
  3276. }
  3277. ++directory;
  3278. }
  3279. #else
  3280. /* Local form is canonical form */
  3281. UNUSED (pathname);
  3282. #endif
  3283. }
  3284. /*
  3285. * put out a byte to the macro file, keeping the offset
  3286. */
  3287. void putm(char c)
  3288. {
  3289. #ifdef M_DEBUG
  3290. fputc (c, stderr);
  3291. #endif
  3292. mfptr++;
  3293. mfputc(c,mfile) ;
  3294. }
  3295. /*
  3296. * get a byte from the macro file
  3297. */
  3298. int getm()
  3299. {
  3300. int ch;
  3301. floc++;
  3302. ch = mfgetc(mfile) ;
  3303. if (ch == EOF) {
  3304. ch = 0;
  3305. fprintf(stderr,"bad macro read\n") ;
  3306. }
  3307. return(ch);
  3308. }
  3309. /*
  3310. * pop standard input
  3311. */
  3312. void popsi()
  3313. {
  3314. int i;
  3315. if (est)
  3316. {
  3317. for (i=0; i<PARMMAX; i++) {
  3318. if (est[i])
  3319. #ifdef M_DEBUG
  3320. fprintf (stderr, "[Freeing arg%u(%p)]\n", i, est[i]),
  3321. #endif
  3322. free(est[i]);
  3323. }
  3324. floc = est[FLOC];
  3325. free(est);
  3326. expptr--;
  3327. est = expptr ? (char **) expstack[expptr-1] : (char **) 0;
  3328. mfseek(mfile, (long)floc, 0);
  3329. if (lineptr > linebuf) lineptr--;
  3330. }
  3331. }
  3332. /*
  3333. * return a unique name for a local symbol
  3334. * c is the parameter number, n is the macro number.
  3335. */
  3336. char *getlocal(int c, int n)
  3337. {
  3338. static char local_label[10];
  3339. invented++;
  3340. if (c >= 26)
  3341. c += 'a' - '0';
  3342. sprintf(local_label, "?%c%04d", c+'a', n) ;
  3343. return(local_label);
  3344. }
  3345. /*
  3346. * read in a symbol table
  3347. */
  3348. void insymtab(char *name)
  3349. {
  3350. struct stab *t;
  3351. int s, i;
  3352. FILE *sfile;
  3353. t = (struct stab *) tempbuf;
  3354. decanonicalise (name);
  3355. if ((sfile = fopen(name, "rb")) == NULL)
  3356. return;
  3357. fread((char *)t, 1, sizeof *t, sfile);
  3358. if (t->t_value != SYMMAJIC)
  3359. {
  3360. fclose (sfile);
  3361. return;
  3362. }
  3363. s = t->t_token;
  3364. for (i=0; i<s; i++) {
  3365. fread((char *)t, 1, sizeof *t, sfile);
  3366. if (tokenofitem(UNDECLARED) != UNDECLARED)
  3367. continue;
  3368. yylval.itemptr->i_token = t->t_token;
  3369. yylval.itemptr->i_value = t->t_value;
  3370. if (t->t_token == MACRO)
  3371. yylval.itemptr->i_value += mfptr;
  3372. }
  3373. while ((s = fread(tempbuf, 1, TEMPBUFSIZE, sfile)) > 0) {
  3374. mfptr += s;
  3375. mfwrite(tempbuf, 1, s, mfile) ;
  3376. }
  3377. fclose (sfile);
  3378. }
  3379. /*
  3380. * write out symbol table
  3381. */
  3382. void outsymtab(char *name)
  3383. {
  3384. struct stab *t;
  3385. struct item *ip;
  3386. int i;
  3387. FILE *sfile;
  3388. t = (struct stab *) tempbuf;
  3389. decanonicalise (name);
  3390. if ((sfile = fopen(name, "wb")) == NULL)
  3391. return;
  3392. for (ip=itemtab; ip<itemmax; ip++) {
  3393. if (ip->i_token == UNDECLARED) {
  3394. ip->i_token = 0;
  3395. nitems--;
  3396. }
  3397. }
  3398. copyname(title, (char *)t);
  3399. t->t_value = SYMMAJIC;
  3400. t->t_token = nitems;
  3401. fwrite((char *)t, 1, sizeof *t, sfile);
  3402. for (ip=itemtab; ip<itemmax; ip++) {
  3403. if (ip->i_token != 0) {
  3404. t->t_token = ip->i_token;
  3405. t->t_value = ip->i_value;
  3406. copyname(ip->i_string, (char *)t);
  3407. fwrite((char *)t, 1, sizeof *t, sfile);
  3408. }
  3409. }
  3410. mfseek(mfile, (long)0, 0);
  3411. while((i = mfread(tempbuf, 1, TEMPBUFSIZE, mfile) ) > 0)
  3412. fwrite(tempbuf, 1, i, sfile);
  3413. fclose (sfile);
  3414. }
  3415. /*
  3416. * copy a name into the symbol file
  3417. */
  3418. void copyname(char *st1, char *st2)
  3419. {
  3420. char *s1, *s2;
  3421. int i;
  3422. i = (MAXSYMBOLSIZE+2) & ~01;
  3423. s1 = st1;
  3424. s2 = st2;
  3425. while((*s2++ = *s1++)) i--; /* -Wall-ishness :-) -RJM */
  3426. while(--i > 0) *s2++ = '\0';
  3427. }
  3428. /* get the next source file */
  3429. void next_source(char *sp)
  3430. {
  3431. if(now_in == NEST_IN -1)
  3432. error("Too many nested includes") ;
  3433. decanonicalise (sp);
  3434. if ((now_file = fopen(sp, "r")) == NULL) {
  3435. #ifdef __riscos
  3436. if (riscos_thbk)
  3437. riscos_throwback(2,src_name[now_in],linein[now_in],"Cannot open include file");
  3438. #endif
  3439. fileerror("Cannot open include file", sp) ;
  3440. }
  3441. if (pass2 && iflist()) {
  3442. lineout() ;
  3443. fprintf(fout, "**** %s ****\n",sp) ;
  3444. }
  3445. /* save the list control flag with the current line number */
  3446. if (lstoff)
  3447. linein[now_in] = - linein[now_in] ;
  3448. /* no list if include files are turned off */
  3449. lstoff |= iopt ;
  3450. /* save the new file descriptor. */
  3451. fin[++now_in] = now_file ;
  3452. /* start with line 0 */
  3453. linein[now_in] = 0 ;
  3454. /* save away the file name */
  3455. src_name[now_in] = malloc(strlen(sp)+1) ;
  3456. strcpy(src_name[now_in],sp) ;
  3457. }
  3458. #ifdef __riscos
  3459. /*
  3460. * On entry sp should point to the full pathname of a file in RISC OS form.
  3461. * Searches for the last dot, and sets the local CSD to that path.
  3462. * Does not corrupt the string.
  3463. */
  3464. void riscos_set_csd(char *sp)
  3465. {
  3466. char *s1 = strrchr (sp, '.');
  3467. if (s1 != NULL)
  3468. {
  3469. *s1=0;
  3470. _swix(DDEUtils_Prefix,1,sp);
  3471. *s1='.';
  3472. }
  3473. }
  3474. void riscos_throwback(int severity, char *file, int line, char *error)
  3475. {
  3476. if (riscos_throwback_started==0)
  3477. {
  3478. riscos_throwback_started=1;
  3479. *riscos_thbkf=0;
  3480. _swix(DDEUtils_ThrowbackStart,0);
  3481. }
  3482. if (strcmp(file, riscos_thbkf)!=0)
  3483. {
  3484. _swix(DDEUtils_ThrowbackSend,4+1,0,file); /* Notify of a change of file */
  3485. strcpy(riscos_thbkf,file);
  3486. }
  3487. _swix(DDEUtils_ThrowbackSend,32+16+8+4+1,1,file,line,severity,error);
  3488. }
  3489. #endif