acid
This commit is contained in:
parent
22a7368ef2
commit
564ca709d0
14 changed files with 6578 additions and 0 deletions
49
src/cmd/acid/Notes
Normal file
49
src/cmd/acid/Notes
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
Changes from the Plan 9 acid (beyond the
|
||||||
|
obvious changes necessary to compile without
|
||||||
|
Ken's compiler and with the new libmach interface).
|
||||||
|
========================================
|
||||||
|
|
||||||
|
the input-line print verb is %Z, so that %L can be for locations
|
||||||
|
|
||||||
|
the register block is explicitly "mapped" at 0 by xget1, xget2, ...
|
||||||
|
for compatibility with old acid, even though libmach
|
||||||
|
doesn't participate in this lie anymore.
|
||||||
|
|
||||||
|
main accepts pid, file, and core in any order
|
||||||
|
|
||||||
|
the ptab only records pids (no ctl fd anymore).
|
||||||
|
|
||||||
|
new builtin sysstop(pid) runs pid until the next syscall
|
||||||
|
|
||||||
|
map() returns 5-tuples: (name, filename, base, end, offset)
|
||||||
|
filename is new
|
||||||
|
|
||||||
|
map() expects a 5-tuple too
|
||||||
|
|
||||||
|
strace expects a list of register names and values like
|
||||||
|
{"PC", *PC, "SP", *SP}
|
||||||
|
|
||||||
|
strace returns 5-tuples now:
|
||||||
|
{fn, pc, callerpc, paramlist, locallist}
|
||||||
|
|
||||||
|
new builtin includepipe(cmd) includes the standard output
|
||||||
|
of running cmd.
|
||||||
|
|
||||||
|
symbols returns 4-tuples now: {name, type, addr, file}
|
||||||
|
|
||||||
|
new builtin textfile() returns the current set of open text files
|
||||||
|
as a list of {file, base} pairs.
|
||||||
|
|
||||||
|
new builtin textfile({file, base}) adds a new file's symbols and text
|
||||||
|
offset by base for relocatables.
|
||||||
|
|
||||||
|
new builtin deltextfile(file) removes a file from the set of open text files.
|
||||||
|
|
||||||
|
both textfile and deltextfile update symbols.
|
||||||
|
|
||||||
|
====
|
||||||
|
|
||||||
|
yet to be done:
|
||||||
|
|
||||||
|
elflink has the linking info for elf on linux
|
||||||
|
|
||||||
313
src/cmd/acid/acid.h
Normal file
313
src/cmd/acid/acid.h
Normal file
|
|
@ -0,0 +1,313 @@
|
||||||
|
/* acid.h */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Eof = -1,
|
||||||
|
Strsize = 4096,
|
||||||
|
Hashsize = 128,
|
||||||
|
Maxarg = 512,
|
||||||
|
NFD = 100,
|
||||||
|
Maxproc = 50,
|
||||||
|
Maxval = 10,
|
||||||
|
Mempergc = 1024*1024,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* #pragma varargck type "L" void */
|
||||||
|
|
||||||
|
typedef struct Node Node;
|
||||||
|
typedef struct String String;
|
||||||
|
typedef struct Lsym Lsym;
|
||||||
|
typedef struct List List;
|
||||||
|
typedef struct Store Store;
|
||||||
|
typedef struct Gc Gc;
|
||||||
|
typedef struct Strc Strc;
|
||||||
|
typedef struct Rplace Rplace;
|
||||||
|
typedef struct Ptab Ptab;
|
||||||
|
typedef struct Value Value;
|
||||||
|
typedef struct Type Type;
|
||||||
|
typedef struct Frtype Frtype;
|
||||||
|
|
||||||
|
Extern int kernel;
|
||||||
|
Extern int nlcount;
|
||||||
|
Extern int remote;
|
||||||
|
Extern int text;
|
||||||
|
Extern int cor;
|
||||||
|
Extern int silent;
|
||||||
|
Extern Fhdr *fhdr;
|
||||||
|
Extern Fhdr *chdr;
|
||||||
|
Extern int line;
|
||||||
|
Extern Biobuf* bout;
|
||||||
|
Extern Biobuf* io[32];
|
||||||
|
Extern int iop;
|
||||||
|
Extern int pid;
|
||||||
|
Extern char symbol[Strsize];
|
||||||
|
Extern int interactive;
|
||||||
|
Extern Node* code;
|
||||||
|
Extern int na;
|
||||||
|
Extern int wtflag;
|
||||||
|
Extern Regs* correg;
|
||||||
|
Extern Map* cormap;
|
||||||
|
Extern Map* symmap;
|
||||||
|
Extern Lsym* hash[Hashsize];
|
||||||
|
Extern long dogc;
|
||||||
|
Extern Rplace* ret;
|
||||||
|
Extern char* symfil;
|
||||||
|
Extern char* corfil;
|
||||||
|
Extern int gotint;
|
||||||
|
Extern long flen;
|
||||||
|
Extern Gc* gcl;
|
||||||
|
Extern int stacked;
|
||||||
|
Extern jmp_buf err;
|
||||||
|
Extern Node* prnt;
|
||||||
|
Extern Node* fomt;
|
||||||
|
Extern List* tracelist;
|
||||||
|
Extern int initialising;
|
||||||
|
Extern int quiet;
|
||||||
|
Extern Fhdr* corhdr;
|
||||||
|
Extern Fhdr* symhdr;
|
||||||
|
|
||||||
|
extern void (*expop[])(Node*, Node*);
|
||||||
|
#define expr(n, r) (r)->store.comt=0; (*expop[(unsigned char)((n)->op)])(n, r);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TINT,
|
||||||
|
TFLOAT,
|
||||||
|
TSTRING,
|
||||||
|
TLIST,
|
||||||
|
TCODE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Type
|
||||||
|
{
|
||||||
|
Type* next;
|
||||||
|
int offset;
|
||||||
|
char fmt;
|
||||||
|
char depth;
|
||||||
|
Lsym* type;
|
||||||
|
Lsym* tag;
|
||||||
|
Lsym* base;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Frtype
|
||||||
|
{
|
||||||
|
Lsym* var;
|
||||||
|
Type* type;
|
||||||
|
Frtype* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ptab
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
/* int ctl; */
|
||||||
|
};
|
||||||
|
Extern Ptab ptab[Maxproc];
|
||||||
|
|
||||||
|
struct Rplace
|
||||||
|
{
|
||||||
|
jmp_buf rlab;
|
||||||
|
Node* stak;
|
||||||
|
Node* val;
|
||||||
|
Lsym* local;
|
||||||
|
Lsym** tail;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Gc
|
||||||
|
{
|
||||||
|
char gcmark;
|
||||||
|
Gc* gclink;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Store
|
||||||
|
{
|
||||||
|
char fmt;
|
||||||
|
Type* comt;
|
||||||
|
union {
|
||||||
|
vlong ival;
|
||||||
|
double fval;
|
||||||
|
String* string;
|
||||||
|
List* l;
|
||||||
|
Node* cc;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct List
|
||||||
|
{
|
||||||
|
Gc gc;
|
||||||
|
List* next;
|
||||||
|
char type;
|
||||||
|
Store store;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Value
|
||||||
|
{
|
||||||
|
char set;
|
||||||
|
char type;
|
||||||
|
Store store;
|
||||||
|
Value* pop;
|
||||||
|
Lsym* scope;
|
||||||
|
Rplace* ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Lsym
|
||||||
|
{
|
||||||
|
char* name;
|
||||||
|
int lexval;
|
||||||
|
Lsym* hash;
|
||||||
|
Value* v;
|
||||||
|
Type* lt;
|
||||||
|
Node* proc;
|
||||||
|
Frtype* local;
|
||||||
|
void (*builtin)(Node*, Node*);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
Gc gc;
|
||||||
|
char op;
|
||||||
|
char type;
|
||||||
|
Node* left;
|
||||||
|
Node* right;
|
||||||
|
Lsym* sym;
|
||||||
|
int builtin;
|
||||||
|
Store store;
|
||||||
|
};
|
||||||
|
#define ZN (Node*)0
|
||||||
|
|
||||||
|
struct String
|
||||||
|
{
|
||||||
|
Gc gc;
|
||||||
|
char *string;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
|
List* addlist(List*, List*);
|
||||||
|
void addvarsym(Fhdr*);
|
||||||
|
List* al(int);
|
||||||
|
Node* an(int, Node*, Node*);
|
||||||
|
void append(Node*, Node*, Node*);
|
||||||
|
int bool(Node*);
|
||||||
|
void build(Node*);
|
||||||
|
void call(char*, Node*, Node*, Node*, Node*);
|
||||||
|
void catcher(void*, char*);
|
||||||
|
void checkqid(int, int);
|
||||||
|
void cmd(void);
|
||||||
|
Node* con(int);
|
||||||
|
List* construct(Node*);
|
||||||
|
void ctrace(int);
|
||||||
|
void decl(Node*);
|
||||||
|
void defcomplex(Node*, Node*);
|
||||||
|
void deinstall(int);
|
||||||
|
void delete(List*, int n, Node*);
|
||||||
|
void delvarsym(char*);
|
||||||
|
void dostop(int);
|
||||||
|
Lsym* enter(char*, int);
|
||||||
|
void error(char*, ...);
|
||||||
|
void execute(Node*);
|
||||||
|
void fatal(char*, ...);
|
||||||
|
ulong findframe(ulong);
|
||||||
|
void flatten(Node**, Node*);
|
||||||
|
void gc(void);
|
||||||
|
char* getstatus(int);
|
||||||
|
void* gmalloc(long);
|
||||||
|
void indir(Map*, ulong, char, Node*);
|
||||||
|
void installbuiltin(void);
|
||||||
|
void kinit(void);
|
||||||
|
int Zfmt(Fmt*);
|
||||||
|
int listcmp(List*, List*);
|
||||||
|
int listlen(List*);
|
||||||
|
List* listvar(char*, long);
|
||||||
|
void loadmodule(char*);
|
||||||
|
void loadvars(void);
|
||||||
|
Lsym* look(char*);
|
||||||
|
void ltag(char*);
|
||||||
|
void marklist(List*);
|
||||||
|
Lsym* mkvar(char*);
|
||||||
|
void msg(int, char*);
|
||||||
|
void notes(int);
|
||||||
|
int nproc(char**);
|
||||||
|
void nthelem(List*, int, Node*);
|
||||||
|
int numsym(char);
|
||||||
|
void odot(Node*, Node*);
|
||||||
|
void pcode(Node*, int);
|
||||||
|
void pexpr(Node*);
|
||||||
|
int popio(void);
|
||||||
|
void pstr(String*);
|
||||||
|
void pushfd(int);
|
||||||
|
void pushfile(char*);
|
||||||
|
void pushstr(Node*);
|
||||||
|
ulong raddr(char*);
|
||||||
|
void readtext(char*);
|
||||||
|
void readcore(void);
|
||||||
|
void restartio(void);
|
||||||
|
String *runenode(Rune*);
|
||||||
|
int scmp(String*, String*);
|
||||||
|
void sproc(int);
|
||||||
|
String* stradd(String*, String*);
|
||||||
|
String* strnode(char*);
|
||||||
|
String* strnodlen(char*, int);
|
||||||
|
#define system acidsystem
|
||||||
|
char* system(void);
|
||||||
|
int trlist(Map*, Regs*, ulong, ulong, Symbol*, int);
|
||||||
|
void unwind(void);
|
||||||
|
void userinit(void);
|
||||||
|
void varreg(void);
|
||||||
|
void varsym(void);
|
||||||
|
Waitmsg* waitfor(int);
|
||||||
|
void whatis(Lsym*);
|
||||||
|
void windir(Map*, Node*, Node*, Node*);
|
||||||
|
void yyerror(char*, ...);
|
||||||
|
int yylex(void);
|
||||||
|
int yyparse(void);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ONAME,
|
||||||
|
OCONST,
|
||||||
|
OMUL,
|
||||||
|
ODIV,
|
||||||
|
OMOD,
|
||||||
|
OADD,
|
||||||
|
OSUB,
|
||||||
|
ORSH,
|
||||||
|
OLSH,
|
||||||
|
OLT,
|
||||||
|
OGT,
|
||||||
|
OLEQ,
|
||||||
|
OGEQ,
|
||||||
|
OEQ,
|
||||||
|
ONEQ,
|
||||||
|
OLAND,
|
||||||
|
OXOR,
|
||||||
|
OLOR,
|
||||||
|
OCAND,
|
||||||
|
OCOR,
|
||||||
|
OASGN,
|
||||||
|
OINDM,
|
||||||
|
OEDEC,
|
||||||
|
OEINC,
|
||||||
|
OPINC,
|
||||||
|
OPDEC,
|
||||||
|
ONOT,
|
||||||
|
OIF,
|
||||||
|
ODO,
|
||||||
|
OLIST,
|
||||||
|
OCALL,
|
||||||
|
OCTRUCT,
|
||||||
|
OWHILE,
|
||||||
|
OELSE,
|
||||||
|
OHEAD,
|
||||||
|
OTAIL,
|
||||||
|
OAPPEND,
|
||||||
|
ORET,
|
||||||
|
OINDEX,
|
||||||
|
OINDC,
|
||||||
|
ODOT,
|
||||||
|
OLOCAL,
|
||||||
|
OFRAME,
|
||||||
|
OCOMPLEX,
|
||||||
|
ODELETE,
|
||||||
|
OCAST,
|
||||||
|
OFMT,
|
||||||
|
OEVAL,
|
||||||
|
OWHAT,
|
||||||
|
};
|
||||||
1460
src/cmd/acid/builtin.c
Normal file
1460
src/cmd/acid/builtin.c
Normal file
File diff suppressed because it is too large
Load diff
413
src/cmd/acid/dbg.y
Normal file
413
src/cmd/acid/dbg.y
Normal file
|
|
@ -0,0 +1,413 @@
|
||||||
|
%{
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern extern
|
||||||
|
#include "acid.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union
|
||||||
|
{
|
||||||
|
Node *node;
|
||||||
|
Lsym *sym;
|
||||||
|
ulong ival;
|
||||||
|
float fval;
|
||||||
|
String *string;
|
||||||
|
}
|
||||||
|
|
||||||
|
%type <node> expr monexpr term stmnt name args zexpr slist
|
||||||
|
%type <node> member members mname castexpr idlist
|
||||||
|
%type <sym> zname
|
||||||
|
|
||||||
|
%left ';'
|
||||||
|
%right '='
|
||||||
|
%left Tfmt
|
||||||
|
%left Toror
|
||||||
|
%left Tandand
|
||||||
|
%left '|'
|
||||||
|
%left '^'
|
||||||
|
%left '&'
|
||||||
|
%left Teq Tneq
|
||||||
|
%left '<' '>' Tleq Tgeq
|
||||||
|
%left Tlsh Trsh
|
||||||
|
%left '+' '-'
|
||||||
|
%left '*' '/' '%'
|
||||||
|
%right Tdec Tinc Tindir '.' '[' '('
|
||||||
|
|
||||||
|
%token <sym> Tid
|
||||||
|
%token <ival> Tconst Tfmt
|
||||||
|
%token <fval> Tfconst
|
||||||
|
%token <string> Tstring
|
||||||
|
%token Tif Tdo Tthen Telse Twhile Tloop Thead Ttail Tappend Tfn Tret Tlocal
|
||||||
|
%token Tcomplex Twhat Tdelete Teval Tbuiltin
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
prog :
|
||||||
|
| prog bigstmnt
|
||||||
|
;
|
||||||
|
|
||||||
|
bigstmnt : stmnt
|
||||||
|
{
|
||||||
|
/* hold on to current command for gc */
|
||||||
|
mkvar("_thiscmd")->proc = $1;
|
||||||
|
execute($1);
|
||||||
|
gc();
|
||||||
|
if(interactive && nlcount){
|
||||||
|
Bprint(bout, "acid; ");
|
||||||
|
nlcount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| Tfn Tid '(' args ')' zsemi '{' slist '}'
|
||||||
|
{
|
||||||
|
$2->proc = an(OLIST, $4, $8);
|
||||||
|
}
|
||||||
|
| Tfn Tid
|
||||||
|
{
|
||||||
|
$2->proc = nil;
|
||||||
|
}
|
||||||
|
| Tcomplex name '{' members '}' ';'
|
||||||
|
{
|
||||||
|
defcomplex($2, $4);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
zsemi :
|
||||||
|
| ';' zsemi
|
||||||
|
|
||||||
|
members : member
|
||||||
|
| members member
|
||||||
|
{
|
||||||
|
$$ = an(OLIST, $1, $2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
mname : Tid
|
||||||
|
{
|
||||||
|
$$ = an(ONAME, ZN, ZN);
|
||||||
|
$$->sym = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
member : Tconst Tconst mname ';'
|
||||||
|
{
|
||||||
|
$3->store.u.ival = $2;
|
||||||
|
$3->store.fmt = $1;
|
||||||
|
$$ = $3;
|
||||||
|
}
|
||||||
|
| Tconst mname Tconst mname ';'
|
||||||
|
{
|
||||||
|
$4->store.u.ival = $3;
|
||||||
|
$4->store.fmt = $1;
|
||||||
|
$4->right = $2;
|
||||||
|
$$ = $4;
|
||||||
|
}
|
||||||
|
| mname Tconst mname ';'
|
||||||
|
{
|
||||||
|
$3->store.u.ival = $2;
|
||||||
|
$3->left = $1;
|
||||||
|
$$ = $3;
|
||||||
|
}
|
||||||
|
| '{' members '}' ';'
|
||||||
|
{
|
||||||
|
$$ = an(OCTRUCT, $2, ZN);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
zname :
|
||||||
|
{ $$ = 0; }
|
||||||
|
| Tid
|
||||||
|
;
|
||||||
|
|
||||||
|
slist : stmnt
|
||||||
|
| slist stmnt
|
||||||
|
{
|
||||||
|
$$ = an(OLIST, $1, $2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
stmnt : zexpr ';'
|
||||||
|
| '{' slist '}'
|
||||||
|
{
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
| Tif expr Tthen stmnt
|
||||||
|
{
|
||||||
|
$$ = an(OIF, $2, $4);
|
||||||
|
}
|
||||||
|
| Tif expr Tthen stmnt Telse stmnt
|
||||||
|
{
|
||||||
|
$$ = an(OIF, $2, an(OELSE, $4, $6));
|
||||||
|
}
|
||||||
|
| Tloop expr ',' expr Tdo stmnt
|
||||||
|
{
|
||||||
|
$$ = an(ODO, an(OLIST, $2, $4), $6);
|
||||||
|
}
|
||||||
|
| Twhile expr Tdo stmnt
|
||||||
|
{
|
||||||
|
$$ = an(OWHILE, $2, $4);
|
||||||
|
}
|
||||||
|
| Tret expr ';'
|
||||||
|
{
|
||||||
|
$$ = an(ORET, $2, ZN);
|
||||||
|
}
|
||||||
|
| Tlocal idlist
|
||||||
|
{
|
||||||
|
$$ = an(OLOCAL, $2, ZN);
|
||||||
|
}
|
||||||
|
| Tcomplex Tid name ';'
|
||||||
|
{
|
||||||
|
$$ = an(OCOMPLEX, $3, ZN);
|
||||||
|
$$->sym = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
idlist : Tid
|
||||||
|
{
|
||||||
|
$$ = an(ONAME, ZN, ZN);
|
||||||
|
$$->sym = $1;
|
||||||
|
}
|
||||||
|
| idlist ',' Tid
|
||||||
|
{
|
||||||
|
$$ = an(ONAME, $1, ZN);
|
||||||
|
$$->sym = $3;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
zexpr :
|
||||||
|
{ $$ = 0; }
|
||||||
|
| expr
|
||||||
|
;
|
||||||
|
|
||||||
|
expr : castexpr
|
||||||
|
| expr '*' expr
|
||||||
|
{
|
||||||
|
$$ = an(OMUL, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '/' expr
|
||||||
|
{
|
||||||
|
$$ = an(ODIV, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '%' expr
|
||||||
|
{
|
||||||
|
$$ = an(OMOD, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '+' expr
|
||||||
|
{
|
||||||
|
$$ = an(OADD, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '-' expr
|
||||||
|
{
|
||||||
|
$$ = an(OSUB, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Trsh expr
|
||||||
|
{
|
||||||
|
$$ = an(ORSH, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Tlsh expr
|
||||||
|
{
|
||||||
|
$$ = an(OLSH, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '<' expr
|
||||||
|
{
|
||||||
|
$$ = an(OLT, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '>' expr
|
||||||
|
{
|
||||||
|
$$ = an(OGT, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Tleq expr
|
||||||
|
{
|
||||||
|
$$ = an(OLEQ, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Tgeq expr
|
||||||
|
{
|
||||||
|
$$ = an(OGEQ, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Teq expr
|
||||||
|
{
|
||||||
|
$$ = an(OEQ, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Tneq expr
|
||||||
|
{
|
||||||
|
$$ = an(ONEQ, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '&' expr
|
||||||
|
{
|
||||||
|
$$ = an(OLAND, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '^' expr
|
||||||
|
{
|
||||||
|
$$ = an(OXOR, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '|' expr
|
||||||
|
{
|
||||||
|
$$ = an(OLOR, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Tandand expr
|
||||||
|
{
|
||||||
|
$$ = an(OCAND, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Toror expr
|
||||||
|
{
|
||||||
|
$$ = an(OCOR, $1, $3);
|
||||||
|
}
|
||||||
|
| expr '=' expr
|
||||||
|
{
|
||||||
|
$$ = an(OASGN, $1, $3);
|
||||||
|
}
|
||||||
|
| expr Tfmt
|
||||||
|
{
|
||||||
|
$$ = an(OFMT, $1, con($2));
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
castexpr : monexpr
|
||||||
|
| '(' Tid ')' monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OCAST, $4, ZN);
|
||||||
|
$$->sym = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
monexpr : term
|
||||||
|
| '*' monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OINDM, $2, ZN);
|
||||||
|
}
|
||||||
|
| '@' monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OINDC, $2, ZN);
|
||||||
|
}
|
||||||
|
| '+' monexpr
|
||||||
|
{
|
||||||
|
$$ = con(0);
|
||||||
|
$$ = an(OADD, $2, $$);
|
||||||
|
}
|
||||||
|
| '-' monexpr
|
||||||
|
{
|
||||||
|
$$ = con(0);
|
||||||
|
$$ = an(OSUB, $$, $2);
|
||||||
|
}
|
||||||
|
| Tdec monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OEDEC, $2, ZN);
|
||||||
|
}
|
||||||
|
| Tinc monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OEINC, $2, ZN);
|
||||||
|
}
|
||||||
|
| Thead monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OHEAD, $2, ZN);
|
||||||
|
}
|
||||||
|
| Ttail monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OTAIL, $2, ZN);
|
||||||
|
}
|
||||||
|
| Tappend monexpr ',' monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OAPPEND, $2, $4);
|
||||||
|
}
|
||||||
|
| Tdelete monexpr ',' monexpr
|
||||||
|
{
|
||||||
|
$$ = an(ODELETE, $2, $4);
|
||||||
|
}
|
||||||
|
| '!' monexpr
|
||||||
|
{
|
||||||
|
$$ = an(ONOT, $2, ZN);
|
||||||
|
}
|
||||||
|
| '~' monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OXOR, $2, con(-1));
|
||||||
|
}
|
||||||
|
| Teval monexpr
|
||||||
|
{
|
||||||
|
$$ = an(OEVAL, $2, ZN);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
term : '(' expr ')'
|
||||||
|
{
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
| '{' args '}'
|
||||||
|
{
|
||||||
|
$$ = an(OCTRUCT, $2, ZN);
|
||||||
|
}
|
||||||
|
| term '[' expr ']'
|
||||||
|
{
|
||||||
|
$$ = an(OINDEX, $1, $3);
|
||||||
|
}
|
||||||
|
| term Tdec
|
||||||
|
{
|
||||||
|
$$ = an(OPDEC, $1, ZN);
|
||||||
|
}
|
||||||
|
| term '.' Tid
|
||||||
|
{
|
||||||
|
$$ = an(ODOT, $1, ZN);
|
||||||
|
$$->sym = $3;
|
||||||
|
}
|
||||||
|
| term Tindir Tid
|
||||||
|
{
|
||||||
|
$$ = an(ODOT, an(OINDM, $1, ZN), ZN);
|
||||||
|
$$->sym = $3;
|
||||||
|
}
|
||||||
|
| term Tinc
|
||||||
|
{
|
||||||
|
$$ = an(OPINC, $1, ZN);
|
||||||
|
}
|
||||||
|
| name '(' args ')'
|
||||||
|
{
|
||||||
|
$$ = an(OCALL, $1, $3);
|
||||||
|
}
|
||||||
|
| Tbuiltin name '(' args ')'
|
||||||
|
{
|
||||||
|
$$ = an(OCALL, $2, $4);
|
||||||
|
$$->builtin = 1;
|
||||||
|
}
|
||||||
|
| name
|
||||||
|
| Tconst
|
||||||
|
{
|
||||||
|
$$ = con($1);
|
||||||
|
}
|
||||||
|
| Tfconst
|
||||||
|
{
|
||||||
|
$$ = an(OCONST, ZN, ZN);
|
||||||
|
$$->type = TFLOAT;
|
||||||
|
$$->store.fmt = 'f';
|
||||||
|
$$->store.u.fval = $1;
|
||||||
|
}
|
||||||
|
| Tstring
|
||||||
|
{
|
||||||
|
$$ = an(OCONST, ZN, ZN);
|
||||||
|
$$->type = TSTRING;
|
||||||
|
$$->store.u.string = $1;
|
||||||
|
$$->store.fmt = 's';
|
||||||
|
}
|
||||||
|
| Twhat zname
|
||||||
|
{
|
||||||
|
$$ = an(OWHAT, ZN, ZN);
|
||||||
|
$$->sym = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
name : Tid
|
||||||
|
{
|
||||||
|
$$ = an(ONAME, ZN, ZN);
|
||||||
|
$$->sym = $1;
|
||||||
|
}
|
||||||
|
| Tid ':' name
|
||||||
|
{
|
||||||
|
$$ = an(OFRAME, $3, ZN);
|
||||||
|
$$->sym = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
args : zexpr
|
||||||
|
| args ',' zexpr
|
||||||
|
{
|
||||||
|
$$ = an(OLIST, $1, $3);
|
||||||
|
}
|
||||||
|
;
|
||||||
153
src/cmd/acid/dot.c
Normal file
153
src/cmd/acid/dot.c
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern extern
|
||||||
|
#include "acid.h"
|
||||||
|
|
||||||
|
Type*
|
||||||
|
srch(Type *t, char *s)
|
||||||
|
{
|
||||||
|
Type *f;
|
||||||
|
|
||||||
|
f = 0;
|
||||||
|
while(t) {
|
||||||
|
if(strcmp(t->tag->name, s) == 0) {
|
||||||
|
if(f == 0 || t->depth < f->depth)
|
||||||
|
f = t;
|
||||||
|
}
|
||||||
|
t = t->next;
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
odot(Node *n, Node *r)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
Type *t;
|
||||||
|
Node res;
|
||||||
|
ulong addr;
|
||||||
|
|
||||||
|
s = n->sym->name;
|
||||||
|
if(s == 0)
|
||||||
|
fatal("dodot: no tag");
|
||||||
|
|
||||||
|
expr(n->left, &res);
|
||||||
|
if(res.store.comt == 0)
|
||||||
|
error("no type specified for (expr).%s", s);
|
||||||
|
|
||||||
|
if(res.type != TINT)
|
||||||
|
error("pointer must be integer for (expr).%s", s);
|
||||||
|
|
||||||
|
t = srch(res.store.comt, s);
|
||||||
|
if(t == 0)
|
||||||
|
error("no tag for (expr).%s", s);
|
||||||
|
|
||||||
|
/* Propagate types */
|
||||||
|
if(t->type)
|
||||||
|
r->store.comt = t->type->lt;
|
||||||
|
|
||||||
|
addr = res.store.u.ival+t->offset;
|
||||||
|
if(t->fmt == 'a') {
|
||||||
|
r->op = OCONST;
|
||||||
|
r->store.fmt = 'a';
|
||||||
|
r->type = TINT;
|
||||||
|
r->store.u.ival = addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
indir(cormap, addr, t->fmt, r);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static Type **tail;
|
||||||
|
static Lsym *base;
|
||||||
|
|
||||||
|
void
|
||||||
|
buildtype(Node *m, int d)
|
||||||
|
{
|
||||||
|
Type *t;
|
||||||
|
|
||||||
|
if(m == ZN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(m->op) {
|
||||||
|
case OLIST:
|
||||||
|
buildtype(m->left, d);
|
||||||
|
buildtype(m->right, d);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OCTRUCT:
|
||||||
|
buildtype(m->left, d+1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
t = malloc(sizeof(Type));
|
||||||
|
t->next = 0;
|
||||||
|
t->depth = d;
|
||||||
|
t->tag = m->sym;
|
||||||
|
t->base = base;
|
||||||
|
t->offset = m->store.u.ival;
|
||||||
|
if(m->left) {
|
||||||
|
t->type = m->left->sym;
|
||||||
|
t->fmt = 'a';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
t->type = 0;
|
||||||
|
if(m->right)
|
||||||
|
t->type = m->right->sym;
|
||||||
|
t->fmt = m->store.fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
*tail = t;
|
||||||
|
tail = &t->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
defcomplex(Node *tn, Node *m)
|
||||||
|
{
|
||||||
|
tail = &tn->sym->lt;
|
||||||
|
base = tn->sym;
|
||||||
|
buildtype(m, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
decl(Node *n)
|
||||||
|
{
|
||||||
|
Node *l;
|
||||||
|
Value *v;
|
||||||
|
Frtype *f;
|
||||||
|
Lsym *type;
|
||||||
|
|
||||||
|
type = n->sym;
|
||||||
|
if(type->lt == 0)
|
||||||
|
error("%s is not a complex type", type->name);
|
||||||
|
|
||||||
|
l = n->left;
|
||||||
|
if(l->op == ONAME) {
|
||||||
|
v = l->sym->v;
|
||||||
|
v->store.comt = type->lt;
|
||||||
|
v->store.fmt = 'a';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frame declaration
|
||||||
|
*/
|
||||||
|
for(f = l->sym->local; f; f = f->next) {
|
||||||
|
if(f->var == l->left->sym) {
|
||||||
|
f->type = n->sym->lt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f = malloc(sizeof(Frtype));
|
||||||
|
if(f == 0)
|
||||||
|
fatal("out of memory");
|
||||||
|
|
||||||
|
f->type = type->lt;
|
||||||
|
|
||||||
|
f->var = l->left->sym;
|
||||||
|
f->next = l->sym->local;
|
||||||
|
l->sym->local = f;
|
||||||
|
}
|
||||||
538
src/cmd/acid/exec.c
Normal file
538
src/cmd/acid/exec.c
Normal file
|
|
@ -0,0 +1,538 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern extern
|
||||||
|
#include "acid.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
error(char *fmt, ...)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char buf[2048];
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
/* Unstack io channels */
|
||||||
|
if(iop != 0) {
|
||||||
|
for(i = 1; i < iop; i++)
|
||||||
|
Bterm(io[i]);
|
||||||
|
bout = io[0];
|
||||||
|
iop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
gotint = 0;
|
||||||
|
Bflush(bout);
|
||||||
|
if(silent)
|
||||||
|
silent = 0;
|
||||||
|
else {
|
||||||
|
va_start(arg, fmt);
|
||||||
|
vseprint(buf, buf+sizeof(buf), fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
fprint(2, "%Z: (error) %s\n", buf);
|
||||||
|
}
|
||||||
|
while(popio())
|
||||||
|
;
|
||||||
|
interactive = 1;
|
||||||
|
longjmp(err, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unwind(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Lsym *s;
|
||||||
|
Value *v;
|
||||||
|
|
||||||
|
for(i = 0; i < Hashsize; i++) {
|
||||||
|
for(s = hash[i]; s; s = s->hash) {
|
||||||
|
while(s->v->pop) {
|
||||||
|
v = s->v->pop;
|
||||||
|
free(s->v);
|
||||||
|
s->v = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
execute(Node *n)
|
||||||
|
{
|
||||||
|
Value *v;
|
||||||
|
Lsym *sl;
|
||||||
|
Node *l, *r;
|
||||||
|
int i, s, e;
|
||||||
|
Node res, xx;
|
||||||
|
static int stmnt;
|
||||||
|
|
||||||
|
gc();
|
||||||
|
if(gotint)
|
||||||
|
error("interrupted");
|
||||||
|
|
||||||
|
if(n == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(stmnt++ > 5000) {
|
||||||
|
Bflush(bout);
|
||||||
|
stmnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = n->left;
|
||||||
|
r = n->right;
|
||||||
|
|
||||||
|
switch(n->op) {
|
||||||
|
default:
|
||||||
|
expr(n, &res);
|
||||||
|
if(ret || (res.type == TLIST && res.store.u.l == 0))
|
||||||
|
break;
|
||||||
|
prnt->right = &res;
|
||||||
|
expr(prnt, &xx);
|
||||||
|
break;
|
||||||
|
case OASGN:
|
||||||
|
case OCALL:
|
||||||
|
expr(n, &res);
|
||||||
|
break;
|
||||||
|
case OCOMPLEX:
|
||||||
|
decl(n);
|
||||||
|
break;
|
||||||
|
case OLOCAL:
|
||||||
|
for(n = n->left; n; n = n->left) {
|
||||||
|
if(ret == 0)
|
||||||
|
error("local not in function");
|
||||||
|
sl = n->sym;
|
||||||
|
if(sl->v->ret == ret)
|
||||||
|
error("%s declared twice", sl->name);
|
||||||
|
v = gmalloc(sizeof(Value));
|
||||||
|
v->ret = ret;
|
||||||
|
v->pop = sl->v;
|
||||||
|
sl->v = v;
|
||||||
|
v->scope = 0;
|
||||||
|
*(ret->tail) = sl;
|
||||||
|
ret->tail = &v->scope;
|
||||||
|
v->set = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ORET:
|
||||||
|
if(ret == 0)
|
||||||
|
error("return not in function");
|
||||||
|
expr(n->left, ret->val);
|
||||||
|
longjmp(ret->rlab, 1);
|
||||||
|
case OLIST:
|
||||||
|
execute(n->left);
|
||||||
|
execute(n->right);
|
||||||
|
break;
|
||||||
|
case OIF:
|
||||||
|
expr(l, &res);
|
||||||
|
if(r && r->op == OELSE) {
|
||||||
|
if(bool(&res))
|
||||||
|
execute(r->left);
|
||||||
|
else
|
||||||
|
execute(r->right);
|
||||||
|
}
|
||||||
|
else if(bool(&res))
|
||||||
|
execute(r);
|
||||||
|
break;
|
||||||
|
case OWHILE:
|
||||||
|
for(;;) {
|
||||||
|
expr(l, &res);
|
||||||
|
if(!bool(&res))
|
||||||
|
break;
|
||||||
|
execute(r);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ODO:
|
||||||
|
expr(l->left, &res);
|
||||||
|
if(res.type != TINT)
|
||||||
|
error("loop must have integer start");
|
||||||
|
s = res.store.u.ival;
|
||||||
|
expr(l->right, &res);
|
||||||
|
if(res.type != TINT)
|
||||||
|
error("loop must have integer end");
|
||||||
|
e = res.store.u.ival;
|
||||||
|
for(i = s; i <= e; i++)
|
||||||
|
execute(r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bool(Node *n)
|
||||||
|
{
|
||||||
|
int true = 0;
|
||||||
|
|
||||||
|
if(n->op != OCONST)
|
||||||
|
fatal("bool: not const");
|
||||||
|
|
||||||
|
switch(n->type) {
|
||||||
|
case TINT:
|
||||||
|
if(n->store.u.ival != 0)
|
||||||
|
true = 1;
|
||||||
|
break;
|
||||||
|
case TFLOAT:
|
||||||
|
if(n->store.u.fval != 0.0)
|
||||||
|
true = 1;
|
||||||
|
break;
|
||||||
|
case TSTRING:
|
||||||
|
if(n->store.u.string->len)
|
||||||
|
true = 1;
|
||||||
|
break;
|
||||||
|
case TLIST:
|
||||||
|
if(n->store.u.l)
|
||||||
|
true = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
convflt(Node *r, char *flt)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
c = flt[0];
|
||||||
|
if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
|
||||||
|
r->type = TSTRING;
|
||||||
|
r->store.fmt = 's';
|
||||||
|
r->store.u.string = strnode(flt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r->type = TFLOAT;
|
||||||
|
r->store.u.fval = atof(flt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
regbyoff(ulong addr)
|
||||||
|
{
|
||||||
|
Regdesc *r;
|
||||||
|
|
||||||
|
if(mach == nil)
|
||||||
|
error("no mach, no registers");
|
||||||
|
for(r=mach->reglist; r->name; r++)
|
||||||
|
if(r->offset == addr)
|
||||||
|
return r->name;
|
||||||
|
error("no register at %#lux", addr);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xget1(Map *m, ulong addr, u8int *a, int n)
|
||||||
|
{
|
||||||
|
if(addr < 0x100)
|
||||||
|
return lget1(m, correg, locreg(regbyoff(addr)), a, n);
|
||||||
|
else
|
||||||
|
return get1(m, addr, a, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xget2(Map *m, ulong addr, u16int *a)
|
||||||
|
{
|
||||||
|
if(addr < 0x100)
|
||||||
|
return lget2(m, correg, locreg(regbyoff(addr)), a);
|
||||||
|
else
|
||||||
|
return get2(m, addr, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xget4(Map *m, ulong addr, u32int *a)
|
||||||
|
{
|
||||||
|
if(addr < 0x100)
|
||||||
|
return lget4(m, correg, locreg(regbyoff(addr)), a);
|
||||||
|
else
|
||||||
|
return get4(m, addr, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xget8(Map *m, ulong addr, u64int *a)
|
||||||
|
{
|
||||||
|
if(addr < 0x100)
|
||||||
|
return lget8(m, correg, locreg(regbyoff(addr)), a);
|
||||||
|
else
|
||||||
|
return get8(m, addr, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
indir(Map *m, ulong addr, char fmt, Node *r)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u32int ival;
|
||||||
|
u64int vval;
|
||||||
|
int ret;
|
||||||
|
u8int cval;
|
||||||
|
u16int sval;
|
||||||
|
char buf[512], reg[12];
|
||||||
|
|
||||||
|
r->op = OCONST;
|
||||||
|
r->store.fmt = fmt;
|
||||||
|
switch(fmt) {
|
||||||
|
default:
|
||||||
|
error("bad pointer format '%c' for *", fmt);
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
case 'b':
|
||||||
|
r->type = TINT;
|
||||||
|
ret = xget1(m, addr, &cval, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
r->store.u.ival = cval;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'd':
|
||||||
|
case 'u':
|
||||||
|
case 'o':
|
||||||
|
case 'q':
|
||||||
|
case 'r':
|
||||||
|
r->type = TINT;
|
||||||
|
ret = xget2(m, addr, &sval);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
r->store.u.ival = sval;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
case 'B':
|
||||||
|
case 'X':
|
||||||
|
case 'D':
|
||||||
|
case 'U':
|
||||||
|
case 'O':
|
||||||
|
case 'Q':
|
||||||
|
r->type = TINT;
|
||||||
|
ret = xget4(m, addr, &ival);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
r->store.u.ival = ival;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
case 'W':
|
||||||
|
case 'Y':
|
||||||
|
case 'Z':
|
||||||
|
r->type = TINT;
|
||||||
|
ret = xget8(m, addr, &vval);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
r->store.u.ival = vval;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
r->type = TSTRING;
|
||||||
|
for(i = 0; i < sizeof(buf)-1; i++) {
|
||||||
|
ret = xget1(m, addr, (uchar*)&buf[i], 1);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
addr++;
|
||||||
|
if(buf[i] == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf[i] = 0;
|
||||||
|
if(i == 0)
|
||||||
|
strcpy(buf, "(null)");
|
||||||
|
r->store.u.string = strnode(buf);
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
r->type = TSTRING;
|
||||||
|
for(i = 0; i < sizeof(buf)-2; i += 2) {
|
||||||
|
ret = xget1(m, addr, (uchar*)&buf[i], 2);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
addr += 2;
|
||||||
|
if(buf[i] == 0 && buf[i+1] == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf[i++] = 0;
|
||||||
|
buf[i] = 0;
|
||||||
|
r->store.u.string = runenode((Rune*)buf);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
if ((*mach->das)(m, addr, fmt, buf, sizeof(buf)) < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
r->type = TSTRING;
|
||||||
|
r->store.fmt = 's';
|
||||||
|
r->store.u.string = strnode(buf);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
ret = xget1(m, addr, (uchar*)buf, mach->szfloat);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
mach->ftoa32(buf, sizeof(buf), (void*) buf);
|
||||||
|
convflt(r, buf);
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
ret = xget1(m, addr, (uchar*)buf, mach->szfloat);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
mach->ftoa32(buf, sizeof(buf), (void*) buf);
|
||||||
|
r->type = TSTRING;
|
||||||
|
r->store.u.string = strnode(buf);
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
ret = xget1(m, addr, (uchar*)buf, mach->szdouble);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
mach->ftoa64(buf, sizeof(buf), (void*) buf);
|
||||||
|
convflt(r, buf);
|
||||||
|
break;
|
||||||
|
case '3': /* little endian ieee 80 with hole in bytes 8&9 */
|
||||||
|
ret = xget1(m, addr, (uchar*)reg, 10);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
memmove(reg+10, reg+8, 2); /* open hole */
|
||||||
|
memset(reg+8, 0, 2); /* fill it */
|
||||||
|
leieeeftoa80(buf, sizeof(buf), reg);
|
||||||
|
convflt(r, buf);
|
||||||
|
break;
|
||||||
|
case '8': /* big-endian ieee 80 */
|
||||||
|
ret = xget1(m, addr, (uchar*)reg, 10);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
beieeeftoa80(buf, sizeof(buf), reg);
|
||||||
|
convflt(r, buf);
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
ret = xget1(m, addr, (uchar*)buf, mach->szdouble);
|
||||||
|
if (ret < 0)
|
||||||
|
error("indir: %r");
|
||||||
|
mach->ftoa64(buf, sizeof(buf), (void*) buf);
|
||||||
|
r->type = TSTRING;
|
||||||
|
r->store.u.string = strnode(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
windir(Map *m, Node *addr, Node *rval, Node *r)
|
||||||
|
{
|
||||||
|
uchar cval;
|
||||||
|
ushort sval;
|
||||||
|
Node res, aes;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(m == 0)
|
||||||
|
error("no map for */@=");
|
||||||
|
|
||||||
|
expr(rval, &res);
|
||||||
|
expr(addr, &aes);
|
||||||
|
|
||||||
|
if(aes.type != TINT)
|
||||||
|
error("bad type lhs of @/*");
|
||||||
|
|
||||||
|
if(m != cormap && wtflag == 0)
|
||||||
|
error("not in write mode");
|
||||||
|
|
||||||
|
r->type = res.type;
|
||||||
|
r->store.fmt = res.store.fmt;
|
||||||
|
r->store = res.store;
|
||||||
|
|
||||||
|
switch(res.store.fmt) {
|
||||||
|
default:
|
||||||
|
error("bad pointer format '%c' for */@=", res.store.fmt);
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
case 'b':
|
||||||
|
cval = res.store.u.ival;
|
||||||
|
ret = put1(m, aes.store.u.ival, &cval, 1);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
case 'x':
|
||||||
|
case 'd':
|
||||||
|
case 'u':
|
||||||
|
case 'o':
|
||||||
|
sval = res.store.u.ival;
|
||||||
|
ret = put2(m, aes.store.u.ival, sval);
|
||||||
|
r->store.u.ival = sval;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
case 'B':
|
||||||
|
case 'X':
|
||||||
|
case 'D':
|
||||||
|
case 'U':
|
||||||
|
case 'O':
|
||||||
|
ret = put4(m, aes.store.u.ival, res.store.u.ival);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
case 'W':
|
||||||
|
case 'Y':
|
||||||
|
case 'Z':
|
||||||
|
ret = put8(m, aes.store.u.ival, res.store.u.ival);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
case 'R':
|
||||||
|
ret = put1(m, aes.store.u.ival, (uchar*)res.store.u.string->string, res.store.u.string->len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
error("windir: %r");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)
|
||||||
|
{
|
||||||
|
int np, i;
|
||||||
|
Rplace rlab;
|
||||||
|
Node *n, res;
|
||||||
|
Value *v, *f;
|
||||||
|
Lsym *s, *next;
|
||||||
|
Node *avp[Maxarg], *ava[Maxarg];
|
||||||
|
|
||||||
|
rlab.local = 0;
|
||||||
|
|
||||||
|
na = 0;
|
||||||
|
flatten(avp, parameters);
|
||||||
|
np = na;
|
||||||
|
na = 0;
|
||||||
|
flatten(ava, local);
|
||||||
|
if(np != na) {
|
||||||
|
if(np < na)
|
||||||
|
error("%s: too few arguments", fn);
|
||||||
|
error("%s: too many arguments", fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
rlab.tail = &rlab.local;
|
||||||
|
|
||||||
|
ret = &rlab;
|
||||||
|
for(i = 0; i < np; i++) {
|
||||||
|
n = ava[i];
|
||||||
|
switch(n->op) {
|
||||||
|
default:
|
||||||
|
error("%s: %d formal not a name", fn, i);
|
||||||
|
case ONAME:
|
||||||
|
expr(avp[i], &res);
|
||||||
|
s = n->sym;
|
||||||
|
break;
|
||||||
|
case OINDM:
|
||||||
|
res.store.u.cc = avp[i];
|
||||||
|
res.type = TCODE;
|
||||||
|
res.store.comt = 0;
|
||||||
|
if(n->left->op != ONAME)
|
||||||
|
error("%s: %d formal not a name", fn, i);
|
||||||
|
s = n->left->sym;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(s->v->ret == ret)
|
||||||
|
error("%s already declared at this scope", s->name);
|
||||||
|
|
||||||
|
v = gmalloc(sizeof(Value));
|
||||||
|
v->ret = ret;
|
||||||
|
v->pop = s->v;
|
||||||
|
s->v = v;
|
||||||
|
v->scope = 0;
|
||||||
|
*(rlab.tail) = s;
|
||||||
|
rlab.tail = &v->scope;
|
||||||
|
|
||||||
|
v->store = res.store;
|
||||||
|
v->type = res.type;
|
||||||
|
v->set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->val = retexp;
|
||||||
|
if(setjmp(rlab.rlab) == 0)
|
||||||
|
execute(body);
|
||||||
|
|
||||||
|
for(s = rlab.local; s; s = next) {
|
||||||
|
f = s->v;
|
||||||
|
next = f->scope;
|
||||||
|
s->v = f->pop;
|
||||||
|
free(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
1018
src/cmd/acid/expr.c
Normal file
1018
src/cmd/acid/expr.c
Normal file
File diff suppressed because it is too large
Load diff
661
src/cmd/acid/lex.c
Normal file
661
src/cmd/acid/lex.c
Normal file
|
|
@ -0,0 +1,661 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern extern
|
||||||
|
#include "acid.h"
|
||||||
|
#include "y.tab.h"
|
||||||
|
|
||||||
|
struct keywd
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int terminal;
|
||||||
|
}
|
||||||
|
keywds[] =
|
||||||
|
{
|
||||||
|
"do", Tdo,
|
||||||
|
"if", Tif,
|
||||||
|
"then", Tthen,
|
||||||
|
"else", Telse,
|
||||||
|
"while", Twhile,
|
||||||
|
"loop", Tloop,
|
||||||
|
"head", Thead,
|
||||||
|
"tail", Ttail,
|
||||||
|
"append", Tappend,
|
||||||
|
"defn", Tfn,
|
||||||
|
"return", Tret,
|
||||||
|
"local", Tlocal,
|
||||||
|
"aggr", Tcomplex,
|
||||||
|
"union", Tcomplex,
|
||||||
|
"adt", Tcomplex,
|
||||||
|
"complex", Tcomplex,
|
||||||
|
"delete", Tdelete,
|
||||||
|
"whatis", Twhat,
|
||||||
|
"eval", Teval,
|
||||||
|
"builtin", Tbuiltin,
|
||||||
|
0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
char cmap[256] =
|
||||||
|
{
|
||||||
|
['0'] '\0'+1,
|
||||||
|
['n'] '\n'+1,
|
||||||
|
['r'] '\r'+1,
|
||||||
|
['t'] '\t'+1,
|
||||||
|
['b'] '\b'+1,
|
||||||
|
['f'] '\f'+1,
|
||||||
|
['a'] '\a'+1,
|
||||||
|
['v'] '\v'+1,
|
||||||
|
['\\'] '\\'+1,
|
||||||
|
['"'] '"'+1,
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
kinit(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; keywds[i].name; i++)
|
||||||
|
enter(keywds[i].name, keywds[i].terminal);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct IOstack IOstack;
|
||||||
|
struct IOstack
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int line;
|
||||||
|
char *text;
|
||||||
|
char *ip;
|
||||||
|
Biobuf *fin;
|
||||||
|
IOstack *prev;
|
||||||
|
};
|
||||||
|
IOstack *lexio;
|
||||||
|
|
||||||
|
void
|
||||||
|
setacidfile(void)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
Lsym *l;
|
||||||
|
|
||||||
|
if(lexio)
|
||||||
|
name = lexio->name;
|
||||||
|
else
|
||||||
|
name = "";
|
||||||
|
l = mkvar("acidfile");
|
||||||
|
l->v->set = 1;
|
||||||
|
l->v->store.fmt = 's';
|
||||||
|
l->v->type = TSTRING;
|
||||||
|
l->v->store.u.string = strnode(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pushfile(char *file)
|
||||||
|
{
|
||||||
|
Biobuf *b;
|
||||||
|
IOstack *io;
|
||||||
|
|
||||||
|
if(file)
|
||||||
|
b = Bopen(file, OREAD);
|
||||||
|
else{
|
||||||
|
b = Bopen(unsharp("#d/0"), OREAD);
|
||||||
|
file = "<stdin>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(b == 0)
|
||||||
|
error("pushfile: %s: %r", file);
|
||||||
|
|
||||||
|
io = malloc(sizeof(IOstack));
|
||||||
|
if(io == 0)
|
||||||
|
fatal("no memory");
|
||||||
|
io->name = strdup(file);
|
||||||
|
if(io->name == 0)
|
||||||
|
fatal("no memory");
|
||||||
|
io->line = line;
|
||||||
|
line = 1;
|
||||||
|
io->text = 0;
|
||||||
|
io->fin = b;
|
||||||
|
io->prev = lexio;
|
||||||
|
lexio = io;
|
||||||
|
setacidfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pushfd(int fd)
|
||||||
|
{
|
||||||
|
pushfile("/dev/null");
|
||||||
|
close(lexio->fin->fid);
|
||||||
|
free(lexio->name);
|
||||||
|
lexio->name = smprint("<fd#d>", fd);
|
||||||
|
lexio->fin->fid = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pushstr(Node *s)
|
||||||
|
{
|
||||||
|
IOstack *io;
|
||||||
|
|
||||||
|
io = malloc(sizeof(IOstack));
|
||||||
|
if(io == 0)
|
||||||
|
fatal("no memory");
|
||||||
|
io->line = line;
|
||||||
|
line = 1;
|
||||||
|
io->name = strdup("<string>");
|
||||||
|
if(io->name == 0)
|
||||||
|
fatal("no memory");
|
||||||
|
io->line = line;
|
||||||
|
line = 1;
|
||||||
|
io->text = strdup(s->store.u.string->string);
|
||||||
|
if(io->text == 0)
|
||||||
|
fatal("no memory");
|
||||||
|
io->ip = io->text;
|
||||||
|
io->fin = 0;
|
||||||
|
io->prev = lexio;
|
||||||
|
lexio = io;
|
||||||
|
setacidfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
restartio(void)
|
||||||
|
{
|
||||||
|
Bflush(lexio->fin);
|
||||||
|
Binit(lexio->fin, 0, OREAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
popio(void)
|
||||||
|
{
|
||||||
|
IOstack *s;
|
||||||
|
|
||||||
|
if(lexio == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(lexio->prev == 0){
|
||||||
|
if(lexio->fin)
|
||||||
|
restartio();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lexio->fin)
|
||||||
|
Bterm(lexio->fin);
|
||||||
|
else
|
||||||
|
free(lexio->text);
|
||||||
|
free(lexio->name);
|
||||||
|
line = lexio->line;
|
||||||
|
s = lexio;
|
||||||
|
lexio = s->prev;
|
||||||
|
free(s);
|
||||||
|
setacidfile();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Zfmt(Fmt *f)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char buf[1024];
|
||||||
|
IOstack *e;
|
||||||
|
|
||||||
|
e = lexio;
|
||||||
|
if(e) {
|
||||||
|
i = sprint(buf, "%s:%d", e->name, line);
|
||||||
|
while(e->prev) {
|
||||||
|
e = e->prev;
|
||||||
|
if(initialising && e->prev == 0)
|
||||||
|
break;
|
||||||
|
i += sprint(buf+i, " [%s:%d]", e->name, e->line);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
sprint(buf, "no file:0");
|
||||||
|
fmtstrcpy(f, buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unlexc(int s)
|
||||||
|
{
|
||||||
|
if(s == '\n')
|
||||||
|
line--;
|
||||||
|
|
||||||
|
if(lexio->fin)
|
||||||
|
Bungetc(lexio->fin);
|
||||||
|
else
|
||||||
|
lexio->ip--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lexc(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if(lexio->fin) {
|
||||||
|
c = Bgetc(lexio->fin);
|
||||||
|
if(gotint)
|
||||||
|
error("interrupt");
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = *lexio->ip++;
|
||||||
|
if(c == 0)
|
||||||
|
return -1;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
escchar(char c)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
char buf[Strsize];
|
||||||
|
|
||||||
|
if(c >= '0' && c <= '9') {
|
||||||
|
n = 1;
|
||||||
|
buf[0] = c;
|
||||||
|
for(;;) {
|
||||||
|
c = lexc();
|
||||||
|
if(c == Eof)
|
||||||
|
error("%d: <eof> in escape sequence", line);
|
||||||
|
if(strchr("0123456789xX", c) == 0) {
|
||||||
|
unlexc(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf[n++] = c;
|
||||||
|
}
|
||||||
|
buf[n] = '\0';
|
||||||
|
return strtol(buf, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = cmap[(unsigned char)c];
|
||||||
|
if(n == 0)
|
||||||
|
return c;
|
||||||
|
return n-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eatstring(void)
|
||||||
|
{
|
||||||
|
int esc, c, cnt;
|
||||||
|
char buf[Strsize];
|
||||||
|
|
||||||
|
esc = 0;
|
||||||
|
for(cnt = 0;;) {
|
||||||
|
c = lexc();
|
||||||
|
switch(c) {
|
||||||
|
case Eof:
|
||||||
|
error("%d: <eof> in string constant", line);
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
error("newline in string constant");
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
if(esc)
|
||||||
|
goto Default;
|
||||||
|
esc = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
if(esc == 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Fall through */
|
||||||
|
default:
|
||||||
|
Default:
|
||||||
|
if(esc) {
|
||||||
|
c = escchar(c);
|
||||||
|
esc = 0;
|
||||||
|
}
|
||||||
|
buf[cnt++] = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(cnt >= Strsize)
|
||||||
|
error("string token too long");
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
buf[cnt] = '\0';
|
||||||
|
yylval.string = strnode(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eatnl(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
line++;
|
||||||
|
for(;;) {
|
||||||
|
c = lexc();
|
||||||
|
if(c == Eof)
|
||||||
|
error("eof in comment");
|
||||||
|
if(c == '\n')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
yylex(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
extern char vfmt[];
|
||||||
|
|
||||||
|
loop:
|
||||||
|
Bflush(bout);
|
||||||
|
c = lexc();
|
||||||
|
switch(c) {
|
||||||
|
case Eof:
|
||||||
|
if(gotint) {
|
||||||
|
gotint = 0;
|
||||||
|
stacked = 0;
|
||||||
|
Bprint(bout, "\nacid; ");
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
return Eof;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
eatstring();
|
||||||
|
return Tstring;
|
||||||
|
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
goto loop;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
line++;
|
||||||
|
if(interactive == 0)
|
||||||
|
goto loop;
|
||||||
|
if(stacked) {
|
||||||
|
print("\t");
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
nlcount++;
|
||||||
|
return ';';
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
c = lexc();
|
||||||
|
unlexc(c);
|
||||||
|
if(isdigit(c))
|
||||||
|
return numsym('.');
|
||||||
|
|
||||||
|
return '.';
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case ';':
|
||||||
|
case ':':
|
||||||
|
case ',':
|
||||||
|
case '~':
|
||||||
|
case '?':
|
||||||
|
case '*':
|
||||||
|
case '@':
|
||||||
|
case '^':
|
||||||
|
case '%':
|
||||||
|
return c;
|
||||||
|
case '{':
|
||||||
|
stacked++;
|
||||||
|
return c;
|
||||||
|
case '}':
|
||||||
|
stacked--;
|
||||||
|
return c;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
c = lexc();
|
||||||
|
if(strchr(vfmt, c) == 0) {
|
||||||
|
unlexc(c);
|
||||||
|
return '\\';
|
||||||
|
}
|
||||||
|
yylval.ival = c;
|
||||||
|
return Tfmt;
|
||||||
|
|
||||||
|
case '!':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '=')
|
||||||
|
return Tneq;
|
||||||
|
unlexc(c);
|
||||||
|
return '!';
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '+')
|
||||||
|
return Tinc;
|
||||||
|
unlexc(c);
|
||||||
|
return '+';
|
||||||
|
|
||||||
|
case '/':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '/') {
|
||||||
|
eatnl();
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
unlexc(c);
|
||||||
|
return '/';
|
||||||
|
|
||||||
|
case '\'':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '\\')
|
||||||
|
yylval.ival = escchar(lexc());
|
||||||
|
else
|
||||||
|
yylval.ival = c;
|
||||||
|
c = lexc();
|
||||||
|
if(c != '\'') {
|
||||||
|
error("missing '");
|
||||||
|
unlexc(c);
|
||||||
|
}
|
||||||
|
return Tconst;
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '&')
|
||||||
|
return Tandand;
|
||||||
|
unlexc(c);
|
||||||
|
return '&';
|
||||||
|
|
||||||
|
case '=':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '=')
|
||||||
|
return Teq;
|
||||||
|
unlexc(c);
|
||||||
|
return '=';
|
||||||
|
|
||||||
|
case '|':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '|')
|
||||||
|
return Toror;
|
||||||
|
unlexc(c);
|
||||||
|
return '|';
|
||||||
|
|
||||||
|
case '<':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '=')
|
||||||
|
return Tleq;
|
||||||
|
if(c == '<')
|
||||||
|
return Tlsh;
|
||||||
|
unlexc(c);
|
||||||
|
return '<';
|
||||||
|
|
||||||
|
case '>':
|
||||||
|
c = lexc();
|
||||||
|
if(c == '=')
|
||||||
|
return Tgeq;
|
||||||
|
if(c == '>')
|
||||||
|
return Trsh;
|
||||||
|
unlexc(c);
|
||||||
|
return '>';
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
c = lexc();
|
||||||
|
|
||||||
|
if(c == '>')
|
||||||
|
return Tindir;
|
||||||
|
|
||||||
|
if(c == '-')
|
||||||
|
return Tdec;
|
||||||
|
unlexc(c);
|
||||||
|
return '-';
|
||||||
|
|
||||||
|
default:
|
||||||
|
return numsym(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
numsym(char first)
|
||||||
|
{
|
||||||
|
int c, isbin, isfloat, ishex;
|
||||||
|
char *sel, *p;
|
||||||
|
Lsym *s;
|
||||||
|
|
||||||
|
symbol[0] = first;
|
||||||
|
p = symbol;
|
||||||
|
|
||||||
|
ishex = 0;
|
||||||
|
isbin = 0;
|
||||||
|
isfloat = 0;
|
||||||
|
if(first == '.')
|
||||||
|
isfloat = 1;
|
||||||
|
|
||||||
|
if(isdigit(*p++) || isfloat) {
|
||||||
|
for(;;) {
|
||||||
|
c = lexc();
|
||||||
|
if(c < 0)
|
||||||
|
error("%d: <eof> eating symbols", line);
|
||||||
|
|
||||||
|
if(c == '\n')
|
||||||
|
line++;
|
||||||
|
sel = "01234567890.xb";
|
||||||
|
if(ishex)
|
||||||
|
sel = "01234567890abcdefABCDEF";
|
||||||
|
else if(isbin)
|
||||||
|
sel = "01";
|
||||||
|
else if(isfloat)
|
||||||
|
sel = "01234567890eE-+";
|
||||||
|
|
||||||
|
if(strchr(sel, c) == 0) {
|
||||||
|
unlexc(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(c == '.')
|
||||||
|
isfloat = 1;
|
||||||
|
if(!isbin && c == 'x')
|
||||||
|
ishex = 1;
|
||||||
|
if(!ishex && c == 'b')
|
||||||
|
isbin = 1;
|
||||||
|
*p++ = c;
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
if(isfloat) {
|
||||||
|
yylval.fval = atof(symbol);
|
||||||
|
return Tfconst;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isbin)
|
||||||
|
yylval.ival = strtoul(symbol+2, 0, 2);
|
||||||
|
else
|
||||||
|
yylval.ival = strtoul(symbol, 0, 0);
|
||||||
|
return Tconst;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
c = lexc();
|
||||||
|
if(c < 0)
|
||||||
|
error("%d <eof> eating symbols", line);
|
||||||
|
if(c == '\n')
|
||||||
|
line++;
|
||||||
|
if(c != '_' && c != '$' && c <= '~' && !isalnum(c)) { /* checking against ~ lets UTF names through */
|
||||||
|
unlexc(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*p++ = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
s = look(symbol);
|
||||||
|
if(s == 0)
|
||||||
|
s = enter(symbol, Tid);
|
||||||
|
|
||||||
|
yylval.sym = s;
|
||||||
|
return s->lexval;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lsym*
|
||||||
|
enter(char *name, int t)
|
||||||
|
{
|
||||||
|
Lsym *s;
|
||||||
|
ulong h;
|
||||||
|
char *p;
|
||||||
|
Value *v;
|
||||||
|
|
||||||
|
h = 0;
|
||||||
|
for(p = name; *p; p++)
|
||||||
|
h = h*3 + *p;
|
||||||
|
h %= Hashsize;
|
||||||
|
|
||||||
|
s = gmalloc(sizeof(Lsym));
|
||||||
|
memset(s, 0, sizeof(Lsym));
|
||||||
|
s->name = strdup(name);
|
||||||
|
|
||||||
|
s->hash = hash[h];
|
||||||
|
hash[h] = s;
|
||||||
|
s->lexval = t;
|
||||||
|
|
||||||
|
v = gmalloc(sizeof(Value));
|
||||||
|
s->v = v;
|
||||||
|
|
||||||
|
v->store.fmt = 'X';
|
||||||
|
v->type = TINT;
|
||||||
|
memset(v, 0, sizeof(Value));
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
delsym(Lsym *s)
|
||||||
|
{
|
||||||
|
char *q;
|
||||||
|
ulong h;
|
||||||
|
Lsym *p;
|
||||||
|
|
||||||
|
h = 0;
|
||||||
|
for(q = s->name; *q; q++)
|
||||||
|
h = h*3 + *q;
|
||||||
|
h %= Hashsize;
|
||||||
|
|
||||||
|
if(hash[h] == s)
|
||||||
|
hash[h] = s->hash;
|
||||||
|
else{
|
||||||
|
for(p=hash[h]; p && p->hash != s; p=p->hash)
|
||||||
|
;
|
||||||
|
if(p)
|
||||||
|
p->hash = s->hash;
|
||||||
|
}
|
||||||
|
s->hash = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lsym*
|
||||||
|
look(char *name)
|
||||||
|
{
|
||||||
|
Lsym *s;
|
||||||
|
ulong h;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
h = 0;
|
||||||
|
for(p = name; *p; p++)
|
||||||
|
h = h*3 + *p;
|
||||||
|
h %= Hashsize;
|
||||||
|
|
||||||
|
for(s = hash[h]; s; s = s->hash)
|
||||||
|
if(strcmp(name, s->name) == 0)
|
||||||
|
return s;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lsym*
|
||||||
|
mkvar(char *s)
|
||||||
|
{
|
||||||
|
Lsym *l;
|
||||||
|
|
||||||
|
l = look(s);
|
||||||
|
if(l == 0)
|
||||||
|
l = enter(s, Tid);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
270
src/cmd/acid/list.c
Normal file
270
src/cmd/acid/list.c
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern extern
|
||||||
|
#include "acid.h"
|
||||||
|
|
||||||
|
static List **tail;
|
||||||
|
|
||||||
|
List*
|
||||||
|
construct(Node *l)
|
||||||
|
{
|
||||||
|
List *lh, **save;
|
||||||
|
|
||||||
|
save = tail;
|
||||||
|
lh = 0;
|
||||||
|
tail = &lh;
|
||||||
|
build(l);
|
||||||
|
tail = save;
|
||||||
|
|
||||||
|
return lh;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
listlen(List *l)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
while(l) {
|
||||||
|
len++;
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
build(Node *n)
|
||||||
|
{
|
||||||
|
List *l;
|
||||||
|
Node res;
|
||||||
|
|
||||||
|
if(n == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(n->op) {
|
||||||
|
case OLIST:
|
||||||
|
build(n->left);
|
||||||
|
build(n->right);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
expr(n, &res);
|
||||||
|
l = al(res.type);
|
||||||
|
l->store = res.store;
|
||||||
|
*tail = l;
|
||||||
|
tail = &l->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List*
|
||||||
|
addlist(List *l, List *r)
|
||||||
|
{
|
||||||
|
List *f;
|
||||||
|
|
||||||
|
if(l == 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
for(f = l; f->next; f = f->next)
|
||||||
|
;
|
||||||
|
f->next = r;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
append(Node *r, Node *list, Node *val)
|
||||||
|
{
|
||||||
|
List *l, *f;
|
||||||
|
|
||||||
|
l = al(val->type);
|
||||||
|
l->store = val->store;
|
||||||
|
l->next = 0;
|
||||||
|
|
||||||
|
r->op = OCONST;
|
||||||
|
r->type = TLIST;
|
||||||
|
|
||||||
|
if(list->store.u.l == 0) {
|
||||||
|
list->store.u.l = l;
|
||||||
|
r->store.u.l = l;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(f = list->store.u.l; f->next; f = f->next)
|
||||||
|
;
|
||||||
|
f->next = l;
|
||||||
|
r->store.u.l = list->store.u.l;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
listcmp(List *l, List *r)
|
||||||
|
{
|
||||||
|
if(l == r)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
while(l) {
|
||||||
|
if(r == 0)
|
||||||
|
return 0;
|
||||||
|
if(l->type != r->type)
|
||||||
|
return 0;
|
||||||
|
switch(l->type) {
|
||||||
|
case TINT:
|
||||||
|
if(l->store.u.ival != r->store.u.ival)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case TFLOAT:
|
||||||
|
if(l->store.u.fval != r->store.u.fval)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case TSTRING:
|
||||||
|
if(scmp(l->store.u.string, r->store.u.string) == 0)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case TLIST:
|
||||||
|
if(listcmp(l->store.u.l, r->store.u.l) == 0)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
l = l->next;
|
||||||
|
r = r->next;
|
||||||
|
}
|
||||||
|
if(l != r)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nthelem(List *l, int n, Node *res)
|
||||||
|
{
|
||||||
|
if(n < 0)
|
||||||
|
error("negative index in []");
|
||||||
|
|
||||||
|
while(l && n--)
|
||||||
|
l = l->next;
|
||||||
|
|
||||||
|
res->op = OCONST;
|
||||||
|
if(l == 0) {
|
||||||
|
res->type = TLIST;
|
||||||
|
res->store.u.l = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res->type = l->type;
|
||||||
|
res->store = l->store;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
delete(List *l, int n, Node *res)
|
||||||
|
{
|
||||||
|
List **tl;
|
||||||
|
|
||||||
|
if(n < 0)
|
||||||
|
error("negative index in delete");
|
||||||
|
|
||||||
|
res->op = OCONST;
|
||||||
|
res->type = TLIST;
|
||||||
|
res->store.u.l = l;
|
||||||
|
|
||||||
|
for(tl = &res->store.u.l; l && n--; l = l->next)
|
||||||
|
tl = &l->next;
|
||||||
|
|
||||||
|
if(l == 0)
|
||||||
|
error("element beyond end of list");
|
||||||
|
*tl = l->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
List*
|
||||||
|
listvar(char *s, long v)
|
||||||
|
{
|
||||||
|
List *l, *tl;
|
||||||
|
|
||||||
|
tl = al(TLIST);
|
||||||
|
|
||||||
|
l = al(TSTRING);
|
||||||
|
tl->store.u.l = l;
|
||||||
|
l->store.fmt = 's';
|
||||||
|
l->store.u.string = strnode(s);
|
||||||
|
l->next = al(TINT);
|
||||||
|
l = l->next;
|
||||||
|
l->store.fmt = 'X';
|
||||||
|
l->store.u.ival = v;
|
||||||
|
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List*
|
||||||
|
listlocals(Map *map, Regs *regs, Symbol *fn, int class)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u32int val;
|
||||||
|
Symbol s;
|
||||||
|
List **tail, *l2;
|
||||||
|
|
||||||
|
l2 = 0;
|
||||||
|
tail = &l2;
|
||||||
|
if(fn == nil)
|
||||||
|
return l2;
|
||||||
|
for(i = 0; indexlsym(fn, i, &s)>=0; i++) {
|
||||||
|
if(s.class != class)
|
||||||
|
continue;
|
||||||
|
if(class == CAUTO && s.name[0] == '.')
|
||||||
|
continue;
|
||||||
|
if(lget4(map, regs, s.loc, &val) < 0)
|
||||||
|
continue;
|
||||||
|
*tail = listvar(s.name, val);
|
||||||
|
tail = &(*tail)->next;
|
||||||
|
}
|
||||||
|
return l2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List*
|
||||||
|
listparams(Map *map, Regs *regs, Symbol *fn)
|
||||||
|
{
|
||||||
|
return listlocals(map, regs, fn, CPARAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List*
|
||||||
|
listautos(Map *map, Regs *regs, Symbol *fn)
|
||||||
|
{
|
||||||
|
return listlocals(map, regs, fn, CAUTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
trlist(Map *map, Regs *regs, ulong pc, ulong callerpc, Symbol *sym, int depth)
|
||||||
|
{
|
||||||
|
List *q, *l;
|
||||||
|
static List **tail;
|
||||||
|
|
||||||
|
if (tracelist == 0) /* first time */
|
||||||
|
tail = &tracelist;
|
||||||
|
|
||||||
|
q = al(TLIST);
|
||||||
|
*tail = q;
|
||||||
|
tail = &q->next;
|
||||||
|
|
||||||
|
l = al(TINT); /* Function address */
|
||||||
|
q->store.u.l = l;
|
||||||
|
l->store.u.ival = sym ? sym->loc.addr : pc;
|
||||||
|
l->store.fmt = 'X';
|
||||||
|
|
||||||
|
l->next = al(TINT); /* actual pc address */
|
||||||
|
l = l->next;
|
||||||
|
l->store.u.ival = pc;
|
||||||
|
l->store.fmt = 'X';
|
||||||
|
|
||||||
|
l->next = al(TINT); /* called from address */
|
||||||
|
l = l->next;
|
||||||
|
l->store.u.ival = callerpc;
|
||||||
|
l->store.fmt = 'X';
|
||||||
|
|
||||||
|
l->next = al(TLIST); /* make list of params */
|
||||||
|
l = l->next;
|
||||||
|
if(sym)
|
||||||
|
l->store.u.l = listparams(map, regs, sym);
|
||||||
|
|
||||||
|
l->next = al(TLIST); /* make list of locals */
|
||||||
|
l = l->next;
|
||||||
|
if(sym)
|
||||||
|
l->store.u.l = listautos(map, regs, sym);
|
||||||
|
|
||||||
|
return depth<40;
|
||||||
|
}
|
||||||
630
src/cmd/acid/main.c
Normal file
630
src/cmd/acid/main.c
Normal file
|
|
@ -0,0 +1,630 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern
|
||||||
|
#include "acid.h"
|
||||||
|
#include "y.tab.h"
|
||||||
|
|
||||||
|
extern int __ifmt(Fmt*);
|
||||||
|
|
||||||
|
static Biobuf bioout;
|
||||||
|
static char* lm[16];
|
||||||
|
static int nlm;
|
||||||
|
static char* mtype;
|
||||||
|
|
||||||
|
static int attachfiles(int, char**);
|
||||||
|
int xfmt(Fmt*);
|
||||||
|
int isnumeric(char*);
|
||||||
|
void die(void);
|
||||||
|
void setcore(Fhdr*);
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprint(2, "usage: acid [-c core] [-l module] [-m machine] [-qrw] [-k] [pid] [file]\n");
|
||||||
|
exits("usage");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
Lsym *l;
|
||||||
|
Node *n;
|
||||||
|
char buf[128], *s;
|
||||||
|
int pid, i;
|
||||||
|
|
||||||
|
argv0 = argv[0];
|
||||||
|
pid = 0;
|
||||||
|
quiet = 1;
|
||||||
|
|
||||||
|
mtype = 0;
|
||||||
|
ARGBEGIN{
|
||||||
|
case 'A':
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mtype = ARGF();
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
wtflag = 1;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
s = ARGF();
|
||||||
|
if(s == 0)
|
||||||
|
usage();
|
||||||
|
lm[nlm++] = s;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
kernel++;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
quiet = 0;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
pid = 1;
|
||||||
|
remote++;
|
||||||
|
kernel++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
}ARGEND
|
||||||
|
|
||||||
|
fmtinstall('x', xfmt);
|
||||||
|
fmtinstall('Z', Zfmt);
|
||||||
|
fmtinstall('L', locfmt);
|
||||||
|
Binit(&bioout, 1, OWRITE);
|
||||||
|
bout = &bioout;
|
||||||
|
|
||||||
|
kinit();
|
||||||
|
initialising = 1;
|
||||||
|
pushfile(0);
|
||||||
|
loadvars();
|
||||||
|
installbuiltin();
|
||||||
|
|
||||||
|
if(mtype && machbyname(mtype) == 0)
|
||||||
|
print("unknown machine %s", mtype);
|
||||||
|
|
||||||
|
if (attachfiles(argc, argv) < 0)
|
||||||
|
varreg(); /* use default register set on error */
|
||||||
|
if(mach == nil)
|
||||||
|
mach = machcpu;
|
||||||
|
|
||||||
|
symhdr = nil; /* not supposed to use this anymore */
|
||||||
|
|
||||||
|
l = mkvar("acid");
|
||||||
|
l->v->set = 1;
|
||||||
|
l->v->type = TLIST;
|
||||||
|
l->v->store.u.l = nil;
|
||||||
|
|
||||||
|
loadmodule("/usr/local/plan9/acid/port");
|
||||||
|
for(i = 0; i < nlm; i++) {
|
||||||
|
if(access(lm[i], AREAD) >= 0)
|
||||||
|
loadmodule(lm[i]);
|
||||||
|
else {
|
||||||
|
sprint(buf, "/usr/local/plan9/acid/%s", lm[i]);
|
||||||
|
loadmodule(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userinit();
|
||||||
|
varsym();
|
||||||
|
|
||||||
|
l = look("acidmap");
|
||||||
|
if(l && l->proc) {
|
||||||
|
n = an(ONAME, ZN, ZN);
|
||||||
|
n->sym = l;
|
||||||
|
n = an(OCALL, n, ZN);
|
||||||
|
execute(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
interactive = 1;
|
||||||
|
initialising = 0;
|
||||||
|
line = 1;
|
||||||
|
|
||||||
|
notify(catcher);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
if(setjmp(err)) {
|
||||||
|
Binit(&bioout, 1, OWRITE);
|
||||||
|
unwind();
|
||||||
|
}
|
||||||
|
stacked = 0;
|
||||||
|
|
||||||
|
Bprint(bout, "acid; ");
|
||||||
|
|
||||||
|
if(yyparse() != 1)
|
||||||
|
die();
|
||||||
|
restartio();
|
||||||
|
|
||||||
|
unwind();
|
||||||
|
}
|
||||||
|
Bputc(bout, '\n');
|
||||||
|
exits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
attachfiles(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
int i, omode;
|
||||||
|
Fhdr *hdr;
|
||||||
|
Lsym *l;
|
||||||
|
Value *v;
|
||||||
|
|
||||||
|
interactive = 0;
|
||||||
|
if(setjmp(err))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unix and Plan 9 differ on what the right order of pid, text, and core is.
|
||||||
|
* I never remember anyway. Let's just accept them in any order.
|
||||||
|
*/
|
||||||
|
omode = wtflag ? ORDWR : OREAD;
|
||||||
|
for(i=0; i<argc; i++){
|
||||||
|
if(isnumeric(argv[i])){
|
||||||
|
if(pid){
|
||||||
|
fprint(2, "already have pid %d; ignoring pid %d\n", pid, argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(corhdr){
|
||||||
|
fprint(2, "already have core %s; ignoring pid %d\n", corfil, pid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pid = atoi(argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if((hdr = crackhdr(argv[i], omode)) == nil){
|
||||||
|
fprint(2, "crackhdr %s: %r\n", argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);
|
||||||
|
if(hdr->ftype == FCORE){
|
||||||
|
if(pid){
|
||||||
|
fprint(2, "already have pid %d; ignoring core %s\n", pid, argv[i]);
|
||||||
|
uncrackhdr(hdr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(corhdr){
|
||||||
|
fprint(2, "already have core %s; ignoring core %s\n", corfil, argv[i]);
|
||||||
|
uncrackhdr(hdr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
corhdr = hdr;
|
||||||
|
corfil = argv[i];
|
||||||
|
}else{
|
||||||
|
if(symhdr){
|
||||||
|
fprint(2, "already have text %s; ignoring text %s\n", symfil, argv[i]);
|
||||||
|
uncrackhdr(hdr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
symhdr = hdr;
|
||||||
|
symfil = argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(symhdr==nil){
|
||||||
|
symfil = "a.out";
|
||||||
|
if(pid){
|
||||||
|
if((s = proctextfile(pid)) != nil){
|
||||||
|
fprint(2, "pid %d: text %s\n", pid, s);
|
||||||
|
symfil = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* XXX pull command from core */
|
||||||
|
|
||||||
|
if((hdr = crackhdr(symfil, omode)) == nil){
|
||||||
|
fprint(2, "crackhdr %s: %r\n", symfil);
|
||||||
|
symfil = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(symhdr)
|
||||||
|
syminit(symhdr);
|
||||||
|
|
||||||
|
if(!mach)
|
||||||
|
mach = machcpu;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up maps.
|
||||||
|
*/
|
||||||
|
symmap = allocmap();
|
||||||
|
cormap = allocmap();
|
||||||
|
if(symmap == nil || cormap == nil)
|
||||||
|
sysfatal("allocating maps: %r");
|
||||||
|
|
||||||
|
if(symhdr){
|
||||||
|
if(mapfile(symhdr, 0, symmap, nil) < 0)
|
||||||
|
fprint(2, "mapping %s: %r\n", symfil);
|
||||||
|
mapfile(symhdr, 0, cormap, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
l = mkvar("objtype");
|
||||||
|
v = l->v;
|
||||||
|
v->store.fmt = 's';
|
||||||
|
v->set = 1;
|
||||||
|
v->store.u.string = strnode(mach->name);
|
||||||
|
v->type = TSTRING;
|
||||||
|
|
||||||
|
l = mkvar("textfile");
|
||||||
|
v = l->v;
|
||||||
|
v->store.fmt = 's';
|
||||||
|
v->set = 1;
|
||||||
|
v->store.u.string = strnode(symfil ? symfil : "");
|
||||||
|
v->type = TSTRING;
|
||||||
|
|
||||||
|
l = mkvar("systype");
|
||||||
|
v = l->v;
|
||||||
|
v->store.fmt = 's';
|
||||||
|
v->set = 1;
|
||||||
|
v->store.u.string = strnode(symhdr ? symhdr->aname : "");
|
||||||
|
v->type = TSTRING;
|
||||||
|
|
||||||
|
l = mkvar("corefile");
|
||||||
|
v = l->v;
|
||||||
|
v->store.fmt = 's';
|
||||||
|
v->set = 1;
|
||||||
|
v->store.u.string = strnode(corfil ? corfil : "");
|
||||||
|
v->type = TSTRING;
|
||||||
|
|
||||||
|
if(pid)
|
||||||
|
sproc(pid);
|
||||||
|
if(corhdr)
|
||||||
|
setcore(corhdr);
|
||||||
|
varreg();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setcore(Fhdr *hdr)
|
||||||
|
{
|
||||||
|
unmapproc(cormap);
|
||||||
|
unmapfile(corhdr, cormap);
|
||||||
|
free(correg);
|
||||||
|
correg = nil;
|
||||||
|
|
||||||
|
if(hdr == nil)
|
||||||
|
error("no core");
|
||||||
|
if(mapfile(hdr, 0, cormap, &correg) < 0)
|
||||||
|
error("mapfile %s: %r", hdr->filename);
|
||||||
|
corhdr = hdr;
|
||||||
|
corfil = hdr->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
die(void)
|
||||||
|
{
|
||||||
|
Lsym *s;
|
||||||
|
List *f;
|
||||||
|
|
||||||
|
Bprint(bout, "\n");
|
||||||
|
|
||||||
|
s = look("proclist");
|
||||||
|
if(s && s->v->type == TLIST) {
|
||||||
|
for(f = s->v->store.u.l; f; f = f->next){
|
||||||
|
detachproc((int)f->store.u.ival);
|
||||||
|
Bprint(bout, "/bin/kill -9 %d\n", (int)f->store.u.ival);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
userinit(void)
|
||||||
|
{
|
||||||
|
Lsym *l;
|
||||||
|
Node *n;
|
||||||
|
char buf[128], *p;
|
||||||
|
|
||||||
|
sprint(buf, "/usr/local/plan9/acid/%s", mach->name);
|
||||||
|
loadmodule(buf);
|
||||||
|
p = getenv("home");
|
||||||
|
if(p != 0) {
|
||||||
|
sprint(buf, "%s/lib/acid", p);
|
||||||
|
silent = 1;
|
||||||
|
loadmodule(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
interactive = 0;
|
||||||
|
if(setjmp(err)) {
|
||||||
|
unwind();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
l = look("acidinit");
|
||||||
|
if(l && l->proc) {
|
||||||
|
n = an(ONAME, ZN, ZN);
|
||||||
|
n->sym = l;
|
||||||
|
n = an(OCALL, n, ZN);
|
||||||
|
execute(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
loadmodule(char *s)
|
||||||
|
{
|
||||||
|
interactive = 0;
|
||||||
|
if(setjmp(err)) {
|
||||||
|
unwind();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pushfile(s);
|
||||||
|
silent = 0;
|
||||||
|
yyparse();
|
||||||
|
popio();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
an(int op, Node *l, Node *r)
|
||||||
|
{
|
||||||
|
Node *n;
|
||||||
|
|
||||||
|
n = gmalloc(sizeof(Node));
|
||||||
|
memset(n, 0, sizeof(Node));
|
||||||
|
n->gc.gclink = gcl;
|
||||||
|
gcl = (Gc*)n;
|
||||||
|
n->op = op;
|
||||||
|
n->left = l;
|
||||||
|
n->right = r;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
List*
|
||||||
|
al(int t)
|
||||||
|
{
|
||||||
|
List *l;
|
||||||
|
|
||||||
|
l = gmalloc(sizeof(List));
|
||||||
|
memset(l, 0, sizeof(List));
|
||||||
|
l->type = t;
|
||||||
|
l->gc.gclink = gcl;
|
||||||
|
gcl = (Gc*)l;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
con(int v)
|
||||||
|
{
|
||||||
|
Node *n;
|
||||||
|
|
||||||
|
n = an(OCONST, ZN, ZN);
|
||||||
|
n->store.u.ival = v;
|
||||||
|
n->store.fmt = 'X';
|
||||||
|
n->type = TINT;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fatal(char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
vseprint(buf, buf+sizeof(buf), fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
fprint(2, "%s: %Z (fatal problem) %s\n", argv0, buf);
|
||||||
|
exits(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
yyerror(char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
if(strcmp(fmt, "syntax error") == 0) {
|
||||||
|
yyerror("syntax error, near symbol '%s'", symbol);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
va_start(arg, fmt);
|
||||||
|
vseprint(buf, buf+sizeof(buf), fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
print("%Z: %s\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
marktree(Node *n)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(n == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
marktree(n->left);
|
||||||
|
marktree(n->right);
|
||||||
|
|
||||||
|
n->gc.gcmark = 1;
|
||||||
|
if(n->op != OCONST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(n->type) {
|
||||||
|
case TSTRING:
|
||||||
|
n->store.u.string->gc.gcmark = 1;
|
||||||
|
break;
|
||||||
|
case TLIST:
|
||||||
|
marklist(n->store.u.l);
|
||||||
|
break;
|
||||||
|
case TCODE:
|
||||||
|
marktree(n->store.u.cc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
marklist(List *l)
|
||||||
|
{
|
||||||
|
while(l) {
|
||||||
|
l->gc.gcmark = 1;
|
||||||
|
switch(l->type) {
|
||||||
|
case TSTRING:
|
||||||
|
l->store.u.string->gc.gcmark = 1;
|
||||||
|
break;
|
||||||
|
case TLIST:
|
||||||
|
marklist(l->store.u.l);
|
||||||
|
break;
|
||||||
|
case TCODE:
|
||||||
|
marktree(l->store.u.cc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gc(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Lsym *f;
|
||||||
|
Value *v;
|
||||||
|
Gc *m, **p, *next;
|
||||||
|
|
||||||
|
if(dogc < Mempergc)
|
||||||
|
return;
|
||||||
|
dogc = 0;
|
||||||
|
|
||||||
|
/* Mark */
|
||||||
|
for(m = gcl; m; m = m->gclink)
|
||||||
|
m->gcmark = 0;
|
||||||
|
|
||||||
|
/* Scan */
|
||||||
|
for(i = 0; i < Hashsize; i++) {
|
||||||
|
for(f = hash[i]; f; f = f->hash) {
|
||||||
|
marktree(f->proc);
|
||||||
|
if(f->lexval != Tid)
|
||||||
|
continue;
|
||||||
|
for(v = f->v; v; v = v->pop) {
|
||||||
|
switch(v->type) {
|
||||||
|
case TSTRING:
|
||||||
|
v->store.u.string->gc.gcmark = 1;
|
||||||
|
break;
|
||||||
|
case TLIST:
|
||||||
|
marklist(v->store.u.l);
|
||||||
|
break;
|
||||||
|
case TCODE:
|
||||||
|
marktree(v->store.u.cc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free */
|
||||||
|
p = &gcl;
|
||||||
|
for(m = gcl; m; m = next) {
|
||||||
|
next = m->gclink;
|
||||||
|
if(m->gcmark == 0) {
|
||||||
|
*p = next;
|
||||||
|
free(m); /* Sleazy reliance on my malloc */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p = &m->gclink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
gmalloc(long l)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
dogc += l;
|
||||||
|
p = malloc(l);
|
||||||
|
if(p == 0)
|
||||||
|
fatal("out of memory");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
checkqid(int f1, int pid)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
Dir *d1, *d2;
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
if(kernel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d1 = dirfstat(f1);
|
||||||
|
if(d1 == nil){
|
||||||
|
print("checkqid: (qid not checked) dirfstat: %r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprint(buf, "/proc/%d/text", pid);
|
||||||
|
fd = open(buf, OREAD);
|
||||||
|
if(fd < 0 || (d2 = dirfstat(fd)) == nil){
|
||||||
|
print("checkqid: (qid not checked) dirstat %s: %r\n", buf);
|
||||||
|
free(d1);
|
||||||
|
if(fd >= 0)
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if(d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers || d1->qid.type != d2->qid.type){
|
||||||
|
print("path %llux %llux vers %lud %lud type %d %d\n",
|
||||||
|
d1->qid.path, d2->qid.path, d1->qid.vers, d2->qid.vers, d1->qid.type, d2->qid.type);
|
||||||
|
print("warning: image does not match text for pid %d\n", pid);
|
||||||
|
}
|
||||||
|
free(d1);
|
||||||
|
free(d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
catcher(void *junk, char *s)
|
||||||
|
{
|
||||||
|
USED(junk);
|
||||||
|
|
||||||
|
if(strstr(s, "interrupt")) {
|
||||||
|
gotint = 1;
|
||||||
|
noted(NCONT);
|
||||||
|
}
|
||||||
|
if(strstr(s, "child"))
|
||||||
|
noted(NCONT);
|
||||||
|
fprint(2, "note: %s\n", s);
|
||||||
|
noted(NDFLT);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
system(void)
|
||||||
|
{
|
||||||
|
char *cpu, *p, *q;
|
||||||
|
static char kernel[128];
|
||||||
|
|
||||||
|
cpu = getenv("cputype");
|
||||||
|
if(cpu == 0) {
|
||||||
|
cpu = "mips";
|
||||||
|
print("$cputype not set; assuming %s\n", cpu);
|
||||||
|
}
|
||||||
|
p = getenv("terminal");
|
||||||
|
if(p == 0 || (p=strchr(p, ' ')) == 0 || p[1] == ' ' || p[1] == 0) {
|
||||||
|
p = "9power";
|
||||||
|
print("missing or bad $terminal; assuming %s\n", p);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
p++;
|
||||||
|
q = strchr(p, ' ');
|
||||||
|
if(q)
|
||||||
|
*q = 0;
|
||||||
|
sprint(kernel, "/%s/9%s", cpu, p);
|
||||||
|
}
|
||||||
|
return kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
isnumeric(char *s)
|
||||||
|
{
|
||||||
|
while(*s) {
|
||||||
|
if(*s < '0' || *s > '9')
|
||||||
|
return 0;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xfmt(Fmt *f)
|
||||||
|
{
|
||||||
|
f->flags ^= FmtSharp;
|
||||||
|
return __ifmt(f);
|
||||||
|
}
|
||||||
32
src/cmd/acid/mkfile
Normal file
32
src/cmd/acid/mkfile
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<$PLAN9/src/mkhdr
|
||||||
|
|
||||||
|
TARG=acid
|
||||||
|
UOFILES=\
|
||||||
|
main.$O\
|
||||||
|
lex.$O\
|
||||||
|
util.$O\
|
||||||
|
exec.$O\
|
||||||
|
expr.$O\
|
||||||
|
list.$O\
|
||||||
|
builtin.$O\
|
||||||
|
proc.$O\
|
||||||
|
dot.$O\
|
||||||
|
print.$O\
|
||||||
|
|
||||||
|
OFILES=$UOFILES y.tab.$O
|
||||||
|
|
||||||
|
YFILES=dbg.y
|
||||||
|
HFILES=acid.h
|
||||||
|
|
||||||
|
BIN=/home/rsc/bin
|
||||||
|
|
||||||
|
SHORTLIB=mach2 regexp9 bio 9
|
||||||
|
|
||||||
|
<$PLAN9/src/mkone
|
||||||
|
|
||||||
|
CFLAGS=$CFLAGS -I../libmach2
|
||||||
|
|
||||||
|
lex.$O: y.tab.h
|
||||||
|
util.$O: y.tab.h
|
||||||
|
builtin.$O: y.tab.h
|
||||||
|
main.$O: y.tab.h
|
||||||
446
src/cmd/acid/print.c
Normal file
446
src/cmd/acid/print.c
Normal file
|
|
@ -0,0 +1,446 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern extern
|
||||||
|
#include "acid.h"
|
||||||
|
|
||||||
|
static char *binop[] =
|
||||||
|
{
|
||||||
|
[OMUL] "*",
|
||||||
|
[ODIV] "/",
|
||||||
|
[OMOD] "%",
|
||||||
|
[OADD] "+",
|
||||||
|
[OSUB] "-",
|
||||||
|
[ORSH] ">>",
|
||||||
|
[OLSH] "<<",
|
||||||
|
[OLT] "<",
|
||||||
|
[OGT] ">",
|
||||||
|
[OLEQ] "<=",
|
||||||
|
[OGEQ] ">=",
|
||||||
|
[OEQ] "==",
|
||||||
|
[ONEQ] "!=",
|
||||||
|
[OLAND] "&",
|
||||||
|
[OXOR] "^",
|
||||||
|
[OLOR] "|",
|
||||||
|
[OCAND] "&&",
|
||||||
|
[OCOR] "||",
|
||||||
|
[OASGN] " = ",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
|
||||||
|
char *typenames[] =
|
||||||
|
{
|
||||||
|
[TINT] "integer",
|
||||||
|
[TFLOAT] "float",
|
||||||
|
[TSTRING] "string",
|
||||||
|
[TLIST] "list",
|
||||||
|
[TCODE] "code",
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
cmp(const void *va, const void *vb)
|
||||||
|
{
|
||||||
|
char **a = (char**)va;
|
||||||
|
char **b = (char**)vb;
|
||||||
|
|
||||||
|
return strcmp(*a, *b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fundefs(void)
|
||||||
|
{
|
||||||
|
Lsym *l;
|
||||||
|
char **vec;
|
||||||
|
int i, j, n, max, col, f, g, s;
|
||||||
|
|
||||||
|
max = 0;
|
||||||
|
f = 0;
|
||||||
|
g = 100;
|
||||||
|
vec = malloc(sizeof(char*)*g);
|
||||||
|
if(vec == 0)
|
||||||
|
fatal("out of memory");
|
||||||
|
|
||||||
|
for(i = 0; i < Hashsize; i++) {
|
||||||
|
for(l = hash[i]; l; l = l->hash) {
|
||||||
|
if(l->proc == 0 && l->builtin == 0)
|
||||||
|
continue;
|
||||||
|
n = strlen(l->name);
|
||||||
|
if(n > max)
|
||||||
|
max = n;
|
||||||
|
if(f >= g) {
|
||||||
|
g *= 2;
|
||||||
|
vec = realloc(vec, sizeof(char*)*g);
|
||||||
|
if(vec == 0)
|
||||||
|
fatal("out of memory");
|
||||||
|
}
|
||||||
|
vec[f++] = l->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qsort(vec, f, sizeof(char*), cmp);
|
||||||
|
max++;
|
||||||
|
col = 60/max;
|
||||||
|
s = (f+col-1)/col;
|
||||||
|
|
||||||
|
for(i = 0; i < s; i++) {
|
||||||
|
for(j = i; j < f; j += s)
|
||||||
|
Bprint(bout, "%-*s", max, vec[j]);
|
||||||
|
Bprint(bout, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
whatis(Lsym *l)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
int def;
|
||||||
|
Type *ti;
|
||||||
|
|
||||||
|
if(l == 0) {
|
||||||
|
fundefs();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
def = 0;
|
||||||
|
if(l->v->set) {
|
||||||
|
t = l->v->type;
|
||||||
|
Bprint(bout, "%s variable", typenames[t]);
|
||||||
|
if(t == TINT || t == TFLOAT)
|
||||||
|
Bprint(bout, " format %c", l->v->store.fmt);
|
||||||
|
if(l->v->store.comt)
|
||||||
|
Bprint(bout, " complex %s",
|
||||||
|
l->v->store.comt->base->name);
|
||||||
|
Bputc(bout, '\n');
|
||||||
|
def = 1;
|
||||||
|
}
|
||||||
|
if(l->lt) {
|
||||||
|
Bprint(bout, "complex %s {\n", l->name);
|
||||||
|
for(ti = l->lt; ti; ti = ti->next) {
|
||||||
|
if(ti->type) {
|
||||||
|
if(ti->fmt == 'a') {
|
||||||
|
Bprint(bout, "\t%s %d %s;\n",
|
||||||
|
ti->type->name, ti->offset,
|
||||||
|
ti->tag->name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Bprint(bout, "\t'%c' %s %d %s;\n",
|
||||||
|
ti->fmt, ti->type->name, ti->offset,
|
||||||
|
ti->tag->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Bprint(bout, "\t'%c' %d %s;\n",
|
||||||
|
ti->fmt, ti->offset, ti->tag->name);
|
||||||
|
}
|
||||||
|
Bprint(bout, "};\n");
|
||||||
|
def = 1;
|
||||||
|
}
|
||||||
|
if(l->proc) {
|
||||||
|
Bprint(bout, "defn %s(", l->name);
|
||||||
|
pexpr(l->proc->left);
|
||||||
|
Bprint(bout, ") {\n");
|
||||||
|
pcode(l->proc->right, 1);
|
||||||
|
Bprint(bout, "}\n");
|
||||||
|
def = 1;
|
||||||
|
}
|
||||||
|
if(l->builtin) {
|
||||||
|
Bprint(bout, "builtin function\n");
|
||||||
|
def = 1;
|
||||||
|
}
|
||||||
|
if(def == 0)
|
||||||
|
Bprint(bout, "%s is undefined\n", l->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
slist(Node *n, int d)
|
||||||
|
{
|
||||||
|
if(n == 0)
|
||||||
|
return;
|
||||||
|
if(n->op == OLIST)
|
||||||
|
Bprint(bout, "%.*s{\n", d-1, tabs);
|
||||||
|
pcode(n, d);
|
||||||
|
if(n->op == OLIST)
|
||||||
|
Bprint(bout, "%.*s}\n", d-1, tabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pcode(Node *n, int d)
|
||||||
|
{
|
||||||
|
Node *r, *l;
|
||||||
|
|
||||||
|
if(n == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
r = n->right;
|
||||||
|
l = n->left;
|
||||||
|
|
||||||
|
switch(n->op) {
|
||||||
|
default:
|
||||||
|
Bprint(bout, "%.*s", d, tabs);
|
||||||
|
pexpr(n);
|
||||||
|
Bprint(bout, ";\n");
|
||||||
|
break;
|
||||||
|
case OLIST:
|
||||||
|
pcode(n->left, d);
|
||||||
|
pcode(n->right, d);
|
||||||
|
break;
|
||||||
|
case OLOCAL:
|
||||||
|
Bprint(bout, "%.*slocal", d, tabs);
|
||||||
|
while(l) {
|
||||||
|
Bprint(bout, " %s", l->sym->name);
|
||||||
|
l = l->left;
|
||||||
|
if(l == 0)
|
||||||
|
Bprint(bout, ";\n");
|
||||||
|
else
|
||||||
|
Bprint(bout, ",");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OCOMPLEX:
|
||||||
|
Bprint(bout, "%.*scomplex %s %s;\n", d, tabs, n->sym->name, l->sym->name);
|
||||||
|
break;
|
||||||
|
case OIF:
|
||||||
|
Bprint(bout, "%.*sif ", d, tabs);
|
||||||
|
pexpr(l);
|
||||||
|
d++;
|
||||||
|
Bprint(bout, " then\n");
|
||||||
|
if(r && r->op == OELSE) {
|
||||||
|
slist(r->left, d);
|
||||||
|
Bprint(bout, "%.*selse\n", d-1, tabs);
|
||||||
|
slist(r->right, d);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
slist(r, d);
|
||||||
|
break;
|
||||||
|
case OWHILE:
|
||||||
|
Bprint(bout, "%.*swhile ", d, tabs);
|
||||||
|
pexpr(l);
|
||||||
|
d++;
|
||||||
|
Bprint(bout, " do\n");
|
||||||
|
slist(r, d);
|
||||||
|
break;
|
||||||
|
case ORET:
|
||||||
|
Bprint(bout, "%.*sreturn ", d, tabs);
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, ";\n");
|
||||||
|
break;
|
||||||
|
case ODO:
|
||||||
|
Bprint(bout, "%.*sloop ", d, tabs);
|
||||||
|
pexpr(l->left);
|
||||||
|
Bprint(bout, ", ");
|
||||||
|
pexpr(l->right);
|
||||||
|
Bprint(bout, " do\n");
|
||||||
|
slist(r, d+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pexpr(Node *n)
|
||||||
|
{
|
||||||
|
Node *r, *l;
|
||||||
|
|
||||||
|
if(n == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
r = n->right;
|
||||||
|
l = n->left;
|
||||||
|
|
||||||
|
switch(n->op) {
|
||||||
|
case ONAME:
|
||||||
|
Bprint(bout, "%s", n->sym->name);
|
||||||
|
break;
|
||||||
|
case OCONST:
|
||||||
|
switch(n->type) {
|
||||||
|
case TINT:
|
||||||
|
Bprint(bout, "%d", (int)n->store.u.ival);
|
||||||
|
break;
|
||||||
|
case TFLOAT:
|
||||||
|
Bprint(bout, "%g", n->store.u.fval);
|
||||||
|
break;
|
||||||
|
case TSTRING:
|
||||||
|
pstr(n->store.u.string);
|
||||||
|
break;
|
||||||
|
case TLIST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OMUL:
|
||||||
|
case ODIV:
|
||||||
|
case OMOD:
|
||||||
|
case OADD:
|
||||||
|
case OSUB:
|
||||||
|
case ORSH:
|
||||||
|
case OLSH:
|
||||||
|
case OLT:
|
||||||
|
case OGT:
|
||||||
|
case OLEQ:
|
||||||
|
case OGEQ:
|
||||||
|
case OEQ:
|
||||||
|
case ONEQ:
|
||||||
|
case OLAND:
|
||||||
|
case OXOR:
|
||||||
|
case OLOR:
|
||||||
|
case OCAND:
|
||||||
|
case OCOR:
|
||||||
|
Bputc(bout, '(');
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, binop[(uchar)n->op]);
|
||||||
|
pexpr(r);
|
||||||
|
Bputc(bout, ')');
|
||||||
|
break;
|
||||||
|
case OASGN:
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, binop[(uchar)n->op]);
|
||||||
|
pexpr(r);
|
||||||
|
break;
|
||||||
|
case OINDM:
|
||||||
|
Bprint(bout, "*");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OEDEC:
|
||||||
|
Bprint(bout, "--");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OEINC:
|
||||||
|
Bprint(bout, "++");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OPINC:
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, "++");
|
||||||
|
break;
|
||||||
|
case OPDEC:
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, "--");
|
||||||
|
break;
|
||||||
|
case ONOT:
|
||||||
|
Bprint(bout, "!");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OLIST:
|
||||||
|
pexpr(l);
|
||||||
|
if(r) {
|
||||||
|
Bprint(bout, ",");
|
||||||
|
pexpr(r);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OCALL:
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, "(");
|
||||||
|
pexpr(r);
|
||||||
|
Bprint(bout, ")");
|
||||||
|
break;
|
||||||
|
case OCTRUCT:
|
||||||
|
Bprint(bout, "{");
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, "}");
|
||||||
|
break;
|
||||||
|
case OHEAD:
|
||||||
|
Bprint(bout, "head ");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OTAIL:
|
||||||
|
Bprint(bout, "tail ");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OAPPEND:
|
||||||
|
Bprint(bout, "append ");
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, ",");
|
||||||
|
pexpr(r);
|
||||||
|
break;
|
||||||
|
case ODELETE:
|
||||||
|
Bprint(bout, "delete ");
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, ",");
|
||||||
|
pexpr(r);
|
||||||
|
break;
|
||||||
|
case ORET:
|
||||||
|
Bprint(bout, "return ");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OINDEX:
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, "[");
|
||||||
|
pexpr(r);
|
||||||
|
Bprint(bout, "]");
|
||||||
|
break;
|
||||||
|
case OINDC:
|
||||||
|
Bprint(bout, "@");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case ODOT:
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, ".%s", n->sym->name);
|
||||||
|
break;
|
||||||
|
case OFRAME:
|
||||||
|
Bprint(bout, "%s:%s", n->sym->name, l->sym->name);
|
||||||
|
break;
|
||||||
|
case OCAST:
|
||||||
|
Bprint(bout, "(%s)", n->sym->name);
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OFMT:
|
||||||
|
pexpr(l);
|
||||||
|
Bprint(bout, "\\%c", (int)r->store.u.ival);
|
||||||
|
break;
|
||||||
|
case OEVAL:
|
||||||
|
Bprint(bout, "eval ");
|
||||||
|
pexpr(l);
|
||||||
|
break;
|
||||||
|
case OWHAT:
|
||||||
|
Bprint(bout, "whatis");
|
||||||
|
if(n->sym)
|
||||||
|
Bprint(bout, " %s", n->sym->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pstr(String *s)
|
||||||
|
{
|
||||||
|
int i, c;
|
||||||
|
|
||||||
|
Bputc(bout, '"');
|
||||||
|
for(i = 0; i < s->len; i++) {
|
||||||
|
c = s->string[i];
|
||||||
|
switch(c) {
|
||||||
|
case '\0':
|
||||||
|
c = '0';
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
c = 'n';
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
c = 'r';
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
c = 't';
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
c = 'b';
|
||||||
|
break;
|
||||||
|
case '\f':
|
||||||
|
c = 'f';
|
||||||
|
break;
|
||||||
|
case '\a':
|
||||||
|
c = 'a';
|
||||||
|
break;
|
||||||
|
case '\v':
|
||||||
|
c = 'v';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
c = '\\';
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
c = '"';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Bputc(bout, c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Bputc(bout, '\\');
|
||||||
|
Bputc(bout, c);
|
||||||
|
}
|
||||||
|
Bputc(bout, '"');
|
||||||
|
}
|
||||||
251
src/cmd/acid/proc.c
Normal file
251
src/cmd/acid/proc.c
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern extern
|
||||||
|
#include "acid.h"
|
||||||
|
#include "y.tab.h"
|
||||||
|
|
||||||
|
static void install(int);
|
||||||
|
|
||||||
|
void
|
||||||
|
sproc(int xpid)
|
||||||
|
{
|
||||||
|
Lsym *s;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(symmap == 0)
|
||||||
|
error("no map");
|
||||||
|
|
||||||
|
if(pid == xpid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(xpid <= 0)
|
||||||
|
error("bad pid");
|
||||||
|
|
||||||
|
unmapproc(cormap);
|
||||||
|
unmapfile(corhdr, cormap);
|
||||||
|
free(correg);
|
||||||
|
correg = nil;
|
||||||
|
|
||||||
|
if(mapproc(xpid, cormap, &correg) < 0)
|
||||||
|
error("setproc %d: %r", pid);
|
||||||
|
|
||||||
|
/* XXX check text file here? */
|
||||||
|
|
||||||
|
pid = xpid;
|
||||||
|
s = look("pid");
|
||||||
|
s->v->store.u.ival = pid;
|
||||||
|
|
||||||
|
for(i=0; i<cormap->nseg; i++)
|
||||||
|
if(cormap->seg[i].file == nil){
|
||||||
|
if(strcmp(cormap->seg[i].name, "data") == 0)
|
||||||
|
cormap->seg[i].name = "*data";
|
||||||
|
if(strcmp(cormap->seg[i].name, "text") == 0)
|
||||||
|
cormap->seg[i].name = "*text";
|
||||||
|
}
|
||||||
|
install(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nproc(char **argv)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
int pid, i, fd;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
switch(pid) {
|
||||||
|
case -1:
|
||||||
|
error("new: fork %r");
|
||||||
|
case 0:
|
||||||
|
rfork(RFNAMEG|RFNOTEG);
|
||||||
|
if(ctlproc(getpid(), "hang") < 0)
|
||||||
|
fatal("new: hang %d: %r", getpid());
|
||||||
|
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
for(i = 3; i < NFD; i++)
|
||||||
|
close(i);
|
||||||
|
|
||||||
|
open("/dev/tty", OREAD);
|
||||||
|
open("/dev/tty", OWRITE);
|
||||||
|
open("/dev/tty", OWRITE);
|
||||||
|
exec(argv[0], argv);
|
||||||
|
fatal("new: exec %s: %r");
|
||||||
|
default:
|
||||||
|
install(pid);
|
||||||
|
msg(pid, "waitstop");
|
||||||
|
notes(pid);
|
||||||
|
sproc(pid);
|
||||||
|
dostop(pid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
notes(int pid)
|
||||||
|
{
|
||||||
|
Lsym *s;
|
||||||
|
Value *v;
|
||||||
|
int i, n;
|
||||||
|
char **notes;
|
||||||
|
List *l, **tail;
|
||||||
|
|
||||||
|
s = look("notes");
|
||||||
|
if(s == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
v = s->v;
|
||||||
|
n = procnotes(pid, ¬es);
|
||||||
|
if(n < 0)
|
||||||
|
error("procnotes pid=%d: %r", pid);
|
||||||
|
|
||||||
|
v->set = 1;
|
||||||
|
v->type = TLIST;
|
||||||
|
v->store.u.l = 0;
|
||||||
|
tail = &v->store.u.l;
|
||||||
|
for(i=0; i<n; i++) {
|
||||||
|
l = al(TSTRING);
|
||||||
|
l->store.u.string = strnode(notes[i]);
|
||||||
|
l->store.fmt = 's';
|
||||||
|
*tail = l;
|
||||||
|
tail = &l->next;
|
||||||
|
}
|
||||||
|
free(notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dostop(int pid)
|
||||||
|
{
|
||||||
|
Lsym *s;
|
||||||
|
Node *np, *p;
|
||||||
|
|
||||||
|
s = look("stopped");
|
||||||
|
if(s && s->proc) {
|
||||||
|
np = an(ONAME, ZN, ZN);
|
||||||
|
np->sym = s;
|
||||||
|
np->store.fmt = 'D';
|
||||||
|
np->type = TINT;
|
||||||
|
p = con(pid);
|
||||||
|
p->store.fmt = 'D';
|
||||||
|
np = an(OCALL, np, p);
|
||||||
|
execute(np);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
install(int pid)
|
||||||
|
{
|
||||||
|
Lsym *s;
|
||||||
|
List *l;
|
||||||
|
int i, new, p;
|
||||||
|
|
||||||
|
new = -1;
|
||||||
|
for(i = 0; i < Maxproc; i++) {
|
||||||
|
p = ptab[i].pid;
|
||||||
|
if(p == pid)
|
||||||
|
return;
|
||||||
|
if(p == 0 && new == -1)
|
||||||
|
new = i;
|
||||||
|
}
|
||||||
|
if(new == -1)
|
||||||
|
error("no free process slots");
|
||||||
|
|
||||||
|
ptab[new].pid = pid;
|
||||||
|
|
||||||
|
s = look("proclist");
|
||||||
|
l = al(TINT);
|
||||||
|
l->store.fmt = 'D';
|
||||||
|
l->store.u.ival = pid;
|
||||||
|
l->next = s->v->store.u.l;
|
||||||
|
s->v->store.u.l = l;
|
||||||
|
s->v->set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
deinstall(int pid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Lsym *s;
|
||||||
|
List *f, **d;
|
||||||
|
|
||||||
|
for(i = 0; i < Maxproc; i++) {
|
||||||
|
if(ptab[i].pid == pid) {
|
||||||
|
detachproc(pid);
|
||||||
|
// close(ptab[i].ctl);
|
||||||
|
ptab[i].pid = 0;
|
||||||
|
s = look("proclist");
|
||||||
|
d = &s->v->store.u.l;
|
||||||
|
for(f = *d; f; f = f->next) {
|
||||||
|
if(f->store.u.ival == pid) {
|
||||||
|
*d = f->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s = look("pid");
|
||||||
|
if(s->v->store.u.ival == pid)
|
||||||
|
s->v->store.u.ival = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
msg(int pid, char *msg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char err[ERRMAX];
|
||||||
|
|
||||||
|
for(i = 0; i < Maxproc; i++) {
|
||||||
|
if(ptab[i].pid == pid) {
|
||||||
|
if(ctlproc(pid, msg) < 0){
|
||||||
|
errstr(err, sizeof err);
|
||||||
|
if(strcmp(err, "process exited") == 0)
|
||||||
|
deinstall(pid);
|
||||||
|
error("msg: pid=%d %s: %s", pid, msg, err);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("msg: pid=%d: not found for %s", pid, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
getstatus(int pid)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
static char buf[128];
|
||||||
|
|
||||||
|
sprint(buf, "/proc/%d/status", pid);
|
||||||
|
fd = open(buf, OREAD);
|
||||||
|
if(fd < 0)
|
||||||
|
error("open %s: %r", buf);
|
||||||
|
read(fd, buf, sizeof(buf));
|
||||||
|
close(fd);
|
||||||
|
p = buf+56+12; /* Do better! */
|
||||||
|
while(*p == ' ')
|
||||||
|
p--;
|
||||||
|
p[1] = '\0';
|
||||||
|
return buf+56; /* ditto */
|
||||||
|
}
|
||||||
|
|
||||||
|
Waitmsg*
|
||||||
|
waitfor(int pid)
|
||||||
|
{
|
||||||
|
Waitmsg *w;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
if((w = wait()) == nil)
|
||||||
|
error("wait %r");
|
||||||
|
if(w->pid == pid)
|
||||||
|
return w;
|
||||||
|
free(w);
|
||||||
|
}
|
||||||
|
return nil; /* ken */
|
||||||
|
}
|
||||||
344
src/cmd/acid/util.c
Normal file
344
src/cmd/acid/util.c
Normal file
|
|
@ -0,0 +1,344 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mach.h>
|
||||||
|
#define Extern extern
|
||||||
|
#include "acid.h"
|
||||||
|
#include "y.tab.h"
|
||||||
|
|
||||||
|
static int syren;
|
||||||
|
|
||||||
|
Lsym*
|
||||||
|
unique(char *buf, Symbol *s)
|
||||||
|
{
|
||||||
|
Lsym *l;
|
||||||
|
int i, renamed;
|
||||||
|
|
||||||
|
renamed = 0;
|
||||||
|
strcpy(buf, s->name);
|
||||||
|
for(;;) {
|
||||||
|
l = look(buf);
|
||||||
|
if(l == 0 || (l->lexval == Tid && l->v->set == 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(syren == 0 && !quiet) {
|
||||||
|
print("Symbol renames:\n");
|
||||||
|
syren = 1;
|
||||||
|
}
|
||||||
|
i = strlen(buf)+1;
|
||||||
|
memmove(buf+1, buf, i);
|
||||||
|
buf[0] = '$';
|
||||||
|
renamed++;
|
||||||
|
if(renamed > 5 && !quiet) {
|
||||||
|
print("Too many renames; must be X source!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(renamed && !quiet)
|
||||||
|
print("\t%s=%s %c/%Z\n", s->name, buf, s->type, s->loc);
|
||||||
|
if(l == 0)
|
||||||
|
l = enter(buf, Tid);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
varsym(void)
|
||||||
|
{
|
||||||
|
Lsym *l;
|
||||||
|
Fhdr *fp;
|
||||||
|
|
||||||
|
l = mkvar("symbols");
|
||||||
|
if(l->v->set)
|
||||||
|
return;
|
||||||
|
|
||||||
|
l->v->set = 1;
|
||||||
|
l->v->type = TLIST;
|
||||||
|
l->v->store.u.l = nil;
|
||||||
|
|
||||||
|
for(fp=fhdrlist; fp; fp=fp->next){
|
||||||
|
if(fp->ftype == FCORE)
|
||||||
|
continue;
|
||||||
|
addvarsym(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l->v->store.u.l == nil)
|
||||||
|
print("no debugging symbols\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
addvarsym(Fhdr *fp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Symbol s;
|
||||||
|
Lsym *l;
|
||||||
|
String *file;
|
||||||
|
ulong v;
|
||||||
|
char buf[1024];
|
||||||
|
List *list, **tail, *tl;
|
||||||
|
|
||||||
|
if(fp == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
l = look("symbols");
|
||||||
|
if(l == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
l->v->set = 1;
|
||||||
|
l->v->type = TLIST;
|
||||||
|
tail = &l->v->store.u.l;
|
||||||
|
while(*tail)
|
||||||
|
tail = &(*tail)->next;
|
||||||
|
|
||||||
|
file = strnode(fp->filename);
|
||||||
|
for(i=0; findexsym(fp, i, &s)>=0; i++){
|
||||||
|
switch(s.type) {
|
||||||
|
case 'T':
|
||||||
|
case 'L':
|
||||||
|
case 'D':
|
||||||
|
case 'B':
|
||||||
|
case 'b':
|
||||||
|
case 'd':
|
||||||
|
case 'l':
|
||||||
|
case 't':
|
||||||
|
if(s.name[0] == '.')
|
||||||
|
continue;
|
||||||
|
if(s.loc.type != LADDR)
|
||||||
|
continue;
|
||||||
|
v = s.loc.addr;
|
||||||
|
tl = al(TLIST);
|
||||||
|
*tail = tl;
|
||||||
|
tail = &tl->next;
|
||||||
|
|
||||||
|
l = unique(buf, &s);
|
||||||
|
l->v->set = 1;
|
||||||
|
l->v->type = TINT;
|
||||||
|
l->v->store.u.ival = v;
|
||||||
|
if(l->v->store.comt == 0)
|
||||||
|
l->v->store.fmt = 'X';
|
||||||
|
|
||||||
|
/* Enter as list of { name, type, value, file } */
|
||||||
|
list = al(TSTRING);
|
||||||
|
tl->store.u.l = list;
|
||||||
|
list->store.u.string = strnode(buf);
|
||||||
|
list->store.fmt = 's';
|
||||||
|
list->next = al(TINT);
|
||||||
|
list = list->next;
|
||||||
|
list->store.fmt = 'c';
|
||||||
|
list->store.u.ival = s.type;
|
||||||
|
list->next = al(TINT);
|
||||||
|
list = list->next;
|
||||||
|
list->store.fmt = 'X';
|
||||||
|
list->store.u.ival = v;
|
||||||
|
list->next = al(TSTRING);
|
||||||
|
list = list->next;
|
||||||
|
list->store.fmt = 's';
|
||||||
|
list->store.u.string = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*tail = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
infile(List *list, char *file, char **name)
|
||||||
|
{
|
||||||
|
/* name */
|
||||||
|
if(list->type != TSTRING)
|
||||||
|
return 0;
|
||||||
|
*name = list->store.u.string->string;
|
||||||
|
if(list->next == nil)
|
||||||
|
return 0;
|
||||||
|
list = list->next;
|
||||||
|
|
||||||
|
/* type character */
|
||||||
|
if(list->next == nil)
|
||||||
|
return 0;
|
||||||
|
list = list->next;
|
||||||
|
|
||||||
|
/* address */
|
||||||
|
if(list->next == nil)
|
||||||
|
return 0;
|
||||||
|
list = list->next;
|
||||||
|
|
||||||
|
/* file */
|
||||||
|
if(list->type != TSTRING)
|
||||||
|
return 0;
|
||||||
|
return strcmp(list->store.u.string->string, file) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
delvarsym(char *file)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
Lsym *l;
|
||||||
|
List **lp, *p;
|
||||||
|
|
||||||
|
l = look("symbols");
|
||||||
|
if(l == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(l->v->type != TLIST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(lp=&l->v->store.u.l; *lp; lp=&(*lp)->next){
|
||||||
|
while(*lp){
|
||||||
|
p = *lp;
|
||||||
|
if(p->type != TLIST)
|
||||||
|
break;
|
||||||
|
if(!infile(p->store.u.l, file, &name))
|
||||||
|
break;
|
||||||
|
*lp = p->next;
|
||||||
|
/* XXX remove from hash tables */
|
||||||
|
}
|
||||||
|
if(*lp == nil)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
varreg(void)
|
||||||
|
{
|
||||||
|
Lsym *l;
|
||||||
|
Value *v;
|
||||||
|
Regdesc *r;
|
||||||
|
List **tail, *li;
|
||||||
|
|
||||||
|
l = mkvar("registers");
|
||||||
|
v = l->v;
|
||||||
|
v->set = 1;
|
||||||
|
v->type = TLIST;
|
||||||
|
v->store.u.l = 0;
|
||||||
|
tail = &v->store.u.l;
|
||||||
|
|
||||||
|
if(mach == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(r = mach->reglist; r->name; r++) {
|
||||||
|
l = mkvar(r->name);
|
||||||
|
v = l->v;
|
||||||
|
v->set = 1;
|
||||||
|
v->store.u.ival = r->offset;
|
||||||
|
v->store.fmt = r->format;
|
||||||
|
v->type = TINT;
|
||||||
|
|
||||||
|
li = al(TSTRING);
|
||||||
|
li->store.u.string = strnode(r->name);
|
||||||
|
li->store.fmt = 's';
|
||||||
|
*tail = li;
|
||||||
|
tail = &li->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = mkvar("bpinst"); /* Breakpoint text */
|
||||||
|
v = l->v;
|
||||||
|
v->type = TSTRING;
|
||||||
|
v->store.fmt = 's';
|
||||||
|
v->set = 1;
|
||||||
|
v->store.u.string = gmalloc(sizeof(String));
|
||||||
|
v->store.u.string->len = mach->bpsize;
|
||||||
|
v->store.u.string->string = gmalloc(mach->bpsize);
|
||||||
|
memmove(v->store.u.string->string, mach->bpinst, mach->bpsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
loadvars(void)
|
||||||
|
{
|
||||||
|
Lsym *l;
|
||||||
|
Value *v;
|
||||||
|
|
||||||
|
l = mkvar("proc");
|
||||||
|
v = l->v;
|
||||||
|
v->type = TINT;
|
||||||
|
v->store.fmt = 'X';
|
||||||
|
v->set = 1;
|
||||||
|
v->store.u.ival = 0;
|
||||||
|
|
||||||
|
l = mkvar("pid"); /* Current process */
|
||||||
|
v = l->v;
|
||||||
|
v->type = TINT;
|
||||||
|
v->store.fmt = 'D';
|
||||||
|
v->set = 1;
|
||||||
|
v->store.u.ival = 0;
|
||||||
|
|
||||||
|
mkvar("notes"); /* Pending notes */
|
||||||
|
|
||||||
|
l = mkvar("proclist"); /* Attached processes */
|
||||||
|
l->v->type = TLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
String*
|
||||||
|
strnodlen(char *name, int len)
|
||||||
|
{
|
||||||
|
String *s;
|
||||||
|
|
||||||
|
s = gmalloc(sizeof(String)+len+1);
|
||||||
|
s->string = (char*)s+sizeof(String);
|
||||||
|
s->len = len;
|
||||||
|
if(name != 0)
|
||||||
|
memmove(s->string, name, len);
|
||||||
|
s->string[len] = '\0';
|
||||||
|
|
||||||
|
s->gc.gclink = gcl;
|
||||||
|
gcl = (Gc*)s;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
String*
|
||||||
|
strnode(char *name)
|
||||||
|
{
|
||||||
|
return strnodlen(name, strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
String*
|
||||||
|
runenode(Rune *name)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
Rune *p;
|
||||||
|
String *s;
|
||||||
|
|
||||||
|
p = name;
|
||||||
|
for(len = 0; *p; p++)
|
||||||
|
len++;
|
||||||
|
|
||||||
|
len++;
|
||||||
|
len *= sizeof(Rune);
|
||||||
|
s = gmalloc(sizeof(String)+len);
|
||||||
|
s->string = (char*)s+sizeof(String);
|
||||||
|
s->len = len;
|
||||||
|
memmove(s->string, name, len);
|
||||||
|
|
||||||
|
s->gc.gclink = gcl;
|
||||||
|
gcl = (Gc*)s;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
String*
|
||||||
|
stradd(String *l, String *r)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
String *s;
|
||||||
|
|
||||||
|
len = l->len+r->len;
|
||||||
|
s = gmalloc(sizeof(String)+len+1);
|
||||||
|
s->gc.gclink = gcl;
|
||||||
|
gcl = (Gc*)s;
|
||||||
|
s->len = len;
|
||||||
|
s->string = (char*)s+sizeof(String);
|
||||||
|
memmove(s->string, l->string, l->len);
|
||||||
|
memmove(s->string+l->len, r->string, r->len);
|
||||||
|
s->string[s->len] = 0;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
scmp(String *sr, String *sl)
|
||||||
|
{
|
||||||
|
if(sr->len != sl->len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(memcmp(sr->string, sl->string, sl->len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue