示例#1
0
static int
rd_expr_shift (const char **p, int *valid, int level, int *check,
	       int print_errors)
{
  int result;
  if (verbose >= 6)
    fprintf (stderr, "%5d (0x%04x): Starting to read shift expression "
	     "(string=%s).\n", stack[sp].line, addr, *p);
  result = rd_term (p, valid, level, check, print_errors);
  *p = delspc (*p);
  while ((**p == '<' || **p == '>') && (*p)[1] == **p)
    {
      *check = 0;
      if (**p == '<')
	{
	  (*p) += 2;
	  result <<= rd_term (p, valid, level, check, print_errors);
	}
      else if (**p == '>')
	{
	  (*p) += 2;
	  result >>= rd_term (p, valid, level, check, print_errors);
	}
      *p = delspc (*p);
    }
示例#2
0
static int
rd_term (const char **p, int *valid, int level, int *check, int print_errors)
{
  /* read a term of an expression */
  int result;
  if (verbose >= 6)
    fprintf (stderr, "%5d (0x%04x): Starting to read term (string=%s).\n",
	     stack[sp].line, addr, *p);
  result = rd_factor (p, valid, level, check, print_errors);
  *p = delspc (*p);
  while (**p == '+' || **p == '-')
    {
      *check = 0;
      if (**p == '+')
	{
	  (*p)++;
	  result += rd_factor (p, valid, level, check, print_errors);
	}
      else if (**p == '-')
	{
	  (*p)++;
	  result -= rd_factor (p, valid, level, check, print_errors);
	}
      *p = delspc (*p);
    }
  if (verbose >= 7)
    fprintf (stderr, "%5d (0x%04x): rd_term returned %d (%04x).\n",
	     stack[sp].line, addr, result, result);
  return result;
}
示例#3
0
static int
rd_number (const char **p, const char **endp, int base)
{
  int result = 0, i;
  char *c, num[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  if (verbose >= 6)
    fprintf (stderr, "%5d (0x%04x): Starting to read number of base %d"
	     "(string=%s).\n", stack[sp].line, addr, base, *p);
  num[base] = '\0';
  *p = delspc (*p);
  while (**p && (c = strchr (num, tolower (**p))))
    {
      i = c - num;
      if (verbose >= 7)
	fprintf (stderr, "%5d (0x%04x): Digit found:%1x.\n", stack[sp].line,
		 addr, i);
      result = result * base + i;
      (*p)++;
    }
  if (endp)
    *endp = *p;
  *p = delspc (*p);
  if (verbose >= 7)
    fprintf (stderr, "%5d (0x%04x): rd_number returned %d (%04x).\n",
	     stack[sp].line, addr, result, result);
  return result;
}
示例#4
0
/* read away a comma, error if there is none */
static void rd_comma (const char **p) {
	*p = delspc (*p);
	if (**p != ',') {
		eprintf ("`,' expected. Remainder of line: %s\n", *p);
		return;
	}
	*p = delspc ((*p) + 1);
}
示例#5
0
/* find any of the list[] entries as the start of ptr and return index */
static int indx (const char **ptr, const char **list, int error, const char **expr) {
	int i;
	*ptr = delspc (*ptr);
	if (!**ptr) {
		if (error) {
			eprintf ("unexpected end of line\n");
			return 0;
		} else return 0;
	}
	if (comma > 1)
		rd_comma (ptr);
	for (i = 0; list[i]; i++) {
		const char *input = *ptr;
		const char *check = list[i];
		int had_expr = 0;
		if (!list[i][0])
			continue;
		while (*check) {
			if (*check == ' ') {
				input = delspc (input);
			} else if (*check == '*') {
				*expr = input;
				mem_delimiter = check[1];
				rd_expr (&input, mem_delimiter, NULL, sp, 0);
				had_expr = 1;
			} else if (*check == '+') {
				if (*input == '+' || *input == '-') {
					*expr = input;
					mem_delimiter = check[1];
					rd_expr (&input, mem_delimiter, NULL, sp, 0);
				}
			} else if (*check == *input || (*check >= 'a' && *check <= 'z'
						&& *check - 'a' + 'A' == *input))
				++input;
			else break;

			++check;
		}
		if (*check || (isalnum ((const unsigned char)check[-1]) && isalnum ((const unsigned char)input[0])))
			continue;
		if (had_expr) {
			input = delspc (input);
			if (*input && *input != ',')
				continue;
		}
		*ptr = input;
		comma++;
		return i + 1;
	}
	//if (error) eprintf ("parse error. Remainder of line=%s\n", *ptr);
	return 0;
}
示例#6
0
/* read a number from 0 to 7, for bit, set or res */
static int rd_0_7 (const char **p) {
	*p = delspc (*p);
	if (**p == 0)
		return 0;
	bitsetres = *p;
	skipword (p, ',');
	return 1;
}
示例#7
0
/* read a word from input and store it in readword. return 1 on success */
static int rd_word (const char **p, char delimiter) {
	*p = delspc (*p);
	if (**p == 0)
		return 0;
	readword = *p;
	mem_delimiter = delimiter;
	skipword (p, delimiter);
	return 1;
}
示例#8
0
static int
check_label (struct label *labels, const char **p, struct label **ret,
	     struct label **previous, int force_skip)
{
  struct label *l;
  const char *c;
  unsigned s2;
  *p = delspc (*p);
  for (c = *p; isalnum (*c) || *c == '_' || *c == '.'; ++c)
    {
    }
  s2 = c - *p;
  for (l = labels; l; l = l->next)
    {
      unsigned s1, s;
      int cmp;
      s1 = strlen (l->name);
      s = s1 < s2 ? s1 : s2;
      cmp = strncmp (l->name, *p, s);
      if (cmp > 0 || (cmp == 0 && s1 > s))
	{
	  if (force_skip)
	    *p = c;
	  return 0;
	}
      if (cmp < 0 || s2 > s)
	{
	  if (previous)
	    *previous = l;
	  continue;
	}
      *p = c;
      /* if label is not valid, compute it */
      if (l->ref)
	{
	  compute_ref (l->ref, 1);
	  if (!l->ref->done)
	    {
	      /* label was not valid, and isn't computable.  tell the
	       * caller that it doesn't exist, so it will try again later.
	       * Set ret to show actual existence.  */
	      if (verbose >= 6)
		fprintf (stderr,
			 "%5d (0x%04x): returning invalid label %s.\n",
			 stack[sp].line, addr, l->name);
	      *ret = l;
	      return 0;
	    }
	}
      *ret = l;
      return 1;
    }
  if (force_skip)
    *p = c;
  return 0;
}
示例#9
0
/* read a byte from input and store it in readbyte. return 1 on success */
static int rd_byte (const char **p, char delimiter) {
	*p = delspc (*p);
	if (**p == 0)
		return 0;
	readbyte = *p;
	writebyte = 1;
	mem_delimiter = delimiter;
	skipword (p, delimiter);
	return 1;
}
示例#10
0
/* do the actual work */
static int assemble (const char *str, unsigned char *_obuf) {
	int ifcount = 0, noifcount = 0;
	const char *ptr;
	char *bufptr;
	int r, s;			/* registers */

	obuflen = 0;
	obuf = _obuf;
	/* continue assembling until the last input file is done */
	//for (file = 0; file < infilecount; ++file)
	do {
		int cmd, cont = 1;
		// XXX: must free
		z80buffer = strdup (str);
		if (!cont)
			break;		/* break to next source file */
		//	  if (havelist)
		//	    fprintf (listfile, "%04x", addr);
		for (bufptr = z80buffer; (bufptr = strchr (bufptr, '\n'));)
			*bufptr = ' ';
		for (bufptr = z80buffer; (bufptr = strchr (bufptr, '\r'));)
			*bufptr = ' ';
		ptr = z80buffer;
		//lastlabel = NULL;
		baseaddr = addr;
		++stack[sp].line;
		ptr = delspc (ptr);
		if (!*ptr)
			continue;
		if (!noifcount && !define_macro)
			readlabel (&ptr, 1);
		else
			readlabel (&ptr, 0);
		ptr = delspc (ptr);
		if (!*ptr)
			continue;
		comma = 0;
		indexed = 0;
		indexjmp = 0;
		writebyte = 0;
		readbyte = 0;
		readword = 0;
		cmd = readcommand (&ptr) - 1;
			int i, have_quote;
			switch (cmd) {
			case Z80_ADC:
				if (!(r = rd_a_hl (&ptr)))
					break;
				if (r == HL) {
					if (!(r = rd_rr_ (&ptr)))
						break;
					wrtb (0xED);
					wrtb (0x4A + 0x10 * --r);
					break;
				}
				if (!(r = rd_r (&ptr)))
					break;
				wrtb (0x88 + --r);
				break;
			case Z80_ADD:
				if (!(r = rd_r_add (&ptr)))
					break;
				if (r == addHL) {
					if (!(r = rd_rrxx (&ptr)))
						break;
					wrtb (0x09 + 0x10 * --r);	/* ADD HL/IX/IY, qq  */
					break;
				}
				if (has_argument (&ptr)) {
					if (r != A) {
						eprintf ("parse error before: %s\n", ptr);
						break;
					}
					if (!(r = rd_r (&ptr)))
						break;
					wrtb (0x80 + --r);	/* ADD A,r  */
					break;
				}
				wrtb (0x80 + --r);	/* ADD r  */
				break;
			case Z80_AND:
				if (!(r = rd_r (&ptr)))
					break;
				wrtb (0xA0 + --r);
				break;
			case Z80_BIT:
				if (!rd_0_7 (&ptr))
					break;
				rd_comma (&ptr);
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x40 + (r - 1));
				break;
			case Z80_CALL:
				if ((r = rd_cc (&ptr))) {
					wrtb (0xC4 + 8 * --r);
					rd_comma (&ptr);
				} else wrtb (0xCD);
				break;
			case Z80_CCF:
				wrtb (0x3F);
				break;
			case Z80_CP:
				if (!(r = rd_r (&ptr)))
					break;
				wrtb (0xB8 + --r);
				break;
			case Z80_CPD:
				wrtb (0xED);
				wrtb (0xA9);
				break;
			case Z80_CPDR:
				wrtb (0xED);
				wrtb (0xB9);
				break;
			case Z80_CPI:
				wrtb (0xED);
				wrtb (0xA1);
				break;
			case Z80_CPIR:
				wrtb (0xED);
				wrtb (0xB1);
				break;
			case Z80_CPL:
				wrtb (0x2F);
				break;
			case Z80_DAA:
				wrtb (0x27);
				break;
			case Z80_DEC:
				if (!(r = rd_r_rr (&ptr)))
					break;
				if (r < 0) {
					wrtb (0x05 - 8 * ++r);
					break;
				}
				wrtb (0x0B + 0x10 * --r);
				break;
			case Z80_DI:
				wrtb (0xF3);
				break;
			case Z80_DJNZ:
				wrtb (0x10);
				//rd_wrt_jr (&ptr, '\0');
				break;
			case Z80_EI:
				wrtb (0xFB);
				break;
			case Z80_EX:
				if (!(r = rd_ex1 (&ptr)))
					break;
				switch (r) {
				case DE:
					if (!rd_hl (&ptr))
						break;
					wrtb (0xEB);
					break;
				case AF:
					if (!rd_af_ (&ptr))
						break;
					wrtb (0x08);
					break;
				default:
					if (!rd_hlx (&ptr))
						break;
					wrtb (0xE3);
				}
				break;
			case Z80_EXX:
				wrtb (0xD9);
				break;
			case Z80_HALT:
				wrtb (0x76);
				break;
			case Z80_IM:
				if (!(r = rd_0_2 (&ptr)))
					break;
				wrtb (0xED);
				wrtb (0x46 + 8 * --r);
				break;
			case Z80_IN:
				if (!(r = rd_in (&ptr)))
					break;
				if (r == A) {
					if (!(r = rd_nnc (&ptr)))
						break;
					if (r == C) {
						wrtb (0xED);
						wrtb (0x40 + 8 * (A - 1));
						break;
					}
					wrtb (0xDB);
					break;
				}
				if (!rd_c (&ptr))
					break;
				wrtb (0xED);
				wrtb (0x40 + 8 * --r);
				break;
			case Z80_INC:
				if (!(r = rd_r_rr (&ptr)))
					break;
				if (r < 0) {
					wrtb (0x04 - 8 * ++r);
					break;
				}
				wrtb (0x03 + 0x10 * --r);
				break;
			case Z80_IND:
				wrtb (0xED);
				wrtb (0xAA);
				break;
			case Z80_INDR:
				wrtb (0xED);
				wrtb (0xBA);
				break;
			case Z80_INI:
				wrtb (0xED);
				wrtb (0xA2);
				break;
			case Z80_INIR:
				wrtb (0xED);
				wrtb (0xB2);
				break;
			case Z80_JP:
				r = rd_jp (&ptr);
				if (r < 0) {
					wrtb (0xE9);
					break;
				}
				if (r) {
					wrtb (0xC2 + 8 * --r);
					rd_comma (&ptr);
				} else wrtb (0xC3);
				break;
			case Z80_JR:
				r = rd_jr (&ptr);
				if (r)
					rd_comma (&ptr);
				wrtb (0x18 + 8 * r);
				break;
			case Z80_LD:
				if (!(r = rd_ld (&ptr)))
					break;
				switch (r) {
				case ld_BC:
				case ld_DE:
					if (!rd_a (&ptr))
						break;
					wrtb (0x02 + 0x10 * (r == ld_DE));
					break;
				case ld_HL:
					r = rd_ld_hl (&ptr);
					wrtb (0x70 + --r);
					break;
				case ld_NN:
					if (!(r = rd_ld_nn (&ptr)))
						break;
					if (r == ld_nnA || r == ld_nnHL) {
						wrtb (0x22 + 0x10 * (r == ld_nnA));
						break;
					}
					wrtb (0xED);
					wrtb (0x43 + 0x10 * --r);
					break;
				case ldA:
					if (!(r = rd_lda (&ptr)))
						break;
					if (r == A_NN) {
						wrtb (0x3A);
						break;
					}
					if (r == A_I || r == A_R) {
						wrtb (0xED);
						wrtb (0x57 + 8 * (r == A_R));
						break;
					}
					if (r < 0) {
						wrtb (0x0A - 0x10 * ++r);
						break;
					}
					wrtb (0x78 + --r);
					break;
				case ldB:
				case ldC:
				case ldD:
				case ldE:
				case ldH:
				case ldL:
					if (!(s = rd_ldbcdehla (&ptr)))
						break;
					wrtb (0x40 + 0x08 * (r - 7) + (s - 1));
					break;
				case ldBC:
				case ldDE:
					s = rd_nn_nn (&ptr);
					if (s == _NN) {
						wrtb (0xED);
						wrtb (0x4B + 0x10 * (r == ldDE));
						break;
					}
					wrtb (0x01 + (r == ldDE) * 0x10);
					break;
				case ldHL:
					r = rd_nn_nn (&ptr);
					wrtb (0x21 + (r == _NN) * 9);
					break;
				case ldI:
				case ldR:
					if (!rd_a (&ptr))
						break;
					wrtb (0xED);
					wrtb (0x47 + 0x08 * (r == ldR));
					break;
				case ldSP:
					r = rd_sp (&ptr);
					if (r == SPHL) {
						wrtb (0xF9);
						break;
					}
					if (r == SPNN) {
						wrtb (0x31);
						break;
					}
					wrtb (0xED);
					wrtb (0x7B);
					break;
				}
				break;
			case Z80_LDD:
				wrtb (0xED);
				wrtb (0xA8);
				break;
			case Z80_LDDR:
				wrtb (0xED);
				wrtb (0xB8);
				break;
			case Z80_LDI:
				wrtb (0xED);
				wrtb (0xA0);
				break;
			case Z80_LDIR:
				wrtb (0xED);
				wrtb (0xB0);
				break;
			case Z80_NEG:
				wrtb (0xED);
				wrtb (0x44);
				break;
			case Z80_NOP:
				wrtb (0x00);
				break;
			case Z80_OR:
				if (!(r = rd_r (&ptr)))
					break;
				wrtb (0xB0 + --r);
				break;
			case Z80_OTDR:
				wrtb (0xED);
				wrtb (0xBB);
				break;
			case Z80_OTIR:
				wrtb (0xED);
				wrtb (0xB3);
				break;
			case Z80_OUT:
				if (!(r = rd_nnc (&ptr)))
					break;
				if (r == C) {
					if (!(r = rd_out (&ptr)))
						break;
					wrtb (0xED);
					wrtb (0x41 + 8 * --r);
					break;
				}
				if (!rd_a (&ptr))
					break;
				wrtb (0xD3);
				break;
			case Z80_OUTD:
				wrtb (0xED);
				wrtb (0xAB);
				break;
			case Z80_OUTI:
				wrtb (0xED);
				wrtb (0xA3);
				break;
			case Z80_POP:
				if (!(r = rd_stack (&ptr)))
					break;
				wrtb (0xC1 + 0x10 * --r);
				break;
			case Z80_PUSH:
				if (!(r = rd_stack (&ptr)))
					break;
				wrtb (0xC5 + 0x10 * --r);
				break;
			case Z80_RES:
				if (!rd_0_7 (&ptr))
					break;
				rd_comma (&ptr);
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x80 + --r);
				break;
			case Z80_RET:
				if (!(r = rd_cc (&ptr))) {
					wrtb (0xC9);
					break;
				}
				wrtb (0xC0 + 8 * --r);
				break;
			case Z80_RETI:
				wrtb (0xED);
				wrtb (0x4D);
				break;
			case Z80_RETN:
				wrtb (0xED);
				wrtb (0x45);
				break;
			case Z80_RL:
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x10 + --r);
				break;
			case Z80_RLA:
				wrtb (0x17);
				break;
			case Z80_RLC:
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x00 + --r);
				break;
			case Z80_RLCA:
				wrtb (0x07);
				break;
			case Z80_RLD:
				wrtb (0xED);
				wrtb (0x6F);
				break;
			case Z80_RR:
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x18 + --r);
				break;
			case Z80_RRA:
				wrtb (0x1F);
				break;
			case Z80_RRC:
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x08 + --r);
				break;
			case Z80_RRCA:
				wrtb (0x0F);
				break;
			case Z80_RRD:
				wrtb (0xED);
				wrtb (0x67);
				break;
			case Z80_RST:
				ptr = "";
				break;
			case Z80_SBC:
				if (!(r = rd_a_hl (&ptr)))
					break;
				if (r == HL) {
					if (!(r = rd_rr_ (&ptr)))
						break;
					wrtb (0xED);
					wrtb (0x42 + 0x10 * --r);
					break;
				}
				if (!(r = rd_r (&ptr)))
					break;
				wrtb (0x98 + --r);
				break;
			case Z80_SCF:
				wrtb (0x37);
				break;
			case Z80_SET:
				if (!rd_0_7 (&ptr))
					break;
				rd_comma (&ptr);
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0xC0 + --r);
				break;
			case Z80_SLA:
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x20 + --r);
				break;
			case Z80_SLI:
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x30 + --r);
				break;
			case Z80_SRA:
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x28 + --r);
				break;
			case Z80_SRL:
				if (!(r = rd_r_ (&ptr)))
					break;
				wrtb (0xCB);
				wrtb (0x38 + --r);
				break;
			case Z80_SUB:
				if (!(r = rd_r (&ptr)))
					break;
				if (has_argument (&ptr)) {/* SUB A,r ?  */
					if (r != A) {
						eprintf ("parse error before: %s\n", ptr);
						break;
					}
					if (!(r = rd_r (&ptr)))
						break;
				}
				wrtb (0x90 + --r);
				break;
			case Z80_XOR:
				if (!(r = rd_r (&ptr)))
					break;
				wrtb (0xA8 + --r);
				break;
			case Z80_DEFB:
			case Z80_DB:
			case Z80_DEFM:
			case Z80_DM:
				ptr = delspc (ptr);
				while (1) {
					have_quote = (*ptr == '"' || *ptr == '\'');
					if (have_quote) {
						/* Read string.  */
						int quote = *ptr;
						++ptr;
						while (*ptr != quote)
						{
							write_one_byte (rd_character (&ptr, NULL, 1), 0);
							if (*ptr == 0)
							{
								eprintf ("end of line in quoted string\n");
								break;
							}
						}
						++ptr;
					} else {
						/* Read expression.  */
						skipword (&ptr, ',');
					}
					ptr = delspc (ptr);
					if (*ptr == ',') {
						++ptr;
						continue;
					}
					if (*ptr != 0)
						eprintf ("junk in byte definition: %s\n", ptr);
					break;
				}
				break;
			case Z80_DEFW:
			case Z80_DW:
				if (!(r = rd_word (&ptr, ','))) {
					eprintf ("No data for word definition\n");
					break;
				}
				while (1) {
					ptr = delspc (ptr);
					if (*ptr != ',')
						break;
					++ptr;
					if (!(r = rd_word (&ptr, ',')))
						eprintf ("Missing expression in defw\n");
				}
				break;
			case Z80_DEFS:
			case Z80_DS:
				r = rd_expr (&ptr, ',', NULL, sp, 1);
				if (r < 0) {
					eprintf ("ds should have its first argument >=0"
							" (not -0x%x)\n", -r);
					break;
				}
				ptr = delspc (ptr);
				if (*ptr) {
					rd_comma (&ptr);
					readbyte = 0;
					rd_byte (&ptr, '\0');
					writebyte = 0;
					break;
				}
				for (i = 0; i < r; i++) {
					write_one_byte (0, 0);
				}
				break;
			case Z80_END:
				break;
			case Z80_ORG:
				addr = rd_expr (&ptr, '\0', NULL, sp, 1) & 0xffff;
				break;
			case Z80_IF:
				if (rd_expr (&ptr, '\0', NULL, sp, 1))
					ifcount++;
				else
					noifcount++;
				break;
			case Z80_ELSE:
				if (ifcount == 0)
				{
					eprintf ("else without if\n");
					break;
				}
				noifcount = 1;
				ifcount--;
				break;
			case Z80_ENDIF:
				if (noifcount == 0 && ifcount == 0) {
					eprintf ("endif without if\n");
					break;
				}
				if (noifcount)
					noifcount--;
				else
					ifcount--;
				break;
			case Z80_ENDM:
				if (stack[sp].file)
					eprintf ("endm outside macro definition\n");
				break;
			case Z80_SEEK:
				eprintf ("seek error\n");
				break;
			default:
				//eprintf ("command or comment expected (was %s)\n", ptr);
				return 0;
			}
	} while (0);
	//free (infile);
	return obuflen;
}
示例#11
0
/* look ahead for a comma, no error if not found */
static int has_argument (const char **p) {
	const char *q = delspc (*p);
	return (*q == ',');
}
示例#12
0
static int
rd_value (const char **p, int *valid, int level, int *check, int print_errors)
{
  int sign = 1, not = 0, base, v;
  const char *p0, *p1, *p2;
  if (verbose >= 6)
    fprintf (stderr, "%5d (0x%04x): Starting to read value (string=%s).\n",
	     stack[sp].line, addr, *p);
  *p = delspc (*p);
  while (**p && strchr ("+-~", **p))
    {
      if (**p == '-')
	sign = -sign;
      else if (**p == '~')
	not = ~not;
      (*p)++;
      *p = delspc (*p);
    }
  base = 10;			/* Default base for suffixless numbers */

  /* Check for parenthesis around full expression: not if no parenthesis */
  if (**p != '(')
    *check = 0;

  switch (**p)
    {
      int exist, retval;
      char quote;
      int dummy_check;
    case '(':
      (*p)++;
      dummy_check = 0;
      retval = not ^ (sign * do_rd_expr (p, ')', valid, level, &dummy_check,
					 print_errors));
      ++*p;
      return retval;
    case '0':
      if ((*p)[1] == 'x')
	{
	  (*p) += 2;
	  return not ^ (sign * rd_number (p, NULL, 0x10));
	}
      base = 8;		/* If first digit it 0, assume octal unless suffix */
      /* fall through */
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      p0 = *p;
      rd_number (p, &p1, 36);	/* Advance to end of numeric string */
      p1--;			/* Last character in numeric string */
      switch (*p1)
	{
	case 'h':
	case 'H':
	  base = 16;
	  break;
	case 'b':
	case 'B':
	  base = 2;
	  break;
	case 'o':
	case 'O':
	case 'q':
	case 'Q':
	  base = 8;
	  break;
	case 'd':
	case 'D':
	  base = 10;
	  break;
	default:		/* No suffix */
	  p1++;
	  break;
	}
      v = rd_number (&p0, &p2, base);
      if (p1 != p2)
	{
	  if (valid)
	    *valid = 0;
	  else if (print_errors)
	    printerr (1, "invalid character in number: \'%c\'\n", *p2);
	}
      return not ^ (sign * v);
    case '$':
      ++*p;
      *p = delspc (*p);
      p0 = *p;
      v = rd_number (&p0, &p2, 0x10);
      if (p2 == *p)
	{
	  v = baseaddr;
	}
      else
	*p = p2;
      return not ^ (sign * v);
    case '%':
      (*p)++;
      return not ^ (sign * rd_number (p, NULL, 2));
    case '\'':
    case '"':
      quote = **p;
      ++*p;
      retval = not ^ (sign * rd_character (p, valid, print_errors));
      if (**p != quote)
	{
	  if (valid)
	    *valid = 0;
	  else if (print_errors)
	    printerr (1, "missing closing quote (%c)\n", quote);
	  return 0;
	}
      ++*p;
      return retval;
    case '@':
      return not ^ (sign * rd_otherbasenumber (p, valid, print_errors));
    case '?':
      rd_label (p, &exist, NULL, level, 0);
      return not ^ (sign * exist);
    case '&':
      {
	++*p;
	switch (**p)
	  {
	  case 'h':
	  case 'H':
	    base = 0x10;
	    break;
	  case 'o':
	  case 'O':
	    base = 010;
	    break;
	  case 'b':
	  case 'B':
	    base = 2;
	    break;
	  default:
	    if (valid)
	      *valid = 0;
	    else if (print_errors)
	      printerr (1, "invalid literal starting with &%c\n", **p);
	    return 0;
	  }
	++*p;
	return not ^ (sign * rd_number (p, NULL, base));
      }
    default:
      {
	int value;
	exist = 1;
	value = rd_label (p, valid ? &exist : NULL, NULL, level, print_errors);
	if (!exist)
	  *valid = 0;
	return not ^ (sign * value);
      }
    }
}