157 lines
2.9 KiB
C
157 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;
|
|
}
|
|
|