home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-23 | 41.3 KB | 1,203 lines |
- Newsgroups: alt.sources
- Path: sparky!uunet!cs.utexas.edu!qt.cs.utexas.edu!yale.edu!newsserver.jvnc.net!princeton!csservices!tyrolia!mg
- From: mg@tyrolia (Michael Golan)
- Subject: Duel - a language for debugging C programs part 3/6
- Message-ID: <1993Jan22.034626.21105@csservices.Princeton.EDU>
- Sender: news@csservices.Princeton.EDU (USENET News System)
- Organization: Department of Computer Science, Princeton University
- Date: Fri, 22 Jan 1993 03:46:26 GMT
- Lines: 1192
-
- Submitted-by: mg@cs.princeton.edu
- Archive-name: duel/part03
-
- #!/bin/sh
- # This is part 03 of duel
- if touch 2>&1 | fgrep 'amc' > /dev/null
- then TOUCH=touch
- else TOUCH=true
- fi
- # ============= src/proto.h ==============
- echo "x - extracting src/proto.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/proto.h &&
- X/* DUEL - A Very High Level Debugging Langauge. */
- X/* Public domain code */
- X/* Written by Michael Golan mg@cs.princeton.edu */
- X/*$Header: /tmp_mnt/n/fs/grad2/mg/duel/RCS/proto.h,v 1.9 93/01/13 16:22:37 mg Exp $*/
- X
- X/* prototypes for all of duel's global functions */
- X
- XFUNC tctype* duel_mkctype_ptr(tctype *t);
- XFUNC tctype* duel_mkctype_func(tctype *t);
- XFUNC tctype* duel_mkctype_array(tctype *t,int size);
- XFUNC tctype* duel_mkctype_struct(char *name,size_t size,int fields_no,
- X bool is_union);
- XPROC duel_mkctype_struct_field(tctype *t,int field_no,char *name,
- X int bitpos,int bitlen, tctype *fctype);
- XFUNC tctype* duel_mkctype_enum(char *name,tctype_kind real_type_kind,
- X size_t size,int enumerators_no);
- XPROC duel_mkctype_enumerator(tctype *t,int enumerator_no,char *name,int val);
- X
- XPROC duel_init_basic_ctypes(void);
- X
- XPROC duel_print_value(tvalue *v);
- XPROC duel_print_type(tctype *t,int expand);
- XPROC duel_sprint_scalar_value(char *s,tvalue *v);
- X
- X
- XPROC duel_fatal(char *msg);
- XPROC duel_abort(void);
- XPROC duel_cleanup(void);
- X
- XFUNC tnode* duel_parse(char *s);
- X
- X
- XPROC duel_reset_eval(void);
- XFUNC bool duel_eval(tnode *n,tvalue *v);
- XFUNC bool duel_get_dot_name(tvalue *v,char *name,tvalue *ret);
- X
- XFUNC tnode* duel_set_eval_loc(tnode *n);
- XFUNC char* duel_set_input_string(char *s);
- XPROC duel_op_error(char *mesg,char *op,tvalue *v1,tvalue *v2);
- XPROC duel_gen_error(char *mesg,char *arg1);
- X
- X
- XFUNC bool duel_try_get_rvalue(tvalue *v,char *op);
- XPROC duel_standardize_func_parm(tvalue *p);
- XFUNC bool duel_do_op_to(tvalue *v1,tvalue *v2,int n,tvalue *r);
- XPROC duel_do_cast(tctype *tout,tvalue *v);
- XFUNC bool duel_mk_logical(tvalue *v,char *op);
- XPROC duel_set_symb_val(tvalue *r,char *format,tvalue *v1,tvalue *v2);
- XPROC duel_get_struct_val(tvalue *v,char *op);
- XPROC duel_get_struct_ptr_val(tvalue *v,char *op);
- XFUNC int duel_get_int_val(tvalue *v,char *op);
- XFUNC int duel_get_posint_val(tvalue *v,char *op);
- XPROC duel_apply_unary_op(topcode op,tvalue *v);
- XPROC duel_apply_post_unary_op(topcode op,tvalue *v);
- XFUNC bool duel_apply_bin_op(topcode op,tvalue *v1,tvalue *v2,tvalue *r);
- XPROC duel_find_func_frame(tvalue *v,char *op);
- X
- X
- X/* debugger dependent functions */
- X
- XFUNC void* duel_malloc(size_t size);
- XPROC duel_free(void *);
- X
- XFUNC bool duel_get_target_bytes(ttarget_ptr from,void *to,size_t n);
- XFUNC bool duel_put_target_bytes(ttarget_ptr to,void *from,size_t n);
- X
- XFUNC bool duel_get_target_bitfield(ttarget_ptr struct_at,int bitpos,
- X int bitlen,void *to,tctype_kind tkind);
- XFUNC bool duel_get_target_variable(char *name, int frame_no, tvalue *v);
- XFUNC tctype* duel_get_target_typedef(char *name);
- XFUNC tctype* duel_get_target_struct_tag(char *name);
- XFUNC tctype* duel_get_target_union_tag(char *name);
- XFUNC tctype* duel_get_target_enum_tag(char *name);
- XFUNC ttarget_ptr duel_alloc_target_space(size_t n);
- X
- XFUNC int duel_get_frames_number(void);
- XFUNC ttarget_ptr duel_get_function_for_frame(int frame_no);
- XPROC duel_target_func_call(tvalue *func, tvalue *parms[],
- X int parms_no,tvalue *ret);
- X
- X/* prototypes for misc functions */
- X
- XFUNC char* strncpyz(char *to,char *from,size_t len);
- X
- XPROC duel_free_val_list(tval_list *l);
- XPROC duel_free_nodes(tnode *);
- X
- XFUNC tvalue* duel_find_alias(char *name);
- XPROC duel_set_alias(char *name,tvalue *v);
- XPROC duel_clear_aliases(void);
- XPROC duel_show_aliases(void);
- X
- SHAR_EOF
- $TOUCH -am 0113165193 src/proto.h &&
- chmod 0644 src/proto.h ||
- echo "restore of src/proto.h failed"
- set `wc -c src/proto.h`;Wc_c=$1
- if test "$Wc_c" != "3352"; then
- echo original size 3352, current size $Wc_c
- fi
- # ============= src/duel.c ==============
- echo "x - extracting src/duel.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/duel.c &&
- X/* DUEL - A Very High Level Debugging Langauge. */
- X/* Public domain code */
- X/* Written by Michael Golan mg@cs.princeton.edu */
- X/*$Header: /tmp_mnt/n/fs/grad2/mg/duel/RCS/duel.c,v 1.7 93/01/12 21:28:44 mg Exp $*/
- X
- X/* this module contains the entery point to duel - duel_eval_and_pasre.
- X */
- X
- X/*
- X * $Log: duel.c,v $
- X * Revision 1.7 93/01/12 21:28:44 mg
- X * cleanup and set for release
- X *
- X * Revision 1.6 93/01/06 23:57:10 mg
- X * added alias, clear commands, new memory alloc/release
- X *
- X * Revision 1.5 93/01/03 07:26:47 mg
- X * new printing setup
- X *
- X * Revision 1.4 92/12/24 23:32:38 mg
- X * better struct support, misc changes
- X *
- X * Revision 1.3 92/10/19 15:02:04 mg
- X * lcc happy, size zero arrays
- X *
- X * Revision 1.2 92/10/14 02:03:15 mg
- X * misc
- X *
- X */
- X
- X#include <setjmp.h>
- X#define DEF /* define global variables */
- X#include "duel.h"
- X#include "patchlevel.h"
- X#define VERSION "DUEL 1.00"
- X
- Xstatic jmp_buf duel_abort_jmp ; /* abort current execution */
- Xstatic tnode *root ; /* root of current eval node */
- X
- X
- X/* abort evaluation of current expression */
- X
- XPROC duel_abort(void)
- X{
- X longjmp(duel_abort_jmp,1);
- X}
- X
- XPROC duel_cleanup(void) /* cleanup malloc, etc, when duel eval ends*/
- X{
- X duel_free_nodes(root);
- X root=NULL ;
- X}
- X
- XLPROC help(void)
- X{
- X printf(
- X"Duel - Debugging U (might) Even Like -- A high level debugging language\n\n\
- XDuel was designed to overcome problems with traditional debuggers' print\n\
- Xstatement. It supports the C operators, many C constructs, and many new\n\
- Xoperators for easy exploration of the program's space, e.g.\n\
- Xx[..100] >? 0 show positive x[i] for i=0 to 99\n\
- Xy[10..20].code !=? 0 show non-zero y[i].code for i=10 to 20\n\
- Xh-->next->code expand linked list h->next, h->next->next ...\n\
- Xhead-->next.if(code>0) name show name for each element with code>0\n\
- Xx[i:=..100]=y[i]; array copy. i is an alias to vals 0..99\n\
- Xhead-->next[[10..15]] the 10th to 15th element of a linked list\n\
- X#/(head-->next->val==?4) count elements with val==4\n\
- Xhead-->next->if(next) val >? next->val check if list is sorted by val\n\
- X\n\
- XDuel was written by Michael Golan at Princeton University. Send email to\n\
- Xmg@cs.princeton.edu. Duel is public domain code. No copy left or right.\n\
- Xall but 500 lines are independent of gdb. Port it! Make it Commercial!\n\
- X\n\
- XTry \"dl\" without paramaters for a list of commands\n");
- X}
- X
- XLPROC examples(void)
- X{
- X printf("\
- Xx[10..20,22,24,40..60] display x[i] for the selected indexes\n\
- Xx[9..0] display x[i] backwards\n\
- Xx[..100] >? 5 <? 10 display x[i] if 5<x[i]<10\n\
- Xx[0..99]=>if(_>5 && _<10) _ same\n\
- Xval[..50].if(is_dx) x else y \
- Xval[i].x or val[i].y depending on val[i].is_dx\n\
- Xemp[..50].if(is_m) _ return emp[i] if emp[i].is_m.\n\
- Xx[i:=..100]=y[i] ; assign y[i] to x[i]\n\
- Xx[i:=..100] >? x[i+1] check if x[i] is not sorted\n\
- X(x[..100] >? 0)[[2]] return the 3rd positive x[i]\n\
- Xargv[0..]@0 argv[0] argv[1] .. until first null\n\
- Xemp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0\n\
- Xhead-->next->val val of each element in a linked list\n\
- X*head-->next[[20]] element 20 of list, '*' display struct w/fields\n\
- X#/head-->next count elements on a linked list\n\
- X#/(head-->next-val>?5) count those over 5\n\
- Xhead-->(next!=?head) expand cyclic linked list (tail->head)\n\
- X(T mytype) x convert x to a user defined type mytype\n\
- Xint i ; for(i=0 ;i<5 .. declare variable, use C construct.\n");
- X}
- X
- XLPROC operators(void)
- X{
- X printf("\
- XDUEL operators in decreasing precedence. All C operators are accepted!\n\n\
- X{x} same as (x) but x's value is used for symbol emp[{i}]\n\
- Xx-->y expands data structure from x, using y root-->(left,right)->key\n\
- Xx.y eval y under x's scope, like pascal \"with\". x is accesible as '_'\n\
- Xx->y same as (*x).y. hash[..50]->if(_!=0) key\n\
- Xx[[y]] select the y'th elements of x head-->next[[..6]]\n\
- Xx@y eval x, stop as soon as y true (_==y if y const). argv[0..]@0\n\
- Xx@y eval x, set alias y as counter of generated values\n");
- X printf("\
- X#/x count number of values from x #/head-->next\n\
- Xframe(n) use with '.' to reference stack frames. frame(3).val\n\
- Xx..y x, x+1, x+2 .. y. (if x>y, return them backwards) x[10..20]\n\
- X..y like 0..y-1 x[..1024]\n\
- Xx.. like x..maxint. Caution: use only with x@y or x[[y]]\n\
- Xx>?y x if x>y else nothing. also <? <=? >=? ==? and !=? x[..10]<?0\n\
- X&&/x 1 or 0 if x!=0 for all x values. ||/x similar &&/x[..100]>=0\n\
- Xx,y x, then y.\n\
- Xx=>y eval y for each x, setting '_' to x's values x[..50]=>_*_\n\
- Xif(x) y C statements are operators. Also for(), while(), if() else\n\
- Xx;y Evaluate and ignore x's value, then return y\n");
- X}
- X
- X/* entry point into duel. s is the expression to evaluate */
- X
- Xvoid duel_parse_and_eval(char *s)
- X{
- X static first=1 ;
- X if(first) { /* init stuff */
- X duel_init_basic_ctypes();
- X printf("%s.%d, public domain debugging language. \"dl\" for help\n",
- X VERSION,PATCHLEVEL);
- X first=0 ;
- X }
- X if(!s || *s==0) { /* no input, give some help */
- X printf("Supported DUEL commands: (see man page duel(1))\n");
- X printf("duel help - give basic help\n");
- X printf("duel examples - show useful usage examples\n");
- X printf("duel ops - operators summary\n");
- X printf("duel alias - show current aliases\n");
- X printf("duel clear - clear all aliases\n\n");
- X return ;
- X }
- X if(strcmp(s,"?")==0 || strcmp(s,"help")==0) {
- X help();
- X return ;
- X }
- X if(strcmp(s,"examples")==0 || strcmp(s,"ex")==0 ) {
- X examples();
- X return ;
- X }
- X if(strcmp(s,"operators")==0 || strcmp(s,"ops")==0) {
- X operators();
- X return ;
- X }
- X if(strcmp(s,"debug")==0) { /* turn debugging of duel itself */
- X duel_debug= !duel_debug ;
- X printf("duel debug mode %d\n",duel_debug);
- X return ;
- X }
- X if(strcmp(s,"clear")==0) {
- X duel_clear_aliases();
- X printf("Aliases table cleared\n");
- X return ;
- X }
- X if(strcmp(s,"alias")==0 || strcmp(s,"aliases")==0) {
- X duel_show_aliases();
- X return ;
- X }
- X if(setjmp(duel_abort_jmp)==0) { /* set abort point */
- X if((root=duel_parse(s))!=NULL) {
- X tvalue v ;
- X duel_set_input_string(s);
- X duel_reset_eval();
- X
- X while(duel_eval(root,&v)) {
- X duel_print_value(&v);
- X printf("\n");
- X }
- X }
- X }
- X duel_cleanup();
- X}
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- SHAR_EOF
- $TOUCH -am 0113165193 src/duel.c &&
- chmod 0644 src/duel.c ||
- echo "restore of src/duel.c failed"
- set `wc -c src/duel.c`;Wc_c=$1
- if test "$Wc_c" != "6871"; then
- echo original size 6871, current size $Wc_c
- fi
- # ============= src/parse.y ==============
- echo "x - extracting src/parse.y (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/parse.y &&
- X%{
- X/* DUEL - A Very High Level Debugging Langauge. */
- X/* Public domain code */
- X/* Written by Michael Golan mg@cs.princeton.edu */
- X/*$Header: /tmp_mnt/n/fs/grad2/mg/duel/RCS/parse.y,v 1.9 93/01/12 21:53:07 mg Exp $*/
- X
- X/* this module contains the duel parser, in yacc, plus a simple lexer.
- X * the lexer is slow, but duel expressions are tiny.
- X * the parsing generate an AST with essentially no type checking.
- X * names are only looked up when the refer explicitly to types. This forces
- X * the use of "T" before user types. You can't parse (x)(y) correctly, if
- X * you want the node to contain "cast" or "func", without knowing the x is
- X * not a type. (It is interesting to note that (x *)(y) is clearly a cast,
- X * but it can not be parsed without a context sensitive grammer!).
- X * yacc is also not smart enough to recognize e.g. "if(e) e ; else e" as
- X * a special case (redundent ';'). I hacked this in the lexer. It should
- X * reduce the trouble with C->duel coding. (It can also be done for {e1}e2,
- X * in some speical cases, e.g. if e2 is a keyword, or a name or a unary op,
- X * but this can confuse some people, e.g. in {i}[5], so I left it alone.)
- X * Finally, the %/ operator is accepted as "#/" and "%%" as "#", to those
- X * who wish to keep gdb with # comments.
- X * memory: nodes are alloc'ed dynamically. a parsing error loose so-far
- X * allocated nodes, which is normally acceptable (yyerror can probably hack
- X * into the yacc stack to release them.)
- X */
- X
- X/*
- X * $Log: parse.y,v $
- X * Revision 1.9 93/01/12 21:53:07 mg
- X * cleanup and set for release
- X *
- X * Revision 1.8 93/01/07 00:14:33 mg
- X * add &&/ ||/
- X * fixed parsing of trailing ';' was a mess.
- X * ignore ';' before 'else' and '}' w/warning.
- X *
- X * Revision 1.7 93/01/03 07:31:01 mg
- X * error reporting
- X *
- X * Revision 1.6 92/12/24 23:35:50 mg
- X * began src pos support
- X *
- X * Revision 1.5 92/10/19 15:08:02 mg
- X * frames() added; bug fixed
- X *
- X * Revision 1.4 92/10/14 02:06:32 mg
- X * misc/change casting parsing/variable def.
- X *
- X * Revision 1.3 92/09/16 11:09:39 mg
- X * add typedef/struct support, const strings
- X * cleanup s/r conflict by setting ELSE to a token. explained some stuff in
- X * comments.
- X *
- X * Revision 1.2 92/09/15 06:10:46 mg
- X * cosmetics and new ops: x@y, for() while() ..x and x..
- X * generic '.' and '_' support. x@y. '..x' and 'x..'. while(), for(), ?:
- X *
- X */
- X
- X#include "duel.h"
- X
- Xstatic char *inputstr ; /* pointer to string being parsed */
- Xstatic char *lexptr ; /* current lexer pointer into input str */
- Xstatic tnode *root ; /* result of parsing stored here */
- X
- X/* pick unique names for globals of yacc. gdb has other parsers! */
- X#define yyparse duel_yyparse
- X#define yylex duel_yylex
- X#define yyerror duel_yyerror
- X#define yylval duel_yylval
- X#define yychar duel_yychar
- X#define yydebug duel_yydebug
- X#define yypact duel_yypact
- X#define yyr1 duel_yyr1
- X#define yyr2 duel_yyr2
- X#define yydef duel_yydef
- X#define yychk duel_yychk
- X#define yypgo duel_yypgo
- X#define yyact duel_yyact
- X#define yyexca duel_yyexca
- X#define yyerrflag duel_yyerrflag
- X#define yynerrs duel_yynerrs
- X#define yyps duel_yyps
- X#define yypv duel_yypv
- X#define yys duel_yys
- X#define yystate duel_yystate
- X#define yytmp duel_yytmp
- X#define yyv duel_yyv
- X#define yyval duel_yyval
- X#define yylloc duel_yylloc
- X
- Xtypedef struct { /* token info for operators */
- X int src_pos ; /* source position */
- X topcode opcode ; /* opcode */
- X } topinfo ;
- X
- Xtypedef struct { /* token info for symbols */
- X int src_pos ; /* source position */
- X char *name ; /* symbol */
- X } tnameinfo ;
- X
- X/* these are used as operators to mknode_... when source location is unknown*/
- Xstatic topinfo seq_op = { -1,';' } ; /* sequencing operator, src pos unkown */
- Xstatic topinfo decl_op = { -1,OP_DECL } ; /* declare var op, src pos unkown */
- X
- X/* local prototypes. */
- XLPROC yyerror(char *msg);
- XLFUNC int yylex (void);
- X
- XLPROC push_type(char desc) ;
- XLPROC push_type_int(char desc,tnode *n) ;
- XLFUNC bool pop_type(char *desc,int *size);
- X
- XLFUNC tnode* mknode_op(top_kind,topinfo opinfo,tnode*,tnode*,tnode*,tnode*);
- XLFUNC tnode* mknode_const(int src_pos,tctype *ctype);
- XLFUNC tnode* mknode_ctype(tctype *ctype);
- XLFUNC tnode* mknode_name(tnameinfo nameinfo);
- XLFUNC tnode* mknode_modified_ctype(tctype *base);
- X
- X#define mknode_post_unary(op,n) (mknode_op(OPK_POST_UNARY,op,n, 0, 0,0))
- X#define mknode_unary(op,n) (mknode_op(OPK_UNARY, op,n, 0, 0,0))
- X#define mknode_sunary(op,n) (mknode_op(OPK_SUNARY, op,n, 0, 0,0))
- X#define mknode_bin(op,n1,n2) (mknode_op(OPK_BIN, op,n1,n2,0,0))
- X#define mknode_sbin(op,n1,n2) (mknode_op(OPK_SBIN, op,n1,n2,0,0))
- X#define mknode_tri(op,n1,n2,n3) (mknode_op(OPK_TRI, op,n1,n2,n3,0))
- X
- Xstatic tctype *decl_tbase ; /* used for variables decl */
- X
- X/* #define YYDEBUG 1 */
- X
- X%}
- X
- X%union
- X {
- X tnode *node ; /* node pointer for constructed exp tree */
- X tctype *ctype; /* type for type nodes */
- X tnameinfo nameinfo ; /* a name/symbol + src position */
- X topinfo opinfo; /* keyword/operator + source position */
- X }
- X
- X%type <node> start duel_inp duel_exp exp type nameexp sm_exp oexp
- X%type <node> all_decls vars_decl var_decl name_decl1 name_decl
- X%type <ctype> typebase
- X%type <nameinfo> name
- X
- X%token <node> T_CONST
- X%token <nameinfo> T_SYM
- X%token <opinfo> T_ASSIGN T_DEFVAR
- X
- X
- X%token <opinfo> T_CHAR T_INT T_SHORT T_LONG T_UNSIGNED T_FLOAT T_DOUBLE T_VOID
- X%token <opinfo> T_STRUCT T_UNION T_ENUM T_SIZEOF T_TYPEDEF_INDICATOR
- X
- X%token <opinfo> T_IF T_ELSE T_FOR T_WHILE
- X%token <opinfo> ';' ',' '=' '?' '|' '^' '&' '<' '>' '+' '-' '*' '/' '%'
- X%token <opinfo> '.' '[' ']' '(' ')' '{' '}' '#' '@' '!' '~'
- X%token <opinfo> T_OR T_AND T_RSH T_LSH T_INC T_DEC T_COUNT T_FRAME T_TO
- X%token <opinfo> T_DFS T_BFS T_ARROW T_OSEL T_CSEL T_IMP T_ANDL T_ORL
- X%token <opinfo> T_EQ T_NE T_EQQ T_NEQ T_LE T_GE T_LSQ T_GTQ T_LEQ T_GEQ
- X
- X%left ';'
- X%right STMT T_ELSE
- X%right T_IMP
- X%right ','
- X%right '=' T_ASSIGN T_DEFVAR
- X%right '?'
- X%left T_OR T_ORL
- X%left T_AND T_ANDL
- X%left '|'
- X%left '^'
- X%left '&'
- X%left T_EQ T_NE T_EQQ T_NEQ
- X%left '<' '>' T_LE T_GE T_LSQ T_GTQ T_LEQ T_GEQ
- X%nonassoc T_TO
- X%left T_LSH T_RSH
- X%left '+' '-'
- X%left '*' '/' '%'
- X%right UNARY T_INC T_DEC T_COUNT T_FRAME
- X%left T_DFS T_BFS T_POS T_ARROW '.' '[' ']' '(' ')' '{' '}' '#' '@' T_OSEL T_CSEL
- X%%
- X
- Xstart : duel_inp { root=$1 ; }
- X ;
- X
- Xduel_inp : all_decls
- X | all_decls ';'
- X | all_decls ';' duel_exp { $$=mknode_sbin($2,$1,$3);}
- X | duel_exp
- X ;
- Xduel_exp : sm_exp
- X | sm_exp ';' { $$=mknode_sbin($2,$1,0); }
- X ;
- Xall_decls: vars_decl
- X | all_decls ';' vars_decl { $$=mknode_sbin($2,$1,$3); }
- X ;
- X
- Xvars_decl: typebase { decl_tbase=$1 ; } var_decl { $$=$3 ; }
- X ;
- Xvar_decl : name_decl1
- X | var_decl ',' name_decl1 { $$=mknode_sbin(seq_op,$1,$3); }
- X ;
- X
- Xname_decl1: name_decl { $$=mknode_sbin(decl_op,$1,
- X mknode_modified_ctype(decl_tbase)); }
- X ;
- X
- Xname_decl : '(' name_decl ')' { $$=$2 ; }
- X | '(' name_decl ')' '(' ')' { $$=$2 ; push_type('('); }
- X | '*' name_decl { $$=$2 ; push_type('*'); }
- X | name_decl '[' T_CONST ']' { $$=$1 ; push_type_int('[',$3); }
- X | nameexp
- X ;
- X
- X/* Statements - not really, these are expressions too!
- X Notes: for(;;) oexp - will create lots of shift/reduce conflicts,
- X 'for(;;;)' and 'for(;;) exp' are specified
- X instead and yacc handle this as a "standard" s/r.
- X the only diff is yacc dont complain on these!
- X if() - same comments as above, plus, we prevent meaningless
- X if's like in C: ' if(x); else;' - a useless statement.
- X */
- Xexp : T_IF '(' exp ')' exp %prec STMT { $$=mknode_tri($1,$3,$5,0); }
- X | T_IF '(' exp ')' exp T_ELSE %prec STMT
- X { $$=mknode_tri($1,$3,$5,0); }
- X | T_IF '(' exp ')' T_ELSE exp %prec STMT
- X { $$=mknode_tri($1,$3,0,$6); }
- X | T_IF '(' exp ')' exp T_ELSE exp %prec STMT
- X { $$=mknode_tri($1,$3,$5,$7); }
- X
- X | T_FOR '(' oexp ';' exp ';' oexp ')' exp %prec STMT
- X { $$=mknode_op(OPK_QUAD,$1,$3,$5,$7,$9); }
- X | T_FOR '(' oexp ';' exp ';' oexp ')' %prec STMT
- X { $$=mknode_op(OPK_QUAD,$1,$3,$5,$7,0); }
- X | T_WHILE '(' exp ')' exp %prec STMT
- X { $$=mknode_sbin($1,$3,$5); }
- X | T_WHILE '(' exp ')' %prec STMT
- X { $$=mknode_sbin($1,$3,0); }
- X ;
- X
- X/* Expressions */
- X
- Xexp : '*' exp %prec UNARY { $$=mknode_unary( $1,$2); }
- X | '&' exp %prec UNARY { $$=mknode_unary( $1,$2); }
- X | '-' exp %prec UNARY { $$=mknode_unary( $1,$2); }
- X | '!' exp %prec UNARY { $$=mknode_unary( $1,$2); }
- X | '~' exp %prec UNARY { $$=mknode_unary( $1,$2); }
- X | T_COUNT exp %prec UNARY { $$=mknode_sunary($1,$2); }
- X | T_ANDL exp { $$=mknode_sunary($1,$2); }
- X | T_ORL exp { $$=mknode_sunary($1,$2); }
- X | T_INC exp %prec UNARY { $$=mknode_unary( $1,$2); }
- X | T_DEC exp %prec UNARY { $$=mknode_unary( $1,$2); }
- X | exp T_INC %prec UNARY { $$=mknode_post_unary($2,$1); }
- X | exp T_DEC %prec UNARY { $$=mknode_post_unary($2,$1); }
- X | T_SIZEOF exp %prec UNARY { $$=mknode_unary( $1,$2); }
- X | T_SIZEOF '(' type ')' %prec UNARY { $$=mknode_sunary($1,$3); }
- X | T_FRAME '(' exp ')' %prec UNARY { $$=mknode_unary( $1,$3); }
- X ;
- X
- Xexp : exp T_DFS exp { $$=mknode_sbin($2,$1,$3); }
- X | exp T_BFS exp { $$=mknode_sbin($2,$1,$3); }
- X
- X | exp '#' nameexp { $$=mknode_sbin($2,$1,$3); }
- X | exp '@' exp { $$=mknode_sbin($2,$1,$3); }
- X | exp T_ARROW exp { $$=mknode_sbin($2,$1,$3); }
- X | exp '.' exp { $$=mknode_sbin($2,$1,$3); }
- X | exp '[' exp ']' { $$=mknode_bin( $2,$1,$3); }
- X | exp T_OSEL exp T_CSEL { $$=mknode_sbin($2,$1,$3); }
- X | exp '(' oexp ')' %prec '.' { $$=mknode_op(OPK_FUNC,$2,$1,$3,0,0); }
- X | '(' sm_exp ')' { $$=mknode_unary($1,$2); }
- X | '{' sm_exp '}' { $$=mknode_unary($1,$2); }
- X ;
- X
- Xexp : '(' type ')' exp %prec UNARY
- X { $$=mknode_op(OPK_CAST,$1,$2,$4,0,0); }
- X ;
- X
- X /* Bin ops in decreasing precedence order: */
- X
- Xexp : exp '*' exp { $$=mknode_bin($2,$1,$3); }
- X | exp '/' exp { $$=mknode_bin($2,$1,$3); }
- X | exp '%' exp { $$=mknode_bin($2,$1,$3); }
- X | exp '+' exp { $$=mknode_bin($2,$1,$3); }
- X | exp '-' exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_LSH exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_RSH exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_EQ exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_NE exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_EQQ exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_NEQ exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_LE exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_GE exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_LEQ exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_GEQ exp { $$=mknode_bin($2,$1,$3); }
- X | exp '<' exp { $$=mknode_bin($2,$1,$3); }
- X | exp '>' exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_LSQ exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_GTQ exp { $$=mknode_bin($2,$1,$3); }
- X | exp '&' exp { $$=mknode_bin($2,$1,$3); }
- X | exp '|' exp { $$=mknode_bin($2,$1,$3); }
- X | exp '^' exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_AND exp { $$=mknode_sbin($2,$1,$3); }
- X | exp T_OR exp { $$=mknode_sbin($2,$1,$3); }
- X ;
- X
- Xexp : exp '?' exp ':' exp %prec '?'
- X { $$=mknode_tri($2,$1,$3,$5); }
- X ;
- X
- Xexp : exp '=' exp { $$=mknode_bin($2,$1,$3); }
- X | exp T_ASSIGN exp { $$=mknode_op(OPK_ASSIGN,$2, $1,$3,0,0); }
- X |nameexp T_DEFVAR exp { $$=mknode_sbin($2,$1,$3); }
- X ;
- X
- X /* generating expressions */
- X
- Xexp : exp T_TO exp { $$=mknode_sbin($2,$1,$3); }
- X | T_TO exp { $$=mknode_sbin($1, 0,$2); }
- X | exp T_TO { $$=mknode_sbin($2,$1, 0); }
- X | exp ',' exp { $$=mknode_sbin($2,$1,$3); }
- X | exp T_IMP exp { $$=mknode_sbin($2,$1,$3); }
- X ;
- X
- Xsm_exp : sm_exp ';' exp { $$=mknode_sbin($2,$1,$3); }
- X | exp
- X ;
- X
- Xoexp : exp /* optional expression, eg in for() */
- X | { $$=0 ; }
- X ;
- X
- Xexp : T_CONST ;
- Xexp : nameexp ;
- Xnameexp : name { $$=mknode_name($1) ; } ;
- X
- Xtype : typebase type_mod { $$=mknode_modified_ctype($1); }
- X ;
- X/* type_mod has no value. bison warning is meaningless. I cant find a way
- X * to shut it up
- X */
- Xtype_mod: '(' type_mod ')'
- X | '(' type_mod ')' '(' ')' { push_type('('); }
- X | '*' type_mod { push_type('*'); }
- X | type_mod '[' T_CONST ']' { push_type_int('[',$3); }
- X |
- X ;
- X
- X
- X/* note that names are evaluated at runtime. hence (name)(x) is ambigious
- X * as either a function call or a cast.
- X * We could identify a typedef 'name' as such and return a special token from
- X * the lexr, but this will make 'x.(5+y)' illegal if y is both a field and
- X * a typedef (Note that gdb's own code include such things).
- X *
- X * there is a complex solution, that keeps the the casting as a syntax tree,
- X * and compute ctype at runtime, too. However, we want to compute all types at
- X * parse time. Out solution forces the reserved word T_TYPEDEF_INDICATOR to
- X * appear before any typedef name. (the reserved word is normally just 'T')
- X * example: instead of '(list *) x' use in duel: '(T list *) x'
- X */
- X
- Xtypebase: T_TYPEDEF_INDICATOR name {
- X $$=duel_get_target_typedef($2.name);
- X if($$==NULL) {
- X tvalue v;
- X if(duel_get_target_variable($2.name,-1,&v)) $$=v.ctype;
- X else { yyerror("not a typedef name"); YYABORT ; }
- X }
- X }
- X ;
- X
- Xtypebase: T_CHAR { $$ = ctype_char; }
- X | T_UNSIGNED T_CHAR { $$ = ctype_uchar; }
- X | T_INT { $$ = ctype_int; }
- X | T_UNSIGNED { $$ = ctype_uint; }
- X | T_UNSIGNED T_INT { $$ = ctype_uint; }
- X | T_LONG { $$ = ctype_long; }
- X | T_LONG T_INT { $$ = ctype_long; }
- X | T_UNSIGNED T_LONG { $$ = ctype_ulong; }
- X | T_UNSIGNED T_LONG T_INT { $$ = ctype_ulong; }
- X | T_SHORT { $$ = ctype_short; }
- X | T_SHORT T_INT { $$ = ctype_short; }
- X | T_UNSIGNED T_SHORT { $$ = ctype_ushort; }
- X | T_UNSIGNED T_SHORT T_INT { $$ = ctype_ushort; }
- X | T_FLOAT { $$ = ctype_float ; }
- X | T_DOUBLE { $$ = ctype_double; }
- X | T_VOID { $$ = ctype_void; }
- X | T_STRUCT name
- X { $$ = duel_get_target_struct_tag($2.name);
- X if($$==NULL) { yyerror("not a struct tag"); YYABORT ; }}
- X | T_UNION name
- X { $$ = duel_get_target_union_tag($2.name);
- X if($$==NULL) { yyerror("not a union tag"); YYABORT ; }}
- X | T_ENUM name
- X { $$ = duel_get_target_enum_tag($2.name);
- X if($$==NULL) { yyerror("not an enum tag"); YYABORT ; }}
- X ;
- X
- Xname : T_SYM ;
- X%%
- X
- Xstatic struct stoken { /* all opcodes we recognize */
- X char *opstr ; /* op code as a string */
- X int token ; /* token to return to yacc */
- X int opcode ; /* opcode value associated with the token */
- X } tokens[] = { /* the special tokens, longer ones 1st! */
- X {">>=",T_ASSIGN, OP_RSH},
- X {"<<=",T_ASSIGN, OP_LSH},
- X {"-->",T_DFS, OP_DFS},
- X {"->>",T_BFS, OP_BFS},
- X {"==?", T_EQQ, OP_EQQ},
- X {"!=?", T_NEQ, OP_NEQ},
- X {"<=?", T_LEQ, OP_LEQ},
- X {">=?", T_GEQ, OP_GEQ},
- X {"&&/", T_ANDL, OP_AND},
- X {"||/", T_ORL, OP_OR},
- X
- X {"<?", T_LSQ, OP_LSQ},
- X {">?", T_GTQ, OP_GTQ},
- X {"#/", T_COUNT, '#' },
- X {"%/", T_COUNT, '#' }, /* gdb insists to recognize # as start of comma!*/
- X {"%%", '#', '#' }, /* same. so %/ for #/ and %% for #. not doc!*/
- X {"+=", T_ASSIGN, '+'},
- X {"-=", T_ASSIGN, '-'},
- X {"*=", T_ASSIGN, '*'},
- X {"/=", T_ASSIGN, '/'},
- X {"%=", T_ASSIGN, '%'},
- X {"|=", T_ASSIGN, '|'},
- X {"&=", T_ASSIGN, '&'},
- X {"^=", T_ASSIGN, '^'},
- X {":=", T_DEFVAR,OP_DEF},
- X {"++", T_INC, OP_INC },
- X {"--", T_DEC, OP_DEC },
- X {"->", T_ARROW, OP_ARR },
- X {"&&", T_AND, OP_AND },
- X {"||", T_OR, OP_OR },
- X {"<<", T_LSH, OP_LSH },
- X {">>", T_RSH, OP_RSH },
- X {"==", T_EQ, OP_EQ },
- X {"!=", T_NE, OP_NE },
- X {"<=", T_LE, OP_LE },
- X {">=", T_GE, OP_GE },
- X {"..", T_TO, OP_TO },
- X {"=>", T_IMP, OP_IMP },
- X {"[[", T_OSEL, OP_SEL },
- X {"]]", T_CSEL, OP_SEL },
- X };
- X
- Xstatic struct skeyword { /* all keywords we recognize */
- X char *keyword_str ; /* keyword as a string */
- X int token ; /* token to return to yacc */
- X topcode opcode ; /* opcode associated w/keyword */
- X } keywords[] = {
- X {"if", T_IF , OP_IF},
- X {"else", T_ELSE },
- X {"for", T_FOR , OP_FOR},
- X {"while", T_WHILE , OP_WHILE},
- X {"sizeof", T_SIZEOF , OP_SIZ},
- X {"frame", T_FRAME , OP_FRAME},
- X
- X {"T", T_TYPEDEF_INDICATOR },
- X {"struct", T_STRUCT },
- X {"union", T_UNION },
- X {"enum", T_ENUM },
- X
- X {"unsigned",T_UNSIGNED },
- X /*{"signed", T_SIGNED },*/
- X {"short", T_SHORT },
- X {"long", T_LONG },
- X {"char", T_CHAR },
- X {"int", T_INT },
- X {"double", T_DOUBLE },
- X {"float", T_FLOAT },
- X {"void", T_VOID },
- X } ;
- X
- X
- XLFUNC tnode* duel_lex_int(void) /* parse next token as integer num */
- X{
- X tnode *n ;
- X ulong val=0 ;
- X char *p=lexptr ;
- X bool is_l=0,is_u=0 ;
- X int base=10 ;
- X int src_pos=lexptr-inputstr ;
- X
- X if(*p=='0') { /* figure out the base */
- X p++ ;
- X if(*p=='x' || *p=='X') base=16,p++ ;
- X else
- X if(isdigit(*p)) base=8 ; /* avoid having '0' as a base 8 (uint) */
- X }
- X
- X while(isdigit(*p) || base==16 && isxdigit(*p)) { /* get the value */
- X val*=base ;
- X if(isupper(*p)) val+= *p-'A'+10 ;
- X else if(islower(*p)) val+= *p-'a'+10 ;
- X else val+= *p-'0' ;
- X p++ ;
- X }
- X if(*p=='l' || *p=='L') is_l=1,p++ ; /* yuk. figure 0L etc */
- X if(*p=='u' || *p=='U') is_u=1,p++ ;
- X if(!is_l && (*p=='l' || *p=='L')) is_l=1,p++ ;
- X is_u=is_u || base!=10 ;
- X
- X if(is_l && is_u || (long) val < 0 || ((uint) val != val && is_u)) {
- X n=mknode_const(src_pos,ctype_ulong);
- X n->cnst.u.rval_ulong=val ;
- X }
- X else
- X if(is_l || (uint) val != val) {
- X n=mknode_const(src_pos,ctype_long) ;
- X n->cnst.u.rval_long=(long) val ;
- X }
- X else
- X if(is_u || (int) val < 0) {
- X n=mknode_const(src_pos,ctype_uint) ;
- X n->cnst.u.rval_uint=(uint) val ;
- X }
- X else {
- X n=mknode_const(src_pos,ctype_int) ;
- X n->cnst.u.rval_int=(int) val ;
- X }
- X strncpyz(n->cnst.symb_val,lexptr,p-lexptr); /* save the symbolic val*/
- X lexptr=p ;
- X return n ;
- X}
- X
- XLFUNC tnode* duel_lex_float(void) /* parse next token as float num */
- X{
- X tnode *n=0 ;
- X char *p=lexptr ;
- X double val ;
- X char c,tmpc ;
- X bool ok=TRUE;
- X int src_pos = lexptr - inputstr ;
- X
- X /* this is disgusting.. why isnt there a lib call to recognize floats?! */
- X while(isdigit(*p)) p++ ;
- X if(*p=='.') p++ ;
- X while(isdigit(*p)) p++ ;
- X if(*p=='e' || *p=='E') {
- X p++ ;
- X if(*p=='+' || *p=='-') p++ ;
- X if(!isdigit(*p)) ok=FALSE ; /* force digit (scanf allows 1e-.2 ?!) */
- X while(isdigit(*p)) p++ ;
- X }
- X tmpc= *p ; *p=0 ;
- X ok=ok && sscanf(lexptr,"%lf%c",&val,&c)==1 ;
- X *p=tmpc ;
- X if(!ok) yyerror("Invalid float constant.");
- X
- X n=mknode_const(src_pos,ctype_double);
- X n->cnst.u.rval_double=val ;
- X strncpyz(n->cnst.symb_val,lexptr,p-lexptr); /* save the symbolic val*/
- X lexptr=p ;
- X return(n);
- X}
- X
- X/* parse_escaped_char -- parse an escaped char (e.g. '\n').
- X * lexptr expected to point to text right after the '\'.
- X * return: actual char value (e.g. 012 if 'n' or '012' is found.)
- X * lexptr is advanced after the espaced char.
- X */
- X
- XLFUNC char parse_escaped_char(void)
- X{
- X char retc ;
- X switch(lexptr[0]) {
- X case 'n': retc='\n' ; break ;
- X case 'r': retc='\r' ; break ;
- X case '0': case '1': case '2': case '3':
- X retc= (char) ((lexptr[0]-'0')*0100 + (lexptr[1]-'0')*010 +
- X (lexptr[2]-'0')) ;
- X lexptr+=2 ;
- X break ;
- X default: retc=lexptr[0] ; /* default also takes care of '\'' '\\' */
- X }
- X lexptr++ ;
- X return retc ;
- X}
- X
- X/* FUNC yylex -- return the next token to yacc.
- X * GLOBALS: lexptr point to the string we are parsing next. it is updated.
- X */
- X
- XLFUNC int yylex (void)
- X{
- X int c,i,src_pos ;
- X char *p ;
- X
- X for(c= *lexptr; c==' ' || c=='\t' || c=='\n' ; c= *++lexptr); /* skip blank*/
- X
- X src_pos = lexptr - inputstr ; /* current char being parsed */
- X yylval.opinfo.src_pos = src_pos ;
- X
- X for (i = 0; i < sizeof(tokens)/sizeof(struct stoken) ; i++) {
- X int l=strlen(tokens[i].opstr) ; /* check next token vs table */
- X if(strncmp(lexptr,tokens[i].opstr,l)==0) {
- X lexptr+=l ;
- X yylval.opinfo.opcode = tokens[i].opcode;
- X return tokens[i].token ;
- X }
- X }
- X
- X switch (c = *lexptr) {
- X case 0: return 0;
- X case '\'': /* char constant, but stored as int (ansi-c) */
- X p=lexptr++ ;
- X c = *lexptr++ ;
- X if (c == '\\') c=parse_escaped_char();
- X if( *lexptr++ != '\'') yyerror("Invalid character constant.");
- X yylval.node=mknode_const(src_pos,ctype_int) ;
- X yylval.node->cnst.u.rval_int=c ;
- X strncpyz(yylval.node->cnst.symb_val,p,lexptr-p); /*save the symbol. val*/
- X return T_CONST ;
- X
- X case '0': /* chk hex */
- X if(lexptr[1]=='x' || lexptr[1]=='X') {
- X yylval.node=duel_lex_int();
- X return T_CONST ;
- X }
- X /* fall thru for other numbers */
- X case '1': case '2': case '3': /* decimal or floating point number */
- X case '4': case '5': case '6': case '7': case '8': case '9':
- X for(p=lexptr ; *p>='0' && *p<='9' ; p++ ) ; /*find next non digit*/
- X if(*p=='.' && p[1]!='.' || *p=='e' || *p=='E')
- X yylval.node=duel_lex_float();
- X else yylval.node=duel_lex_int();
- X return T_CONST ;
- X
- X case '(': case ')':
- X case '<': case '>':
- X case '[': case ']':
- X case '{': case '}':
- X case '+': case '-': case '*': case '/': case '%':
- X case '|': case '&': case '^': case '~': case '!':
- X case ',': case '?': case ':': case '=':
- X case '.': case '@': case '$': case '#': case '`': case '\\':
- X lexptr++;
- X yylval.opinfo.opcode=c ;
- X return c;
- X case ';': { /* hack, ignore ';' before '}' and else. for C compatability*/
- X char *save_lexptr= ++lexptr ;
- X int tok=yylex() ; /* hack, call myself for next token */
- X if(tok=='}' || tok==T_ELSE) {
- X printf("warning: useless ';' ignored\n");
- X return tok ;
- X }
- X /* else restore position and return the ';' */
- X lexptr=save_lexptr ;
- X yylval.opinfo.opcode=';' ;
- X yylval.opinfo.src_pos = src_pos ;
- X return ';';
- X }
- X case '"': {
- X char s[512] ;
- X size_t len=0 ;
- X ttarget_ptr dptr ;
- X tnode *n ;
- X
- X p=lexptr++ ;
- X while((c= *lexptr++)!='"') {
- X if (c == '\\') c=parse_escaped_char();
- X s[len++]=c ;
- X }
- X s[len++]=0 ;
- X dptr=duel_alloc_target_space(len);
- X duel_put_target_bytes(dptr,s,len);
- X
- X n=mknode_const(src_pos,ctype_charptr);
- X n->cnst.u.rval_ptr=dptr ;
- X len=lexptr-p ;
- X if(len>60) len=60 ;
- X strncpyz(n->cnst.symb_val,p,len); /* save the symbolic val*/
- X yylval.node=n ;
- X return T_CONST ;
- X }
- X }
- X
- X if(c != '_' && !isalpha(c))
- X yyerror ("Invalid character in expression.");
- X
- X p=lexptr ;
- X do { c= *++lexptr ; } while(c=='_' || isalnum(c));
- X
- X for (i = 0; i < sizeof(keywords)/sizeof(struct skeyword) ; i++) {
- X int l=strlen(keywords[i].keyword_str) ; /* check next token vs keywords*/
- X if(l==lexptr-p && strncmp(p,keywords[i].keyword_str,l)==0) {
- X yylval.opinfo.opcode=keywords[i].opcode ;
- X return keywords[i].token ;
- X }
- X }
- X
- X /* the symbol/name found is not a reserved word, so return it as a T_SYM
- X */
- X
- X i=lexptr-p ; /* length of string found (symbol/name) */
- X yylval.nameinfo.src_pos=src_pos ;
- X yylval.nameinfo.name=duel_malloc(i+1);
- X strncpyz(yylval.nameinfo.name,p,i);
- X return T_SYM;
- X}
- X
- XLPROC yyerror(char *msg)
- X{
- X int i,n=lexptr-inputstr ;
- X printf("%s\n",inputstr);
- X for(i=0 ; i<n ; i++) printf("-");
- X printf("^ %s\n",msg);
- X}
- X
- X/*************************************************************************/
- X/* utility functions used to parse the expression and build it as a tree */
- X/*************************************************************************/
- X
- X/* mknode_op -- make a tree node of type op with given opcode and kids
- X */
- X
- XLFUNC tnode* mknode_op(top_kind op_kind,topinfo opinfo,
- X tnode *k1,tnode *k2,tnode *k3,tnode *k4)
- X{
- X tnode *n ;
- X duel_assert(opinfo.opcode>' ');
- X n=(tnode *) duel_malloc(sizeof(tnode));
- X duel_bzero((char*) n,sizeof(tnode));
- X n->node_kind=NK_OP ;
- X n->op_kind=op_kind ;
- X n->op=opinfo.opcode ;
- X n->src_pos=opinfo.src_pos ;
- X n->kids[0]=k1 ; n->kids[1]=k2 ; n->kids[2]=k3 ; n->kids[3]=k4 ;
- X return n ;
- X}
- X
- X
- X /* mknode_const -- make a constant node for the given type.
- X */
- X
- XLFUNC tnode* mknode_const(int src_pos,tctype *ctype)
- X{
- X tnode *n ;
- X n=(tnode *) duel_malloc(sizeof(tnode));
- X duel_bzero((char*) n,sizeof(tnode));
- X n->node_kind=NK_CONST ;
- X n->src_pos=src_pos ;
- X n->cnst.val_kind=VK_RVALUE ;
- X n->cnst.ctype=ctype ;
- X return n ;
- X}
- X
- X /* mknode_ctype -- make a node of the given c-type.
- X */
- X
- XLFUNC tnode* mknode_ctype(tctype *ctype)
- X{
- X tnode *n ;
- X n=(tnode *) duel_malloc(sizeof(tnode));
- X duel_bzero((char*) n,sizeof(tnode));
- X n->node_kind=NK_CTYPE ;
- X n->ctype=ctype ;
- X return n ;
- X}
- X
- X /* mknode_name -- make a node of the given name/symbol.
- X * input is pointer to the saved name (on heap)
- X */
- X
- XLFUNC tnode* mknode_name(tnameinfo nameinfo)
- X{
- X tnode *n ;
- X n=(tnode *) duel_malloc(sizeof(tnode));
- X duel_bzero((char*) n,sizeof(tnode));
- X n->node_kind=NK_NAME ;
- X n->name=nameinfo.name ;
- X n->src_pos=nameinfo.src_pos ;
- X return n ;
- X}
- X
- X/* In order to parse C types, which are 'reversed' in the parser, a stack
- X * is used to push abstract declarators, e.g. in (*)() we first push a func
- X * indicator '(' and then push a pointer indicator '*'. for arrays we push
- X * a '[' and the array size.
- X * This stack is popped and a ctype is constructed at the end of the
- X * abstract type parsing. The following functions implement the stack
- X */
- X
- Xtypedef struct stype_desc { /* stack of type descriptors is made of these */
- X char desc ;
- X int size ;
- X struct stype_desc *next ; /* next on stack */
- X } ttype_desc ;
- X
- Xttype_desc *top = 0 ;
- X
- X
- XLPROC push_type(char desc) /* put desc on the types stack */
- X{
- X ttype_desc *p = (ttype_desc* ) duel_malloc(sizeof(ttype_desc));
- X p->desc=desc ;
- X p->size=0 ;
- X p->next=top ;
- X top=p ;
- X}
- X
- X/* push_type_int -- same as push_type but also set the size parameter, which
- X * is given as a constant node (which is expected to be int)
- X */
- X
- XLPROC push_type_int(char desc,tnode *n)
- X{
- X duel_assert(n->node_kind==NK_CONST);
- X if(n->cnst.ctype != ctype_int ||
- X n->cnst.u.rval_int <=0 ) duel_gen_error("Illegal array size",0);
- X push_type(desc);
- X top->size=n->cnst.u.rval_int ;
- X}
- X
- XLFUNC bool pop_type(char *desc,int *size) /* pop item from stack. */
- X{
- X ttype_desc *p = top ;
- X if(p==0) return FALSE ;
- X *desc=p->desc ;
- X *size=p->size ;
- X top=p->next ;
- X duel_free(p) ;
- X return TRUE ;
- X}
- X
- X
- X/* abstract type-modifiers were pushed on a stack. Retrieve
- X * them (reversed) creating type nodes as we go
- X * input: base type (e.g. 'long').
- X * returns: node of the modified type.
- X * modification is based on the stack of things pushed while parsing.
- X */
- X
- XLFUNC tnode* mknode_modified_ctype(tctype *base)
- X{
- X int size;
- X char tdesc ; /* descriptor of abs decl eg '*' */
- X tctype *t=base ; /* type under construction */
- X
- X while(pop_type(&tdesc,&size)) /* pop next abs decl */
- X switch (tdesc) {
- X case '*': t=duel_mkctype_ptr(t); break ;
- X case '(': t=duel_mkctype_func(t); break ;
- X case '[': t=duel_mkctype_array(t,size); break ;
- X }
- X return mknode_ctype(t) ;
- X}
- X
- X/* entry point for parsing. the given expression is parsed into the given
- X * node as root.
- X */
- X
- XFUNC tnode* duel_parse(char *s)
- X{
- X lexptr=inputstr=s ;
- X top=0 ; /* reset the types stack */
- X if(duel_yyparse()) root=NULL ;
- X return root ;
- X}
- SHAR_EOF
- $TOUCH -am 0113165193 src/parse.y &&
- chmod 0644 src/parse.y ||
- echo "restore of src/parse.y failed"
- set `wc -c src/parse.y`;Wc_c=$1
- if test "$Wc_c" != "29171"; then
- echo original size 29171, current size $Wc_c
- fi
- echo "End of part 3, continue with part 4"
- exit 0
-