PageRenderTime 9ms CodeModel.GetById 46ms app.highlight 10ms RepoModel.GetById 1ms 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

Large files files are truncated, but you can click here to view the full 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
  23#define ZMAC_VERSION	"1.3"
  24/* #define ZMAC_BETA	"b4" */
  25
  26#include <stdio.h>
  27#include <string.h>
  28#include <stdlib.h>
  29#include <stdarg.h>
  30#include <time.h>
  31#include "mio.h"
  32#include "getoptn.h"
  33
  34#define UNUSED(var) ((void) var)
  35
  36#if defined (__riscos__) && !defined (__riscos)
  37#define __riscos
  38#endif
  39
  40#ifdef __riscos
  41#include "swis.h"
  42#define DDEUtils_Prefix		0x42580
  43#define DDEUtils_ThrowbackStart	0x42587
  44#define DDEUtils_ThrowbackSend	0x42588
  45#define DDEUtils_ThrowbackEnd	0x42589
  46#endif
  47
  48#ifndef OS_DIR_SEP
  49#if defined (MSDOS)
  50#define OS_DIR_SEP '\\'
  51#elif defined (__riscos)
  52#define OS_DIR_SEP '.'
  53#else
  54#define OS_DIR_SEP '/'
  55#endif
  56#endif
  57
  58#ifndef OS_EXT_SEP
  59#if defined (__riscos)
  60#define OS_EXT_SEP '/'
  61#else
  62#define OS_EXT_SEP '.'
  63#endif
  64#endif
  65
  66/*
  67 * DEBUG turns on pass reporting.
  68 * Macro debug and Token debug enables.
  69#define	DEBUG
  70#define	M_DEBUG
  71#define	T_DEBUG
  72 */
  73
  74#define ITEMTABLESIZE	2000
  75#define TEMPBUFSIZE	200
  76#define LINEBUFFERSIZE	200
  77#define EMITBUFFERSIZE	200
  78#define MAXSYMBOLSIZE	40
  79#define IFSTACKSIZE	20
  80#define MAXIFS		1024
  81#define TITLELEN	50
  82#define BINPERLINE	16
  83#define	PARMMAX		25
  84#define MAXEXP		25
  85#define SYMMAJIC	07203
  86#define	NEST_IN		8
  87
  88
  89#define loop	for(;;)
  90
  91void yyerror(char *err)
  92{
  93	UNUSED (err);		/* we will do our own error printing */
  94	/* printf ("Oops! %s\n", err); */
  95}
  96
  97struct	item	{
  98	char	*i_string;
  99	int	i_value;
 100	int	i_token;
 101	int	i_uses;
 102	int	i_equbad;
 103};
 104
 105FILE	*fout,
 106	*fbuf,
 107	*fin[NEST_IN],
 108	*now_file ;
 109
 110int	pass2;	/* set when pass one completed */
 111int	dollarsign ;	/* location counter */
 112int	olddollar ;	/* kept to put out binary */
 113
 114/* program counter save for PHASE/DEPHASE */
 115int	phdollar, phbegin, phaseflag ;
 116
 117char	*src_name[NEST_IN] ;
 118int	linein[NEST_IN] ;
 119int	now_in ;
 120
 121
 122#define bflag	0	/* balance error */
 123#define eflag	1	/* expression error */
 124#define fflag	2	/* syntax error */
 125#define iflag	3	/* bad digits */
 126#define mflag	4	/* multiply defined */
 127#define pflag	5	/* phase error */
 128#define uflag	6	/* undeclared used */
 129#define vflag	7	/* value out of range */
 130#define oflag	8	/* phase/dephase error */
 131#define frflag	9	/* double forward ref. via equ error */
 132#define zflag	10	/* Z80-only instruction (when `-z' option in use) */
 133#define orgflag 11	/* retrograde org error (when `-h' option not in use) */
 134
 135#define FLAGS	12	/* number of flags */
 136
 137char	err[FLAGS];
 138int	keeperr[FLAGS];
 139char	errlet[FLAGS]="BEFIMPUVORZG";
 140char	*errname[FLAGS]={
 141	"Balance",
 142	"Expression",
 143	"Syntax",
 144	"Digit",
 145	"Mult. def.",
 146	"Phase",
 147	"Undeclared",
 148	"Value",
 149	"Phase/Dephase",
 150	"Forward ref. to EQU with forward ref.",
 151	"Z80-specific instruction",
 152	"Retrograde ORG"
 153};
 154char	*warnname[]={
 155	"Symbol length exceeded",
 156	"Non-standard syntax",
 157	"Could replace JP with JR",
 158	"Could replace LD A, 0 with XOR A if flags unimportant",
 159	"Could replace RLC A with RLCA if S, Z and P/V flags unimportant",
 160	"Could replace RRC A with RRCA if S, Z and P/V flags unimportant",
 161	"Could replace RL A with RLA if S, Z and P/V flags unimportant",
 162	"Could replace RR A with RRA if S, Z and P/V flags unimportant",
 163	"Could replace SLA A with ADD A, A if H and P/V flags unimportant"
 164};
 165
 166/* for "0 symbols", "1 symbol", "2 symbols", etc. */
 167#define DO_PLURAL(x)	(x),((x)==1)?"":"s"
 168
 169char	linebuf[LINEBUFFERSIZE];
 170char	*lineptr;
 171char	*linemax = linebuf+LINEBUFFERSIZE;
 172
 173char	outbin[BINPERLINE];
 174char	*outbinp = outbin;
 175char	*outbinm = outbin+BINPERLINE;
 176
 177char	emitbuf[EMITBUFFERSIZE];
 178char	*emitptr;
 179
 180char	ifstack[IFSTACKSIZE];
 181char	*ifptr;
 182char	*ifstmax = ifstack+IFSTACKSIZE-1;
 183
 184
 185char	expif[MAXIFS];
 186char	*expifp;
 187char	*expifmax = expif+MAXIFS;
 188
 189char	hexadec[] = "0123456789ABCDEF" ;
 190char	*expstack[MAXEXP];
 191int	expptr;
 192
 193
 194int	nitems;
 195int	linecnt;
 196int	nbytes;
 197int	invented;
 198
 199
 200char	tempbuf[TEMPBUFSIZE];
 201char	*tempmax = tempbuf+TEMPBUFSIZE-1;
 202
 203char	inmlex;
 204char	arg_flag;
 205char	quoteflag;
 206int	parm_number;
 207int	exp_number;
 208char	symlong[] = "Symbol too long";
 209
 210int	disp;
 211#define FLOC	PARMMAX
 212#define TEMPNUM	PARMMAX+1
 213char	**est;
 214char	**est2;
 215
 216char	*floc;
 217int	mfptr;
 218FILE	*mfile;
 219
 220
 221char	*title;
 222char	titlespace[TITLELEN];
 223char	*timp;
 224char	*sourcef;
 225/* changed to cope with filenames longer than 14 chars -rjm 1998-12-15 */
 226char	src[1024];
 227char	bin[1024];
 228char	mtmp[1024];
 229char	listf[1024];
 230char	writesyms[1024];
 231#ifdef __riscos
 232char	riscos_thbkf[1024];
 233#endif
 234
 235char	bopt = 1,
 236	edef = 1,
 237	eopt = 1,
 238	fdef = 0,
 239	fopt = 0,
 240	gdef = 1,
 241	gopt = 1,
 242	iopt = 0 ,	/* list include files */
 243	lstoff = 0,
 244	lston = 0,	/* flag to force listing on */
 245	lopt = 0,
 246	mdef = 0,
 247	mopt = 0,
 248	nopt = 1,	/* line numbers on as default */
 249	oldoopt = 0,
 250	popt = 1,	/* form feed as default page eject */
 251	sopt = 0,	/* turn on symbol table listing */
 252	output_hex = 0,	/* `-h', output .hex rather than .bin -rjm */
 253	output_8080_only = 0,	/* `-z', output 8080-compat. ops only -rjm */
 254	show_error_line = 0,	/* `-S', show line which caused error -rjm */
 255	terse_lst_errors = 0,	/* `-t', terse errors in listing -rjm */
 256	continuous_listing = 1,	/* `-d', discontinuous - with page breaks */
 257	suggest_optimise = 0,	/* `-O', suggest optimisations -mgr */
 258#ifdef __riscos
 259	riscos_thbk = 0,	/* `-T', RISC OS throwback -mep */
 260#endif
 261	output_amsdos = 0,	/* `-A', AMSDOS binary file output -mep */
 262	saveopt;
 263
 264char	xeq_flag = 0;
 265int	xeq;
 266
 267time_t	now;
 268int	line;
 269int	page = 1;
 270
 271int	had_errors = 0;		/* if program had errors, do exit(1) */
 272#ifdef __riscos
 273int	riscos_throwback_started = 0;
 274#endif
 275int	not_seen_org = 1;
 276int	first_org_store = 0;
 277
 278struct stab {
 279	char	t_name[MAXSYMBOLSIZE+1];
 280	int	t_value;
 281	int	t_token;
 282};
 283
 284/*
 285 *  push back character
 286 */
 287int	peekc;
 288
 289
 290/* function prototypes */
 291int addtoline(int ac);
 292int iflist(void);
 293int yylex(void);
 294int tokenofitem(int deftoken);
 295int nextchar(void);
 296int skipline(int ac);
 297void usage(void);
 298int main(int argc, char *argv[]);
 299int getarg(void);
 300int getm(void);
 301void yyerror(char *err);
 302void emit(int num, ...);
 303void emit1(int opcode,int regvalh,int data16,int type);
 304void emitdad(int rp1,int rp2);
 305void emitjr(int opcode,int expr);
 306void emitjp(int opcode,int expr);
 307void putbin(int v);
 308void flushbin(void);
 309void puthex(char byte, FILE *buf);
 310void list(int optarg);
 311void lineout(void);
 312void eject(void);
 313void space(int n);
 314void lsterr1(void);
 315void lsterr2(int lst);
 316void errorprt(int errnum);
 317void warnprt(int warnnum, int warnoff);
 318void list1(void);
 319void interchange(int i, int j);
 320void custom_qsort(int m, int n);
 321void setvars(void);
 322void error(char *as);
 323void fileerror(char *as,char *filename);
 324void justerror(char *as);
 325void putsymtab(void);
 326void erreport(void);
 327void mlex(void);
 328void suffix_if_none(char *str,char *suff);
 329void suffix(char *str,char *suff);
 330void decanonicalise(char *str);
 331void putm(char c);
 332void popsi(void);
 333char *getlocal(int c, int n);
 334void insymtab(char *name);
 335void outsymtab(char *name);
 336void copyname(char *st1, char *st2);
 337void next_source(char *sp);
 338void doatexit (void);
 339#ifdef __riscos
 340void riscos_set_csd(char *sp);
 341void riscos_throwback(int severity, char *file, int line, char *error);
 342#endif
 343
 344
 345
 346
 347/*
 348 *  add a character to the output line buffer
 349 */
 350int addtoline(int ac)
 351{
 352	/* check for EOF from stdio */
 353	if (ac == -1)
 354		ac = 0 ;
 355	if (inmlex)
 356		return(ac);
 357	if (lineptr >= linemax)
 358		error("line buffer overflow");
 359	*lineptr++ = ac;
 360	return(ac);
 361}
 362
 363
 364/*
 365 *  put values in buffer for outputing
 366 */
 367
 368void emit(int bytes, ...)
 369{
 370	va_list ap;
 371	unsigned char *oldemitptr=(unsigned char *)emitptr;
 372	int c;
 373
 374	va_start(ap,bytes);
 375
 376	while	(--bytes >= 0)
 377		if (emitptr >= &emitbuf[EMITBUFFERSIZE])
 378			error("emit buffer overflow");
 379		else {
 380			*emitptr++ = va_arg(ap,int);
 381		}
 382
 383	if (output_8080_only) {
 384		/* test for Z80-specific ops. These start with one of
 385		 * sixteen byte values, listed below. The values were
 386		 * taken from "A Z80 Workshop Manual" by E. A. Parr. -rjm
 387		 */
 388		/* As far as I can tell from my own literature
 389		 * review, 0x02, 0x0a, 0x12 and 0x1a are valid
 390		 * 8080 opcodes (LDAX/STAX B/D) -mgr
 391		 */
 392		c=*oldemitptr;
 393		if (/* c==0x02 || */ c==0x08 || /* c==0x0a || */ c==0x10 ||
 394		    /* c==0x12 || */ c==0x18 || /* c==0x1a || */ c==0x20 ||
 395		    c==0x28 || c==0x30 || c==0x38 || c==0xcb ||
 396		    c==0xd9 || c==0xdd || c==0xed || c==0xfd)
 397			err[zflag]++;
 398	}
 399
 400	va_end(ap);
 401}
 402
 403/* for emitted data - as above, without 8080 test.
 404 * Duplicating the code was easier than putting an extra arg in all
 405 * those emit()s. :-} Hopefully this isn't too unbearably nasty. -rjm
 406 */
 407void dataemit(int bytes, ...)
 408{
 409	va_list ap;
 410
 411	va_start(ap,bytes);
 412
 413	while	(--bytes >= 0)
 414		if (emitptr >= &emitbuf[EMITBUFFERSIZE])
 415			error("emit buffer overflow");
 416		else {
 417			*emitptr++ = va_arg(ap,int);
 418		}
 419	va_end(ap);
 420}
 421
 422
 423void emit1(int opcode,int regvalh,int data16,int type)
 424{
 425	if ((regvalh & 0x8000)) {	/* extra brackets to silence -Wall */
 426		if ((type & 1) == 0 && (disp > 127 || disp < -128))
 427			err[vflag]++;
 428		switch(type) {
 429		case 0:
 430			if (opcode & 0x8000)
 431				emit(4, regvalh >> 8, opcode >> 8, disp, opcode);
 432			else
 433				emit(3, regvalh >> 8, opcode, disp);
 434			break;
 435		case 1:
 436			emit(2, regvalh >> 8, opcode);
 437			break;
 438		case 2:
 439			if (data16 > 255 || data16 < -128)
 440				err[vflag]++;
 441			emit(4, regvalh >> 8, opcode, disp, data16);
 442			break;
 443		case 5:
 444			emit(4, regvalh >> 8, opcode, data16, data16 >> 8);
 445		}
 446	} else
 447		switch(type) {
 448		case 0:
 449			if (opcode & 0100000)
 450				emit(2, opcode >> 8, opcode);
 451			else
 452				emit(1, opcode);
 453			break;
 454		case 1:
 455			if (opcode & 0100000)
 456				emit(2, opcode >> 8, opcode);
 457			else
 458				emit(1, opcode);
 459			break;
 460		case 2:
 461			if (data16 > 255 || data16 < -128)
 462				err[vflag]++;
 463			emit(2, opcode, data16);
 464			break;
 465		case 3:
 466			if (data16 >255 || data16 < -128)
 467				err[vflag]++;
 468			emit(2, opcode, data16);
 469			break;
 470		case 5:
 471			if (opcode & 0100000)
 472				emit(4, opcode >> 8, opcode, data16, data16 >> 8);
 473			else
 474				emit(3, opcode, data16, data16 >> 8);
 475		}
 476}
 477
 478
 479
 480
 481void emitdad(int rp1,int rp2)
 482{
 483	if (rp1 & 0x8000)
 484		emit(2,rp1 >> 8, rp2 + 9);
 485	else
 486		emit(1,rp2 + 9);
 487}
 488
 489
 490void emitjr(int opcode,int expr)
 491{
 492	disp = expr - dollarsign - 2;
 493	if (disp > 127 || disp < -128)
 494		err[vflag]++;
 495	emit(2, opcode, disp);
 496}
 497
 498
 499
 500void emitjp(int opcode,int expr)
 501{
 502	if (suggest_optimise && pass2 && opcode <= 0xda && !output_8080_only) {
 503		disp = expr - dollarsign - 2;
 504		if (disp <= 127 && disp >= -128)
 505			warnprt (2, 0);
 506	}
 507	emit(3, opcode, expr, expr >> 8);
 508}
 509
 510
 511
 512
 513/*
 514 *  put out a byte of binary
 515 */
 516void putbin(int v)
 517{
 518	if(!pass2 || !bopt) return;
 519	*outbinp++ = v;
 520	if (outbinp >= outbinm) flushbin();
 521}
 522
 523
 524
 525/*
 526 *  output one line of binary in INTEL standard form
 527 */
 528void flushbin()
 529{
 530	char *p;
 531	int check=outbinp-outbin;
 532
 533	if (!pass2 || !bopt)
 534		return;
 535	nbytes += check;
 536	if (check) {
 537		if (output_hex) {
 538			putc(':', fbuf);
 539			puthex(check, fbuf);
 540			puthex(olddollar>>8, fbuf);
 541			puthex(olddollar, fbuf);
 542			puthex(0, fbuf);
 543		}
 544		check += (olddollar >> 8) + olddollar;
 545		olddollar += (outbinp-outbin);
 546		for (p=outbin; p<outbinp; p++) {
 547			if (output_hex)
 548				puthex(*p, fbuf);
 549			else
 550				fputc(*p, fbuf);
 551			check += *p;
 552		}
 553		if (output_hex) {
 554			puthex(256-check, fbuf);
 555			putc('\n', fbuf);
 556		}
 557		outbinp = outbin;
 558	}
 559}
 560
 561
 562
 563/*
 564 *  put out one byte of hex
 565 */
 566void puthex(char byte, FILE *buf)
 567{
 568	putc(hexadec[(byte >> 4) & 017], buf);
 569	putc(hexadec[byte & 017], buf);
 570}
 571
 572/*
 573 *  put out a line of output -- also put out binary
 574 */
 575void list(int optarg)
 576{
 577	char *	p;
 578	int	i;
 579	int  lst;
 580
 581	if (!expptr)
 582		linecnt++;
 583	addtoline('\0');
 584	if (pass2) {
 585		lst = iflist();
 586		if (lst) {
 587			lineout();
 588			if (nopt)
 589				fprintf(fout, "%4d:\t", linein[now_in]);
 590			puthex(optarg >> 8, fout);
 591			puthex(optarg, fout);
 592			fputs("  ", fout);
 593			for (p = emitbuf; (p < emitptr) && (p - emitbuf < 4); p++) {
 594				puthex(*p, fout);
 595			}
 596			for (i = 4 - (p-emitbuf); i > 0; i--)
 597				fputs("  ", fout);
 598			putc('\t', fout);
 599			fputs(linebuf, fout);
 600		}
 601
 602		if (bopt) {
 603			for (p = emitbuf; p < emitptr; p++)
 604				putbin(*p);
 605		}
 606
 607
 608		p = emitbuf+4;
 609		while (lst && gopt && p < emitptr) {
 610			lineout();
 611			if (nopt) putc('\t', fout);
 612			fputs("      ", fout);
 613			for (i = 0; (i < 4) && (p < emitptr);i++) {
 614				puthex(*p, fout);
 615				p++;
 616			}
 617			putc('\n', fout);
 618		}
 619
 620
 621		lsterr2(lst);
 622	} else
 623		lsterr1();
 624	dollarsign += emitptr - emitbuf;
 625	emitptr = emitbuf;
 626	lineptr = linebuf;
 627}
 628
 629
 630
 631/*
 632 *  keep track of line numbers and put out headers as necessary
 633 */
 634void lineout()
 635{
 636	if (continuous_listing) {
 637		line = 1;
 638		return;
 639	}
 640	if (line == 60) {
 641		if (popt)
 642			putc('\014', fout);	/* send the form feed */
 643		else
 644			fputs("\n\n\n\n\n", fout);
 645		line = 0;
 646	}
 647	if (line == 0) {
 648		fprintf(fout, "\n\n%s %s\t%s\t Page %d\n\n\n",
 649			&timp[4], &timp[20], title, page++);
 650		line = 4;
 651	}
 652	line++;
 653}
 654
 655
 656/*
 657 *  cause a page eject
 658 */
 659void eject()
 660{
 661	if (pass2 && !continuous_listing && iflist()) {
 662		if (popt) {
 663			putc('\014', fout);	/* send the form feed */
 664		} else {
 665			while (line < 65) {
 666				line++;
 667				putc('\n', fout);
 668			}
 669		}
 670	}
 671	line = 0;
 672}
 673
 674
 675/*
 676 *  space n lines on the list file
 677 */
 678void space(int n)
 679{
 680	int	i ;
 681	if (pass2 && iflist())
 682		for (i = 0; i<n; i++) {
 683			lineout();
 684			putc('\n', fout);
 685		}
 686}
 687
 688
 689/*
 690 *  Error handling - pass 1
 691 */
 692void lsterr1()
 693{
 694	int i;
 695	for (i = 0; i <= 4; i++)
 696		if (err[i]) {
 697			errorprt(i);
 698			err[i] = 0;
 699		}
 700}
 701
 702
 703/*
 704 *  Error handling - pass 2.
 705 */
 706void lsterr2(int lst)
 707{
 708	int i;
 709	for (i=0; i<FLAGS; i++)
 710		if (err[i]) {
 711			if (lst) {
 712				lineout();
 713				/* verbose inline error messages now,
 714				 * must override with `-t' to get old
 715				 * behaviour. -rjm
 716				 */
 717				if (terse_lst_errors)
 718					putc(errlet[i], fout);
 719				else
 720					fprintf(fout,"*** %s error ***",
 721							errname[i]);
 722				putc('\n', fout);
 723			}
 724			err[i] = 0;
 725			keeperr[i]++;
 726			if (i > 4)
 727				errorprt(i);
 728		}
 729
 730	fflush(fout);	/* to avoid putc(har) mix bug */
 731}
 732
 733/*
 734 *  print diagnostic to error terminal
 735 */
 736void errorprt(int errnum)
 737{
 738	had_errors=1;
 739	fprintf(stderr,"%s:%d: %s error\n",
 740		src_name[now_in], linein[now_in], errname[errnum]);
 741	if(show_error_line)
 742		fprintf(stderr, "%s\n", linebuf);
 743#ifdef __riscos
 744	if (riscos_thbk)
 745		riscos_throwback (1, src_name[now_in], linein[now_in], errname[errnum]);
 746#endif
 747}
 748
 749
 750/*
 751 *  print warning to error terminal
 752 */
 753void warnprt(int warnnum, int warnoff)
 754{
 755	fprintf(stderr,"%s:%d: warning: %s\n",
 756		src_name[now_in], linein[now_in] + warnoff, warnname[warnnum]);
 757		/* Offset needed if warning issued while line is being parsed */
 758#ifdef __riscos
 759	if (riscos_thbk)
 760		riscos_throwback (0, src_name[now_in], linein[now_in] + warnoff, warnname[warnnum]);
 761#endif
 762	/* if(show_error_line)
 763		Can't show line because it isn't necessarily complete
 764		fprintf(stderr, "%s\n", linebuf); */
 765}
 766
 767
 768/*
 769 *  list without address -- for comments and if skipped lines
 770 */
 771void list1()
 772{
 773	int lst;
 774
 775	addtoline('\0');
 776	lineptr = linebuf;
 777	if (!expptr) linecnt++;
 778	if (pass2)
 779	{
 780		if ((lst = iflist())) {
 781			lineout();
 782			if (nopt)
 783				fprintf(fout, "%4d:\t", linein[now_in]);
 784			fprintf(fout, "\t\t%s", linebuf);
 785			lsterr2(lst);
 786		}
 787	} else
 788		lsterr1();
 789}
 790
 791
 792/*
 793 *  see if listing is desired
 794 */
 795int iflist()
 796{
 797	int i, j;
 798
 799	if (lston)
 800		return(1) ;
 801	if (lopt)
 802		return(0);
 803	if (*ifptr && !fopt)
 804		return(0);
 805	if (!lstoff && !expptr)
 806		return(1);
 807	j = 0;
 808	for (i=0; i<FLAGS; i++)
 809		if (err[i])
 810			j++;
 811	if (expptr)
 812		return(mopt || j);
 813	if (eopt && j)
 814		return(1);
 815	return(0);
 816}
 817
 818
 819/* moved out of %{..%} bit in parse routine because `bison -y'
 820 * didn't like it... -rjm
 821 */
 822char  *cp;
 823
 824int list_tmp1,list_tmp2;
 825int equ_bad_label=0;
 826
 827%}
 828
 829%union	{
 830	struct item *itemptr;
 831	int ival;
 832	char *cval;
 833	}
 834
 835%token <cval> STRING
 836%token <itemptr> NOOPERAND
 837%token <itemptr> ARITHC
 838%token ADD
 839%token <itemptr> LOGICAL
 840%token <itemptr> AND
 841%token <itemptr> OR
 842%token <itemptr> XOR
 843%token <itemptr> BIT
 844%token CALL
 845%token <itemptr> INCDEC
 846%token <itemptr> DJNZ
 847%token EX
 848%token <itemptr> IM
 849%token PHASE
 850%token DEPHASE
 851%token <itemptr> IN
 852%token JP
 853%token <itemptr> JR
 854%token LD
 855%token <itemptr> OUT
 856%token <itemptr> PUSHPOP
 857%token <itemptr> RET
 858%token <itemptr> SHIFT
 859%token <itemptr> RST
 860%token <itemptr> REGNAME
 861%token <itemptr> ACC
 862%token <itemptr> C
 863%token <itemptr> RP
 864%token <itemptr> HL
 865%token <itemptr> INDEX
 866%token <itemptr> AF
 867%token <itemptr> SP
 868%token <itemptr> MISCREG
 869%token F
 870%token <itemptr> COND
 871%token <itemptr> SPCOND
 872%token <ival> NUMBER
 873%token <itemptr> UNDECLARED
 874%token END
 875%token ORG
 876%token DEFB
 877%token DEFS
 878%token DEFW
 879%token EQU
 880%token DEFL
 881%token <itemptr> LABEL
 882%token <itemptr> EQUATED
 883%token <itemptr> WASEQUATED
 884%token <itemptr> DEFLED
 885%token <itemptr> MULTDEF
 886%token <ival> MOD
 887%token <ival> SHL
 888%token <ival> SHR
 889%token <ival> NOT
 890%token <ival> LT
 891%token <ival> GT
 892%token <ival> EQ
 893%token <ival> LE
 894%token <ival> GE
 895%token <ival> NE
 896%token IF
 897%token ELSE
 898%token ENDIF
 899%token <itemptr> ARGPSEUDO
 900%token <itemptr> LIST
 901%token <itemptr> MINMAX
 902%token MACRO
 903%token <itemptr> MNAME
 904%token <itemptr> OLDMNAME
 905%token ARG
 906%token ENDM
 907%token MPARM
 908%token <ival> ONECHAR
 909%token <ival> TWOCHAR
 910
 911%type <itemptr> label.part symbol
 912%type <ival> reg evenreg realreg mem pushable bcdesp bcdehlsp mar condition
 913%type <ival> spcondition noparenexpr parenexpr expression lxexpression
 914
 915%left '|' OR
 916%left '^' XOR
 917%left '&' AND
 918%left '=' EQ NE
 919%left '<' '>' LT GT LE GE
 920%left SHL SHR
 921%left '+' '-'
 922%left '*' '/' '%' MOD
 923%right '!' '~' NOT UNARY
 924
 925%%
 926
 927
 928statements:
 929	/* Empty file! */
 930|
 931	statements statement
 932;
 933
 934
 935statement:
 936	label.part '\n' {
 937		if ($1) list(dollarsign);
 938		else  list1();
 939	}
 940|
 941	label.part operation '\n' {
 942		list(dollarsign);
 943	}
 944|
 945	symbol EQU expression '\n' {
 946		/* a forward reference to a label in the expression cannot
 947		 * be fixed in a forward reference to the EQU;
 948		 * it would need three passes. -rjm
 949		 */
 950		if(!pass2 && equ_bad_label) {
 951			/* this indicates that the equ has an incorrect
 952			 * (i.e. pass 1) value.
 953			 */
 954			$1->i_equbad = 1;
 955		} else {
 956			/* but if 2nd pass or no forward reference, it's ok. */
 957			$1->i_equbad = 0;
 958		}
 959		equ_bad_label=0;
 960		switch($1->i_token) {
 961		case UNDECLARED: case WASEQUATED:
 962			$1->i_token = EQUATED;
 963			$1->i_value = $3;
 964			break;
 965		case EQUATED:
 966			if ($1->i_value == $3)
 967				break; /* Allow benign redefinition -mgr */
 968			/* Drop-through intentional */
 969		default:
 970			err[mflag]++;
 971			$1->i_token = MULTDEF;
 972		}
 973		list($3);
 974	}
 975|
 976	symbol DEFL expression '\n' {
 977		switch($1->i_token) {
 978		case UNDECLARED: case DEFLED:
 979			$1->i_token = DEFLED;
 980			$1->i_value = $3;
 981			break;
 982		default:
 983			err[mflag]++;
 984			$1->i_token = MULTDEF;
 985		}
 986		list($3);
 987	}
 988|
 989	symbol MINMAX expression ',' expression '\n' {
 990		switch ($1->i_token) {
 991		case UNDECLARED: case DEFLED:
 992			$1->i_token = DEFLED;
 993			if ($2->i_value)	/* max */
 994				list($1->i_value = ($3 > $5? $3:$5));
 995			else list($1->i_value = ($3 < $5? $3:$5));
 996			break;
 997		default:
 998			err[mflag]++;
 999			$1->i_token = MULTDEF;
1000			list($1->i_value);
1001		}
1002	}
1003|
1004	IF expression '\n' {
1005		/* all $2's here were yypc[2].ival before.
1006		 * I think the idea was perhaps to allow constants
1007		 * only...? Anyway, it now allows any expression -
1008		 * which would seem to make sense given the definition
1009		 * above, right? :-)  -rjm
1010		 */
1011		if (ifptr >= ifstmax)
1012			error("Too many ifs");
1013		else {
1014			if (pass2) {
1015				*++ifptr = *expifp++;
1016				if (*ifptr != !($2)) err[pflag]++;
1017			} else {
1018				if (expifp >= expifmax)
1019					error("Too many ifs!");
1020				*expifp++ = !($2);
1021				*++ifptr = !($2);
1022			}
1023		}
1024		saveopt = fopt;
1025		fopt = 1;
1026		list($2);
1027		fopt = saveopt;
1028	}
1029|
1030	ELSE '\n' {
1031		/* FIXME: it would be nice to spot repeated ELSEs, but how? */
1032		*ifptr = !*ifptr;
1033		saveopt = fopt;
1034		fopt = 1;
1035		list1();
1036		fopt = saveopt;
1037	}
1038|
1039	ENDIF '\n' {
1040		if (ifptr == ifstack) err[bflag]++;
1041		else --ifptr;
1042		list1();
1043	}
1044|
1045	label.part END '\n' {
1046		list(dollarsign);
1047		peekc = 0;
1048	}
1049|
1050	label.part END expression '\n' {
1051		xeq_flag++;
1052		xeq = $3;
1053		list($3);
1054		peekc = 0;
1055	}
1056|
1057	label.part DEFS expression '\n' {
1058		if ($3 < 0) err[vflag]++;
1059		list(dollarsign);
1060		if ($3) {
1061			flushbin();
1062			dollarsign += $3;
1063			olddollar = dollarsign;
1064
1065			/* if it's not hex output though, we also need
1066			 * to output zeroes as appropriate. -rjm
1067			 */
1068			if(!output_hex && pass2) {
1069				int f;
1070				for (f=0;f<($3);f++)
1071					fputc(0, fbuf);
1072			}
1073		}
1074	}
1075|
1076	ARGPSEUDO arg_on ARG arg_off '\n' {
1077		list1();
1078		switch ($1->i_value) {
1079
1080		case 0:		/* title */
1081			lineptr = linebuf;
1082			cp = tempbuf;
1083			title = titlespace;
1084			while ((*title++ = *cp++) && (title < &titlespace[TITLELEN]));
1085			*title = 0;
1086			title = titlespace;
1087			break;
1088
1089		case 1:		/* rsym */
1090			if (pass2) break;
1091			insymtab(tempbuf);
1092			break;
1093
1094		case 2:		/* wsym */
1095			strcpy(writesyms, tempbuf);
1096			break;
1097
1098		case 3:		/* include file */
1099			if (*tempbuf == '"' || *tempbuf == '\'')
1100			{
1101				if (tempbuf[strlen (tempbuf) - 1] == '"' || tempbuf[strlen (tempbuf) - 1] == '\'')
1102					tempbuf[strlen (tempbuf) - 1] = 0;
1103				next_source(tempbuf + 1) ;
1104			}
1105			else
1106			{
1107				next_source(tempbuf) ;
1108			}
1109			break ;
1110		}
1111	}
1112|
1113	ARGPSEUDO arg_on arg_off '\n' {
1114		fprintf(stderr,"ARGPSEUDO error\n");
1115		err[fflag]++;
1116		list(dollarsign);
1117	}
1118|
1119	LIST '\n' {
1120		list_tmp1=$1->i_value;
1121		list_tmp2=1;
1122		goto dolopt;
1123	}
1124|
1125	LIST expression '\n' {
1126		list_tmp1=$1->i_value;
1127		list_tmp2=$2;
1128	dolopt:
1129		linecnt++;
1130		if (pass2) {
1131			lineptr = linebuf;
1132			switch (list_tmp1) {
1133			case 0:	/* list */
1134				if (list_tmp2 < 0) lstoff = 1;
1135				if (list_tmp2 > 0) lstoff = 0;
1136				break;
1137
1138			case 1:	/* eject */
1139				if (list_tmp2) eject();
1140				break;
1141
1142			case 2:	/* space */
1143				if ((line + list_tmp2) > 60) eject();
1144				else space(list_tmp2);
1145				break;
1146
1147			case 3:	/* elist */
1148				eopt = edef;
1149				if (list_tmp2 < 0) eopt = 0;
1150				if (list_tmp2 > 0) eopt = 1;
1151				break;
1152
1153			case 4:	/* fopt */
1154				fopt = fdef;
1155				if (list_tmp2 < 0) fopt = 0;
1156				if (list_tmp2 > 0) fopt = 1;
1157				break;
1158
1159			case 5:	/* gopt */
1160				gopt = gdef;
1161				if (list_tmp2 < 0) gopt = 1;
1162				if (list_tmp2 > 0) gopt = 0;
1163				break;
1164
1165			case 6: /* mopt */
1166				mopt = mdef;
1167				if (list_tmp2 < 0) mopt = 0;
1168				if (list_tmp2 > 0) mopt = 1;
1169			}
1170		}
1171	}
1172|
1173	UNDECLARED MACRO parm.list '\n' {
1174		$1->i_token = MNAME;
1175		$1->i_value = mfptr;
1176#ifdef M_DEBUG
1177		fprintf (stderr, "[UNDECLARED MACRO %s]\n", $1->i_string);
1178#endif
1179		mfseek(mfile, (long)mfptr, 0);
1180		list1();
1181		mlex() ;
1182		parm_number = 0;
1183	}
1184|
1185	OLDMNAME MACRO {
1186		$1->i_token = MNAME;
1187#ifdef M_DEBUG
1188		fprintf (stderr, "[OLDNAME MACRO %s]\n", $1->i_string);
1189#endif
1190		while (yychar != ENDM && yychar) {
1191			while (yychar != '\n' && yychar)
1192				yychar = yylex();
1193			list1();
1194			yychar = yylex();
1195		}
1196		while (yychar != '\n' && yychar) yychar = yylex();
1197		list1();
1198		yychar = yylex();
1199	}
1200|
1201	label.part MNAME al arg.list '\n' {
1202#ifdef M_DEBUG
1203		fprintf (stderr, "[MNAME %s]\n", $2->i_string);
1204#endif
1205		$2->i_uses++ ;
1206		arg_flag = 0;
1207		parm_number = 0;
1208		list(dollarsign);
1209		expptr++;
1210		est = est2;
1211		est2 = NULL;
1212		est[FLOC] = floc;
1213		est[TEMPNUM] = (char *)(long)exp_number++;
1214		floc = (char *)(long)($2->i_value);
1215		mfseek(mfile, (long)floc, 0);
1216	}
1217|
1218	error {
1219		err[fflag]++;
1220		quoteflag = 0;
1221		arg_flag = 0;
1222		parm_number = 0;
1223
1224		if (est2)
1225		{
1226			int i;
1227			for (i=0; i<PARMMAX; i++) {
1228				if (est2[i])
1229#ifdef M_DEBUG
1230	fprintf (stderr, "[Freeing2 arg%u(%p)]\n", i, est2[i]),
1231#endif
1232						free(est2[i]);
1233			}
1234			free(est2);
1235			est2 = NULL;
1236		}
1237
1238		while(yychar != '\n' && yychar != '\0') yychar = yylex();
1239		list(dollarsign);
1240		yyclearin;yyerrok;
1241	}
1242;
1243
1244colonordot:
1245	':'
1246|
1247	'.'
1248;
1249
1250maybecolon:
1251	/* empty */
1252|
1253	':'
1254;
1255
1256label.part:
1257	/* empty */
1258	{	$$ = NULL;	}
1259|
1260	colonordot symbol {
1261		switch($2->i_token) {
1262		case UNDECLARED:
1263			if (pass2)
1264				err[pflag]++;
1265			else {
1266				$2->i_token = LABEL;
1267				$2->i_value = dollarsign;
1268			}
1269			break;
1270		case LABEL:
1271			if (!pass2) {
1272				$2->i_token = MULTDEF;
1273				err[mflag]++;
1274			} else if ($2->i_value != dollarsign)
1275				err[pflag]++;
1276			break;
1277		default:
1278			err[mflag]++;
1279			$2->i_token = MULTDEF;
1280		}
1281	}
1282|
1283	symbol maybecolon {
1284		switch($1->i_token) {
1285		case UNDECLARED:
1286			if (pass2)
1287				err[pflag]++;
1288			else {
1289				$1->i_token = LABEL;
1290				$1->i_value = dollarsign;
1291			}
1292			break;
1293		case LABEL:
1294			if (!pass2) {
1295				$1->i_token = MULTDEF;
1296				err[mflag]++;
1297			} else if ($1->i_value != dollarsign)
1298				err[pflag]++;
1299			break;
1300		default:
1301			err[mflag]++;
1302			$1->i_token = MULTDEF;
1303		}
1304	}
1305;
1306
1307
1308operation:
1309	NOOPERAND
1310		{ emit1($1->i_value, 0, 0, 1); }
1311|
1312	JP expression
1313		{ emitjp(0303, $2); }
1314|
1315	CALL expression
1316		{ emit(3, 0315, $2, $2 >> 8); }
1317|
1318	RST expression
1319		{ int a = $2, doneerr=0;
1320		/* added support for normal RST form -rjm */
1321		if (a >= 8) {
1322			if ((a&7)!=0) doneerr=1,err[vflag]++;
1323			a >>= 3;
1324		}
1325		if ((a > 7 || a < 0) && !doneerr) /* don't give two errs... */
1326			err[vflag]++;
1327		emit(1, $1->i_value + (a << 3));
1328	}
1329|
1330	ADD expression
1331		{ emit1(0306, 0, $2, 3); if (pass2) warnprt (1, 0); }
1332|
1333	ADD ACC ',' expression
1334		{ emit1(0306, 0, $4, 3); }
1335|
1336	ARITHC expression
1337		{ emit1(0306 + ($1->i_value << 3), 0, $2, 3); if (pass2) warnprt (1, 0); }
1338|
1339	ARITHC ACC ',' expression
1340		{ emit1(0306 + ($1->i_value << 3), 0, $4, 3); }
1341|
1342	LOGICAL expression
1343		{ emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
1344|
1345	AND expression
1346		{ emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
1347|
1348	OR expression
1349		{ emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
1350|
1351	XOR expression
1352		{ emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
1353|
1354	LOGICAL ACC ',' expression	/* -cdk */
1355		{ emit1(0306 | ($1->i_value << 3), 0, $4, 3); if (pass2) warnprt (1, 0); }
1356|
1357	AND ACC ',' expression	/* -cdk */
1358		{ emit1(0306 | ($1->i_value << 3), 0, $4, 3); if (pass2) warnprt (1, 0); }
1359|
1360	OR ACC ',' expression	/* -cdk */
1361		{ emit1(0306 | ($1->i_value << 3), 0, $4, 3); if (pass2) warnprt (1, 0); }
1362|
1363	XOR ACC ',' expression	/* -cdk */
1364		{ emit1(0306 | ($1->i_value << 3), 0, $4, 3); if (pass2) warnprt (1, 0); }
1365|
1366	ADD reg
1367		{ emit1(0200 + ($2 & 0377), $2, 0, 0); if (pass2) warnprt (1, 0); }
1368|
1369	ADD ACC ',' reg
1370		{ emit1(0200 + ($4 & 0377), $4, 0, 0); }
1371|
1372	ARITHC reg
1373		{ emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); if (pass2) warnprt (1, 0); }
1374|
1375	ARITHC ACC ',' reg
1376		{ emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); }
1377|
1378	LOGICAL reg
1379		{ emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
1380|
1381	AND reg
1382		{ emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
1383|
1384	OR reg
1385		{ emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
1386|
1387	XOR reg
1388		{ emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
1389|
1390	LOGICAL ACC ',' reg		/* -cdk */
1391		{ emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); if (pass2) warnprt (1, 0); }
1392|
1393	AND ACC ',' reg		/* -cdk */
1394		{ emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); if (pass2) warnprt (1, 0); }
1395|
1396	OR ACC ',' reg		/* -cdk */
1397		{ emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); if (pass2) warnprt (1, 0); }
1398|
1399	XOR ACC ',' reg		/* -cdk */
1400		{ emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); if (pass2) warnprt (1, 0); }
1401|
1402	SHIFT reg
1403		{
1404			if (suggest_optimise && pass2 && ($2 & 0377) == 7 && $1->i_value <= 4)
1405				warnprt ($1->i_value + 4, 0);
1406			if (pass2 && $1->i_value == 6)
1407				warnprt (1, 0);
1408			emit1(0145400 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0);
1409		}
1410|
1411	INCDEC reg
1412		{ emit1($1->i_value + (($2 & 0377) << 3) + 4, $2, 0, 0); }
1413|
1414	ARITHC HL ',' bcdehlsp
1415		{ if ($1->i_value == 1)
1416				emit(2,0355,0112+$4);
1417			else
1418				emit(2,0355,0102+$4);
1419		}
1420|
1421	ADD mar ',' bcdesp
1422		{ emitdad($2,$4); }
1423|
1424	ADD mar ',' mar
1425		{
1426			if ($2 != $4) {
1427				fprintf(stderr,"ADD mar, mar error\n");
1428				err[fflag]++;
1429			}
1430			emitdad($2,$4);
1431		}
1432|
1433	INCDEC evenreg
1434		{ emit1(($1->i_value << 3) + ($2 & 0377) + 3, $2, 0, 1); }
1435|
1436	PUSHPOP pushable
1437		{ emit1($1->i_value + ($2 & 0377), $2, 0, 1); }
1438|
1439	BIT expression ',' reg
1440		{
1441			if ($2 < 0 || $2 > 7)
1442				err[vflag]++;
1443			emit1($1->i_value + (($2 & 7) << 3) + ($4 & 0377), $4, 0, 0);
1444		}
1445|
1446	JP condition ',' expression
1447		{ emitjp(0302 + $2, $4); }
1448|
1449	JP '(' mar ')'
1450		{ emit1(0351, $3, 0, 1); }
1451|
1452	JP mar
1453		{ emit1(0351, $2, 0, 1); if (pass2) warnprt (1, 0); }
1454|
1455	CALL condition ',' expression
1456		{ emit(3, 0304 + $2, $4, $4 >> 8); }
1457|
1458	JR expression
1459		{ emitjr(030,$2); }
1460|
1461	JR spcondition ',' expression
1462		{ emitjr($1->i_value + $2, $4); }
1463|
1464	DJNZ expression
1465		{ emitjr($1->i_value, $2); }
1466|
1467	RET
1468		{ emit(1, $1->i_value); }
1469|
1470	RET condition
1471		{ emit(1, 0300 + $2); }
1472|
1473	LD reg ',' reg
1474		{
1475			if (($2 & 0377) == 6 && ($4 & 0377) == 6) {
1476				fprintf(stderr,"LD reg, reg error\n");
1477				err[fflag]++;
1478			}
1479			emit1(0100 + (($2 & 7) << 3) + ($4 & 7),$2 | $4, 0, 0);
1480		}
1481|
1482	LD reg ',' noparenexpr
1483		{
1484			if (suggest_optimise && pass2 && $4 == 0 && ($2 & 0377) == 7)
1485				warnprt (3, 0);
1486			emit1(6 + (($2 & 0377) << 3), $2, $4, 2);
1487		}
1488|
1489	LD reg ',' '(' RP ')'
1490		{	if ($2 != 7) {
1491				fprintf(stderr,"LD reg, (RP) error\n");
1492				err[fflag]++;
1493			}
1494			else emit(1, 012 + $5->i_value);
1495		}
1496|
1497	LD reg ',' parenexpr
1498		{
1499			if ($2 != 7) {
1500				fprintf(stderr,"LD reg, (expr) error\n");
1501				err[fflag]++;
1502			}
1503			else emit(3, 072, $4, $4 >> 8);
1504		}
1505|
1506	LD '(' RP ')' ',' ACC
1507		{ emit(1, 2 + $3->i_value); }
1508|
1509	LD parenexpr ',' ACC
1510		{ emit(3, 062, $2, $2 >> 8); }
1511|
1512	LD reg ',' MISCREG
1513		{
1514			if ($2 != 7) {
1515				fprintf(stderr,"LD reg, MISCREG error\n");
1516				err[fflag]++;
1517			}
1518			else emit(2, 0355, 0127 + $4->i_value);
1519		}
1520|
1521	LD MISCREG ',' ACC
1522		{ emit(2, 0355, 0107 + $2->i_value); }
1523|
1524	LD evenreg ',' lxexpression
1525		{ emit1(1 + ($2 & 060), $2, $4, 5); }
1526|
1527	LD evenreg ',' parenexpr
1528		{
1529			if (($2 & 060) == 040)
1530				emit1(052, $2, $4, 5);
1531			else
1532				emit(4, 0355, 0113 + $2, $4, $4 >> 8);
1533		}
1534|
1535	LD parenexpr ',' evenreg
1536		{
1537			if (($4 & 060) == 040)
1538				emit1(042, $4, $2, 5);
1539			else
1540				emit(4, 0355, 0103 + $4, $2, $2 >> 8);
1541		}
1542|
1543	LD evenreg ',' mar
1544		{
1545			if ($2 != 060) {
1546				fprintf(stderr,"LD evenreg error\n");
1547				err[fflag]++;
1548			}
1549			else
1550				emit1(0371, $4, 0, 1);
1551		}
1552|
1553	EX RP ',' HL
1554		{
1555			if ($2->i_value != 020) {
1556				fprintf(stderr,"EX RP, HL error\n");
1557				err[fflag]++;
1558			}
1559			else
1560				emit(1, 0353);
1561		}
1562|
1563	EX AF ',' AF setqf '\'' clrqf
1564		{ emit(1, 010); }
1565|
1566	EX '(' SP ')' ',' mar
1567		{ emit1(0343, $6, 0, 1); }
1568|
1569	IN realreg ',' parenexpr
1570		{
1571			if ($2 != 7) {
1572				fprintf(stderr,"IN reg, (expr) error\n");
1573				err[fflag]++;
1574			}
1575			else	{
1576				if ($4 < 0 || $4 > 255)
1577					err[vflag]++;
1578				emit(2, $1->i_value, $4);
1579			}
1580		}
1581|
1582	IN realreg ',' '(' C ')'
1583		{ emit(2, 0355, 0100 + ($2 << 3)); }
1584|
1585	IN F ',' '(' C ')'
1586		{ emit(2, 0355, 0160); }
1587|
1588	OUT parenexpr ',' ACC
1589		{
1590			if ($2 < 0 || $2 > 255)
1591				err[vflag]++;
1592			emit(2, $1->i_value, $2);
1593		}
1594|
1595	OUT '(' C ')' ',' realreg
1596		{ emit(2, 0355, 0101 + ($6 << 3)); }
1597|
1598	IM expression
1599		{
1600			if ($2 > 2 || $2 < 0)
1601				err[vflag]++;
1602			else
1603				emit(2, $1->i_value >> 8, $1->i_value + (($2 + ($2 > 0)) << 3));
1604		}
1605|
1606	PHASE expression
1607		{
1608			if (phaseflag) {
1609				err[oflag]++;
1610			} else {
1611				phaseflag = 1;
1612				phdollar = dollarsign;
1613				dollarsign = $2;
1614				phbegin = dollarsign;
1615			}
1616		}
1617|
1618	DEPHASE
1619		{
1620			if (!phaseflag) {
1621				err[oflag]++;
1622			} else {
1623				phaseflag = 0;
1624				dollarsign = phdollar + dollarsign - phbegin;
1625			}
1626		}
1627|
1628	ORG expression
1629		{
1630			if (not_seen_org)
1631				first_org_store=yyvsp[0].ival;
1632			not_seen_org=0;
1633			if (phaseflag) {
1634				err[oflag]++;
1635				dollarsign = phdollar + dollarsign - phbegin;
1636				phaseflag = 0;
1637			}
1638			if ($2-dollarsign) {
1639				flushbin();
1640				if (pass2 && !output_hex && dollarsign != 0) {
1641					if (yyvsp[0].ival < dollarsign) {
1642						err[orgflag]++;
1643					} else {
1644						int f;
1645						for (f=0;f<(yyvsp[0].ival - dollarsign);f++)
1646							fputc(0, fbuf);
1647					}
1648				}
1649				olddollar = $2;
1650				dollarsign = $2;
1651			}
1652		}
1653|
1654	DEFB db.list
1655|
1656	DEFW dw.list
1657|
1658	ENDM
1659;
1660
1661
1662parm.list:
1663|
1664	parm.element
1665|
1666	parm.list ',' parm.element
1667;
1668
1669
1670parm.element:
1671	UNDECLARED
1672		{
1673			$1->i_token = MPARM;
1674			if (parm_number >= PARMMAX)
1675				error("Too many parameters");
1676			$1->i_value = parm_number++;
1677		}
1678;
1679
1680
1681arg.list:
1682	/* empty */
1683|
1684	arg.element
1685|
1686	arg.list ',' arg.element
1687;
1688
1689
1690arg.element:
1691	ARG
1692		{
1693			cp = malloc(strlen(tempbuf)+1);
1694#ifdef M_DEBUG
1695			fprintf (stderr, "[Arg%u(%p): %s]\n", parm_number, cp, tempbuf);
1696#endif
1697			est2[parm_number++] = cp;
1698			strcpy(cp, tempbuf);
1699		}
1700;
1701reg:
1702	realreg
1703|
1704	mem
1705;
1706realreg:
1707	REGNAME
1708		{
1709			$$ = $1->i_value;
1710		}
1711|
1712	ACC
1713		{
1714			$$ = $1->i_value;
1715		}
1716|
1717	C
1718		{
1719			$$ = $1->i_value;
1720		}
1721;
1722mem:
1723	'(' HL ')'
1724		{
1725			$$ = 6;
1726		}
1727|
1728	'(' INDEX expression ')'
1729		{
1730			disp = $3;
1731			$$ = ($2->i_value & 0177400) | 6;
1732		}
1733|
1734	'(' INDEX ')'
1735		{
1736			disp = 0;
1737			$$ = ($2->i_value & 0177400) | 6;
1738		}
1739;
1740evenreg:
1741	bcdesp
1742|
1743	mar
1744;
1745pushable:
1746	RP
1747		{
1748			$$ = $1->i_value;
1749		}
1750|
1751	AF
1752		{
1753			$$ = $1->i_value;
1754		}
1755|
1756	mar
1757;
1758bcdesp:
1759	RP
1760		{
1761			$$ = $1->i_value;
1762		}
1763|
1764	SP
1765		{
1766			$$ = $1->i_value;
1767		}
1768;
1769bcdehlsp:
1770	bcdesp
1771|
1772	HL
1773		{
1774			$$ = $1->i_value;
1775		}
1776;
1777mar:
1778	HL
1779		{
1780			$$ = $1->i_value;
1781		}
1782|
1783	INDEX
1784		{
1785			$$ = $1->i_value;
1786		}
1787;
1788condition:
1789	spcondition
1790|
1791	COND
1792		{
1793			$$ = $1->i_value;
1794		}
1795;
1796spcondition:
1797	SPCOND
1798		{
1799			$$ = $1->i_value;
1800		}
1801|
1802	C
1803		{	$$ = 030;	}
1804;
1805db.list:
1806	db.list.element
1807|
1808	db.list ',' db.list.element
1809;
1810db.list.element:
1811	TWOCHAR
1812		{
1813			dataemit(2, $1, $1>>8);
1814		}
1815|
1816	STRING
1817		{
1818			cp = $1;
1819			while (*cp != '\0')
1820				dataemit(1,*cp++);
1821		}
1822|
1823	expression
1824		{
1825			if ($1 < -128 || $1 > 255)
1826					err[vflag]++;
1827			dataemit(1, $1 & 0377);
1828		}
1829;
1830
1831
1832dw.list:
1833	dw.list.element
1834|
1835	dw.list ',' dw.list.element
1836;
1837
1838
1839dw.list.element:
1840	expression
1841		{
1842			dataemit(2, $1, $1>>8);
1843		}
1844;
1845
1846
1847
1848lxexpression:
1849	noparenexpr
1850|
1851	TWOCHAR
1852;
1853
1854expression:
1855	parenexpr
1856|
1857	noparenexpr
1858;
1859
1860parenexpr:
1861	'(' expression ')'
1862		{	$$ = $2;	}
1863;
1864
1865noparenexpr:
1866	LABEL
1867		{	$$ = $1->i_value; $1->i_uses++ ;	}
1868|
1869	NUMBER
1870|
1871	ONECHAR
1872|
1873	EQUATED
1874		{	$$ = $1->i_value; $1->i_uses++ ;	}
1875|
1876	WASEQUATED
1877		{
1878			$$ = $1->i_value; $1->i_uses++ ;
1879			if ($1->i_equbad) {
1880				/* forward reference to equ with a forward
1881				 * reference of its own cannot be resolved
1882				 * in two passes. -rjm
1883				 */
1884				err[frflag]++;
1885			}
1886		}
1887|
1888	DEFLED
1889		{	$$ = $1->i_value; $1->i_uses++ ;	}
1890|
1891	'$'
1892		{	$$ = dollarsign;	}
1893|
1894	UNDECLARED
1895		{
1896			err[uflag]++;
1897			equ_bad_label=1;
1898			$$ = 0;
1899		}
1900|
1901	MULTDEF
1902		{	$$ = $1->i_value;	}
1903|
1904	expression '+' expression
1905		{	$$ = $1 + $3;	}
1906|
1907	expression '-' expression
1908		{	$$ = $1 - $3;	}
1909|
1910	expression '/' expression
1911		{	if ($3 == 0) err[eflag]++; else $$ = $1 / $3;	}
1912|
1913	expression '*' expression
1914		{	$$ = $1 * $3;	}
1915|
1916	expression '%' expression
1917		{	if ($3 == 0) err[eflag]++; else $$ = $1 % $3;	}
1918|
1919	expression MOD expression
1920		{	if ($3 == 0) err[eflag]++; else $$ = $1 % $3;	}
1921|
1922	expression '&' expression
1923		{	$$ = $1 & $3;	}
1924|
1925	expression AND expression
1926		{	$$ = $1 & $3;	}
1927|
1928	expression '|' expression
1929		{	$$ = $1 | $3;	}
1930|
1931	expression OR expression
1932		{	$$ = $1 | $3;	}
1933|
1934	expression '^' expression
1935		{	$$ = $1 ^ $3;	}
1936|
1937	expression XOR expression
1938		{	$$ = $1 ^ $3;	}
1939|
1940	expression SHL expression
1941		{	$$ = $1 << $3;	}
1942|
1943	expression SHR expression
1944		{	$$ = (($1 >> 1) & 077777) >> ($3 - 1);	}
1945|
1946	expression '<' expression
1947		{	$$ = $1 < $3;	}
1948|
1949	expression '=' expression
1950		{	$$ = $1 == $3;	}
1951|
1952	expression '>' expression
1953		{	$$ = $1 > $3;	}
1954|
1955	expression LT expression
1956		{	$$ = $1 < $3;	}
1957|
1958	expression EQ expression
1959		{	$$ = $1 == $3;	}
1960|
1961	expression GT expression
1962		{	$$ = $1 > $3;	}
1963|
1964	expression LE expression
1965		{	$$ = $1 <= $3;	}
1966|
1967	expression GE expression
1968		{	$$ = $1 >= $3;	}
1969|
1970	expression NE expression
1971		{	$$ = $1 != $3;	}
1972|
1973	'[' expression ']'
1974		{	$$ = $2;	}
1975|
1976	NOT expression
1977		{	$$ = ~$2;	}
1978|
1979	'~' expression
1980		{	$$ = ~$2;	}
1981|
1982	'!' expression
1983		{	$$ = !$2;	}
1984|
1985	'+' expression %prec UNARY
1986		{	$$ = $2;	}
1987|
1988	'-' expression %prec UNARY
1989		{	$$ = -$2;	}
1990;
1991
1992symbol:
1993	UNDECLARED
1994|
1995	LABEL
1996|
1997	MULTDEF
1998|
1999	EQUATED
2000|
2001	WASEQUATED
2002|
2003	DEFLED
2004;
2005
2006
2007al:
2008	{ int i;
2009		if (expptr >= MAXEXP)
2010			error("Macro expansion level");
2011		est2 = (char **) malloc((PARMMAX +4) * sizeof(char *));
2012		expstack[expptr] = (char *)est2 ;
2013		for (i=0; i<PARMMAX; i++)
2014			est2[i] = 0;
2015		arg_flag++;
2016	}
2017;
2018
2019
2020arg_on:
2021	{	arg_flag++;	}
2022;
2023
2024arg_off:
2025		{	arg_flag = 0;	}
2026;
2027
2028setqf:
2029		{	quoteflag++;	}
2030;
2031
2032clrqf:
2033		{	quoteflag = 0;	}
2034
2035;
2036
2037%%
2038
2039#define F_END	0
2040#define OTHER	1
2041#define SPACE	2
2042#define DIGIT	3
2043#define LETTER	4
2044#define STARTER 5
2045#define HEXIN	6
2046
2047
2048/*
2049 *  This is the table of character classes.  It is used by the lexical
2050 *  analyser. (yylex())
2051 */
2052char	charclass[] = {
2053	F_END,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,
2054	OTHER,	SPACE,	OTHER,	OTHER,	OTHER,	SPACE,	OTHER,	OTHER,
2055	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,
2056	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,
2057	SPACE,	OTHER,	OTHER,	HEXIN,	HEXIN,	OTHER,	HEXIN,	OTHER,
2058	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,
2059	DIGIT,	DIGIT,	DIGIT,	DIGIT,	DIGIT,	DIGIT,	DIGIT,	DIGIT,
2060	DIGIT,	DIGIT,	OTHER,	OTHER,	OTHER,	OTHER,	OTHER,	STARTER,
2061	STARTER,LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
2062	LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
2063	LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
2064	LETTER, LETTER, LETTER, OTHER,	OTHER,	OTHER,	OTHER,	LETTER,
2065	OTHER,	LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
2066	LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
2067	LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
2068	LETTER, LETTER, LETTER, OTHER,	OTHER,	OTHER,	OTHER,	OTHER,
2069};
2070
2071
2072/*
2073 *  the following table tells which characters are parts of numbers.
2074 *  The entry is non-zero for characters which can be parts of numbers.
2075 */
2076char	numpart[] = {
2077	0,	0,	0,	0,	0,	0,	0,	0,
2078	0,	0,	0,	0,	0,	0,	0,	0,
2079	0,	0,	0,	0,	0,	0,	0,	0,
2080	0,	0,	0,	0,	0,	0,	0,	0,
2081	0,	0,	0,	0,	0,	0,	0,	0,
2082	0,	0,	0,	0,	0,	0,	0,	0,
2083	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
2084	'8',	'9',	0,	0,	0,	0,	0,	0,
2085	0,	'A',	'B',	'C',	'D',	'E',	'F',	0,
2086	'H',	0,	0,	0,	0,	0,	0,	'O',
2087	0,	'Q',	0,	0,	0,	0,	0,	0,
2088	0,	0,	0,	0,	0,	0,	0,	0,
2089	0,	'a',	'b',	'c',	'd',	'e',	'f',	0,
2090	'h',	0,	0,	0,	0,	0,	0,	'o',
2091	0,	'q',	0,	0,	0,	0,	0,	0,
2092	0,	0,	0,	0,	0,	0,	0,	0,
2093	0};
2094
2095
2096
2097
2098/*
2099 *  the following table is a list of assembler mnemonics;
2100 *  for each mnemonic the associated machine-code bit pattern
2101 *  and symbol type are given.
2102 */
2103struct	item	keytab[] = {
2104	{"a",	7,	ACC,		0},
2105	{"adc",	1,	ARITHC,		0},
2106	{"add",	0,	ADD,		0},
2107	{"af",	060,	AF,		0},
2108	{"and",	4,	AND,		0},
2109	{"ascii",0,	DEFB,		0},
2110	{"b",	0,	REGNAME,	0},
2111	{"bc",	0,	RP,		0},
2112	{"bit",	0145500,BIT,		0},
2113	{"block",0,	DEFS,		0},
2114	{"byte",0,	DEFB,		0},
2115	{"c",	1,	C,		0},
2116	{"call",0315,	CALL,		0},
2117	{"ccf",	077,	NOOPERAND,	0},
2118	{"cmp",	7,	LOGICAL,	0},		/* -cdk */
2119	{"cond",0,	IF,		0},
2120	{"cp",	7,	LOGICAL,	0},
2121	{"cpd",	0166651,NOOPERAND,	0},
2122	{"cpdr",0166671,NOOPERAND,	0},
2123	{"cpi",	0166641,NOOPERAND,	0},
2124	{"cpir",0166661,NOOPERAND,	0},
2125	{"cpl",	057,	NOOPERAND,	0},
2126	{"d",	2,	REGNAME,	0},
2127	{"daa",	0047,	NOOPERAND,	0},
2128	{"db",	0,	DEFB,		0},
2129	{"de",	020,	RP,		0},
2130	{"dec",	1,	INCDEC,		0},
2131	{"defb",0,	DEFB,		0},
2132	{"defl",0,	DEFL,		0},
2133	{"defm",0,	DEFB,		0},
2134	{"defs",0,	DEFS,		0},
2135	{"defw",0,	DEFW,		0},
2136	{"dephase",0,	DEPHASE,	0},
2137	{"di",	0363,	NOOPERAND,	0},
2138	{"djnz",020,	DJNZ,		0},
2139	{"ds",	0,	DEFS,		0},
2140	{"dw",	0,	DEFW,		0},
2141	{"e",	3,	REGNAME,	0},
2142	{"ei",	0373,	NOOPERAND,	0},
2143	{"eject",1,	LIST,		0},
2144	{"elist",3,	LIST,		0},
2145	{"else",0,	ELSE,		0},
2146	{"end",	0,	END,		0},
2147	{"endc",0,	ENDIF,		0},
2148	{"endif",0,	ENDIF,		0},
2149	{"endm", 0,	ENDM,		0},
2150	{"eq",	0,	EQ,		0},
2151	{"equ",	0,	EQU,		0},
2152	{"ex",	0,	EX,		0},
2153	{"exx",	0331,	NOOPERAND,	0},
2154	{"f",	0,	F,		0},
2155	{"flist",4,	LIST,		0},
2156	{"ge",	0,	GE,		0},
2157	{"glist",5,	LIST,		0},
2158	{"gt",	0,	GT,		0},
2159	{"h",	4,	REGNAME,	0},
2160	{"halt",0166,	NOOPERAND,	0},
2161	{"hl",	040,	HL,		0},
2162	{"i",	0,	MISCREG,	0},
2163	{"if",	0,	IF,		0},
2164	{"im",	0166506,IM,		0},
2165	{"in",	0333,	IN,		0},
2166	{"inc",	0,	INCDEC,		0},
2167	{"include", 3,	ARGPSEUDO,	0},
2168	{"ind",	0166652,NOOPERAND,	0},
2169	{"indr",0166672,NOOPERAND,	0},
2170	{"ini",	0166642,NOOPERAND,	0},
2171	{"inir",0166662,NOOPERAND,	0},
2172	{"ix",	0156440,INDEX,		0},
2173	{"iy",	0176440,INDEX,		0},
2174	{"jmp",	0303,	JP,		0},		/* -cdk */
2175	{"jp",	0303,	JP,		0},
2176	{"jr",	040,	JR,		0},
2177	{"l",	5,	REGNAME,	0},
2178	{"ld",	0,	LD,		0},
2179	{"ldd",	0166650,NOOPERAND,	0},
2180	{"lddr",0166670,NOOPERAND,	0},
2181	{"ldi",	0166640,NOOPERAND,	0},
2182	{"ldir",0166660,NOOPERAND,	0},
2183	{"le",	0,	LE,		0},
2184	{"list",0,	LIST,		0},
2185	{"lt",	0,	LT,		0},
2186	{"m",	070,	COND,		0},
2187	{"macro",0,	MACRO,		0},
2188	{"max",	1,	MINMAX,		0},
2189	{"min",	0,	MINMAX,		0},
2190	{"mlist",6,	LIST,		0},
2191	{"mod",	0,	MOD,		0},
2192	{"nc",	020,	SPCOND,		0},
2193	{"ne",	0,	NE,		0},
2194	{"neg",	0166504,NOOPERAND,	0},
2195	{"nolist",-1,	LIST,		0},
2196	{"nop",	0,	NOOPERAND,	0},
2197	{"not",	0,	NOT,		0},
2198	{"nv",	040,	COND,		0},
2199	{"nz",	0,	SPCOND,		0},
2200	{"or",	6,	OR,		0},
2201	{"org",	0,	ORG,		0},
2202	{"otdr",0166673,NOOPERAND,	0},
2203	{"otir",0166663,NOOPERAND,	0},
2204	{"out",	0323,	OUT,		0},
2205	{"outd",0166653,NOOPERAND,	0},
2206	{"outi",0166643,NOOPERAND,	0},
2207	{"p",	060,	COND,		0},
2208	{"pe",	050,	COND,		0},
2209	{"phase",0,	PHASE,		0},
2210	{"po",	040,	COND,		0},
2211	{"pop",	0301,	PUSHPOP,	0},
2212	{"push", 0305,	PUSHPOP,	0},
2213	{"r",	010,	MISCREG,	0},
2214	{"read", 3,	ARGPSEUDO,	0},
2215	{"res",	0145600,BIT,		0},
2216	{"ret",	0311,	RET,		0},
2217	{"reti",0166515,NOOPERAND,	0},
2218	{"retn",0166505,NOOPERAND,	0},
2219	{"rl",	2,	SHIFT,		0},
2220	{"rla",	027,	NOOPERAND,	0},
2221	{"rlc",	0,	SHIFT,		0},
2222	{"rlca",07,	NOOPERAND,	0},
2223	{"rld",	0166557,NOOPERAND,	0},
2224	{"rmem",0,	DEFS,		0},
2225	{"rr",	3,	SHIFT,		0},
2226	{"rra",	037,	NOOPERAND,	0},
2227	{"rrc",	1,	SHIFT,		0},
2228	{"rrca",017,	NOOPERAND,	0},
2229	{"rrd",	0166547,NOOPERAND,	0},
2230	{"rst",	0307,	RST,		0},
2231	{"rsym",1,	ARGPSEUDO,	0},
2232	{"sbc",	3,	ARITHC,		0},
2233	{"scf",	067,	NOOPERAND,	0},
2234	{"set",	0145700,BIT,		0},
2235	{"shl",	0,	SHL,		0},
2236	{"shr",	0,	SHR,		0},
2237	{"sla",	4,	SHIFT,		0},
2238	{"sll",	6,	SHIFT,		0}, /* Undocumented */
2239	{"sp",	060,	SP,		0},
2240	{"space",2,	LIST,		0},
2241	{"sra",	5,	SHIFT,		0},
2242	{"srl",	7,	SHIFT,		0},
2243	{"sub",	2,	LOGICAL,	0},
2244	{"text",0,	DEFB,		0},
2245	{"title",0,	ARGPSEUDO,	0},
2246	{"v",	050,	COND,		0},
2247	{"word",0,	DEFW,		0},
2248	{"wsym",2,	ARGPSEUDO,	0},
2249	{"xor",	5,	XOR,		0},
2250	{"z",	010,	SPCOND,		0}
2251};
2252
2253/*
2254 *  user-defined items are tabulated in the following table.
2255 */
2256
2257struct item	itemtab[ITEMTABLESIZE];
2258struct item	*itemmax = itemtab+ITEMTABLESIZE;
2259
2260
2261
2262
2263
2264/*
2265 *  lexical analyser, called by yyparse.
2266 */
2267int yylex()
2268{
2269	int	c;
2270	char *p;
2271	int	radix;
2272	int  limit;
2273	int leadinghex = 0;
2274
2275	if (arg_flag)
2276		return(getarg());
2277loop switch(charclass[c = nextchar()]) {
2278	case F_END:
2279		if (expptr) {
2280			popsi();
2281			continue;
2282		} else return(0);
2283
2284	case SPACE:
2285		break;
2286	case LETTER:
2287	case STARTER:
2288		p = tempbuf;
2289		do {
2290			if (p >= tempmax)
2291				error(symlong);
2292			*p++ = (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
2293			while	((c = nextchar()) == '$')
2294				;
2295		} while	(charclass[c]==LETTER || charclass[c]==DIGIT);
2296		if (p - tempbuf > MAXSYMBOLSIZE)
2297		{
2298			if (pass2) warnprt (0, 1);
2299			p = tempbuf + MAXSYMBOLSIZE;
2300		}
2301		*p++ = '\0';
2302		peekc = c;
2303		return(tokenofitem(UNDECLARED));
2304	case HEXIN:
2305	{
2306		int corig = c;
2307		if (*ifptr) return (skipline(c));
2308		while ((c = nextchar ()) == '$');
2309		if (!numpart[c])
2310		{
2311			peekc = c;
2312			return (corig);
2313		}
2314		leadinghex = 1;
2315		/* fall through */
2316	}
2317	case DIGIT:
2318		if (*ifptr) return (skipline(c));
2319		p = tempbuf;
2320		do	{
2321			if (p >= tempmax)
2322				error(symlong);
2323			*p++ = (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
2324			while	((c = nextchar()) == '$');
2325			}
2326			while(numpart[c]);
2327		peekc = c;
2328		if (leadinghex)
2329		{
2330			*p++ = 'h';
2331		}
2332		*p-- = '\0';
2333		switch(*p)	{
2334			case 'o':
2335			case 'q':
2336				radix = 8;
2337				limit = 020000;
2338				*p = '\0';
2339				break;
2340			case 'd':
2341				radix = 10;
2342				limit = 6553;
2343				*p = '\0';
2344				break;
2345			case 'h':
2346				radix = 16;
2347				limit = 010000;
2348				*p = '\0';
2349				break;
2350			case 'b':
2351				radix = 2;
2352				limit = 077777;
2353				*p = '\0';
2354				break;
2355			default:
2356				radix = 10;
2357				limit = 6553;
2358				p++;
2359				break;
2360			}
2361
2362		/*
2363		 *  tempbuf now points to the number, null terminated
2364		 *  with radix 'radix'.
2365		 */
2366		yylval.ival = 0;
2367		p = tempbuf;
2368		do	{
2369			c = *p - (*p > '9' ? ('a' - 10) : '0');
2370			if (c >= radix)
2371				{
2372				err[iflag]++;
2373				yylval.ival = 0;
2374				break;
2375				}
2376			if (yylval.ival < limit ||
2377				(radix == 10 && yylval.ival == 6553 && c < 6) ||
2378				(radix == 2 && yylval.ival == limit))
2379				yylval.ival = yylval.ival * radix + c;
2380			else {
2381				err[vflag]++;
2382				yylval.ival = 0;
2383				break;
2384				}
2385			}
2386			while(*++p != '\0');
2387		return(NUMBER);
2388	default:
2389		if (*ifptr)
2390			return(skipline(c));
2391		switch(c) {
2392		int corig;
2393		case ';':
2394			return(skipline(c));
2395		case '\'':
2396			if (quoteflag) return('\'');
2397		case '"':
2398			corig = c;
2399			p = tempbuf;
2400			p[1] = 0;
2401			do	switch(c = nextchar())	{
2402			case '\0':
2403			case '\n':
2404				err[bflag]++;
2405				goto retstring;
2406			case '\'':
2407			case '"':
2408				if (c == corig && (c = nextchar()) != corig) {
2409				retstring:
2410					peekc = c;
2411					*p = '\0';
2412					if ((p-tempbuf) >2) {
2413						yylval.cval = tempbuf;
2414						return(STRING);
2415					} else if (p-tempbuf == 2)	{
2416						p = tempbuf;
2417						yylval.ival = *p++ ;
2418						yylval.ival |= *p<<8;
2419						return(TWOCHAR);
2420					} else	{
2421						p = tempbuf;
2422						yylval.ival = *p++;
2423						return(ONECHAR);
2424					}
2425				}
2426			default:
2427				*p++ = c;
2428			} while (p < tempmax);
2429			/*
2430			 *  if we break out here, our string is longer than
2431			 *  our input line
2432			 */
2433			error("string buffer overflow");
2434		case '<':
2435			corig = c;
2436			switch (c = nextchar ()) {
2437			case '=':
2438				return LE;
2439			case '<':
2440				return SHL;
2441			case '>':
2442				return NE;
2443			default:
2444				peekc = c;
2445				return corig;
2446			}
2447			/* break; suppress "unreachable" warning for tcc */
2448		case '>':
2449			corig = c;
2450			switch (c = nextchar ()) {
2451			case '=':
2452				return GE;
2453			case '>':
2454				return SHR;
2455			default:
2456				peekc = c;
2457				return corig;
2458			}
2459			/* break; suppress "unreachable" warning for tcc */
2460		case '!':
2461			corig = c;
2462			switch (c = nextchar ()) {
2463			case '=':
2464				return NE;
2465			default:
2466				peekc = c;
2467				return corig;
2468			}
2469			/* break; suppress "unreachable" warning for tcc */
2470		case '=':
2471			corig = c;
2472			switch (c = nextchar ()) {
2473			case '=':
2474				return EQ;
2475			default:
2476				peekc = c;
2477				return corig;
2478			}
2479			/* break; suppress "unreachable" warning for tcc */
2480		default:
2481			return(c);
2482		}
2483	}
2484}
2485
2486/*
2487 *  return the token associated with the string pointed to by
2488 *  tempbuf.  if no token is associated with the string, associate
2489 *  deftoken with the string and return deftoken.
2490 *  in either case, cause yylval to point to the relevant
2491 *  symbol table entry.
2492 */
2493
2494int tokenofitem(int deftoken)
2495{
2496	char *p;
2497	struct item *	ip;
2498	int  i;
2499	int  r, l, u, hash;
2500
2501
2502#ifdef T_DEBUG
2503	fputs("'tokenofitem entry'	", stderr) ;
2504	fputs(tempbuf, stderr) ;
2505#endif
2506	if (strcmp (tempbuf, "cmp") == 0 ||
2507	    strcmp (tempbuf, "jmp") == 0 ||
2508	    strcmp (tempbuf, "v")   == 0 ||
2509	    strcmp (tempbuf, "nv")  == 0)
2510		if (pass2) warnprt (1, 1);
2511	/*
2512	 *  binary search
2513	 */
2514	l = 0;
2515	u = (sizeof keytab/sizeof keytab[0])-1;
2516	while (l <= u) {
2517		i = (l+u)/2;
2518		ip = &keytab[i];
2519		if ((r = strcmp(tempbuf, ip->i_string)) == 0)
2520			goto found;
2521		if (r < 0)
2522			u = i-1;
2523		else
2524			l = i+1;
2525	}
2526
2527	/*
2528	 *  hash into item table
2529	 */
2530	hash = 0;
2531	p = tempbuf;
2532	while (*p) hash += *p++;
2533	hash %= ITEMTABLESIZE;
2534	ip = &itemtab[hash];
2535
2536	loop {
2537		if (ip->i_token == 0)
2538			break;
2539		if (strcmp(tempbuf, ip->i_string) == 0)
2540			goto found;
2541		if (++ip >= itemmax)
2542			ip = itemtab;
2543	}
2544
2545	if (!deftoken) {
2546		i = 0 ;
2547		goto token_done ;
2548	}
2549	if (++nitems > ITEMTABLESIZE-20)
2550		error("item table overflow");
2551	ip->i_string = malloc(strlen(tempbuf)+1);
2552	ip->i_token = deftoken;
2553	ip->i_uses = 0;
2554	ip->i_equbad = 0;
2555	strcpy(ip->i_string, tempbuf);
2556
2557found:
2558	if (*ifptr) {
2559		if (ip->i_token == ENDIF) {
2560			i = ENDIF ;
2561			goto token_done ;
2562		}
2563		if (ip->i_token == ELSE) {
2564			/* We must only honour the ELSE if it is not
2565			   in a nested failed IF/ELSE */
2566			char forbid = 0;
2567			char *ifstackptr;
2568			for (ifstackptr = ifstack; ifstackptr != ifptr; ++ifstackptr) {
2569				if (*ifstackptr) {
2570					forbid = 1;
2571					break;
2572				}
2573			}
2574			if (!forbid) {
2575				i = ELSE;
2576				goto token_done;
2577			}
2578		}
2579		if (ip->i_token == IF) {
2580			if (ifptr >= ifstmax)
2581				error("Too many ifs");
2582			else *++ifptr = 1;
2583		}
2584		i = skipline(' ');
2585		goto token_done ;
2586	}
2587	yylval.itemptr = ip;
2588	i = ip->i_token;
2589	if (i == EQU) equ_bad_label=0;
2590token_done:
2591#ifdef T_DEBUG
2592	fputs("\t'tokenofitem exit'\n", stderr) ;
2593#endif
2594	return(i) ;
2595}
2596
2597
2598/*
2599 *  interchange two entries in the item table -- used by custom_qsort
2600 */
2601void interchange(int i, int j)
2602{
2603	struct item *fp, *tp;
2604	struct item temp;
2605
2606	fp = &itemtab[i];
2607	tp = &itemtab[j];
2608	temp.i_string = fp->i_string;
2609	temp.i_value = fp->i_value;
2610	temp.i_token = fp->i_token;
2611	temp.i_uses = fp->i_uses;
2612	temp.i_equbad = fp->i_equbad;
2613
2614	fp->i_string = tp->i_string;
2615	fp->i_value = tp->i_value;
2616	fp->i_token = tp->i_token;
2617	fp->i_uses = tp->i_uses;
2618	fp->i_equbad = tp->i_equbad;
2619
2620	tp->i_string = temp.i_string;
2621	tp->i_value = temp.i_value;
2622	tp->i_token = temp.i_token;
2623	tp->i_uses = temp.i_uses;
2624	tp->i_equbad = temp.i_equbad;
2625}
2626
2627
2628
2629/*
2630 *  quick sort -- used by putsymtab to sort the symbol table
2631 */
2632void custom_qsort(int m, int n)
2633{
2634	int  i, j;
2635
2636	if (m < n) {
2637		i = m;
2638		j = n+1;
2639		loop {
2640			do i++; while(strcmp(itemtab[i].i_string,
2641					itemtab[m].i_string) < 0);
2642			do j--; while(strcmp(itemtab[j].i_string,
2643					itemtab[m].i_string) > 0);
2644			if (i < j) interchange(i, j); else break;
2645		}
2646		interchange(m, j);
2647		custom_qsort(m, j-1);
2648		custom_qsort(j+1, n);
2649	}
2650}
2651
2652
2653
2654/*
2655 *  get the next character
2656 */
2657int nextchar()
2658{
2659	int c, ch;
2660	static  char  *earg;
2661
2662	if (peekc != -1) {
2663		c = peekc;
2664		peekc = -1;
2665		return(c);
2666	}
2667
2668start:
2669	if (earg) {
2670		if (*earg)
2671			return(addtoline(*earg++));
2672		earg = 0;
2673	}
2674
2675	if (expptr) {
2676		if ((ch = getm()) == '\1') {	/*  expand argument  */
2677			ch = getm() - 'A';
2678			if (ch >= 0 && ch < PARMMAX && est[ch])
2679				earg = est[ch];
2680			goto start;
2681		}
2682		if (ch == '\2') {	/*  local symbol  */
2683			ch = getm() - 'A';
2684			if (ch >= 0 && ch < PARMMAX && est[ch]) {
2685				earg = est[ch];
2686				goto start;
2687			}
2688			earg = getlocal(ch, (int)(long)est[TEMPNUM]);
2689			goto start…

Large files files are truncated, but you can click here to view the full file