158 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * mdbexp.c - MINIX expresion parser
 | 
						|
 *
 | 
						|
 * Written by Bruce D. Szablak
 | 
						|
 *
 | 
						|
 * This free software is provided for non-commerical use. No warrantee
 | 
						|
 * of fitness for any use is implied. You get what you pay for. Anyone
 | 
						|
 * may make modifications and distribute them, but please keep this header
 | 
						|
 * in the distribution.
 | 
						|
 */
 | 
						|
 | 
						|
#include "mdb.h"
 | 
						|
#include <ctype.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include "proto.h"
 | 
						|
 | 
						|
FORWARD _PROTOTYPE(long value , (char *s , char **s_p , int *seg_p ));
 | 
						|
FORWARD _PROTOTYPE(long lookup , (char *s , char **s_p , int *seg_p ));
 | 
						|
 | 
						|
#define idchar(c) (isalpha(c) || isdigit(c) || (c) == '_')
 | 
						|
 | 
						|
/* 
 | 
						|
 * Get an expression for mdb
 | 
						|
 */
 | 
						|
PUBLIC char *getexp(buf, exp_p, seg_p)
 | 
						|
char *buf;
 | 
						|
int *seg_p;
 | 
						|
long *exp_p;
 | 
						|
{
 | 
						|
  long v = 0L;
 | 
						|
 | 
						|
  buf = skip(buf);
 | 
						|
  if ((isalpha(*buf) && (isspace(buf[1]) || buf[1] == ';')) 
 | 
						|
      || *buf == '\n'
 | 
						|
      || *buf == ';'
 | 
						|
      || *buf == '/'
 | 
						|
      || *buf == '!'
 | 
						|
      || *buf == '?'
 | 
						|
      || *buf == '@'
 | 
						|
      || *buf == '#') {
 | 
						|
	*exp_p = 0L;
 | 
						|
	return buf;
 | 
						|
  }
 | 
						|
  v = value(buf, &buf, seg_p);
 | 
						|
  buf = skip(buf);
 | 
						|
  if (*buf == '+')
 | 
						|
	v += value(skip(buf + 1), &buf, seg_p);
 | 
						|
  else if (*buf == '-')
 | 
						|
	v -= value(skip(buf + 1), &buf, seg_p);
 | 
						|
  *exp_p = v;
 | 
						|
  return skip(buf);
 | 
						|
}
 | 
						|
 | 
						|
/* 
 | 
						|
 * Get value 
 | 
						|
 *
 | 
						|
 * 	\c 	escaped characters
 | 
						|
 * 	digits	number
 | 
						|
 * 	$xx	registers 
 | 
						|
 *	\n	0L
 | 
						|
 *	then calls lookup for symbols
 | 
						|
 */
 | 
						|
PRIVATE long value(s, s_p, seg_p)
 | 
						|
char *s, **s_p;
 | 
						|
int *seg_p;
 | 
						|
{
 | 
						|
  long k;
 | 
						|
 | 
						|
  if (*s == '\'') {		/* handle character constants here */
 | 
						|
	*s_p = s + 2;
 | 
						|
	return s[1];
 | 
						|
  }
 | 
						|
  if (*s == '-' || isdigit(*s))
 | 
						|
	return strtol(s, s_p, 0);
 | 
						|
  if (*s == '$') {
 | 
						|
	k = reg_addr(s + 1);
 | 
						|
	*s_p = s + 3;
 | 
						|
	return get_reg(curpid, k);
 | 
						|
	k = reg_addr(s + 1);
 | 
						|
	*s_p = s + 3;
 | 
						|
	return get_reg(curpid, k);
 | 
						|
  }
 | 
						|
  if (*s == '\n') {
 | 
						|
	*s_p = s + 1;
 | 
						|
	return 0L;
 | 
						|
  }
 | 
						|
  return lookup(s, s_p, seg_p);
 | 
						|
}
 | 
						|
 | 
						|
/* 
 | 
						|
 * Lookup symbol - return value
 | 
						|
 * Handle special cases: _start T: D: S: 
 | 
						|
 * then call symbolvalue()
 | 
						|
 */
 | 
						|
PRIVATE long lookup(s, s_p, seg_p)
 | 
						|
char *s, **s_p;
 | 
						|
int *seg_p;
 | 
						|
{
 | 
						|
  long value;
 | 
						|
  char c;
 | 
						|
  int l;
 | 
						|
 | 
						|
  for (l = 1; idchar(s[l]); ++l) {}
 | 
						|
  c = s[l];
 | 
						|
  s[l] = 0;
 | 
						|
 | 
						|
  if (strcmp("_start", s) == 0) {
 | 
						|
	*seg_p = T;
 | 
						|
	if (c == ':') c = '+';
 | 
						|
	*(*s_p = s + 6) = c;
 | 
						|
	return st_addr;
 | 
						|
  }
 | 
						|
  if (strcmp("T", s) == 0) {
 | 
						|
	*seg_p = T;
 | 
						|
	if (c == ':') c = '+';
 | 
						|
	*(*s_p = s + 1) = c;
 | 
						|
	return st_addr;
 | 
						|
  }
 | 
						|
  if (strcmp("D", s) == 0) {
 | 
						|
	*seg_p = D;
 | 
						|
	if (c == ':') c = '+';
 | 
						|
	*(*s_p = s + 1) = c;
 | 
						|
	return sd_addr;
 | 
						|
  }
 | 
						|
  if (strcmp("S", s) == 0) {
 | 
						|
	*seg_p = S;
 | 
						|
	if (c == ':') c = '+';
 | 
						|
	*(*s_p = s + 1) = c;
 | 
						|
	return sk_addr;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((value = symbolvalue(s, TRUE)) != 0L) {
 | 
						|
	*seg_p = T;
 | 
						|
	*(*s_p = s + l) = c;
 | 
						|
	return value;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((value = symbolvalue(s, FALSE)) != 0L) {
 | 
						|
	*seg_p = D;
 | 
						|
	*(*s_p = s + l) = c;
 | 
						|
	return value;
 | 
						|
  }
 | 
						|
 | 
						|
  Printf("%s: ", s);
 | 
						|
  mdb_error("symbol not found\n");
 | 
						|
}
 | 
						|
 | 
						|
/* Skip spaces */
 | 
						|
PUBLIC char *skip(s)
 | 
						|
register char *s;
 | 
						|
{
 | 
						|
  while (isspace(*s)) ++s;
 | 
						|
  return *s ? s : s - 1;
 | 
						|
}
 | 
						|
 |