diff options
author | 2008-04-07 23:00:12 +0000 | |
---|---|---|
committer | 2008-04-07 23:00:12 +0000 | |
commit | 38454e6310c6e9e679b6171d2007e40b46cd513c (patch) | |
tree | fd9587c8d8aca71c85a0903a4313f62a6ed29969 /src/patchsets/gdb | |
parent | make sure stupid cvs keywords dont screw up our patches (diff) | |
download | gentoo-38454e6310c6e9e679b6171d2007e40b46cd513c.tar.gz gentoo-38454e6310c6e9e679b6171d2007e40b46cd513c.tar.bz2 gentoo-38454e6310c6e9e679b6171d2007e40b46cd513c.zip |
punt to readd with -kb
Diffstat (limited to 'src/patchsets/gdb')
-rw-r--r-- | src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch | 12130 | ||||
-rw-r--r-- | src/patchsets/gdb/6.8/11_all_gdb-6.6-duel-integrate.patch | 59 |
2 files changed, 0 insertions, 12189 deletions
diff --git a/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch b/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch deleted file mode 100644 index 1abd30b0c9..0000000000 --- a/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch +++ /dev/null @@ -1,12130 +0,0 @@ -Add support for DUEL to gdb. -ftp://ftp.cs.princeton.edu/pub/duel/ - -To make changes: - - patch -p0 < gdb-duel.patch - - cd gdb/duel - - <make changes> - - ./create-patch.sh - -Diffstat: - duel/MANUAL | 501 +++++++ - duel/Makefile | 32 - duel/README | 57 - duel/WHATNEW | 38 - duel/create-patch.sh | 34 - duel/duel.1 | 547 ++++++++ - duel/duel.c | 682 ++++++++++ - duel/duel.h | 35 - duel/duel.pipe | 107 + - duel/duelself.c | 209 +++ - duel/error.c | 112 + - duel/eval.c | 832 ++++++++++++ - duel/evalops.c | 1273 +++++++++++++++++++ - duel/global.h | 450 ++++++ - duel/internals.doc | 129 + - duel/misc.c | 142 ++ - duel/output.c | 53 - duel/output2.c | 141 ++ - duel/parse.c | 3326 +++++++++++++++++++++++++++++++++++++++++++++++++++ - duel/parse.y | 940 ++++++++++++++ - duel/patchlevel.h | 7 - duel/print.c | 299 ++++ - duel/proto.h | 101 + - duel/tsuite.c | 64 - duel/tsuite.gdb | 126 + - duel/tsuite.gdb.out | 293 ++++ - duel/tsuite.self | 111 + - duel/tsuite.self.out | 263 ++++ - duel/types.c | 200 +++ - duel/wishlist.doc | 160 ++ - duelgdb.c | 694 ++++++++++ - 31 files changed, 11958 insertions(+) - ---- gdb/duel/MANUAL -+++ gdb/duel/MANUAL -@@ -0,0 +1,501 @@ -+ -+ -+ -+ DDDDuuuueeeellll((((1111)))) VVVVeeeerrrrssssiiiioooonnnn 1111....11110000 ((((MMMMaaaarrrr 99993333)))) DDDDuuuueeeellll((((1111)))) -+ -+ -+ -+ NNNNAAAAMMMMEEEE -+ duel - A high level C debugging language extension to gdb -+ -+ SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS -+ dddduuuueeeellll [gdb options] [_p_r_o_g[_c_o_r_e|_p_r_o_c_I_D]] -+ -+ DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN -+ Duel is a special purpose language designed for concise state -+ exploration of debugged C programs, currently implemented under the -+ GNU debugger _g_d_b(1). Duel is invoked by entering the shell command -+ _d_u_e_l instead of _g_d_b. It is identical to gdb except for comments, which -+ begin with `##' instead of `#', and the new _d_l command for Duel -+ expressions: -+ -+ _g_d_b> dl x[1..10] >? 5 -+ x[3] = 14 -+ x[8] = 6 -+ -+ prints the array elements x[1] to x[10] that are greater than 5. The -+ output includes the values 14 and 6, as well as their symbolic -+ representation "x[3]" and "x[8]". -+ -+ IIIIFFFF YYYYOOOOUUUU NNNNEEEEVVVVEEEERRRR UUUUSSSSEEEEDDDD GGGGDDDDBBBB -+ The improved functionality added by Duel merits a fresh look even by -+ debugger shunners. Gdb is a powerful debugger with many commands, a -+ thick manual and various interfaces including _e_m_a_c_s(1) and _x_x_g_d_b(1). -+ These gdb commands should help you get started: -+ -+ _b _l_i_n_e set a breakpoint at the line (b func to break at a function) -+ _d _n delete breakpoint number n (gdb prints n when bp occurs) -+ _l _l_i_n_e list the source beginning at line (l file.c:line for module) -+ _r _p_a_r_m run/restart the program with the given parameters -+ _s single-step to the next statement (steps into function calls) -+ _n single-step to the next line, skipping over function calls -+ _c continue execution -+ _b_t show a stack trace -+ _p _e_x_p evaluate a symbolic expression -+ _d_l _e_x_p evaluate a Duel expression -+ _d_l _g_d_b give a gdb command summary -+ -+ The most common use is `b func' followed by `r' followed by several -+ `n' and `s', evaluating expressions in between. -+ -+ DDDDUUUUEEEELLLL QQQQUUUUIIIICCCCKKKK SSSSTTTTAAAARRRRTTTT -+ Duel is implemented by adding the _d_l command to gdb. All gdb commands -+ work as before. The dl command, however, is interpreted by duel. Gdb -+ concepts (such as the value history) do not work in the dl command, -+ and duel concepts are not understood by other gdb command. -+ -+ Duel is based on expressions which return multiple values. The x..y -+ operator returns the integers from x to y; the x,y operator returns x -+ and then y, e.g. -+ -+ _g_d_b> dl (1,9,12..15,22) -+ -+ prints 1, 9, 12, 13, 14, 15 and 22. Such expressions can be used -+ wherever a single value is used, e.g. -+ -+ _g_d_b> dl x[0..99]=0 ; -+ -+ assigns zero to the first 100 elements of array x. The semantics of -+ x[i] are the same as in C. They are applied for each of the values -+ returned by 0..99, which can be thought of as an implied external -+ loop. The trailing semicolon indicates evaluation for side-effects -+ only, with no output. Duel incorporates C operators, casts C -+ statements as expressions, and supports limited variable declaration: -+ -+ _g_d_b> dl int i;for(i=0;i<100;i++) -+ if(x[i]<0) printf("x[%d]=%d\n",i,x[i]); -+ x[7] = -4 -+ -+ The semicolon prevents Duel output; only output from printf is -+ printed. Aliases are defined with x:=y and provide an alternative to -+ variable declaration. We could also return x[i] instead of using -+ printf: -+ -+ _g_d_b> dl if(x[i:=0..99]<0) x[i] -+ x[i] = -4 -+ -+ The symbolic output "x[i]" can be fixed by surrounding i with {}, i.e. -+ -+ _g_d_b> dl if(x[i:=0..99]<0) x[{i}] -+ x[7] = -4 -+ -+ The {} are like (), but force the symbolic evaluation to use i's -+ value, instead of "i". You can usually avoid this altogether with -+ direct Duel operators: -+ -+ _g_d_b> dl x[..100] <? 0 -+ x[7] = -4 -+ -+ The ..n operator is a shorthand for 0..n-1, i.e. ..100 is the same as -+ 0..99. The x<?y, x==?y, x>=?y, etc., operators compare their left -+ side operand to their right side operand as in C, but return the left -+ side value if the comparison result is true. Otherwise, they look for -+ the next values to compare, without returning anything. -+ -+ Duel's x.y and x->y allow an expression y, evaluated under x's scope: -+ -+ _g_d_b> dl emp[..100].(if(code>400) (code,name)) -+ emp[46].code = 682 -+ emp[46].name = "Ela" -+ -+ The if() expression is evaluated under the scope of each element of -+ emp[], an array of structures. In C terms, we had to write: -+ -+ _g_d_b> dl int i; for(i=0; i<100 ; i++) -+ if(emp[i].code>400) emp[{i}].code,emp[{i}].name -+ -+ A useful alternative to loops is the x=>y operator. It returns y for -+ each value of x, setting `_' to reference x's value, e.g. -+ -+ _g_d_b> ..100 => if(emp[_].code>400) emp[_].code,emp[_].name -+ -+ Using `_' instead of `i' also avoids the need for {i}. Finally, the -+ x-->y operator expands lists and other data structures. If head points -+ to a linked list threaded through the next field, then: -+ -+ _g_d_b> dl head-->next->data -+ head->data = 12 -+ head->next->data = 14 -+ head-->next[[2]]->data = 20 -+ head-->next[[3]]->data = 26 -+ -+ produce the data field for each node in the list. x-->y returns x, x- -+ >y, x->y->y, x->y->y->y, ... until a NULL is found. The symbolic -+ output "x-->y[[n]]" indicates that ->y was applied n times. x[[y]] is -+ also the selection operator: -+ -+ _g_d_b> dl head-->next[[50..60]]->data -+ -+ return the 50th through the 60th elements in the list. The #/x -+ operator counts the number of values, so -+ -+ _g_d_b> dl #/( head-->next->data >? 50 ) -+ -+ counts the number of data elements over 50 on the list. Several other -+ operators, including x@y, x#y and active call stack access are -+ described in the operators section. -+ -+ OOOOPPPPEEEERRRRAAAATTTTOOOORRRRSSSS SSSSUUUUMMMMMMMMAAAARRRRYYYY -+ Assoc Operators Details -+ left {} () [] -> . f() --> x-->y expands x->y x->y->y ... -+ x[[y]] x#y x@y generate x; select, index or stop-at y -+ right #/ - * & ! ~ ++ -- (cast) #/x number of x values -+ frame(n) sizeof(x) reference to call stack level n -+ left x/y x*y x%y multiply, divide, reminder -+ left x-y x+y add, subtract -+ left x<<y x>>y shift left/right -+ none x..y ..y x.. ..y = 0..y-1. x..y return x, x+1...y -+ left < > <= >= <? >? <=? >=? x>?y return x if x>y -+ left == != ==? !=? x==?y return x if x==y -+ left x&y bit-and -+ left x^y bit-xor -+ left x|y bit-or -+ left x&&y &&/x &&/x are all x values non-zero? -+ left x||y ||/x ||/x is any x value non-zero? -+ right x? y:z foreach x, if(x) y else z -+ right x:=y x=y x+=y ... x:=y set x as an alias to y -+ left x,y return x, then y -+ right x=>y foreach x, evaluate y with x value `_' -+ right if() else while() for() C statements cast as operators -+ left x;y evaluate and ignore x, return y -+ -+ -+ EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS -+ dl (0xff-0x12)*3 compute simple expression -+ dl (1..10)*(1..10) display multiplication table -+ dl x[10..20,22,24,40..60] display x[i] for the selected indexes -+ dl x[9..0] display x[i] backwards -+ dl x[..100] >? 5 display x[i] that are greater than 5 -+ dl x[..100] >? 5 <? 10 display x[i] if 5<x[i]<10 -+ dl x[..100] ==? (6..9) same -+ dl x[0..99]=>if(_>5 && _<10) _ same -+ dl y[x[..100] !=? 0] display y[x[i]] for each non-zero x[i] -+ dl emp[..50].code display emp[i].code for i=0 to 49 -+ dl emp[..50].(code,name) display emp[i].code & emp[i].name -+ dl val[..50].(is_dbl? x:y) display val[i].x or val[i].y depending -+ on val[i].is_dbl. -+ dl val[..50].if(is_dbl) x else y same as above -+ dl x[..100]=0 ; assign 0 to x[i] -+ dl x[i:=..100]=y[i] ; assign y[i] to x[i] -+ dl x[..100]=y[..100] *ERR* assign y[99] to each x[j] -+ dl x[i:=..3]=(4,5,9)[[i]] assign x[0]=4 x[1]=5 x[2]=9 -+ dl x[..3]=(4,5,9) *ERR* assign 9 to each element -+ dl if(x[i:=..100]<0) x[i]=0 ; assign 0 to negative x[i] -+ dl (hash[..1024]!=?0)->scope hash[i].scope for non-null hash[i] -+ dl x[i:=..100] >? x[i+1] check if x[i] is not sorted -+ dl x[i:=..100] ==? x[j:=..100]=> checks if x has non-unique elements -+ if(i<j) x[{i,j}] -+ dl if(x[i:=..99] == same -+ x[j:=i+1..99]) x[{i,j}] -+ dl (x[..100] >? 0)[[0]] the 1st (0th element) positive x[i] -+ dl (x[..100] >? 0)[[2]] return the 3rd positive x[i] -+ dl (x[..100] >? 0)[[..5]] return the first 5 positive x[i] -+ dl (x[0..] >? 6)[[0]] return the first x[i]>6, no limit on i -+ dl argv[0..]@0 argv[0] argv[1] .. until first null -+ dl x[0..]@-1 >? 9 x[0..n]>9 where n is first x[n]== -1 -+ dl emp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0 -+ -+ dl head-->next->val val of each element in a linked list -+ dl head-->next[[20]] the 21st element of a linked list -+ dl *head-->next[[20]] display above as a struct -+ dl strcmp(head-->next->msg, search linked list for a string -+ "testing") ==? 0 -+ dl #/head-->next count elements on a linked list -+ dl x-->y[[#/x-->y - 1]] last element of a linked list -+ dl x-->y[[#/x-->y - 10..1]] last 10 elements of a linked list -+ dl head-->next-> check if the list is sorted by val -+ if(next) val >? next->val -+ -+ dl head-->(next!=?head) expand cyclic linked list (tail->head) -+ dl head-->(next!=?_) handle termination with p->next==p -+ dl root-->(left,right)->key expand binary tree, show keys -+ dl root-->(left,right)->( check bin tree sorted by key -+ (left!=?0)->key>=?key, (right !=?0 )->key<=?key) -+ -+ dl (1000..=>if(&&/(2,3.._-1=>__%_ find first 10 primes over 1000 -+ ) _)[[..10]] -+ dl (T mytype) x convert x to user defined type mytype -+ dl (struct s*) x convert x to struct s pointer -+ dl if(x) y; else z *ERR* ';' must be followed by an expression -+ dl {x} y *ERR* '}' requires ';' if followed by exp -+ -+ SSSSEEEEMMMMAAAANNNNTTTTIIIICCCCSSSS -+ Duel's semantics are modeled after the Icon programming language. The -+ input consists of expressions which return sequences of values. C -+ statements are cast as expressions, too. Expressions are parsed into -+ abstract syntax trees, which are traversed during evaluation. The -+ evaluation of most nodes (operators) recursively evaluates the next -+ value for each operand, and then applies the operator to produce the -+ next result. Only one value is produced each time, and Duel's eval -+ function keeps a `state' for each node (backtracking, co-routines, -+ consumer-producer or threads are good metaphors for the evaluation -+ mechanism.) -+ -+ For example, in (5,3)+6..8, the evaluation of `+' first retrieves the -+ operands 5 and 6, to compute and return 5+6. Then 7, the next right -+ operand is retrieved and 5+7 is returned, followed by 5+8. Since -+ there are no other right operand value, the next left operand, 3 is -+ fetched. The right operand's computation is restarted returning 6, and -+ 3+6 is returned. The final return values are 3+7 and 3+8. -+ -+ The computation for operators like x>?y is similar, but when x<=y, the -+ next values are fetched instead of returning a value, forming the -+ basis for an implicit search. Operators like `..' return a sequence of -+ values for each pair of operands. For a better understanding of the -+ evaluation mechanism, see the USENIX Winter/93 conference paper "DUEL -+ - A Very High Level Debugging Language". -+ -+ Duel values follow the C semantics. A value is either an "lvalue" (can -+ be used as the left hand side of assignment), or an "rvalue". -+ Therefor, objects like arrays can not be directly manipulated -+ (However, operators like x..y can accomplish such tasks.) -+ -+ Duel types also follow the C semantics, with some important -+ differences. C types are checked statically; Duel types are checked -+ when operators are applied, e.g., (1,1.0)/2 returns 0 (int) and 0.5 -+ (double); (x,y).z returns x.z and y.z even if x and y are of different -+ types, as long as they both have a field z. -+ -+ Values and types of symbols are looked up at run-time (using gdb's -+ lookup rules), allowing dynamic scoping and types, but causing a -+ parsing problem: (x)(y) can be parsed as either a function call x(y) -+ or a cast (x)y; x*y can be parsed as a declaration of y as (x*) or as -+ multiplication. -+ -+ To avoid this ambiguity, the keyword T must precede a user defined -+ type. For example, if value is a typedef, C's (value (*)()) x is -+ written in Duel as: (T value (*)()) x. Types that begin with a -+ reserved keyword don't need T, e.g. (struct value*) x and (long *[5]) -+ y are accepted. As special cases, (type)x and (type*)x are accepted -+ but discouraged (it causes (printf)("hi"), which is valid in C, to -+ fail). A side effect is that "sizeof x" must be written as sizeof(x). -+ -+ OOOOPPPPEEEERRRRAAAATTTTOOOORRRRSSSS -+ _x+_y _x-_y _x*_y _x/_y _x%_y _x^_y _x|_y _x&_y _x<<_y _x>>_y -+ _x>_y _x<_y _x>=_y _x<=_y _x==_y _x!=_y _x=_y _x[_y] -+ -+ These binary operators follow their C semantics. For each value of x, -+ they are evaluated for every value of y, .e.g. (5,2)>(4,1) evaluates -+ as 5>4, 5>1, 2>4, 2>1 returning 1, 1, 0, 1. The y values are re- -+ evaluated for each new value of x, e.g. i=4; (4,5)>i++ evaluates as -+ 4>4 and 5>5. Beware of multiple y values in assignment, e.g. -+ x[..3]=(4,6,9) does not set x[0]=4, x[1]=6 and x[2]=9. It assigns 4, 6 -+ and 9 to each element, having the same effect as x[..3]=9. Use -+ x[i:=..3]=(4,6,9)[[i]] to achieve the desired effect. -+ -+ -_x ~_x &_x *_x !_x ++_x --_x _x++ _x-- _s_i_z_e_o_f(_x) (_t_y_p_e)_x -+ -+ These unary operators follow their C semantics. They are applied to -+ each value of x. The increment and decrement operators require an -+ lvalue, so i:=0 ; i++ produces an error because i is an alias to 0, an -+ rvalue. Parenthesis must be used with sizeof(x), "sizeof x" is not -+ allowed. Cast to user defined type requires generally requires T, -+ e.g., -+ (T val(*)())x, but (val)x and (val*)x are accepted as special cases. -+ -+ _x&&_y _x||_y -+ -+ These logical operators also follow their C semantics, but have non- -+ intuitive results for multi-valued x and y, e.g. (1,0,0) || (1,0) -+ returns 1,1,0,1,0 -- the right hand-side (1,0) is returned for each -+ left-hand side 0. It is best to use these operators only in single -+ value expressions. -+ -+ _x? _y:_z _i_f(_x)_y _i_f(_x)_y _e_l_s_e _z -+ -+ These expressions return the values of y for each non-zero value -+ returned by x, and the values of z for each zero value returned by x, -+ e.g. if(x[..100]==0) y returns y for every x[i]==0, not if all x[i] -+ are zero (if(&&/(x[..100]==0)) y does that). Also, "if(x) y; else z" -+ is illegal. Duel's semicolon is an expression separator, not a -+ terminator. -+ -+ _w_h_i_l_e(_x)_y _f_o_r(_w;_x;_y)_z -+ -+ The while(x)y expression returns y as long as all values of x are -+ non-zero. The for() expression is similar and both have the expected -+ C semantics. For example, "for(i=0 ; i<100 ; i++) x[i]" is the same as -+ x[..100]. Unlike the if() expression, while(x[..100]==0) continue to -+ execute only if all elements of x are zero, i.e. the condition is -+ evaluated into a single value using an implicit &&/x. -+ -+ VVVVaaaarrrriiiiaaaabbbblllleeee ddddeeeeccccllllaaaarrrraaaattttiiiioooonnnn:::: _t_y_p_e _n_a_m_e [,_n_a_m_e ...] ; ... -+ -+ Expressions can begin with variables declaration (but not -+ initialization). Internally, a declaration sets an alias to space -+ allocated in the target by calling malloc(), e.g. `int x' is the same -+ as "x:= *(int *) malloc(sizeof(int))". This is oblivious to the user. -+ The allocated memory is not claimed when a variable is redeclared. -+ Declared variables addresses can be passed to functions and used in -+ other data structures. The keyword `T' must precede user defined types -+ (typedef), e.g. if val is a user defined type, The C code "val -+ *p=(val*) x" becomes "T val *p; p=(T val *) x" in Duel. -+ -+ FFFFuuuunnnnccccttttiiiioooonnnn ccccaaaallllllllssss:::: _f_u_n_c(_p_a_r_m,...) -+ -+ Function calls to the debugged program can be intermixed with Duel -+ code. Multi-valued parameters are handled as with binary operators. -+ The call value can have multiple values, e.g. (x,y)() calls x() and -+ y(). Currently, struct/union parameters and return values are not -+ supported. -+ -+ _x,_y _x.._y .._x _x.. -+ -+ These operators produce multiple values for single value operands. x,y -+ returns x, then y. x..y returns the integers from x to y. When x>y the -+ sequence is returned in descending order, i.e. 5..3 returns 5, 4, 3. -+ The operator ..x is a shorthand for 0..x-1, e.g. ..3 returns 0, 1, 2. -+ The x.. operator is a shorthand for x..maxint. It returns increasing -+ integer values starting at x indefinitely, and should be bounded by -+ [[n]] or @n operators. `,' retains its precedence level in C. The -+ precedence of `..' is above `<' and below arithmetic operators, so -+ 0..n-1 and x==1..9 work as expected. -+ -+ _x<?_y _x>?_y _x>=?_y _x<=?_y _x!=?_y _x==?_y -+ -+ These operators work like their C counterparts but return x if the -+ comparison is true. If the comparison is false, the next (x,y) value -+ is tried, forming the basis of an implicit search. -+ -+ (_x) {_x} _x;_y _x=>_y -+ -+ Both () and {} act as C parenthesis. The curly braces set the returned -+ symbolic value as the actual value, e.g. if i=5 and x[5]=3, then x[i] -+ produces the output "x[i] = 3", x[{i}] produces "x[5] = 3" and {x[i]} -+ produces just "3". The semicolon is an operator. x;y evaluates x, -+ ignoring the results, then evaluate and return y, e.g. (i:=1..3 ; i+5) -+ sets i to 3 and return 8. The x=>y operator evaluate and return y for -+ each value of x, e.g. (i:=1..3 => i+5) returns 6, 7 and 8. The value -+ returned by x is also stored implicitly in `_' which can be used in y, -+ e.g. 1..5 => z[_][_] will output z[1][1], z[2][2] etc. The symbolic -+ value for _ is that of the left side value, hence {_} is not needed. -+ Semicolon has the lowest precedence, so it must be used inside () or -+ {} for compound expressions. The precedence of `=>' is just below `,'. -+ Beware that "if(a) x; else {y;} z" is illegal; a semicolon is not -+ allowed before '}' or 'else' and must be inserted before z. -+ -+ _x->_y _x._y -+ -+ These expression work as in C for a symbol y. If y is an expression, -+ it is evaluated under the scope of x. e.g. x.(a+b) is the same as -+ x.a+x.b, if a and b are field of x (if they are not, they are looked -+ up as local or global variables). x may return multiple values of -+ different types, e.g. (u,v).a returns u.a and v.a, even if u and v are -+ different structures. Also, the value of x is available as `_' inside -+ y, e.g. x[..100].(if(a) _) produces x[i] for each x[i].a!=0. Nested -+ x.y are allowed, e.g. u.(v.(a+b)) would lookup a and b first under v, -+ then under u. -+ -+ AAAAlllliiiiaaaasssseeeessss:::: _x:=_y -+ -+ Aliases store a reference to y in x. Any reference to x is then -+ replaced by y. If y is a constant or an rvalue, its value is replaced -+ for x. If y is an lvalue (e.g. a variable), a reference to same lvalue -+ is returned. for example, x:=emp[5] ; x=9 assigns 9 to emp[5]. -+ Aliases retain their values across invocation of the "dl" command. An -+ alias to a local variable will reference a stray address when the -+ variable goes out of scope. The special command "dl clear" delete all -+ the aliases, and "dl alias" show all current aliases. Symbols are -+ looked up as aliases first, so an alias x will hide a local x. -+ -+ _x-->_y -+ -+ The expansion operator x-->y expands a data structure x following the -+ y links. It returns x, x->y, x->y->y, until a null is found. If x is -+ null, no values are produced. If y returns multiple values, they are -+ stacked and each is further expanded in a depth-first notion. For -+ example, if r is the root of a tree with children u->childs[..u- -+ >nchilds], then u-->(childs[..nchilds]) expands the whole tree. y is -+ an arbitrary expression, evaluated exactly like x->y (this includes -+ `_'.) -+ -+ _x@_y -+ -+ The expression x@y produces the values of x until x.y is non-zero, -+ e.g. for(i=0 ; x[i].code!= -1 && i<100 ; i++) x[i] can be written as -+ x[..100]@(code==-1). The evaluation of x is stopped as soon as y -+ evaluates to true. x->y or x=>y are used to evaluate y when x is not a -+ struct or a union. If y is a constant,(_==y) is used. e.g. s[0..]@0 -+ produces the characters in string s up to but not including the -+ terminating null. -+ -+ #/_x &&/_x ||/_x -+ -+ These operator return a single "summary" value for all the values -+ returned by x. #/x returns the number of values returned by x, e.g. -+ #/(x[..100]>?0) counts the number of positive x[i]. &&/x returns 1 if -+ all the values produced by x are non-zero, and ||/x returns 1 if any -+ of x's values are non-zero. Like in C, the evaluation stops as soon as -+ possible. For example, ||/(x[..100]==0) and &&/(x[..100]==0) check if -+ one or all of x[i] are zero, respectively. -+ -+ _x#_y _x[[_y]] -+ -+ The operator x#y produces the values of x and arranges for y to be an -+ alias for the index of each value in x. It is commonly used with x-->y -+ to produce the element's index, e.g. head-->next->val#i=i assigns -+ each val field its element number in the list. -+ The selection operator x[[y]] produces the yth result of x. If y -+ returns multiple value, each select a value of x, e.g. -+ (5,7,11,13)[3,0,2] returns 13, 5 and 11 (13 is the 3rd element, 5 is -+ the 0th element). Don't use side effects in x, since its evaluation -+ can be restarted depending on y, e.g. after (x[0..i++])[[3,5]] the -+ value of i is unpredictable. -+ -+ _f_r_a_m_e(_n) _f_r_a_m_e_s__n_o _f_u_n_c._x -+ -+ frame(n) for an integer n returns a reference to the nth frame on the -+ stack (0 is the inner most function and frame(frames_no-1) is main()). -+ Frame values can be compared to function pointers, e.g. -+ frame(3)==myfunc is true if the 4th frame is a call to myfunc, and in -+ scope resolution, e.g. frame(3).x return the local variable x of the -+ 4th frame. frames_no is the number of active frames on the stack, -+ e.g. (frames(..frames_no) ==? myfunc).x displays x for all active -+ invocations of myfunc. As a special case, -+ (frames(..frames_no)==?f)[[0]].x can be written as f.x (x can be an -+ expression). -+ -+ -+ BBBBUUUUGGGGSSSS -+ Both `{}' and `;' are operators, not statements or expression -+ separators; "if(x) y; else {z;} u" is illegal; use "if(x) y else {z} ; -+ u". Ambiguities require preceding user-defined types (typedef) with -+ the keyword T, e.g., if value is a user type, C's "sizeof(value*)" is -+ written "sizeof(T value*)", except for the casts "(t)x" and "(t*)x"; -+ sizeof(x) requires parenthesis for variable x. -+ -+ Unimplemented C idiom include: modified-assignment (x+=y), switch, -+ break, continue, do, goto, scopes, function declarations, initializing -+ declared variables, assignment to bit-fields and register variables, -+ and calling functions with a struct/union parameter or return value. -+ gdb does not store function prototypes, so parameters are not checked. -+ -+ Gdb itself is buggy, which shows up, especially in symbol tables and -+ calling target functions. Before you report bug, try to do the closest -+ thing under gdb's "print". Send bug to: mg@cs.princeton.edu. -+ -+ FFFFIIIILLLLEEEESSSS -+ duel.out tracks duel commands usage. Help analyze duel's use by -+ mailing a copy to mg@cs.princeton.edu. -+ Duel is available by anonymous ftp at ftp.cs.princeton.edu:/duel. -+ -+ AAAAUUUUTTTTHHHHOOOORRRR -+ Duel is public domain code -- no copy left or right. See the internals -+ documentation for details on porting Duel and using its code. Duel -+ was designed and written by Michael Golan as part of a PhD thesis in -+ the Computer Science Department of Princeton University. I would like -+ to thank my advisor, Dave Hanson, who helped in all phases of this -+ project and to Matt Blaze for his support and useful insight. -+ -+ Duel stands for Debugging U (might) Even Like, or Don't Use this -+ Exotic Language. Judge for yourself! ---- gdb/duel/Makefile -+++ gdb/duel/Makefile -@@ -0,0 +1,32 @@ -+# -+# generic makefile for Duel 1.10 -+# nothing fancy is required: yacc/bison of parse.y, compile all other modules, -+# and put all of the OBJ= modules into duel.a library. -+# gdb is compiled with its own makefile (you add duel.a and duelgdb.c) -+# selfduel, for testing, is compiled and linked with duel.a -+ -+AR ?= ar -+RANLIB ?= ranlib -+ -+OBJ = duel.o types.o eval.o misc.o parse.o error.o evalops.o print.o -+ -+all: duel.a duelself -+ -+duelself: duel.a output.o -+ -+duel.a: $(OBJ) -+ $(AR) rc $@ $^ -+ $(RANLIB) $@ -+ -+parse.c: parse.y -+ bison -o $@ $^ -+ -+clean distclean: -+ rm -f $(OBJ) y.tab.c parse.c duelself.o duelself duel.a -+ -+install: -+ -+test: duelself -+ duelself <tsuite.self >self.out -+ @echo NOTE: diffs of the @xxxx values are ok -+ diff tsuite.self.out self.out ---- gdb/duel/README -+++ gdb/duel/README -@@ -0,0 +1,57 @@ -+------------------------------------------------------------------------------- -+README for DUEL 1.10 distribution mg@cs.princeton.edu (M. Golan) Mar 93 -+------------------------------------------------------------------------------- -+see WHATNEW for what's new in version 1.10. -+ -+DUEL - A high level language for debugging C programs. -+ -+ Duel is a special purpose language designed for concise state -+ exploration of debugged C programs under existing debuggers. -+ It allows you to explore your program's state better than either -+ the debugger's commands, a C interpreter, or print statements -+ added to your programs. The debugger is extended with the new -+ 'dl' command for Duel expressions, e.g., -+ -+ gdb> dl x[0..10].level >? 5 -+ x[3].level = 14 -+ x[8].level = 6 -+ -+ prints the "level" fields of array elements x[0] to x[10] that are greater -+ than 5. The output includes the values 14 and 6, as well as their -+ symbolic representation "x[3].level" and "x[8].level". Linked list and -+ other complex data structures are just as easy. Most of C (e.g. for, if) -+ is also supported, e.g., int i; for(i=0; i<11; i++) if(x[i].level>5) x[i]. -+ -+Even if you don't normally use debuggers, but you are programming in C, give -+Duel a try! The man page & help even include a summary of useful gdb commands. -+The man page (duel.1) contains an introduction & many examples. -+ -+Duel is debugger-independent, but the current distribution interface only -+with gdb. You will need the source for gdb-4.6, 4.7 or 4.8. Duel is public -+domain code. Do whatever you like with it - add it to commercial debuggers, -+to dbx/sdb or even make it part of the GNU project. -+ -+NO PART OF THIS DISTRIBUTION CONTAINS ANY COPYRIGHT OR DERIVED CODE, -+(i.e. no GPL code, either). Free and public domain code need no disclaimer, -+which is obvious to anyone in the software business. -+ -+Duel is available for anonymous ftp from ftp.cs.princeton.edu, in -+/duel/duel.tar.Z. "tar.Z" format means you should use the command -+ "zcat duel.tar.Z | tar xf -" to unpack the files. -+ -+The Usenix Jan/93 paper about Duel is also available as tech report 399, -+in /reports/1992/399.ps.Z on ftp.cs.princeton.edu, or, in it Usenix -+formatting, as /duel/usenix.paper.ps.Z. The software & man page are more -+up-to-date though. -+ -+See MANIFEST for a list of files in the distribution. The file INSTALL -+explains how to install duel. MANUAL is a formatted version of the manual -+duel.1. -+ -+If you are using duel and find it useful, or have any comments or suggestion, -+please drop me a line! duel.out is automatically produced to contain -+the dl commands you have used, I would appreciate it if you email it to -+me so that I could collect usage information. Thanks! -+ -+Michael Golan -+mg@cs.princeton.edu ---- gdb/duel/WHATNEW -+++ gdb/duel/WHATNEW -@@ -0,0 +1,38 @@ -+------------------------------------------------------------------------------- -+WHATNEW for DUEL 1.10 distribution mg@cs.princeton.edu (M. Golan) Mar 93 -+------------------------------------------------------------------------------- -+patch 1.10.4 fix use of system("date") to support OS/2 -+patch 1.10.3 bug fix left->left bad symbolic, long symbolics caused crash -+patch 1.10.2 bug fix (type*) casting was wrong -+patch 1.10.1 bug fix frame(0).bad_name crashed duel. enum size zero, -+ sometimes possible in symbol tables, now allowed. -+ -+What's New in version 1.10 -+-------------------------- -+Previously, all typedefs had to be preceded with 'T', e.g. (T uint) x. -+The parsing is now hacked, so that the most common cases don't require T: -+(type)x and (type*)x, e.g., (uint)x, *(value *)p. T is still required in -+complex casts like (T value (*)())p, in variable declaration "T uint x ;" -+and with sizeof(T uint). Side effects of this change: (printf)("hi\n") -+won't work, since (printf) is recognized as a cast. This shouldn't be a -+problem - you can use {x} for (x). Also, "sizeof x" is no longer supported, -+you must use sizeof(x) instead. -+ -+An experimental output control through a pipe has been added. To try it, -+you should change duel/src/Makefile to compile output2.o instead of output.o -+(delete duel.a to make sure it won't have both output.o and output2.o). -+When output2.o is linked into duelself and/or gdb, duel fork and execute -+the command duel.pipe in the current directory. All the output from expression -+evaluation is sent to this program and its output is displayed. An example -+duel.pipe, a Perl script, is provided. A lot that can be done with duel.pipe -+to process the results symbolically, e.g., display integers in decimal, -+place values on the same line, fork and execute xgraph, check -+for unique values, etc. I would appreciate any comments on its use. -+ -+A few minor bugs have been fixed. duel.man now contains a nicely formatted -+version of duel.1. Portability was improved. #/(x) provide a better symbolic -+expression. -+ -+What's new in version 1.02 -+-------------------------- -+a few bug fixed, improved portability, gdb4.8 support. ---- gdb/duel/create-patch.sh -+++ gdb/duel/create-patch.sh -@@ -0,0 +1,34 @@ -+#!/bin/sh -+ -+export LC_ALL=C # make sure order/sort is consistent -+ -+make -s clean -+make -s parse.c -+ -+cd ../.. -+mkdir -p empty/gdb/duel -+ -+diff -Nur empty/gdb gdb | \ -+ sed -r \ -+ -e '/^diff -Nur/d' \ -+ -e 's:^--- empty/gdb:--- gdb:' \ -+ -e '/^(---|\+\+\+) /s:\t.*::' \ -+ > gdb-duel.patch.bulk -+cat <<EOF > gdb-duel.patch -+Add support for DUEL to gdb. -+ftp://ftp.cs.princeton.edu/pub/duel/ -+ -+To make changes: -+ - patch -p0 < gdb-duel.patch -+ - cd gdb/duel -+ - <make changes> -+ - ./create-patch.sh -+ -+Diffstat: -+$(diffstat gdb-duel.patch.bulk) -+ -+$(cat gdb-duel.patch.bulk) -+EOF -+rm -r gdb-duel.patch.bulk empty -+ -+echo "updated patch now ready:" $(du -b gdb-duel.patch) ---- gdb/duel/duel.1 -+++ gdb/duel/duel.1 -@@ -0,0 +1,547 @@ -+'\" t -+.\" This document and the Duel source code are in the public domain. -+.\" Note that the duel executable contains GNU code and is not public domain. -+.TH Duel 1 "Mar 93" "Version 1.10" -+.SH NAME -+duel \- A high level C debugging language extension to gdb -+.SH SYNOPSIS -+.B duel -+[gdb options] -+.RB "[\|" \c -+.I prog\c -+.RB "[\|" \c -+.IR core \||\| procID\c -+\&\|]\&\|] -+.ad b -+.SH DESCRIPTION -+Duel is a special purpose language designed for concise state exploration -+of debugged C programs, currently implemented under the GNU debugger -+.IR gdb (1). -+Duel is invoked by entering the shell command -+.I duel -+instead of -+.I gdb. -+It is identical to gdb except for -+comments, which begin with `##' instead of `#', and the new -+.I dl -+command for Duel expressions: -+.nf -+ -+\f2gdb>\f1 dl x[1..10] >? 5 -+x[3] = 14 -+x[8] = 6 -+ -+.fi -+prints the array elements x[1] to x[10] that are greater than 5. -+The output includes the values 14 and 6, as well as their -+symbolic representation "x[3]" and "x[8]". -+.SH IF YOU NEVER USED GDB -+The improved functionality added by Duel merits a fresh look -+even by debugger shunners. -+Gdb is a powerful debugger with many commands, a thick manual and -+various interfaces including -+.IR emacs (1) -+and -+.IR xxgdb (1). -+These gdb commands should help you get started: -+ -+.TS -+l l. -+\f2b line\f1 set a breakpoint at the line (b func to break at a function) -+\f2d n\f1 delete breakpoint number n (gdb prints n when bp occurs) -+\f2l line\f1 list the source beginning at line (l file.c:line for module) -+\f2r parm\f1 run/restart the program with the given parameters -+\f2s\f1 single-step to the next statement (steps into function calls) -+\f2n\f1 single-step to the next line, skipping over function calls -+\f2c\f1 continue execution -+\f2bt\f1 show a stack trace -+\f2p exp\f1 evaluate a symbolic expression -+\f2dl exp\f1 evaluate a Duel expression -+\f2dl gdb\f1 give a gdb command summary -+.TE -+ -+The most common use is `b func' followed by `r' followed by several -+`n' and `s', evaluating expressions in between. -+.SH DUEL QUICK START -+Duel is implemented by adding the -+.I dl -+command to gdb. All gdb commands -+work as before. The dl command, however, is interpreted by duel. -+Gdb concepts (such as the value history) do not work in the dl command, -+and duel concepts are not understood by other gdb command. -+ -+Duel is based on expressions which return multiple values. -+The x..y operator returns -+the integers from x to y; the x,y operator returns x and then y, e.g. -+.sp -+\f2gdb>\f1 dl (1,9,12..15,22) -+.sp -+prints 1, 9, 12, 13, 14, 15 and 22. Such expressions can -+be used wherever a single value is used, e.g. -+.sp -+\f2gdb>\f1 dl x[0..99]=0 ; -+.sp -+assigns zero to the first 100 elements of array x. The semantics of x[i] -+are the same as in C. They are applied for each of the values -+returned by 0..99, which can be thought of as an implied external loop. -+The trailing semicolon indicates evaluation for side-effects only, with no -+output. -+Duel incorporates C operators, casts C statements as -+expressions, and supports limited variable declaration: -+.sp -+.br -+\f2gdb>\f1 dl int i;for(i=0;i<100;i++) -+.br -+ if(x[i]<0) printf("x[%d]=%d\\n",i,x[i]); -+.br -+x[7] = -4 -+.sp -+The semicolon prevents Duel output; -+only output from printf is printed. -+Aliases are defined with x:=y and provide an alternative to variable -+declaration. We could also return x[i] instead of using printf: -+.sp -+\f2gdb>\f1 dl if(x[i:=0..99]<0) x[i] -+.br -+x[i] = -4 -+.sp -+The symbolic output "x[i]" can be fixed by surrounding i with {}, i.e. -+.sp -+\f2gdb>\f1 dl if(x[i:=0..99]<0) x[{i}] -+.br -+x[7] = -4 -+.sp -+The {} are like (), but force the symbolic evaluation to use i's value, -+instead of "i". You can usually avoid this altogether -+with direct Duel operators: -+.sp -+\f2gdb>\f1 dl x[..100] <? 0 -+.br -+x[7] = -4 -+.sp -+The ..n operator is a shorthand for 0..n-1, i.e. ..100 is the same as 0..99. -+The x<?y, x==?y, x>=?y, etc., operators compare their left side operand to -+their right side operand as in C, but return the left side value if -+the comparison result is true. Otherwise, they look for the next -+values to compare, without returning anything. -+ -+Duel's x.y and x->y allow an expression y, evaluated under x's scope: -+.sp -+\f2gdb>\f1 dl emp[..100].(if(code>400) (code,name)) -+.br -+emp[46].code = 682 -+.br -+emp[46].name = "Ela" -+.sp -+The if() expression is evaluated under the scope of each element -+of emp[], an array of structures. In C terms, we had to write: -+.sp -+\f2gdb>\f1 dl int i; for(i=0; i<100 ; i++) -+.br -+ if(emp[i].code>400) emp[{i}].code,emp[{i}].name -+.sp -+A useful alternative to loops is the x=>y operator. It returns y for each -+value of x, setting `_' to reference x's value, e.g. -+.sp -+\f2gdb>\f1 ..100 => if(emp[_].code>400) emp[_].code,emp[_].name -+.sp -+Using `_' instead of `i' also avoids the need for {i}. Finally, -+the x\-\->y operator expands lists and other data structures. If head points -+to a linked list threaded through the next field, then: -+.sp -+\f2gdb>\f1 dl head-->next->data -+.br -+head->data = 12 -+.br -+head->next->data = 14 -+.br -+head-->next[[2]]->data = 20 -+.br -+head-->next[[3]]->data = 26 -+.sp -+produce the data field for each node in the list. x\-\->y -+returns x, x->y, x->y->y, x->y->y->y, ... until a NULL is found. -+The symbolic output "x\-\->y[[n]]" -+indicates that ->y was applied n times. x[[y]] is also the selection -+operator: -+.sp -+\f2gdb>\f1 dl head-->next[[50..60]]->data -+.sp -+return the 50th through the 60th elements in the list. The #/x operator -+counts the number of values, so -+.sp -+\f2gdb>\f1 dl #/( head-->next->data >? 50 ) -+.sp -+counts the number of data elements over 50 on the list. -+Several other operators, including x@y, x#y and -+active call stack access are described in the operators section. -+.SH OPERATORS SUMMARY -+.\"All the C operators have the same precedence and associativity as in C. C -+.\"statements have precedence just below `,' and `;' has the lowest precedence. -+.\"Most Duel operators have the same precedence as their C counterparts. The -+.\"following table is in decreasing precedence: -+.TS -+l l l. -+Assoc Operators Details -+left {} () [] -> . f() --> x-->y expands x->y x->y->y ... -+ x[[y]] x#y x@y generate x; select, index or stop-at y -+right #/ - * & ! ~ ++ -- (cast) #/x number of x values -+ frame(n) sizeof(x) reference to call stack level n -+left x/y x*y x%y multiply, divide, reminder -+left x-y x+y add, subtract -+left x<<y x>>y shift left/right -+none x..y ..y x.. ..y = 0..y-1. x..y return x, x+1...y -+left < > <= >= <? >? <=? >=? x>?y return x if x>y -+left == != ==? !=? x==?y return x if x==y -+left x&y bit-and -+left x^y bit-xor -+left x|y bit-or -+left x&&y &&/x &&/x are all x values non-zero? -+left x||y ||/x ||/x is any x value non-zero? -+right x? y:z foreach x, if(x) y else z -+right x:=y x=y x+=y ... x:=y set x as an alias to y -+left x,y return x, then y -+right x=>y foreach x, evaluate y with x value `_' -+right if() else while() for() C statements cast as operators -+left x;y evaluate and ignore x, return y -+.TE -+ -+.SH EXAMPLES -+.TS -+l l. -+dl (0xff-0x12)*3 compute simple expression -+dl (1..10)*(1..10) display multiplication table -+dl x[10..20,22,24,40..60] display x[i] for the selected indexes -+dl x[9..0] display x[i] backwards -+dl x[..100] >? 5 display x[i] that are greater than 5 -+dl x[..100] >? 5 <? 10 display x[i] if 5<x[i]<10 -+dl x[..100] ==? (6..9) same -+dl x[0..99]=>if(_>5 && _<10) _ same -+dl y[x[..100] !=? 0] display y[x[i]] for each non-zero x[i] -+dl emp[..50].code display emp[i].code for i=0 to 49 -+dl emp[..50].(code,name) display emp[i].code & emp[i].name -+dl val[..50].(is_dbl? x:y) display val[i].x or val[i].y depending -+ on val[i].is_dbl. -+dl val[..50].if(is_dbl) x else y same as above -+dl x[..100]=0 ; assign 0 to x[i] -+dl x[i:=..100]=y[i] ; assign y[i] to x[i] -+dl x[..100]=y[..100] *ERR* assign y[99] to each x[j] -+dl x[i:=..3]=(4,5,9)[[i]] assign x[0]=4 x[1]=5 x[2]=9 -+dl x[..3]=(4,5,9) *ERR* assign 9 to each element -+dl if(x[i:=..100]<0) x[i]=0 ; assign 0 to negative x[i] -+dl (hash[..1024]!=?0)->scope hash[i].scope for non-null hash[i] -+dl x[i:=..100] >? x[i+1] check if x[i] is not sorted -+dl x[i:=..100] ==? x[j:=..100]=> checks if x has non-unique elements -+ if(i<j) x[{i,j}] -+dl if(x[i:=..99] == same -+ x[j:=i+1..99]) x[{i,j}] -+dl (x[..100] >? 0)[[0]] the 1st (0th element) positive x[i] -+dl (x[..100] >? 0)[[2]] return the 3rd positive x[i] -+dl (x[..100] >? 0)[[..5]] return the first 5 positive x[i] -+dl (x[0..] >? 6)[[0]] return the first x[i]>6, no limit on i -+dl argv[0..]@0 argv[0] argv[1] .. until first null -+dl x[0..]@-1 >? 9 x[0..n]>9 where n is first x[n]== -1 -+dl emp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0 -+ -+dl head-->next->val val of each element in a linked list -+dl head-->next[[20]] the 21st element of a linked list -+dl *head-->next[[20]] display above as a struct -+dl strcmp(head-->next->msg, search linked list for a string -+ "testing") ==? 0 -+dl #/head-->next count elements on a linked list -+dl x-->y[[#/x-->y - 1]] last element of a linked list -+dl x-->y[[#/x-->y - 10..1]] last 10 elements of a linked list -+dl head-->next-> check if the list is sorted by val -+ if(next) val >? next->val -+ -+dl head-->(next!=?head) expand cyclic linked list (tail->head) -+dl head-->(next!=?_) handle termination with p->next==p -+dl root-->(left,right)->key expand binary tree, show keys -+dl root-->(left,right)->( check bin tree sorted by key -+ (left!=?0)->key>=?key, (right !=?0 )->key<=?key) -+ -+dl (1000..=>if(&&/(2,3.._-1=>__%_ find first 10 primes over 1000 -+ ) _)[[..10]] -+dl (T mytype) x convert x to user defined type mytype -+dl (struct s*) x convert x to struct s pointer -+dl if(x) y; else z *ERR* ';' must be followed by an expression -+dl {x} y *ERR* '}' requires ';' if followed by exp -+.TE -+.SH SEMANTICS -+Duel's semantics are modeled after the Icon programming language. -+The input consists of expressions which return sequences of values. -+C statements are cast as expressions, too. -+Expressions are parsed into abstract syntax trees, which are -+traversed during evaluation. The evaluation of most nodes (operators) -+recursively evaluates the next value for each operand, and then applies the -+operator to produce the next result. Only one value is produced each time, -+and Duel's eval function keeps a `state' for each node -+(backtracking, co-routines, consumer-producer or threads are good metaphors -+for the evaluation mechanism.) -+ -+For example, in (5,3)+6..8, the -+evaluation of `+' first retrieves the operands 5 and 6, to compute and -+return 5+6. Then 7, the next right operand is retrieved -+and 5+7 is returned, followed by 5+8. -+Since there are no other right operand value, the next left operand, 3 -+is fetched. The right operand's computation is restarted returning -+6, and 3+6 is returned. The final return values are 3+7 and 3+8. -+ -+The computation for operators like x>?y is similar, but when x<=y, -+the next values are fetched instead of returning a value, -+forming the basis for an implicit search. Operators like `..' return a -+sequence of values for each pair of operands. For a better understanding -+of the evaluation mechanism, see the USENIX Winter/93 conference paper -+"DUEL - A Very High Level Debugging Language". -+ -+Duel values follow the C semantics. A value is either an -+"lvalue" (can be used as the left hand side of assignment), or an "rvalue". -+Therefor, objects like arrays can not be directly manipulated (However, -+operators like x..y can accomplish such tasks.) -+ -+Duel types also follow the C semantics, with some important -+differences. C types are checked statically; Duel types are checked -+when operators are applied, e.g., (1,1.0)/2 returns 0 (int) and -+0.5 (double); (x,y).z returns x.z and y.z even if -+x and y are of different types, as long as they both have a field z. -+ -+Values and types of symbols are looked up at run-time (using gdb's lookup -+rules), allowing dynamic scoping and types, but causing a parsing -+problem: (x)(y) can be parsed as either a function call x(y) or a -+cast (x)y; x*y can be parsed as a declaration of y as (x*) or as -+multiplication. -+ -+To avoid this ambiguity, the -+keyword T must precede a user defined type. For example, -+if value is a typedef, C's (value (*)()) x is written in Duel as: -+(T value (*)()) x. Types that begin with a reserved keyword don't -+need T, e.g. (struct value*) x and (long *[5]) y are accepted. -+As special cases, (type)x and (type*)x are accepted but -+discouraged (it causes (printf)("hi"), which is valid in C, to fail). -+A side effect is that "sizeof x" must be written as sizeof(x). -+.SH OPERATORS -+.sp -+.I "x+y x-y x*y x/y x%y x^y x|y x&y x<<y x>>y " -+.br -+.I "x>y x<y x>=y x<=y x==y x!=y x=y x[y]" -+.sp -+These binary operators follow their C semantics. For each value of x, -+they are evaluated for every value of y, .e.g. (5,2)>(4,1) -+evaluates as 5>4, 5>1, 2>4, 2>1 returning 1, 1, 0, 1. -+The y values are re-evaluated for each new value of x, e.g. -+i=4; (4,5)>i++ evaluates as 4>4 and 5>5. -+Beware of multiple y values in assignment, e.g. x[..3]=(4,6,9) does not -+set x[0]=4, x[1]=6 and x[2]=9. It assigns 4, 6 and 9 to each element, having -+the same effect as x[..3]=9. Use x[i:=..3]=(4,6,9)[[i]] to achieve the -+desired effect. -+.sp -+.I "-x ~x &x *x !x ++x --x x++ x-- sizeof(x) (type)x" -+.sp -+These unary operators follow their C semantics. They are applied -+to each value of x. The increment and decrement operators require an -+lvalue, so i:=0 ; i++ produces an error because i is an alias to 0, -+an rvalue. Parenthesis must be used with sizeof(x), "sizeof x" is not -+allowed. Cast to user defined type requires generally requires T, e.g., -+ (T val(*)())x, but (val)x and (val*)x are accepted as special cases. -+.sp -+.I "x&&y x||y" -+.sp -+These logical operators also follow their C semantics, but have non-intuitive -+results for multi-valued x and y, e.g. (1,0,0) || (1,0) returns 1,1,0,1,0 -- -+the right hand-side (1,0) is returned for each left-hand side 0. It is best -+to use these operators only in single value expressions. -+.sp -+.I "x? y:z if(x)y if(x)y else z" -+.sp -+These expressions return the values of y for each non-zero value -+returned by x, and the values of z for each zero value returned by x, e.g. -+if(x[..100]==0) y returns y for every x[i]==0, not if all x[i] are zero -+(if(&&/(x[..100]==0)) y does that). -+Also, "if(x) y; else z" is illegal. Duel's semicolon is -+an expression separator, not a terminator. -+.sp -+.I "while(x)y for(w;x;y)z" -+.sp -+The while(x)y expression returns y as long as all values of x are non-zero. -+The for() expression is similar and both have the expected C semantics. For -+example, "for(i=0 ; i<100 ; i++) x[i]" is the same as x[..100]. Unlike -+the if() expression, while(x[..100]==0) continue to execute only if all -+elements of x are zero, i.e. the condition is evaluated into a single value -+using an implicit &&/x. -+.sp -+.BI "Variable declaration: " "type name [,name ...] ; ..." -+.sp -+Expressions can begin with variables declaration (but not initialization). -+Internally, a declaration sets an alias to space allocated -+in the target by calling malloc(), e.g. `int x' is the same as -+"x:= *(int *) malloc(sizeof(int))". This is oblivious to the user. -+The allocated memory is not claimed when a variable is redeclared. -+Declared variables addresses can be passed to functions and used in other -+data structures. The keyword `T' must precede user defined types (typedef), -+e.g. if val is a user defined type, The C code "val *p=(val*) x" becomes -+"T val *p; p=(T val *) x" in Duel. -+.sp -+.BI "Function calls: " "func(parm,...)" -+.sp -+Function calls to the debugged program can be intermixed with Duel -+code. Multi-valued parameters are handled as with binary operators. -+The call value can have multiple values, e.g. (x,y)() calls x() -+and y(). Currently, struct/union parameters and return values are not -+supported. -+.sp -+.I "x,y x..y ..x x.." -+.sp -+These operators produce multiple values for single value operands. -+x,y returns x, then y. x..y returns the integers from x to y. -+When x>y the sequence is returned in descending order, i.e. 5..3 -+returns 5, 4, 3. -+The operator ..x is a shorthand for 0..x-1, e.g. ..3 returns 0, 1, 2. -+The x.. operator is a shorthand for x..maxint. It returns increasing -+integer values starting at x indefinitely, and should be bounded -+by [[n]] or @n operators. -+`,' retains its precedence level in C. The precedence of `..' -+is above `<' and below arithmetic operators, so 0..n-1 and x==1..9 work -+as expected. -+.sp -+.I "x<?y x>?y x>=?y x<=?y x!=?y x==?y" -+.sp -+These operators work like their C counterparts but return x if the comparison -+is true. If the comparison is false, the next (x,y) value is tried, forming -+the basis of an implicit search. -+.sp -+.I "(x) {x} x;y x=>y" -+.sp -+Both () and {} act as C parenthesis. -+The curly braces set the returned symbolic value -+as the actual value, e.g. if i=5 and x[5]=3, then -+x[i] produces the output "x[i] = 3", x[{i}] produces -+"x[5] = 3" and {x[i]} produces just "3". -+The semicolon is an operator. x;y evaluates x, ignoring the results, -+then evaluate and return y, e.g. (i:=1..3 ; i+5) sets i to 3 and return 8. -+The x=>y operator evaluate and return y for each value of x, -+e.g. (i:=1..3 => i+5) returns 6, 7 and 8. The value returned by x is -+also stored implicitly in `_' which can be used in y, e.g. 1..5 => z[_][_] -+will output z[1][1], z[2][2] etc. The symbolic value for _ is that of the -+left side value, hence {_} is not needed. -+.br -+Semicolon has the lowest precedence, so it must be used inside () or {} -+for compound expressions. The precedence of `=>' is just below `,'. -+Beware that "if(a) x; else {y;} z" is illegal; a semicolon is not allowed -+before '}' or 'else' and must be inserted before z. -+.sp -+.IB "x->y x.y" -+.sp -+These expression work as in C for a symbol y. If y is an expression, it -+is evaluated under the scope of x. e.g. x.(a+b) is the same as x.a+x.b, -+if a and b are field of x (if they are not, they are looked up as local -+or global variables). x may return multiple values of different types, -+e.g. (u,v).a returns u.a and v.a, even if u and v are different structures. -+Also, the value of x is available as `_' inside y, e.g. x[..100].(if(a) _) -+produces x[i] for each x[i].a!=0. Nested x.y are allowed, e.g. -+u.(v.(a+b)) would lookup a and b first under v, then under u. -+.sp -+.BI Aliases: " x:=y" -+.sp -+Aliases store a reference to y in x. Any reference to x is -+then replaced by y. If y is a constant or an rvalue, its -+value is replaced for x. If y is an lvalue (e.g. a variable), a reference -+to same lvalue is returned. for example, x:=emp[5] ; x=9 assigns 9 to -+emp[5]. -+Aliases retain their values across invocation of the "dl" command. An alias -+to a local variable will reference a stray address when the variable -+goes out of scope. -+The special command "dl clear" delete all the aliases, and "dl alias" -+show all current aliases. Symbols are looked up -+as aliases first, so an alias x will hide a local x. -+.sp -+.I x-->y -+.sp -+The expansion operator x-->y expands a data structure x following the y links. -+It returns x, x->y, x->y->y, until a null is found. If x is null, no values -+are produced. If y returns multiple values, they are stacked and each is -+further expanded in a depth-first notion. For example, if r is the root of -+a tree with children u->childs[..u->nchilds], then -+u-->(childs[..nchilds]) expands the whole tree. y is an arbitrary -+expression, evaluated exactly like x->y (this includes `_'.) -+.sp -+.I x@y -+.sp -+The expression x@y produces the values of x until x.y is non-zero, e.g. -+for(i=0 ; x[i].code!= -1 && i<100 ; i++) x[i] can be written as -+x[..100]@(code==-1). -+The evaluation of x is stopped as soon as y evaluates to true. -+x->y or x=>y are used to evaluate y when x is not a struct or a union. If -+y is a constant,(_==y) is used. e.g. s[0..]@0 produces the characters in -+string s up to but not including the terminating null. -+.sp -+.IB "#/x &&/x ||/x" -+.sp -+These operator return a single "summary" value for all the values returned by -+x. #/x returns the number of values returned by x, e.g. -+#/(x[..100]>?0) counts the number of positive x[i]. &&/x returns 1 if all -+the values produced by x are non-zero, and ||/x returns 1 if any of x's values -+are non-zero. Like in C, the evaluation stops as soon as possible. -+For example, ||/(x[..100]==0) and &&/(x[..100]==0) check if one or all of -+x[i] are zero, respectively. -+.sp -+.IB "x#y x[[y]]" -+.sp -+The operator x#y produces the values of x and arranges for y to be an alias -+for the index of each value in x. It is commonly used with x-->y to produce -+the element's index, e.g. head-->next->val#i=i assigns each val field -+its element number in the list. -+.br -+The selection operator x[[y]] produces the yth result of x. If y returns -+multiple value, each select a value of x, e.g. (5,7,11,13)[3,0,2] -+returns 13, 5 and 11 (13 is the 3rd element, 5 is the 0th element). -+Don't use side effects in x, since its evaluation can be restarted depending -+on y, e.g. after (x[0..i++])[[3,5]] the value of i is unpredictable. -+.sp -+.IB "frame(n) frames_no func.x" -+.sp -+frame(n) for an integer n returns a reference to the nth frame -+on the stack (0 is the inner most function and frame(frames_no-1) is main()). -+Frame values can be compared to function pointers, -+e.g. frame(3)==myfunc is true if the 4th frame is a call to myfunc, and in -+scope resolution, e.g. frame(3).x return the local variable x of the 4th frame. -+frames_no is the number of active frames on the stack, e.g. -+(frames(..frames_no) ==? myfunc).x displays x for all active -+invocations of myfunc. As a special case, (frames(..frames_no)==?f)[[0]].x -+can be written as f.x (x can be an expression). -+.sp -+.SH BUGS -+Both `{}' and `;' are operators, not statements or expression separators; -+"if(x) y; else {z;} u" is illegal; use "if(x) y else {z} ; u". Ambiguities -+require preceding -+user-defined types (typedef) with the keyword T, e.g., if -+value is a user type, C's "sizeof(value*)" is written -+"sizeof(T value*)", except for the casts "(t)x" and "(t*)x"; sizeof(x) -+requires parenthesis for variable x. -+ -+Unimplemented C idiom include: modified-assignment -+(x+=y), switch, break, continue, do, goto, scopes, function declarations, -+initializing declared variables, -+assignment to bit-fields and register variables, and -+calling functions with a struct/union parameter or return value. -+gdb does not store function prototypes, so parameters are not checked. -+ -+Gdb itself is buggy, which shows up, especially in symbol tables and -+calling target functions. Before you report bug, try to do the closest -+thing under gdb's "print". Send bug to: mg@cs.princeton.edu. -+.SH FILES -+duel.out tracks duel commands usage. Help analyze duel's use by mailing a -+copy to mg@cs.princeton.edu. -+.br -+Duel is available by anonymous ftp at ftp.cs.princeton.edu:/duel. -+.SH AUTHOR -+Duel is public domain code -- no copy left or right. See the internals -+documentation for details on porting Duel and using its code. -+Duel was designed and written by Michael Golan as part of a PhD thesis -+in the Computer Science Department of Princeton University. -+I would like to thank my advisor, Dave Hanson, who helped in all phases -+of this project and to Matt Blaze for his support and useful insight. -+.sp -+Duel stands for Debugging U (might) Even Like, or Don't Use this Exotic -+Language. Judge for yourself! -+ -+ ---- gdb/duel/duel.c -+++ gdb/duel/duel.c -@@ -0,0 +1,682 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* this module contains the entery point to duel - duel_eval_and_pasre. -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.11 93/03/13 04:03:07 mg -+ * moved VERSION to patchlevel.h -+ * -+ * Revision 1.10 93/03/12 05:41:54 mg -+ * Version 1.10 - support (x)y cast, piped output. -+ * -+ * Revision 1.9 93/02/23 19:09:35 mg -+ * new version 1.02 release (support gdb4.8) -+ * -+ * Revision 1.8 93/02/03 21:56:33 mg -+ * version 1.01 -+ * -+ * Revision 1.7 93/01/12 21:28:44 mg -+ * cleanup and set for release -+ * -+ * Revision 1.6 93/01/06 23:57:10 mg -+ * added alias, clear commands, new memory alloc/release -+ * -+ * Revision 1.5 93/01/03 07:26:47 mg -+ * new printing setup -+ * -+ * Revision 1.4 92/12/24 23:32:38 mg -+ * better struct support, misc changes -+ * -+ * Revision 1.3 92/10/19 15:02:04 mg -+ * lcc happy, size zero arrays -+ * -+ * Revision 1.2 92/10/14 02:03:15 mg -+ * misc -+ * -+ */ -+ -+#include <setjmp.h> -+#define DEF /* define global variables */ -+#include "duel.h" -+#include "patchlevel.h" -+ -+static jmp_buf duel_abort_jmp ; /* abort current execution */ -+static tnode *root ; /* root of current eval node */ -+ -+ -+/* abort evaluation of current expression */ -+ -+PROC duel_abort(void) -+{ -+ longjmp(duel_abort_jmp,1); -+} -+ -+PROC duel_cleanup(void *unused) /* cleanup malloc, etc, when duel eval ends*/ -+{ -+ duel_redirectable_output_abort(); -+ duel_free_nodes(root); -+ root=NULL ; -+} -+ -+LPROC longhelp(void) -+{ -+ duel_printf( -+"Duel(1) Duel(1)\n\ -+\n\ -+NAME\n\ -+ duel - A high level C debugging language extension to gdb\n\ -+\n\ -+DESCRIPTION\n\ -+ Duel is a special purpose language designed for concise state explo-\n\ -+ ration of debugged C programs, currently implemented under the GNU\n\ -+ debugger gdb(1). Duel is invoked by entering the shell command duel\n\ -+ instead of gdb. It is identical to gdb except for comments, which\n\ -+ begin with `##' instead of `#', and the new dl command for Duel expres-\n\ -+ sions:\n\ -+\n\ -+ gdb> dl x[1..10] >? 5\n\ -+ x[3] = 14\n\ -+ x[8] = 6\n\ -+\n\ -+ prints the array elements x[1] to x[10] that are greater than 5. The\n\ -+ output includes the values 14 and 6, as well as their symbolic repre-\n\ -+ sentation \"x[3]\" and \"x[8]\".\n\ -+\n\ -+DUEL QUICK START\n\ -+ Duel is implemented by adding the dl command to gdb. All gdb commands\n\ -+ work as before. The dl command, however, is interpreted by duel. Gdb\n\ -+ concepts (such as the value history) do not work in the dl command, and\n\ -+ duel concepts are not understood by other gdb command.\n\ -+\n\ -+ Duel is based on expressions which return multiple values. The x..y\n\ -+ operator returns the integers from x to y; the x,y operator returns x\n\ -+ and then y, e.g.\n\ -+\n\ -+ gdb> dl (1,9,12..15,22)\n\ -+\n\ -+ prints 1, 9, 12, 13, 14, 15 and 22. Such expressions can be used wher-\n\ -+ ever a single value is used, e.g.\n\ -+\n\ -+ gdb> dl x[0..99]=0 ;\n\ -+\n\ -+ assigns zero to the first 100 elements of array x. The semantics of\n\ -+ x[i] are the same as in C. They are applied for each of the values\n\ -+ returned by 0..99, which can be thought of as an implied external loop.\n\ -+ The trailing semicolon indicates evaluation for side-effects only, with\n\ -+ no output. Duel incorporates C operators, casts C statements as\n\ -+ expressions, and supports limited variable declaration:\n\ -+\n\ -+ gdb> dl int i;for(i=0;i<100;i++)\n\ -+ if(x[i]<0) printf(\"x[%%d]=%%d\\n\",i,x[i]);\n\ -+ x[7] = -4\n\ -+\n\ -+ The semicolon prevents Duel output; only output from printf is printed.\n\ -+ Aliases are defined with x:=y and provide an alternative to variable\n\ -+ declaration. We could also return x[i] instead of using printf:\n\ -+\n\ -+ gdb> dl if(x[i:=0..99]<0) x[i]\n\ -+ x[i] = -4\n\ -+\n\ -+ The symbolic output \"x[i]\" can be fixed by surrounding i with {}, i.e.\n\ -+\n\ -+ gdb> dl if(x[i:=0..99]<0) x[{i}]\n\ -+ x[7] = -4\n\ -+\n\ -+ The {} are like (), but force the symbolic evaluation to use i's value,\n\ -+ instead of \"i\". You can usually avoid this altogether with direct Duel\n\ -+ operators:\n\ -+\n\ -+ gdb> dl x[..100] <? 0\n\ -+ x[7] = -4\n\ -+\n\ -+ The ..n operator is a shorthand for 0..n-1, i.e. ..100 is the same as\n\ -+ 0..99. The x<?y, x==?y, x>=?y, etc., operators compare their left side\n\ -+ operand to their right side operand as in C, but return the left side\n\ -+ value if the comparison result is true. Otherwise, they look for the\n\ -+ next values to compare, without returning anything.\n\ -+\n\ -+ Duel's x.y and x->y allow an expression y, evaluated under x's scope:\n\ -+\n\ -+ gdb> dl emp[..100].(if(code>400) (code,name))\n\ -+ emp[46].code = 682\n\ -+ emp[46].name = \"Ela\"\n\ -+\n\ -+ The if() expression is evaluated under the scope of each element of\n\ -+ emp[], an array of structures. In C terms, we had to write:\n\ -+\n\ -+ gdb> dl int i; for(i=0; i<100 ; i++)\n\ -+ if(emp[i].code>400) emp[{i}].code,emp[{i}].name\n\ -+\n\ -+ A useful alternative to loops is the x=>y operator. It returns y for\n\ -+ each value of x, setting `_' to reference x's value, e.g.\n\ -+\n\ -+ gdb> ..100 => if(emp[_].code>400) emp[_].code,emp[_].name\n\ -+\n\ -+ Using `_' instead of `i' also avoids the need for {i}. Finally, the\n\ -+ x-->y operator expands lists and other data structures. If head points\n\ -+ to a linked list threaded through the next field, then:\n\ -+\n\ -+ gdb> dl head-->next->data\n\ -+ head->data = 12\n\ -+ head->next->data = 14\n\ -+ head-->next[[2]]->data = 20\n\ -+ head-->next[[3]]->data = 26\n\ -+\n\ -+ produce the data field for each node in the list. x-->y returns x,\n\ -+ x->y, x->y->y, x->y->y->y, ... until a NULL is found. The symbolic\n\ -+ output \"x-->y[[n]]\" indicates that ->y was applied n times. x[[y]] is\n\ -+ also the selection operator:\n\ -+\n\ -+ gdb> dl head-->next[[50..60]]->data\n\ -+\n\ -+ return the 50th through the 60th elements in the list. The #/x operator\n\ -+ counts the number of values, so\n\ -+\n\ -+ gdb> dl #/( head-->next->data >? 50 )\n\ -+\n\ -+ counts the number of data elements over 50 on the list. Several other\n\ -+ operators, including x@y, x#y and active call stack access are\n\ -+ described in the operators section.\n\ -+\n\ -+OPERATORS SUMMARY\n\ -+ Assoc Operators Details\n\ -+ left {} () [] -> . f() --> x-->y expands x->y x->y->y ...\n\ -+ x[[y]] x#y x@y generate x; select, index or stop-at y\n\ -+ right #/ - * & ! ~ ++ -- (cast) #/x number of x values\n\ -+ frame(n) sizeof(x) reference to call stack level n\n\ -+ left x/y x*y x%%y multiply, divide, reminder\n\ -+ left x-y x+y add, subtract\n\ -+ left x<<y x>>y shift left/right\n\ -+ none x..y ..y x.. ..y = 0..y-1. x..y return x, x+1...y\n\ -+ left < > <= >= <? >? <=? >=? x>?y return x if x>y\n\ -+ left == != ==? !=? x==?y return x if x==y\n\ -+ left x&y bit-and\n\ -+ left x^y bit-xor\n\ -+ left x|y bit-or\n\ -+ left x&&y &&/x &&/x are all x values non-zero?\n\ -+ left x||y ||/x ||/x is any x value non-zero?\n\ -+ right x? y:z foreach x, if(x) y else z\n\ -+ right x:=y x=y x+=y ... x:=y set x as an alias to y\n\ -+ left x,y return x, then y\n\ -+ right x=>y foreach x, evaluate y with x value `_'\n\ -+ right if() else while() for() C statements cast as operators\n\ -+ left x;y evaluate and ignore x, return y\n\ -+\n\ -+\n\ -+EXAMPLES\n\ -+ dl (0xff-0x12)*3 compute simple expression\n\ -+ dl (1..10)*(1..10) display multiplication table\n\ -+ dl x[10..20,22,24,40..60] display x[i] for the selected indexes\n\ -+ dl x[9..0] display x[i] backwards\n\ -+ dl x[..100] >? 5 display x[i] that are greater than 5\n\ -+ dl x[..100] >? 5 <? 10 display x[i] if 5<x[i]<10\n\ -+ dl x[..100] ==? (6..9) same\n\ -+ dl x[0..99]=>if(_>5 && _<10) _ same\n\ -+ dl y[x[..100] !=? 0] display y[x[i]] for each non-zero x[i]\n\ -+ dl emp[..50].code display emp[i].code for i=0 to 49\n\ -+ dl emp[..50].(code,name) display emp[i].code & emp[i].name\n\ -+ dl val[..50].(is_dbl? x:y) display val[i].x or val[i].y depending\n\ -+ on val[i].is_dbl.\n\ -+ dl val[..50].if(is_dbl) x else y same as above\n\ -+ dl x[..100]=0 ; assign 0 to x[i]\n\ -+ dl x[i:=..100]=y[i] ; assign y[i] to x[i]\n\ -+ dl x[..100]=y[..100] *ERR* assign y[99] to each x[j]\n\ -+ dl x[i:=..3]=(4,5,9)[[i]] assign x[0]=4 x[1]=5 x[2]=9\n\ -+ dl x[..3]=(4,5,9) *ERR* assign 9 to each element\n\ -+ dl if(x[i:=..100]<0) x[i]=0 ; assign 0 to negative x[i]\n\ -+ dl (hash[..1024]!=?0)->scope hash[i].scope for non-null hash[i]\n\ -+ dl x[i:=..100] >? x[i+1] check if x[i] is not sorted\n\ -+ dl x[i:=..100] ==? x[j:=..100]=> checks if x has non-unique elements\n\ -+ if(i<j) x[{i,j}]\n\ -+ dl if(x[i:=..99] == same\n\ -+ x[j:=i+1..99]) x[{i,j}]\n\ -+ dl (x[..100] >? 0)[[0]] the 1st (0th element) positive x[i]\n\ -+\n\ -+ dl (x[..100] >? 0)[[2]] return the 3rd positive x[i]\n\ -+ dl (x[..100] >? 0)[[..5]] return the first 5 positive x[i]\n\ -+ dl (x[0..] >? 6)[[0]] return the first x[i]>6, no limit on i\n\ -+ dl argv[0..]@0 argv[0] argv[1] .. until first null\n\ -+ dl x[0..]@-1 >? 9 x[0..n]>9 where n is first x[n]== -1\n\ -+ dl emp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0\n\ -+\n\ -+ dl head-->next->val val of each element in a linked list\n\ -+ dl head-->next[[20]] the 21st element of a linked list\n\ -+ dl *head-->next[[20]] display above as a struct\n\ -+ dl strcmp(head-->next->msg, search linked list for a string\n\ -+ \"testing\") ==? 0\n\ -+ dl #/head-->next count elements on a linked list\n\ -+ dl x-->y[[#/x-->y - 1]] last element of a linked list\n\ -+ dl x-->y[[#/x-->y - 10..1]] last 10 elements of a linked list\n\ -+ dl head-->next-> check if the list is sorted by val\n\ -+ if(next) val >? next->val\n\ -+\n\ -+ dl head-->(next!=?head) expand cyclic linked list (tail->head)\n\ -+ dl head-->(next!=?_) handle termination with p->next==p\n\ -+ dl root-->(left,right)->key expand binary tree, show keys\n\ -+ dl root-->(left,right)->( check bin tree sorted by key\n\ -+ (left!=?0)->key>=?key, (right !=?0 )->key<=?key)\n\ -+\n\ -+ dl (1000..=>if(&&/(2,3.._-1=>__%%_ find first 10 primes over 1000\n\ -+ ) _)[[..10]]\n\ -+ dl (T mytype) x convert x to user defined type mytype\n\ -+ dl (struct s*) x convert x to struct s pointer\n\ -+ dl if(x) y; else z *ERR* ';' must be followed by an expression\n\ -+ dl {x} y *ERR* '}' requires ';' if followed by exp\n\ -+\n\ -+SEMANTICS\n\ -+ Duel's semantics are modeled after the Icon programming language. The\n\ -+ input consists of expressions which return sequences of values. C\n\ -+ statements are cast as expressions, too. Expressions are parsed into\n\ -+ abstract syntax trees, which are traversed during evaluation. The eval-\n\ -+ uation of most nodes (operators) recursively evaluates the next value\n\ -+ for each operand, and then applies the operator to produce the next\n\ -+ result. Only one value is produced each time, and Duel's eval function\n\ -+ keeps a `state' for each node (backtracking, co-routines, consumer-pro-\n\ -+ ducer or threads are good metaphors for the evaluation mechanism.)\n\ -+\n\ -+ For example, in (5,3)+6..8, the evaluation of `+' first retrieves the\n\ -+ operands 5 and 6, to compute and return 5+6. Then 7, the next right op-\n\ -+ erand is retrieved and 5+7 is returned, followed by 5+8. Since there\n\ -+ are no other right operand value, the next left operand, 3 is fetched.\n\ -+ The right operand's computation is restarted returning 6, and 3+6 is\n\ -+ returned. The final return values are 3+7 and 3+8.\n\ -+\n\ -+ The computation for operators like x>?y is similar, but when x<=y, the\n\ -+ next values are fetched instead of returning a value, forming the basis\n\ -+ for an implicit search. Operators like `..' return a sequence of values\n\ -+ for each pair of operands. For a better understanding of the evaluation\n\ -+ mechanism, see the USENIX Winter/93 conference paper \"DUEL - A Very\n\ -+ High Level Debugging Language\".\n\ -+\n\ -+ Duel values follow the C semantics. A value is either an \"lvalue\" (can\n\ -+ be used as the left hand side of assignment), or an \"rvalue\". There-\n\ -+ for, objects like arrays can not be directly manipulated (However,\n\ -+ operators like x..y can accomplish such tasks.)\n\ -+\n\ -+ Duel types also follow the C semantics, with some important differ-\n\ -+ ences. C types are checked statically; Duel types are checked when\n\ -+ operators are applied, e.g., (1,1.0)/2 returns 0 (int) and 0.5 (dou-\n\ -+ ble); (x,y).z returns x.z and y.z even if x and y are of different\n\ -+ types, as long as they both have a field z.\n\ -+\n\ -+ Values and types of symbols are looked up at run-time (using gdb's\n\ -+ lookup rules), allowing dynamic scoping and types, but causing a pars-\n\ -+ ing problem: (x)(y) can be parsed as either a function call x(y) or a\n\ -+ cast (x)y; x*y can be parsed as a declaration of y as (x*) or as multi-\n\ -+ plication.\n\ -+\n\ -+ To avoid this ambiguity, the keyword T must precede a user defined\n\ -+ type. For example, if value is a typedef, C's (value (*)()) x is writ-\n\ -+ ten in Duel as: (T value (*)()) x. Types that begin with a reserved\n\ -+ keyword don't need T, e.g. (struct value*) x and (long *[5]) y are\n\ -+ accepted. As special cases, (type)x and (type*)x are accepted but dis-\n\ -+ couraged (it causes (printf)(\"hi\"), which is valid in C, to fail). A\n\ -+ side effect is that \"sizeof x\" must be written as sizeof(x).\n\ -+\n\ -+OPERATORS\n\ -+ x+y x-y x*y x/y x%%y x^y x|y x&y x<<y x>>y\n\ -+ x>y x<y x>=y x<=y x==y x!=y x=y x[y]\n\ -+\n\ -+ These binary operators follow their C semantics. For each value of x,\n\ -+ they are evaluated for every value of y, .e.g. (5,2)>(4,1) evaluates as\n\ -+ 5>4, 5>1, 2>4, 2>1 returning 1, 1, 0, 1. The y values are re-evalu-\n\ -+ ated for each new value of x, e.g. i=4; (4,5)>i++ evaluates as 4>4 and\n\ -+ 5>5. Beware of multiple y values in assignment, e.g. x[..3]=(4,6,9)\n\ -+ does not set x[0]=4, x[1]=6 and x[2]=9. It assigns 4, 6 and 9 to each\n\ -+ element, having the same effect as x[..3]=9. Use x[i:=..3]=(4,6,9)[[i]]\n\ -+ to achieve the desired effect.\n\ -+\n\ -+ -x ~x &x *x !x ++x --x x++ x-- sizeof(x) (type)x\n\ -+\n\ -+ These unary operators follow their C semantics. They are applied to\n\ -+ each value of x. The increment and decrement operators require an\n\ -+ lvalue, so i:=0 ; i++ produces an error because i is an alias to 0, an\n\ -+ rvalue. Parenthesis must be used with sizeof(x), \"sizeof x\" is not\n\ -+ allowed. Cast to user defined type requires generally requires T, e.g.,\n\ -+ (T val(*)())x, but (val)x and (val*)x are accepted as special cases.\n\ -+\n\ -+ x&&y x||y\n\ -+\n\ -+ These logical operators also follow their C semantics, but have non-\n\ -+ intuitive results for multi-valued x and y, e.g. (1,0,0) || (1,0)\n\ -+ returns 1,1,0,1,0 -- the right hand-side (1,0) is returned for each\n\ -+ left-hand side 0. It is best to use these operators only in single\n\ -+ value expressions.\n\ -+\n\ -+ x? y:z if(x)y if(x)y else z\n\ -+\n\ -+ These expressions return the values of y for each non-zero value\n\ -+ returned by x, and the values of z for each zero value returned by x,\n\ -+ e.g. if(x[..100]==0) y returns y for every x[i]==0, not if all x[i]\n\ -+ are zero (if(&&/(x[..100]==0)) y does that). Also, \"if(x) y; else z\"\n\ -+ is illegal. Duel's semicolon is an expression separator, not a termina-\n\ -+ tor.\n\ -+\n\ -+ while(x)y for(w;x;y)z\n\ -+\n\ -+ The while(x)y expression returns y as long as all values of x are non-\n\ -+ zero. The for() expression is similar and both have the expected C\n\ -+ semantics. For example, \"for(i=0 ; i<100 ; i++) x[i]\" is the same as\n\ -+ x[..100]. Unlike the if() expression, while(x[..100]==0) continue to\n\ -+ execute only if all elements of x are zero, i.e. the condition is eval-\n\ -+ uated into a single value using an implicit &&/x.\n\ -+\n\ -+ Variable declaration: type name [,name ...] ; ...\n\ -+\n\ -+ Expressions can begin with variables declaration (but not initializa-\n\ -+ tion). Internally, a declaration sets an alias to space allocated in\n\ -+ the target by calling malloc(), e.g. `int x' is the same as \"x:= *(int\n\ -+ *) malloc(sizeof(int))\". This is oblivious to the user. The allocated\n\ -+ memory is not claimed when a variable is redeclared. Declared vari-\n\ -+ ables addresses can be passed to functions and used in other data\n\ -+ structures. The keyword `T' must precede user defined types (typedef),\n\ -+ e.g. if val is a user defined type, The C code \"val *p=(val*) x\"\n\ -+ becomes \"T val *p; p=(T val *) x\" in Duel.\n\ -+\n\ -+ Function calls: func(parm,...)\n\ -+\n\ -+ Function calls to the debugged program can be intermixed with Duel\n\ -+ code. Multi-valued parameters are handled as with binary operators.\n\ -+ The call value can have multiple values, e.g. (x,y)() calls x() and\n\ -+ y(). Currently, struct/union parameters and return values are not sup-\n\ -+ ported.\n\ -+\n\ -+ x,y x..y ..x x..\n\ -+\n\ -+ These operators produce multiple values for single value operands. x,y\n\ -+ returns x, then y. x..y returns the integers from x to y. When x>y the\n\ -+ sequence is returned in descending order, i.e. 5..3 returns 5, 4, 3.\n\ -+ The operator ..x is a shorthand for 0..x-1, e.g. ..3 returns 0, 1, 2.\n\ -+ The x.. operator is a shorthand for x..maxint. It returns increasing\n\ -+ integer values starting at x indefinitely, and should be bounded by\n\ -+ [[n]] or @n operators. `,' retains its precedence level in C. The\n\ -+ precedence of `..' is above `<' and below arithmetic operators, so\n\ -+ 0..n-1 and x==1..9 work as expected.\n\ -+\n\ -+ x<?y x>?y x>=?y x<=?y x!=?y x==?y\n\ -+\n\ -+ These operators work like their C counterparts but return x if the com-\n\ -+ parison is true. If the comparison is false, the next (x,y) value is\n\ -+ tried, forming the basis of an implicit search.\n\ -+\n\ -+ (x) {x} x;y x=>y\n\ -+\n\ -+ Both () and {} act as C parenthesis. The curly braces set the returned\n\ -+ symbolic value as the actual value, e.g. if i=5 and x[5]=3, then x[i]\n\ -+ produces the output \"x[i] = 3\", x[{i}] produces \"x[5] = 3\" and {x[i]}\n\ -+ produces just \"3\". The semicolon is an operator. x;y evaluates x,\n\ -+ ignoring the results, then evaluate and return y, e.g. (i:=1..3 ; i+5)\n\ -+ sets i to 3 and return 8. The x=>y operator evaluate and return y for\n\ -+ each value of x, e.g. (i:=1..3 => i+5) returns 6, 7 and 8. The value\n\ -+ returned by x is also stored implicitly in `_' which can be used in y,\n\ -+ e.g. 1..5 => z[_][_] will output z[1][1], z[2][2] etc. The symbolic\n\ -+ value for _ is that of the left side value, hence {_} is not needed.\n\ -+ Semicolon has the lowest precedence, so it must be used inside () or {}\n\ -+ for compound expressions. The precedence of `=>' is just below `,'.\n\ -+ Beware that \"if(a) x; else {y;} z\" is illegal; a semicolon is not\n\ -+ allowed before '}' or 'else' and must be inserted before z.\n\ -+\n\ -+ x->y x.y\n\ -+\n\ -+ These expression work as in C for a symbol y. If y is an expression, it\n\ -+ is evaluated under the scope of x. e.g. x.(a+b) is the same as x.a+x.b,\n\ -+ if a and b are field of x (if they are not, they are looked up as local\n\ -+ or global variables). x may return multiple values of different types,\n\ -+ e.g. (u,v).a returns u.a and v.a, even if u and v are different struc-\n\ -+ tures. Also, the value of x is available as `_' inside y, e.g.\n\ -+ x[..100].(if(a) _) produces x[i] for each x[i].a!=0. Nested x.y are\n\ -+ allowed, e.g. u.(v.(a+b)) would lookup a and b first under v, then\n\ -+ under u.\n\ -+\n\ -+ Aliases: x:=y\n\ -+\n\ -+ Aliases store a reference to y in x. Any reference to x is then\n\ -+ replaced by y. If y is a constant or an rvalue, its value is replaced\n\ -+ for x. If y is an lvalue (e.g. a variable), a reference to same lvalue\n\ -+ is returned. for example, x:=emp[5] ; x=9 assigns 9 to emp[5]. Aliases\n\ -+ retain their values across invocation of the \"dl\" command. An alias to\n\ -+ a local variable will reference a stray address when the variable goes\n\ -+ out of scope. The special command \"dl clear\" delete all the aliases,\n\ -+ and \"dl alias\" show all current aliases. Symbols are looked up as\n\ -+ aliases first, so an alias x will hide a local x.\n\ -+\n\ -+ x-->y\n\ -+\n\ -+ The expansion operator x-->y expands a data structure x following the y\n\ -+ links. It returns x, x->y, x->y->y, until a null is found. If x is\n\ -+ null, no values are produced. If y returns multiple values, they are\n\ -+ stacked and each is further expanded in a depth-first notion. For exam-\n\ -+ ple, if r is the root of a tree with children u->childs[..u->nchilds],\n\ -+ then u-->(childs[..nchilds]) expands the whole tree. y is an arbitrary\n\ -+ expression, evaluated exactly like x->y (this includes `_'.)\n\ -+\n\ -+ x@y\n\ -+\n\ -+ The expression x@y produces the values of x until x.y is non-zero, e.g.\n\ -+ for(i=0 ; x[i].code!= -1 && i<100 ; i++) x[i] can be written as\n\ -+ x[..100]@(code==-1). The evaluation of x is stopped as soon as y eval-\n\ -+ uates to true. x->y or x=>y are used to evaluate y when x is not a\n\ -+ struct or a union. If y is a constant,(_==y) is used. e.g. s[0..]@0\n\ -+ produces the characters in string s up to but not including the termi-\n\ -+ nating null.\n\ -+\n\ -+ #/x &&/x ||/x\n\ -+\n\ -+ These operator return a single \"summary\" value for all the values\n\ -+ returned by x. #/x returns the number of values returned by x, e.g.\n\ -+ #/(x[..100]>?0) counts the number of positive x[i]. &&/x returns 1 if\n\ -+ all the values produced by x are non-zero, and ||/x returns 1 if any of\n\ -+ x's values are non-zero. Like in C, the evaluation stops as soon as\n\ -+ possible. For example, ||/(x[..100]==0) and &&/(x[..100]==0) check if\n\ -+ one or all of x[i] are zero, respectively.\n\ -+\n\ -+ x#y x[[y]]\n\ -+\n\ -+ The operator x#y produces the values of x and arranges for y to be an\n\ -+ alias for the index of each value in x. It is commonly used with x-->y\n\ -+ to produce the element's index, e.g. head-->next->val#i=i assigns each\n\ -+ val field its element number in the list.\n\ -+ The selection operator x[[y]] produces the yth result of x. If y\n\ -+ returns multiple value, each select a value of x, e.g.\n\ -+ (5,7,11,13)[3,0,2] returns 13, 5 and 11 (13 is the 3rd element, 5 is\n\ -+ the 0th element). Don't use side effects in x, since its evaluation\n\ -+ can be restarted depending on y, e.g. after (x[0..i++])[[3,5]] the\n\ -+ value of i is unpredictable.\n\ -+\n\ -+ frame(n) frames_no func.x\n\ -+\n\ -+ frame(n) for an integer n returns a reference to the nth frame on the\n\ -+ stack (0 is the inner most function and frame(frames_no-1) is main()).\n\ -+ Frame values can be compared to function pointers, e.g.\n\ -+ frame(3)==myfunc is true if the 4th frame is a call to myfunc, and in\n\ -+ scope resolution, e.g. frame(3).x return the local variable x of the\n\ -+ 4th frame. frames_no is the number of active frames on the stack, e.g.\n\ -+ (frames(..frames_no) ==? myfunc).x displays x for all active invoca-\n\ -+ tions of myfunc. As a special case, (frames(..frames_no)==?f)[[0]].x\n\ -+ can be written as f.x (x can be an expression).\n\ -+\n\ -+\n\ -+BUGS\n\ -+ Both `{}' and `;' are operators, not statements or expression separa-\n\ -+ tors; \"if(x) y; else {z;} u\" is illegal; use \"if(x) y else {z} ; u\".\n\ -+ Ambiguities require preceding user-defined types (typedef) with the\n\ -+ keyword T, e.g., if value is a user type, C's \"sizeof(value*)\" is\n\ -+ written \"sizeof(T value*)\", except for the casts \"(t)x\" and \"(t*)x\";\n\ -+ sizeof(x) requires parenthesis for variable x.\n\ -+\n\ -+ Unimplemented C idiom include: modified-assignment (x+=y), switch,\n\ -+ break, continue, do, goto, scopes, function declarations, initializing\n\ -+ declared variables, assignment to bit-fields and register variables,\n\ -+ and calling functions with a struct/union parameter or return value.\n\ -+ gdb does not store function prototypes, so parameters are not checked.\n\ -+\n\ -+ Gdb itself is buggy, which shows up, especially in symbol tables and\n\ -+ calling target functions. Before you report bug, try to do the closest\n\ -+ thing under gdb's \"print\". Send bug to: mg@cs.princeton.edu.\n\ -+\n\ -+FILES\n\ -+ duel.out tracks duel commands usage. Help analyze duel's use by mailing\n\ -+ a copy to mg@cs.princeton.edu.\n\ -+ Duel is available by anonymous ftp at ftp.cs.princeton.edu:/duel.\n\ -+\n\ -+AUTHOR\n\ -+ Duel is public domain code -- no copy left or right. See the internals\n\ -+ documentation for details on porting Duel and using its code. Duel was\n\ -+ designed and written by Michael Golan as part of a PhD thesis in the\n\ -+ Computer Science Department of Princeton University. I would like to\n\ -+ thank my advisor, Dave Hanson, who helped in all phases of this project\n\ -+ and to Matt Blaze for his support and useful insight.\n\ -+\n\ -+ Duel stands for Debugging U (might) Even Like, or Don't Use this Exotic\n\ -+ Language. Judge for yourself!\n\ -+\n\ -+Version 1.10 Mar 93 Duel(1)\n\n"); -+} -+ -+LPROC help(void) -+{ -+ duel_printf( -+"Duel - Debugging U (might) Even Like -- A high level debugging language\n\n\ -+Duel was designed to overcome problems with traditional debuggers' print\n\ -+statement. It supports the C operators, many C constructs, and many new\n\ -+operators for easy exploration of the program's space, e.g.\n\ -+x[..100] >? 0 show positive x[i] for i=0 to 99\n\ -+y[10..20].code !=? 0 show non-zero y[i].code for i=10 to 20\n\ -+h-->next->code expand linked list h->next, h->next->next ...\n\ -+head-->next.if(code>0) name show name for each element with code>0\n\ -+x[i:=..100]=y[i]; array copy. i is an alias to vals 0..99\n\ -+head-->next[[10..15]] the 10th to 15th element of a linked list\n\ -+#/(head-->next->val==?4) count elements with val==4\n\ -+head-->next->if(next) val >? next->val check if list is sorted by val\n\ -+\n\ -+Duel was written by Michael Golan at Princeton University. Send email to\n\ -+mg@cs.princeton.edu. Duel is public domain code. No copy left or right.\n\ -+all but 500 lines are independent of gdb. Port it! Make it Commercial!\n\ -+\n\ -+Try \"dl ops\" for op summary; \"dl\" alone lists all commands\n"); -+} -+ -+LPROC examples(void) -+{ -+ duel_printf("\ -+x[10..20,22,24,40..60] display x[i] for the selected indexes\n\ -+x[9..0] display x[i] backwards\n\ -+x[..100] >? 5 <? 10 display x[i] if 5<x[i]<10\n\ -+x[0..99]=>if(_>5 && _<10) _ same\n\ -+val[..50].if(is_dx) x else y \ -+val[i].x or val[i].y depending on val[i].is_dx\n\ -+emp[..50].if(is_m) _ return emp[i] if emp[i].is_m.\n\ -+x[i:=..100]=y[i] ; assign y[i] to x[i]\n\ -+x[i:=..100] >? x[i+1] check if x[i] is not sorted\n\ -+(x[..100] >? 0)[[2]] return the 3rd positive x[i]\n\ -+argv[0..]@0 argv[0] argv[1] .. until first null\n\ -+emp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0\n\ -+head-->next->val val of each element in a linked list\n\ -+*head-->next[[20]] element 20 of list, '*' display struct w/fields\n\ -+#/head-->next count elements on a linked list\n\ -+#/(head-->next-val>?5) count those over 5\n\ -+head-->(next!=?head) expand cyclic linked list (tail->head)\n\ -+T mytype x ; declare var for user defined type (need 'T')\n\ -+int i ; for(i=0 ;i<5 .. declare variable, use C construct.\n"); -+} -+ -+LPROC operators(void) -+{ -+ duel_printf("\ -+DUEL operators in decreasing precedence. All C operators are accepted!\n\ -+note: precede typedefs by 'T', eg \"sizeof(T uint)\"\n\n\ -+{x} same as (x) but x's value is used for symbol emp[{i}]\n\ -+x-->y expands data structure from x, using y root-->(left,right)->key\n\ -+x.y eval y under x's scope, like pascal \"with\". x is accesible as '_'\n\ -+x->y same as (*x).y. hash[..50]->if(_!=0) key\n\ -+x[[y]] select the y'th elements of x head-->next[[..6]]\n\ -+x@y eval x, stop as soon as y true (_==y if y const). argv[0..]@0\n\ -+x#y eval x, set alias y as values counter (x-->next#n)->level==?n"); -+ duel_printf("\n\ -+#/x count number of values from x #/head-->next\n\ -+frame(n) use with '.' to reference stack frames. frame(3).val\n\ -+x..y x, x+1, x+2 .. y. (if x>y, return them backwards) x[10..20]\n\ -+..y like 0..y-1 x[..1024]\n\ -+x.. like x..maxint. Caution: use only with x@y or x[[y]] name[0..]@0\n\ -+x>?y x if x>y else nothing. also <? <=? >=? ==? and !=? x[..10]<?0\n\ -+&&/x 1 or 0 if x!=0 for all x values. ||/x similar &&/x[..100]>=0\n\ -+x,y x, then y. head-->next->(val,key)\n\ -+x=>y eval y for each x, setting '_' to x's values x[..50]=>_*_\n\ -+if(x) y C statements are operators. Also for(), while(), if() else\n\ -+x;y Evaluate and ignore x's value, then return y\n"); -+} -+ -+/* entry point into duel. s is the expression to evaluate */ -+ -+void duel_parse_and_eval(char *s) -+{ -+ static first=1 ; -+ if(first) { /* init stuff */ -+ duel_init_basic_ctypes(); -+ duel_printf("%s.%d, public domain debugging language. \"dl\" for help\n", -+ VERSION,PATCHLEVEL); -+ duel_redirectable_output_init(); -+ first=0 ; -+ } -+ if(!s || *s==0) { /* no input, give some help */ -+ duel_printf("\ -+Supported DUEL commands:\n\ -+duel help - give basic help (shortcut: dl ?)\n\ -+duel longhelp - give a longer help (dl ?\?)\n\ -+duel examples - show useful usage examples (dl ex)\n\ -+duel operators - operators summary (dl ops)\n\ -+duel aliases - show current aliases (dl alias)\n\ -+duel clear - clear all aliases\n\ -+duel debug - toggle duel debug mode\n"); -+ return ; -+ } -+ if(strcmp(s,"?")==0 || strcmp(s,"help")==0) { -+ help(); -+ return ; -+ } -+ if(strcmp(s,"?\?")==0 || strcmp(s,"longhelp")==0) { -+ longhelp(); -+ return ; -+ } -+ if(strcmp(s,"examples")==0 || strcmp(s,"ex")==0 ) { -+ examples(); -+ return ; -+ } -+ if(strcmp(s,"operators")==0 || strcmp(s,"ops")==0) { -+ operators(); -+ return ; -+ } -+ if(strcmp(s,"debug")==0) { /* turn debugging of duel itself */ -+ duel_debug= !duel_debug ; -+ duel_printf("duel debug mode %d\n",duel_debug); -+ return ; -+ } -+ if(strcmp(s,"clear")==0) { -+ duel_clear_aliases(); -+ duel_printf("Aliases table cleared\n"); -+ return ; -+ } -+ if(strcmp(s,"alias")==0 || strcmp(s,"aliases")==0) { -+ duel_show_aliases(); -+ return ; -+ } -+ if(setjmp(duel_abort_jmp)==0) { /* set abort point */ -+ if((root=duel_parse(s))!=NULL) { -+ tvalue v ; -+ duel_set_input_string(s); /* for src-location err management */ -+ duel_reset_eval(); -+ duel_redirectable_output_start(s); /* allow eval output to go to pipe */ -+ while(duel_eval(root,&v)) { -+ duel_print_value(&v); -+ duel_flush(); -+ } -+ duel_redirectable_output_end(); -+ } -+ } -+ duel_cleanup(0); -+} ---- gdb/duel/duel.h -+++ gdb/duel/duel.h -@@ -0,0 +1,35 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* duel.h - include file to be used with all duel source code. -+ * it defines important global constants & data types, as well as some -+ * global variables. prototypes should go in the duelprot.h file -+ */ -+ -+ -+/* common duel include files. I dunno why people don't like recursive -+ * includes, as long as it is consistent. Note only one level of recursion. -+ * the debugger module itself dont use this file, instead it includes what -+ * it needs directly. -+ * as for including "everything", unless one redefine some standard lib func, -+ * I feel safer including most standard lib files. It seems to prevent errors -+ * even if it garble the name space a bit. -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stddef.h> -+#include <string.h> -+#include <assert.h> -+#include <ctype.h> -+#include <limits.h> -+#include <math.h> -+/* global data and types */ -+ -+#include "global.h" -+ -+/* prototypes for all global functions follows */ -+ -+#include "proto.h" ---- gdb/duel/duel.pipe -+++ gdb/duel/duel.pipe -@@ -0,0 +1,107 @@ -+#!/usr/local/bin/perl -+# perl script opened as a pipe by duel -+# -+# duel(gdb), fork this program and feed it as stdin, the output from -+# evaluating expressions. the input is -+# $$$START: expr where expr is the expression being evaluted -+# $$$DONE end of results -+# $$$ABORT end of results due to error or interrupt -+# $$$SYM: s symbolic output 's' -+# $$$VAL: v value for previous symbolic output -+# -+# the output from this program is fed back into duel, which simply display -+# it. After DONE/ABORT, duel wait for a $$$DONE to get back, so it can -+# return to gdb's prompt. -+# -+# Duel expressions terminates after '|>', the text after which should be -+# processed by the pipe (a "pipe command" if you will). -+# There is no limit to what this program can do. Currently all it does -+# is provide all hex/ all decimal display of integers (|>hex and |>dec), -+# and provide "smart" output, on the same line, when the symbolic output -+# is the same as the values. -+# -+# Some examples of what can be done here: -+# |> sort -- will sort the output -+# |> sort? -- display a message if it was/wasnt sorted -+# |> uniq -- display only uniq values in output -+# |> uniq? -- display message if all output was uniq. -+# |> vals -- only display vals, ignore symbolic -+# |> syms -- only display symbolics, ignore vals -+# |> matrix -- Attempt to display in a matrix format -+# |> compress -- compress into single lines, eg -+# x[i].val=1\n x[i].name="me"\n -+# becomes: x[i] = { val=1, name="me" } -+# |> vector -- attempt to display as vector, eg -+# x[1]=5\bx[4]=3\nx[9]=2\nx[12]=8\n becomes: -+# i 1 4 9 12 -+# x[i] 5 3 2 8 -+# |> smart -- try to figure out one of the above formats... -+# |> plotxy -- plot (sym,val) using xgraph. can convert x[5] -+# symbol into '5' for the x-coord, etc. -+# |> stack -- output of frame(..frames_no).`*`, -+# which hasnt been implemented yet (* is regex), -+# to be formatted as a stack trace... -+# -+# the code below is very simple. A better organization will support -+# adding "functions" (commands) and specify for each command if the -+# function is called only after all values have been collected, or -+# for every value, if the command is active until unset, or just for -+# the specific line it was given on, what flags it set/reset, etc. -+ -+ -+$|=1 ; # flush output on every write to the pipe -+ -+%cmds = ("norm",1,"smart",1,"dec",1,"hex",1) ; -+$smart=0; -+$base=0 ; -+ -+while(<>) { -+ chop; study ; -+ if(/^\$\$\$START: /) { -+ if(/\|\>\s*([^"']*)$/) { # |> pipe-command -+ $_ = $1 ; -+ s/\s+$// ; # clean trailing spaces -+ if($cmds{$_}) { -+ printf "Pipe command '$_'\n" ; -+ $smart=0 if /norm/ ; -+ $smart=1 if /smart/ ; -+ $base=0 if /norm/ ; -+ $base=10 if /dec/ ; -+ $base=16 if /hex/ ; -+ } -+ else { printf "BAD PIP COMMAND '$_'\n" ; } -+ } -+ $same=0 ; -+ } -+ elsif(/^\$\$\$DONE$/) { -+ print "\n" if $same ; # go to next line if not on same -+ print "\$\$\$DONE\n" ; -+ } -+ elsif(/^\$\$\$ABORT$/) { -+ print "\n" if $same ; # go to next line if not on same -+ print "\$\$\$DONE\n" ; -+ } -+ elsif(/^\$\$\$SYM: (.*)$/) { -+ $sym = $1 ; -+ } -+ elsif(/^\$\$\$VAL: (.*)$/) { -+ $_ = $val = $1 ; -+ $_ = oct if($base==10 && /^0x[0-9a-z]*$/) ; -+ $_ = sprintf("0x%2.2x",$_) if($base==16 && /^[1-9]\d*$/) ; -+ if($smart && ( $sym eq $_ || $sym eq $val)) { -+ $sz= 3 + length ; -+ if($same+$sz > 75) { print "\n" ; $same=0 ; } -+ $same+=$sz ; -+ print "$_, " ; -+ } -+ else { -+ print "\n" if $same ; # go to next line if not on same -+ if($sym == $val) { print "$_\n" ; } -+ else { print "$sym = $_\n" ; } -+ $same=0 ; -+ } -+ } -+ else { -+ print "bad duel input to duel.pipe ignored: $_\n" ; -+ } -+} ---- gdb/duel/duelself.c -+++ gdb/duel/duelself.c -@@ -0,0 +1,209 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* self-debugger module, it contains all of duel's access to -+ * the outside world (like duelgdb.c), but is intended to work when duel -+ * is linked with the debuggee directly (not with the debugger!) -+ * if you link this with duel.a, you get a test suite of duel -+ * for the C program: (tsuite.c) -+ * -+ * int gint ; -+ * typedef unsigned int uint ; -+ * int main() { -+ * printf ; malloc ; / * include them in bin * / -+ * char *s="main string" ; -+ * } -+ * -+ * You could link this module with your own program and call it at -+ * "appropriate places", then ship the program with this code, and -+ * use duel at client's site when a crash occurs. However, reading in -+ * the symbol table and figuring out the active frames remains a problem. -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.6 93/03/19 16:55:35 mg -+ * allow execution from within make -+ * -+ * Revision 1.5 93/03/12 05:47:29 mg -+ * *** empty log message *** -+ * -+ * Revision 1.4 93/02/04 00:05:10 mg -+ * avoid Header problems in self.out -+ * -+ * Revision 1.3 93/01/13 16:21:40 mg -+ * made sure printf is declared -+ * -+ * Revision 1.2 93/01/12 21:31:01 mg -+ * brought uptodate with duelgdb.c -+ * cleanup and set for release -+ * -+ */ -+/* include system dependent stuff here */ -+ -+#include "duel.h" -+ -+int main(int argc,char **argv); -+ -+FUNC void* duel_malloc(size_t size) -+{ -+ void *p=malloc(size); -+ if(p==0) duel_fatal("out of memory."); -+ return p; -+} -+ -+PROC duel_free(void *p) -+{ -+ free(p); -+} -+/* fetch n bytes from the target at the given memory address. -+ * the address to fetch from is given by (from). -+ * the value is stored at the 'to' location, which points to space for -+ * n bytes in the debugger. -+ * if the address can not be accessed, false is returned (if all ok, ret true) -+ */ -+ -+FUNC bool duel_get_target_bytes(ttarget_ptr from,void *to,size_t n) -+{ -+ duel_bcopy(to,from,n); -+ return TRUE ; -+} -+ -+/* store n bytes to the debuggee. reverse parms from above */ -+FUNC bool duel_put_target_bytes(ttarget_ptr to,void *from,size_t n) -+{ -+ duel_bcopy(to,from,n); -+ return TRUE ; -+} -+ -+/* fetch the value of a bitfield of a given structure. */ -+ -+FUNC bool duel_get_target_bitfield(ttarget_ptr struct_at,int bitpos, -+ int bitlen,void *to,tctype_kind tkind) -+{ -+ return FALSE ; /* not supported in duelself */ -+} -+ -+/* make a function call to the target. */ -+/* support only passing/returing sizeof(int) upto 5 paramaters */ -+PROC duel_target_func_call(tvalue *func, tvalue *parms[], -+ int parms_no,tvalue *rval) -+{ -+ int (*f)(); -+ int i ; -+ if(parms_no>5) duel_fatal("too many parms"); -+ if(sizeof(func->ctype->u.kid)!=sizeof(int) && -+ func->ctype->u.kid!=ctype_void ) duel_fatal("unsupported func parm"); -+ for(i=0 ; i<parms_no ; i++) { -+ if(parms[i]->val_kind!=VK_RVALUE || parms[i]->ctype->size!=sizeof(int)) -+ duel_fatal("unsupported paramater"); -+ } -+ f=(int (*)()) func->u.lvalue ; -+ switch(parms_no) { -+ case 0: -+ rval->u.rval_int= (*f)(); -+ break ; -+ case 1: -+ rval->u.rval_int= (*f)(parms[0]->u.rval_int); -+ break ; -+ case 2: -+ rval->u.rval_int= (*f)(parms[0]->u.rval_int,parms[1]->u.rval_int); -+ break ; -+ case 3: -+ rval->u.rval_int= (*f)(parms[0]->u.rval_int,parms[1]->u.rval_int, -+ parms[2]->u.rval_int); -+ break ; -+ case 4: -+ rval->u.rval_int= (*f)(parms[0]->u.rval_int,parms[1]->u.rval_int, -+ parms[2]->u.rval_int,parms[3]->u.rval_int); -+ break ; -+ case 5: -+ rval->u.rval_int= (*f)(parms[0]->u.rval_int,parms[1]->u.rval_int, -+ parms[2]->u.rval_int,parms[3]->u.rval_int,parms[4]->u.rval_int); -+ break ; -+ } -+ rval->val_kind=VK_RVALUE ; -+ rval->ctype=func->ctype->u.kid ; -+} -+ -+/* find debuggee variable. -+ * recognize main.s, gint, malloc, printf -+ */ -+ -+int gint ; /* global variable recognized */ -+char **main_s ; /* point to main's 's' */ -+ -+FUNC bool duel_get_target_variable(char *name, int frame_no, tvalue *v) -+{ -+ v->val_kind=VK_LVALUE ; -+ if(frame_no<=0 && strcmp(name,"s")==0) { -+ v->ctype=duel_mkctype_ptr(ctype_char); -+ v->u.lvalue = (void*) main_s ; -+ return TRUE ; -+ } -+ if(frame_no != -1) return FALSE ; -+ if(strcmp(name,"main")==0) { -+ v->ctype=duel_mkctype_func(ctype_void); -+ v->u.lvalue = (void*) main ; -+ return TRUE ; -+ } -+ if(strcmp(name,"malloc")==0) { -+ v->ctype=duel_mkctype_func(duel_mkctype_ptr(ctype_void)); -+ v->u.lvalue = (void*) malloc ; -+ return TRUE ; -+ } -+ if(strcmp(name,"printf")==0) { -+ if(0) printf(""); /* "declare" print */ -+ v->ctype=duel_mkctype_func(ctype_int); -+ v->u.lvalue = (void*) printf ; -+ return TRUE ; -+ } -+ if(strcmp(name,"gint")!=0) return FALSE ; -+ v->ctype= ctype_int ; /* type of this variable */ -+ v->u.lvalue= (void*) &gint ; /* address of variable */ -+ return TRUE ; -+} -+ -+ -+FUNC int duel_get_frames_number(void) -+{ -+ return 1 ; /* main */ -+} -+ -+ -+FUNC ttarget_ptr duel_get_function_for_frame(int frame_no) -+{ -+ if(frame_no==0) return (void*) main ; -+ else duel_fatal("bad frame number - internal err"); -+} -+ -+FUNC tctype* duel_get_target_typedef(char *name) -+{ -+ if(strcmp(name,"uint")==0) return ctype_uint ; -+ return NULL ; -+} -+ -+FUNC tctype* duel_get_target_struct_tag(char *name) { return 0 ; } -+FUNC tctype* duel_get_target_union_tag(char *name) { return 0 ; } -+FUNC tctype* duel_get_target_enum_tag(char *name) { return 0 ; } -+ -+int main(int argc,char **argv) -+{ -+ char *s="main string" ; -+ main_s = &s ; /* put s into the "symbol tbl" */ -+ -+ while(1) { -+ char in[120] ; -+ gets(in); -+ if(feof(stdin)) break ; -+ /* output & input are RCS'ed. avoid $Header in self.out, which is -+ * the input header, which RCS fix... which create mis matches */ -+ if(strncmp(in,"## $Header",10)==0) continue ; -+ printf("dl> %s\n",in); -+ if(in[0]==0 || in[0]=='#' && in[1]=='#') continue ; /* comments */ -+ duel_parse_and_eval(in); -+ } -+ return 0 ; /* to run in make */ -+} ---- gdb/duel/error.c -+++ gdb/duel/error.c -@@ -0,0 +1,112 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* display errors in a neat way */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.5 93/03/12 05:48:27 mg -+ * support output redirection -+ * -+ * Revision 1.4 93/01/12 21:35:31 mg -+ * cleanup and set for release -+ * -+ */ -+ -+#include "duel.h" -+ -+static tnode *curr_eval_node ; /* current node being evaluated */ -+static char *curr_inputstr ; /* current input string being eval */ -+ -+/* indicate the active node where an operator is now evaluated. -+ * if an error occurs, this marker is used to tell the user where -+ * the error is located. -+ * return previous setup to caller, so it can be restored. -+ */ -+ -+FUNC tnode* duel_set_eval_loc(tnode *n) -+{ -+ tnode *prev=curr_eval_node ; -+ curr_eval_node=n ; -+ return prev ; -+} -+ -+/* indicate the current input string which is evaluated -+ * (intended for future versions with multiple input strings) -+ */ -+ -+FUNC char* duel_set_input_string(char *s) -+{ -+ char *prev=curr_inputstr ; -+ curr_inputstr=s ; -+ return prev ; -+} -+/* display source position for errors, based on current node being eval'ed */ -+ -+LPROC print_src_pos(void) -+{ -+ int src_pos=0 ; -+ int i ; -+ if(curr_eval_node) src_pos=curr_eval_node->src_pos ; -+ duel_printf("Error: %s\n",curr_inputstr) ; -+ duel_printf(" ") ; -+ for(i=0 ; i<src_pos ; i++) duel_printf("-"); -+ duel_printf("^-- "); -+} -+ -+/* called for errors that are results of bad user input (syntax/sematics), -+ * e.g. an illegal variable name, etc -+ * the message is printed as a format string for 'op'. -+ * the error location in the source is printed based on the current eval node, -+ * and the value of the given operands are displayed. -+ */ -+ -+PROC duel_op_error(char *mesg,char *op,tvalue *v1,tvalue *v2) -+{ -+ char s[160] ; -+ -+ duel_redirectable_output_abort(); -+ print_src_pos(); -+ duel_printf(mesg,op); -+ duel_printf("\n"); -+ if(v1) { -+ duel_printf("operand%s ``%s'' ",(v2!=0)? "1":"",v1->symb_val); -+ duel_printf("\t-- type: "); -+ duel_print_type(v1->ctype,1); -+ duel_sprint_scalar_value(s,v1); -+ duel_printf("\n\t\t-- value: %s\n",s); -+ } -+ if(v2) { -+ duel_printf("operand%s ``%s'' ",(v1!=0)? "2":"",v2->symb_val); -+ duel_printf("\t-- type: "); -+ duel_print_type(v2->ctype,1); -+ duel_sprint_scalar_value(s,v2); -+ duel_printf("\n\t\t-- value: %s\n",s); -+ } -+ -+ duel_abort(); -+} -+ -+/* handle a genral error, no value (operand) is involved. -+ * location (node) is still displayed -+ */ -+ -+PROC duel_gen_error(char *mesg,char *arg1) -+{ -+ duel_redirectable_output_abort(); -+ print_src_pos(); -+ duel_printf(mesg,arg1); -+ duel_printf("\n"); -+ duel_abort(); -+} -+ -+/* handle fatal messages */ -+ -+PROC duel_fatal(char *msg) -+{ -+ duel_redirectable_output_abort(); -+ duel_printf("Fatal Duel error: %s\n",msg); -+ duel_abort(); -+} ---- gdb/duel/eval.c -+++ gdb/duel/eval.c -@@ -0,0 +1,832 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* this module is the most critical code, the recursive evaluation -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.13 93/03/19 15:39:34 mg -+ * fixed bug in left->left symbolic, and long symbolics which caused crashes -+ * -+ * Revision 1.12 93/03/12 05:48:45 mg -+ * fixed sizeof(type) symbolic -+ * -+ * Revision 1.11 93/02/26 04:59:51 mg -+ * improved symbolic debugging of #/ -+ * -+ * Revision 1.10 93/02/03 21:47:41 mg -+ * fixed dot stack bug; fixed func-call last parm eval bug -+ * -+ * Revision 1.9 93/01/12 21:50:26 mg -+ * cleanup and set for release -+ * -+ * Revision 1.8 93/01/07 00:09:34 mg -+ * scope stack changes a bit. -+ * clear/aliases commands. -+ * func.x support, x.y etc force existance if y field of x., x=>y w/'_' -+ * allow fields in y for x@y, x pointer. -+ * fixed eval_node setup -+ * added &&/ ||/ -+ * -+ * -+ * Revision 1.7 93/01/03 07:29:23 mg -+ * function calls, error reporting, printing. -+ * -+ * Revision 1.6 92/12/24 23:33:48 mg -+ * frames support -+ * -+ * Revision 1.5 92/10/19 15:06:35 mg -+ * *** empty log message *** -+ * -+ * Revision 1.4 92/10/14 02:04:35 mg -+ * misc -+ * -+ * Revision 1.3 92/09/16 11:04:16 mg -+ * *** empty log message *** -+ * -+ * Revision 1.2 92/09/15 05:54:56 mg -+ * cosmetics and new ops: -+ * generic '.' and '_' support. x@y. '..x' and 'x..'. while(), for(), ?: -+ * -+ */ -+ -+#include "duel.h" -+ -+ -+ -+#define DOT_STACK_SIZE 100 /* dot stack size, maximum no. of dots in stmt */ -+ -+/* the scope eval stack. -+ * used for several purposes: to push _'s values (=>), to push structs -+ * and unions for x.y and x->y, and to push func/frame values fro frame(i).x -+ * and func.x/ -+ * realv is the real value for the left side operand. It is used for '_'. -+ * fieldv is the one to be used to fetch actual names. either: -+ * fieldv=realv (for x.y, frame(i).y), fieldv=*realv (for x->y), -+ * fieldv=func_frame(realv) (for func.x), or fieldv=0 (x=>y). -+ */ -+struct { -+ tvalue *realv ; /* actual value for x in x.y or x->y etc. used for _ */ -+ tvalue *fieldv; /* value to use for fetching fields, *realv for x->y */ -+ } dot_stack[DOT_STACK_SIZE] ; -+int dot_stack_top= -1 ; -+ -+PROC duel_reset_eval(void) /* reset evaluation states from previous eval */ -+{ -+ dot_stack_top= -1 ; /* reset stack */ -+} -+ -+/* try to find the given name on the dot_stack of structures. -+ * if found, return true and value in(v) else return false. -+ * the symbolic value is not set. -+ * if top_only, looks only at the top of the stack. -+ */ -+LFUNC bool find_dot_name(char *name,tvalue *v,bool top_only) -+{ -+ int i,j ; -+ tctype_field *f ; -+ tctype *t ; -+ tvalue *x; -+ -+ for(i=dot_stack_top ; i>=0 ; i--) { /* look at the stack[i] */ -+ if(top_only && i!=dot_stack_top) break ; /* consider only top of stk*/ -+ x=dot_stack[i].realv ; -+ if(name[0]=='_' && name[1]==0 || /* _ */ -+ name[1]=='_' && i==dot_stack_top-1 && name[2]==0 || /* __ */ -+ name[1]=='0'+dot_stack_top-i && name[2]==0) { /* _[0-9] */ -+ *v = *x ; -+ return TRUE ; -+ } -+ x=dot_stack[i].fieldv; -+ if(!x) continue ; -+ if(x->val_kind==VK_FVALUE) { -+ if(!duel_get_target_variable(name,x->u.fvalue,v)) continue ; -+ strcpy(v->symb_val,name); -+ return TRUE ; -+ } -+ t=x->ctype ; -+ if(!ctype_kind_struct_like(t)) continue ; -+ duel_assert(x->val_kind==VK_LVALUE); -+ for(j=0 ; j<t->u.f.fields_no ; j++) { /* look at field[j] of struct*/ -+ f= &t->u.f.fields[j] ; -+ if(strcmp(f->name,name)==0) goto found ; -+ } -+ } -+ return FALSE ; -+found: -+ v->ctype=f->ctype ; -+ strcpy(v->symb_val,name); -+ if(f->bitlen==0) { -+ v->u.lvalue=x->u.lvalue+f->bitpos/BITS_PER_BYTE ; -+ v->val_kind=VK_LVALUE ; -+ return TRUE ; -+ } -+ /* special care for a bitfield */ -+ if(f->ctype->type_kind!=CTK_INT && f->ctype->type_kind!=CTK_UINT) -+ duel_gen_error("bitfield '%s' must be int or unsigned",name); -+ v->val_kind=VK_BVALUE ; -+ v->u.bvalue.lvalue=x->u.lvalue ; -+ v->u.bvalue.bitpos=f->bitpos ; -+ v->u.bvalue.bitlen=f->bitlen ; -+ return TRUE ; -+} -+ -+/* find the value of a given symbolic name and -+ * return in in v -+ * if name is not found, aborts with an error -+ */ -+ -+LPROC duel_eval_name(char *name,tvalue *v) -+{ -+ tvalue *aval=duel_find_alias(name) ; /* find internal alias */ -+ if(aval!=NULL) *v= *aval ; -+ else -+ if(find_dot_name(name,v,FALSE)) return ; /* setup name itself */ -+ else -+ if(duel_get_target_variable(name,-1,v)); -+ else -+ if(strcmp(name,"frames_no")==0) { /* check special variables */ -+ v->val_kind=VK_RVALUE ; -+ v->ctype=ctype_int ; -+ v->u.rval_int=duel_get_frames_number(); -+ } -+ else duel_gen_error("variable '%s' not found",name); -+ strcpy(v->symb_val,name); -+} -+ -+ -+LPROC push_val(tval_list *l,tvalue *v) -+{ -+ tval_lcell *e = duel_malloc(sizeof(tval_lcell)); -+ e->val = *v ; -+ e->next=l->head ; -+ l->head=e ; -+ if(l->tail==0) l->tail=e ; -+} -+ -+LPROC append_val(tval_list *l,tvalue *v) -+{ -+ tval_lcell *e=duel_malloc(sizeof(tval_lcell)) ; -+ e->val = *v ; -+ e->next=0 ; -+ if(l->head==0) l->head=l->tail=e ; -+ else l->tail=l->tail->next=e ; -+} -+ -+/* push a whole val-list(ins) into (l) i.e. insert (ins) at the head of(l) -+ */ -+ -+LPROC push_val_list(tval_list *l,tval_list *ins) -+{ -+ if(ins->head==NULL) return ; /* inserted list is empty */ -+ if(l->head==NULL) { *l= *ins ; return ; } /* insert-into is empty */ -+ ins->tail->next=l->head ; -+ l->head=ins->head ; -+} -+ -+ -+/* remove first(top) element */ -+LFUNC bool pop_val(tval_list *l,tvalue *v) -+{ -+ tval_lcell *e=l->head ; -+ if(e==0) return(FALSE); -+ *v=e->val ; -+ l->head=e->next ; -+ return(TRUE); -+} -+/* compute the symbolic value of one iteration of a search (eg -->) operator. -+ * Normally, for (x) and (y) the result x->y is returned. -+ * But, if x === a-->next[[n]] and y === next, then we -+ * return a-->next[[m]] where m=n+1. -+ * Also, instead of returning x->y we return x-->y[[1]] -+ * -+ * note: this was not written for speed! I don't know if it takes -+ * a significant amount of time or not. -+ */ -+ -+LPROC set_search_symb_val(char *opcode,tvalue *xval,tvalue *yval) -+{ -+ char *x = xval->symb_val ; -+ char *y = yval->symb_val ; -+ int i,opl=strlen(opcode),xl=strlen(x),yl=strlen(y) ; -+ char s[3*VALUE_MAX_SYMBOLIC_SIZE]; -+ -+ if(yl+2<xl && strcmp(x+xl-yl,y)==0 && x[xl-yl-2]=='-' && x[xl-yl-1]=='>') -+ sprintf(s,"%-.*s%s%s[[2]]",xl-yl-2,x,opcode,y); -+ else { -+ for(i=xl-1 ; i>0 ; i--) /* see if we have op in x */ -+ if(strncmp(&x[i],opcode,opl)==0) break ; -+ if(i>0 && strncmp(&x[i+opl],y,yl)==0 && -+ x[i+opl+yl]=='[' && x[i+opl+yl+1]=='[' && x[xl-2]==']' && x[xl-1]==']'){ -+ /* x seems to be something like head-->next[1] */ -+ int j,val=0 ; -+ for(j=i+opl+yl+2 ; j<xl-2 ; j++) { -+ if(x[j]<'0' || x[j]>'9') goto simple ; -+ val=10*val+x[j]-'0' ; /* compute index */ -+ } -+ sprintf(s,"%-.*s[[%d]]",i+opl+yl,x,val+1); /* and re-create it */ -+ } -+ else { -+simple: /* we failed to find a x-->y[z] pattern, make new one */ -+ sprintf(s,"%s->%s",x,y); -+ } -+ } -+ s[VALUE_MAX_SYMBOLIC_SIZE-1]=0 ; /* chop as needed */ -+ strcpy(y,s); -+} -+ -+LPROC push_dot_stack(tvalue *realv,tvalue *fieldv) -+{ -+ if(dot_stack_top==DOT_STACK_SIZE) -+ duel_gen_error("expression too complex ('.' and '->' levels)",0); -+ dot_stack[++dot_stack_top].realv=realv ; -+ dot_stack[dot_stack_top].fieldv=fieldv ; -+} -+ -+LPROC pop_dot_stack(void) -+{ -+ duel_assert(dot_stack_top>=0); -+ dot_stack_top-- ; -+} -+ -+/* a simple fetch of a field. used mainly when printing -+ * v must be a struct with the given name field. value is returned in ret. -+ * return false if name not found. -+ */ -+ -+FUNC bool duel_get_dot_name(tvalue *v,char *name,tvalue *ret) -+{ -+ bool ok ; -+ push_dot_stack(v,v); -+ ok=find_dot_name(name,ret,TRUE); -+ pop_dot_stack(); -+ return ok ; -+} -+ -+/* evaluate x.y and similar "with" operators. Special care when y is a -+ * name and not an expression -- force y to be a direct field of x. -+ * y is the 'y' node. v is value to return. op is opcode for error reports -+ * (rv,fv) are values to push on the dot stack. rv is the real 'x' value, -+ * fv is the value of x to use for field lookup (fv= *rv for '->') -+ */ -+ -+LFUNC bool eval_dot(tnode *y,tvalue *v,char *op,tvalue *rv,tvalue *fv) -+{ -+ bool ok ; -+ push_dot_stack(rv,fv); -+ if(y->node_kind!=NK_NAME) ok=duel_eval(y,v); /* "with" style */ -+ else { /* x.y y simply name */ -+ if(++y->eval.level>1) { y->eval.level=0 ; ok=FALSE ; } -+ else { -+ ok=find_dot_name(y->name,v,TRUE); -+ if(!ok) duel_op_error("field not found in operator '%s'",op,rv,0); -+ } -+ } -+ pop_dot_stack(); -+ return ok ; -+} -+ -+ -+/* evaluate special operators like '-->' '?:' etc */ -+ -+/* get the next result of an sop val: -+ * DFS: init by pushing(x) -+ * Iterate: pop x, compute all x->y, push (reversed) -+ * out: x -+ -+ * POS: init by pushing(x), unmarked. -+ * Iterate: pop x, if marked return it. else push back, marked. -+ * compute all x->y, push (reversed) -+ * repeat until marked x is popped. -+ * out: poped x which is marked. -+ -+ * BFS: init by pushing(x) -+ * Iterate: get first(x), -+ * compute all x->y and put into queue. -+ * return x. -+ */ -+ -+/* fetch the next value in a DFS search on x-->y. y is given as a node -+ * and x is popped of the given list. Value is returned in v. -+ * note: the results from x->y are reversed when pushed on the list, -+ * this is so x-->(left,right) would return the left first (put last on -+ * the stack, even though it is computed first!) -+ * malloc problem: newl is kept locally, so in case of ^C while here, mem -+ * it points to will be lost. Normally only a few values -+ */ -+ -+LFUNC bool get_next_dfs_val(tval_list *l, tnode *y,tvalue *v) -+{ -+ tvalue child,x ; -+ tval_list newl ; -+ newl.head=0 ; -+ do { -+ if(!pop_val(l,v)) return(FALSE) ; -+ x= *v ; -+ duel_get_struct_ptr_val(&x,"x-->y"); -+ } while(x.u.lvalue==0) ; /* ignore null pointers */ -+ while(eval_dot(y,&child,"-->",v,&x)) { -+ set_search_symb_val("-->",&x,&child); /* makes x-->y[n] neatly */ -+ append_val(&newl,&child); /* append to childs list */ -+ } -+ push_val_list(l,&newl); /* append new childs to stack */ -+ return(TRUE); /* returns the popped value in v */ -+} -+ -+ -+/* stop the evaluation of the expression at node n. -+ * useful with operators like first(). -+ * each node keeps an internal state allowing it to produce the next value. -+ * this function resets those states. -+ * -+ * How: the internal state is kept in n->eval.level. we reset level to zero -+ * for the node and the subnodes. if the level is already zero, -+ * the node has already gone to the 'initial state', so the subnodes -+ * are not visited. -+ */ -+ -+LPROC stop_eval(tnode *n) -+{ -+ int i; -+ if(n==NULL || n->eval.level==0) return ; /* done! subnodes are also ok */ -+ n->eval.level=0 ; -+ for(i=0 ; i<NODE_MAX_KIDS ; i++) stop_eval(n->kids[i]); -+} -+ -+/* evaluate function paramaters. This recursive function should be called -+ * with the top node for the parms. Parms are parsed as "," operators. -+ * the function leaves the computed values "hanging" on v1 of each "," node. -+ * the last paramater is left at v2 of the function call itself (there isnt -+ * any other reasonable place!). -+ * 2nd paramater is the function call node, used for the last paramater. -+ */ -+ -+LFUNC bool eval_func_parms(tnode *n,tnode *fn) -+{ -+ tvalue *p= &n->eval.v1 ; -+ if(n->node_kind==NK_OP && n->op_kind==OPK_SBIN && n->op==',') { -+ while(n->eval.level==2 || duel_eval(n->kids[0],p)) { -+ n->eval.level=2 ; /* left side active parm in p */ -+ if(eval_func_parms(n->kids[1],fn)) goto ok; -+ n->eval.level=1 ; /*re-eval */ -+ } -+ return FALSE ; -+ } -+ else if(!duel_eval(n,p = &fn->eval.v2)) return FALSE; /* last paramater */ -+ok: -+ duel_standardize_func_parm(p); -+ return TRUE ; -+} -+ -+LFUNC bool eval_func_call(tnode *n,tvalue *v) -+{ -+ -+ tvalue *f= &n->eval.v1 ; -+ tvalue *parms[21]; -+ int i,parms_no ; -+ tnode *p ; -+ -+again: -+ if(n->kids[1]==NULL) { /* no parms */ -+ n->eval.level=1 ; -+ if(!duel_eval(n->kids[0],f)) return FALSE ; -+ } -+ else { -+ while(n->eval.level==2 || duel_eval(n->kids[0],f)) { -+ n->eval.level=2 ; /* function in f */ -+ if(eval_func_parms(n->kids[1],n)) goto ok; -+ n->eval.level=1 ; /*re-eval func */ -+ } -+ return FALSE ; -+ ok: ; -+ } -+ -+ if(f->ctype->type_kind!=CTK_FUNC) duel_op_error("bad function call",0,f,0); -+ -+ p=n->kids[1] ; /* collect paramaters now */ -+ parms_no=0 ; -+ while(p && p->node_kind==NK_OP && p->op_kind==OPK_SBIN && p->op==',') { -+ parms[parms_no++]= &p->eval.v1 ; -+ p=p->kids[1] ; -+ if(parms_no>=20) duel_op_error("too many paramaters",0,0,0); -+ } -+ if(p) parms[parms_no++]= &n->eval.v2 ; /* last paramater */ -+ -+ duel_target_func_call(f,parms,parms_no,v); -+ if(f->ctype->u.kid->type_kind==CTK_VOID) goto again ; /* no return vals */ -+ duel_set_symb_val(v,"%s(",f,0); -+ for(i=0 ; i<parms_no ; i++) -+ duel_set_symb_val(v,"%s%s,",v,parms[i]); -+ if(parms_no>0) v->symb_val[strlen(v->symb_val)-1]='\0' ; /*chop ',' tail*/ -+ strcat(v->symb_val,")"); -+ return TRUE ; -+} -+ -+ -+/* evaluate for special operators: those the produce more than one value, -+ * binary ones. ',' '..' etc -+ */ -+ -+LFUNC bool duel_eval_sbin(tnode *n,tvalue *v) -+{ -+ tval_list *vl = &n->eval.vlist ; -+ tvalue y,*v1= &n->eval.v1, *v2= &n->eval.v2 ; -+ tnode *kid0 = n->kids[0], *kid1 = n->kids[1] ; -+ int vi ; -+ bool ok ; -+#define lev n->eval.level -+ -+ duel_assert(n->node_kind==NK_OP && n->op_kind==OPK_SBIN); -+ switch(n->op) { -+ case OP_DECL: -+ duel_assert(kid0->node_kind==NK_NAME && kid1->node_kind==NK_CTYPE); -+ if(kid1->ctype->size<=0) duel_gen_error("illegal type size",0); -+ v->val_kind=VK_LVALUE ; -+ v->ctype=kid1->ctype ; -+ v->u.lvalue=duel_alloc_target_space(kid1->ctype->size); -+ strcpy(v->symb_val,kid0->name); -+ duel_set_alias(kid0->name,v); -+ break ; -+ case OP_DEF: -+ if(kid0->node_kind!=NK_NAME) -+ duel_gen_error("left side of := must be a simple var",0); -+ if(!duel_eval(kid1,v)) return FALSE ; -+ duel_set_alias(kid0->name,v); -+ return TRUE ; -+ case ',': -+ if(lev==1 && duel_eval(kid0,v)) return TRUE ; -+ lev=2 ; -+ return duel_eval(kid1,v); -+ case ';': -+ /*note: (x;) is not allowed in syntax, but is allowed here and -+ *means eval x, return nothing. used by parser, e.g. terminating ';' -+ *produces no side effects -+ */ -+ -+ if(lev==1) while(duel_eval(kid0,v)) ; /* eval all left size */ -+ lev=2 ; -+ return duel_eval(kid1,v); -+ break ; -+ case OP_IMP: /* a=>b for each _=eval(a) return eval(b) (with _ set) */ -+ if(lev>1) goto im2 ; -+ for(;;) { -+ if(!duel_eval(kid0,v1)) return FALSE ; -+ lev=2 ; -+ im2: push_dot_stack(v1,0); -+ ok=duel_eval(kid1,v); -+ pop_dot_stack(); -+ if(ok) return TRUE ; -+ } -+ case OP_IF: /* if(a) b return eval(b) for each eval(a)!=0 */ -+ if(lev>1) goto if2 ; -+ for(;;) { -+ if(!duel_eval(kid0,v)) return FALSE ; -+ if(!duel_mk_logical(v,"if(x)y")) continue ; -+ lev=2 ; -+ if2: if(duel_eval(kid1,v)) return TRUE ; -+ } -+ case OP_OR: /* a||b normal 'C' logical or */ -+ if(lev>1) goto or2 ; -+ for(;;) { -+ if(!duel_eval(kid0,v)) return FALSE ; -+ if(duel_mk_logical(v,"x||y")) {lev=1 ; return TRUE ;} -+ or2: if(duel_eval(kid1,v)) { -+ lev=2 ; -+ duel_mk_logical(v,"y||x"); -+ return TRUE ; -+ } -+ } -+ case OP_AND: /* a&&b normal 'C' logical and */ -+ if(lev>1) goto an2 ; -+ for(;;) { -+ if(!duel_eval(kid0,v)) return FALSE ; -+ if(!duel_mk_logical(v,"x&&y")) {lev=1 ; return TRUE ;} -+ an2: if(duel_eval(kid1,v)) { -+ lev=2 ; -+ duel_mk_logical(v,"y&&x"); -+ return TRUE ; -+ } -+ } -+ case '.': -+ if(lev>1) goto dt2 ; -+ for(;;) { -+ if(!duel_eval(kid0,v1)) return FALSE ; -+ *v2 = * v1 ; /* copy value for the lookup */ -+ if(ctype_kind_func_ptr_like(v1->ctype)) /* func.x */ -+ duel_find_func_frame(v2,"x.y"); -+ else -+ if(v1->val_kind!=VK_FVALUE) /* type check frame or struct*/ -+ duel_get_struct_val(v1,"x.y"); -+ lev=2 ; -+ dt2: if(!eval_dot(kid1,v,".",v1,v2)) continue ; -+ if(v->ctype!=v1->ctype || v->val_kind!=v1->val_kind || -+ v->u.lvalue != v1->u.lvalue || -+ strcmp(v->symb_val,v1->symb_val)!=0) /* check for x._ */ -+ duel_set_symb_val(v,"%s.%s",v1,v); -+ return TRUE ; -+ } -+ case OP_ARR: -+ if(lev>1) goto ar2 ; -+ for(;;) { -+ if(!duel_eval(kid0,v1)) return FALSE ; -+ *v2 = *v1 ; /* copy value for dereferencing */ -+ duel_get_struct_ptr_val(v2,"x->y"); -+ lev=2 ; -+ ar2: if(!eval_dot(kid1,v,"->",v1,v2)) continue ; -+ if(v->ctype!=v1->ctype || v->val_kind!=v1->val_kind || -+ v->u.lvalue != v1->u.lvalue || -+ strcmp(v->symb_val,v1->symb_val)!=0) /* check for x->_ */ -+ duel_set_symb_val(v,"%s->%s",v1,v); -+ return TRUE ; -+ } -+ case OP_TO: /* a..b Is it legal to have 1..(5,6) sure! */ -+ if(lev>1) goto to2 ; -+ do { -+ if(kid0 && !duel_eval(kid0,v1)) break ; -+ do { -+ if(kid1 && !duel_eval(kid1,v2)) break ; -+ to2: if(duel_do_op_to(kid0? v1:0,kid1? v2:0,++lev-2,v)) return TRUE; -+ } while(kid1); -+ } while(kid0) ; /* either one (kid0 null) or infinite iterations*/ -+ break ; -+ case OP_SEL: /* x[[y]] */ -+ if(lev==1) { lev=2 ; n->eval.counter= -1 ; } -+ if(!duel_eval(kid1,v1)) { -+ stop_eval(kid0); -+ return FALSE ; -+ } -+ vi=duel_get_posint_val(v1,"y[[x]]"); -+ if(vi<=n->eval.counter) { -+ /* v is smaller than previous v value, so reset x and -+ * start over. Example: \x[1,5,3] after \x[1], -+ * we continue to get [5]. but to get [3] we reset -+ * Alternatively, we could have kept a list of old -+ * generated values. -+ */ -+ stop_eval(kid0) ; -+ n->eval.counter= -1 ; -+ } -+ for( ; n->eval.counter<vi ; n->eval.counter++) -+ if(!duel_eval(kid0,v)) -+ duel_op_error("operator x of y[[x]] too large",0,v1,0); -+ return TRUE ; /* value is the last (v) computed */ -+ break ; -+ case '@': /* x@y - generate x stops when y true */ -+ if(!duel_eval(kid0,v)) return FALSE ; -+ if(kid1->node_kind==NK_CONST) { /* special case y constant */ -+ *v2=kid1->cnst ; -+ *v1= *v ; /* because 'apply_bin_op' destroy its args */ -+ duel_apply_bin_op(OP_EQ,v1,v2,&y); -+ if(y.u.rval_int) { stop_eval(kid0); return FALSE ; } -+ return TRUE ; -+ } -+ *v1 = *v ; /* allow fields in y of x@y for x struct ptr */ -+ if(ctype_kind_ptr_like(v->ctype) && -+ ctype_kind_struct_like(v->ctype->u.kid)) -+ duel_get_struct_ptr_val(v1,"x@y"); -+ -+ while(eval_dot(kid1,v2,"@",v,v1)) /* check &&/y */ -+ if(!duel_mk_logical(v2,"y@x")) { /* y==0, so dont stop x */ -+ stop_eval(kid1); -+ return TRUE ; -+ } -+ stop_eval(kid0); -+ break ; -+ case '#': /* x#i define variable i as counter for gen. x*/ -+ if(kid1->node_kind!=NK_NAME) -+ duel_gen_error("x#y 2rd operand must be a name",0); -+ if(!duel_eval(kid0,v)) return FALSE ; -+ if(lev==1) { lev=2 ; n->eval.counter= -1 ; } /* first time */ -+ y.val_kind=VK_RVALUE ; -+ y.ctype=ctype_int ; -+ y.u.rval_int= ++n->eval.counter ; -+ sprintf(y.symb_val,"%d",n->eval.counter); -+ duel_set_alias(kid1->name,&y); -+ return TRUE ; -+ break ; -+ case OP_DFS: /* x-->y */ -+ if(lev>1) goto df2 ; -+ for(;;) { -+ if(!duel_eval(kid0,v)) return FALSE ; -+ duel_free_val_list(vl); -+ push_val(vl,v); -+ lev=2 ; -+ df2: if(get_next_dfs_val(vl,kid1,v)) return TRUE ; -+ } -+ break ; -+ case OP_WHILE: /* while(a) b */ -+ if(lev==2) goto wh2 ; -+ for(;;) { -+ while(duel_eval(kid0,v)) /* check &&/a */ -+ if(!duel_mk_logical(v,"while(x)y")) { -+ stop_eval(kid0); -+ return FALSE ; -+ } -+ lev=2 ; -+ wh2: if(duel_eval(kid1,v)) return TRUE ; -+ } -+ default: duel_assert(0); -+ } -+ return FALSE ; -+#undef lev -+} -+ -+ -+ -+LFUNC bool duel_eval_tri(tnode *n,tvalue *v) -+{ -+#define lev n->eval.level -+ duel_assert(n->node_kind==NK_OP && n->op_kind==OPK_TRI); -+ switch(n->op) { -+ case OP_IF: /* if(a) b else c return eval(b) for each eval(a)!=0 -+ * and eval(c) for each eval(a)==0 (usu. (a) is one result*/ -+ if(lev>1) goto if2; -+ for(;;) { -+ if(!duel_eval(n->kids[0],v)) return FALSE ; -+ lev=(duel_mk_logical(v,"if(x) y else z")? 2:3) ; -+ if2: if(duel_eval(n->kids[lev-1],v)) return TRUE ; -+ } -+ case '?': /* a? b:c has the same semantics as if(a) b else c */ -+ if(lev>1) goto qm2; -+ for(;;) { -+ if(!duel_eval(n->kids[0],v)) return FALSE ; -+ lev=(duel_mk_logical(v,"x? y:z")? 2:3) ; -+ qm2: if(duel_eval(n->kids[lev-1],v)) return TRUE ; -+ } -+ default: duel_assert(0); -+ } -+ return FALSE ; -+#undef lev -+} -+ -+LFUNC bool duel_eval_quad(tnode *n,tvalue *v) -+{ -+#define lev n->eval.level -+ duel_assert(n->node_kind==NK_OP && n->op_kind==OPK_QUAD); -+ switch(n->op) { -+ case OP_FOR: /* for(a;b;c) d ; */ -+ if(lev==1) { lev=2 ; while(duel_eval(n->kids[0],v)); } -+ if(lev==3) goto fr3 ; -+ for(;;) { -+ while(duel_eval(n->kids[1],v)) /* check &&/b */ -+ if(!duel_mk_logical(v,"for(a;x;y)z")) { -+ stop_eval(n->kids[1]); -+ return FALSE ; -+ } -+ lev=3 ; -+ fr3: if(duel_eval(n->kids[3],v)) return TRUE ; -+ while(duel_eval(n->kids[2],v)); -+ } -+ default: duel_assert(0); -+ } -+ return FALSE ; -+#undef lev -+} -+ -+FUNC bool duel_eval(tnode *n,tvalue *v) -+{ -+ tvalue u,tmp ; -+ bool ok=FALSE ; -+ tnode *prev_loc ; -+ -+ if(!n) return FALSE ; -+ prev_loc=duel_set_eval_loc(n); /* set current eval node, save prev */ -+ if(n->eval.level==0) n->eval.level=1 ; /* indicate node is 'active' */ -+ -+ switch(n->node_kind) { -+ case NK_CONST: /* return a 'value' node made of this constant */ -+ if(n->eval.level==1) { -+ n->eval.level=2 ; -+ *v=n->cnst ; -+ ok=TRUE ; -+ } -+ break ; -+ case NK_NAME: -+ if(n->eval.level==1) { -+ n->eval.level=2 ; -+ duel_eval_name(n->name,v); -+ ok=TRUE ; -+ } -+ break ; -+ case NK_OP: -+ switch(n->op_kind) { -+ case OPK_SUNARY: /* special unary ops */ -+ if(n->op=='#') { -+ int count=0 ; -+ if(n->eval.level==1) { -+ while(duel_eval(n->kids[0],&u)) -+ if(count++ == 0) duel_set_symb_val(v,"#/(%s ...)",&u,0); -+ if(count == 0) duel_set_symb_val(v,"#/(empty)",0,0); -+ v->val_kind=VK_RVALUE ; -+ v->ctype=ctype_int ; -+ v->u.rval_int=count ; -+ n->eval.level=2 ; -+ ok=TRUE ; -+ } -+ } -+ else -+ if(n->op==OP_AND) { -+ if(n->eval.level==1) { int result=1 ; -+ while(duel_eval(n->kids[0],v)) { -+ if(!duel_mk_logical(v,"&&/x")) { -+ stop_eval(n->kids[0]); -+ result=0 ; -+ break ; -+ } -+ } -+ v->val_kind=VK_RVALUE ; -+ v->ctype=ctype_int ; -+ v->u.rval_int=result ; -+ sprintf(v->symb_val,"%d",result); -+ n->eval.level=2 ; -+ ok=TRUE ; -+ } -+ } -+ else -+ if(n->op==OP_OR) { -+ if(n->eval.level==1) { int result=0 ; -+ while(duel_eval(n->kids[0],v)) { -+ if(duel_mk_logical(v,"||/x")) { -+ stop_eval(n->kids[0]); -+ result=1 ; -+ break ; -+ } -+ } -+ v->val_kind=VK_RVALUE ; -+ v->ctype=ctype_int ; -+ v->u.rval_int=result ; -+ sprintf(v->symb_val,"%d",result); -+ n->eval.level=2 ; -+ ok=TRUE ; -+ } -+ } -+ else -+ if(n->op==OP_SIZ) { -+ if(n->eval.level==1) { -+ char *tname=n->kids[0]->ctype->name ; -+ duel_assert(n->kids[0]->node_kind==NK_CTYPE); -+ v->val_kind=VK_RVALUE ; -+ v->ctype=ctype_size_t ; -+ v->u.rval_size_t=n->kids[0]->ctype->size ; -+ n->eval.level=2 ; -+ if(tname==NULL || *tname=='\0') tname="T" ; /* cheating */ -+ sprintf(v->symb_val,"sizeof(%s)",tname); -+ ok=TRUE ; -+ } -+ } -+ else duel_assert(0); -+ break ; -+ case OPK_UNARY: -+ if(!duel_eval(n->kids[0],v)) break ; -+ duel_apply_unary_op(n->op,v); -+ ok=TRUE ; -+ break ; -+ case OPK_POST_UNARY: -+ if(!duel_eval(n->kids[0],v)) break ; -+ duel_apply_post_unary_op(n->op,v); -+ ok=TRUE ; -+ break ; -+ case OPK_BIN: /* a+b, compute and hold a, iterate on b, redo a */ -+ while(n->eval.level==2 || duel_eval(n->kids[0],&n->eval.v1)) { -+ n->eval.level=2 ; /* left side active op in vals[0] */ -+ while(duel_eval(n->kids[1],&u)) { -+ tmp= n->eval.v1 ; /* copy left val, it is destoryed*/ -+ ok=duel_apply_bin_op(n->op,&tmp,&u,v); -+ if(ok) goto done; -+ } -+ n->eval.level=1 ; /*left side val no longer valid, re-eval*/ -+ } -+ break ; -+ case OPK_SBIN: /* a,b etc, special ops */ -+ ok=duel_eval_sbin(n,v) ; -+ break ; -+ case OPK_TRI: -+ ok=duel_eval_tri(n,v) ; -+ break ; -+ case OPK_QUAD: -+ ok=duel_eval_quad(n,v) ; -+ break ; -+ case OPK_CAST: -+ duel_assert(n->kids[0]->node_kind==NK_CTYPE); -+ if(!duel_eval(n->kids[1],v)) break ; -+ duel_do_cast(n->kids[0]->ctype,v); -+ ok=TRUE ; -+ break ; -+ case OPK_ASSIGN: -+ duel_gen_error("modified assignment is not supported yet",0); -+ case OPK_FUNC: -+ ok=eval_func_call(n,v) ; -+ break ; -+ default: duel_assert(0); -+ } -+ break ; -+ default: duel_assert(0); -+ } -+done: -+ if(!ok) n->eval.level=0 ; /* no other val available */ -+ duel_set_eval_loc(prev_loc); -+ return ok ; -+} ---- gdb/duel/evalops.c -+++ gdb/duel/evalops.c -@@ -0,0 +1,1273 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* this module contains evalauation code for many standard operators, eg '+' -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.14 93/03/19 15:40:17 mg -+ * fixed bug long symbolics handling -+ * -+ * Revision 1.13 93/03/12 05:50:01 mg -+ * uses tuint instead of uint, etc. -+ * -+ * Revision 1.12 93/02/26 05:00:13 mg -+ * fixed void pointers compare. ctype_voidptr is not unique! -+ * -+ * Revision 1.11 93/02/04 02:09:55 mg -+ * typo -+ * -+ * Revision 1.10 93/02/04 01:24:51 mg -+ * better error reports for "=" -+ * -+ * Revision 1.9 93/02/03 21:47:43 mg -+ * support "signed char" -+ * -+ * Revision 1.8 93/01/12 21:51:29 mg -+ * cleanup and set for release -+ * -+ * Revision 1.7 93/01/07 00:10:51 mg -+ * auto convert func to &func -+ * find a frame for a func -+ * -+ * -+ * Revision 1.6 93/01/03 07:30:02 mg -+ * function calls, error reporting, printing. -+ * -+ * Revision 1.5 92/12/24 23:34:47 mg -+ * frames support -+ * -+ * Revision 1.4 92/10/19 15:07:46 mg -+ * fvalue added (not ready yet), svalues dropped -+ * -+ * Revision 1.3 92/10/14 02:05:10 mg -+ * add print/{x} support -+ * -+ * Revision 1.2 92/09/15 05:48:57 mg -+ * support '..' new formats -+ * -+ */ -+ -+#include "duel.h" -+ -+/* -+ * This file is made up of three parts: -+ * (1) low-level functions that interact with the debugger/type system directly -+ * (2) mid-level functions that compute the result of simple operators like '+' -+ * (3) high-level functions that compute any binary/unary op. -+ * Only some of the functions in (1) are global, and all of the (3) are. -+ * this collection is in one file to allow a minimal of global symbols -+ * (for minimum collision with the debugger) -+ */ -+ -+ -+ -+/**************************************************************************** -+ A low-level set of functions follows. They interact with the type system -+ and the debugger/target's space directly: -+ get_storage_type_kind - retrieve ctype_kind, with special conversion for enums -+ get_rvalue - retrieve the rvalue of a variable/lvalue. -+ set_symb_val - set the symbolic value of a tvalue. -+ upgrade_small_int_types - figure out the type to upgrade to from char etc. -+ find_numeric_result_type - figure type of x+y where + is generic C op -+ convert_scalar_type - convert one scalar type to another -+ get_numeric_val - retrieve rvalue, making sure it is numeric -+ get_scalar_val - retrieve rvalue, making sure it is numeric or pointer -+ get_integral_val- retrieve rvalue, making sure it is an integer -+ get_int_val - retrieve rvalue, make sure it's an integer, return int val -+ get_pointer_val - retrieve rvalue, make sure it's a pointer. -+ ****************************************************************************/ -+ -+/* give the storage-type kind of a given type. -+ * this is the same type-kind as the type itslef, except in the case of enums -+ * where the type-kind of the storage will be CTK_INT etc (integral type) -+ * the storage type kind is set when the enum is created. -+ */ -+ -+LFUNC tctype_kind get_storage_type_kind(tctype *t) -+{ -+ if(t->type_kind!=CTK_ENUM) return t->type_kind ; -+ return t->u.e.real_type_kind ; -+} -+ -+/* try_get_rvalue -- make an rvalue of v. if v is already an rvalue, -+ * nothing is done. Else v is an b/lvalue, so its rvalue is fetched. -+ * special care: -+ * (1) Enums are fetched as int of same size. type stay enum! -+ * (2) Arrays and functions are made into pointers -+ * (3) Bitfields are converted to ints (debugger dependent) -+ * there are no rvalues of 'bitfield' type! -+ * return succ/fail for bad mem ref. the "real" function everyone calls is -+ * get_rvalue (this function is used only by printing functions to avoid -+ * chicken&egg problem of error reporting.) -+ */ -+ -+FUNC duel_try_get_rvalue(tvalue *v,char *op) -+{ -+ void *p ; -+ int n ; -+ bool ok; -+ if(v->val_kind == VK_RVALUE) return TRUE; -+ if(v->val_kind == VK_FVALUE) -+ duel_op_error("illegal type 'frame' for operand x of '%s'",op,v,0); -+ switch(get_storage_type_kind(v->ctype)) { -+ case CTK_CHAR: p= &v->u.rval_char ; n=sizeof(char) ;break ; -+ case CTK_SCHAR: p= &v->u.rval_schar ; n=sizeof(tschar) ;break ; -+ case CTK_UCHAR: p= &v->u.rval_uchar ; n=sizeof(tuchar) ;break ; -+ case CTK_USHORT: p= &v->u.rval_ushort ; n=sizeof(tushort) ;break ; -+ case CTK_SHORT: p= &v->u.rval_short ; n=sizeof(short) ;break ; -+ case CTK_INT: p= &v->u.rval_int ; n=sizeof(int) ;break ; -+ case CTK_UINT: p= &v->u.rval_uint ; n=sizeof(tuint) ;break ; -+ case CTK_LONG: p= &v->u.rval_long ; n=sizeof(long) ;break ; -+ case CTK_ULONG: p= &v->u.rval_ulong ; n=sizeof(tulong) ;break ; -+ case CTK_LONGLONG:p= &v->u.rval_longlong ; n=sizeof(long long) ;break ; -+ case CTK_ULONGLONG:p= &v->u.rval_ulonglong;n=sizeof(tulonglong) ;break ; -+ case CTK_FLOAT: p= &v->u.rval_float ; n=sizeof(float) ;break ; -+ case CTK_DOUBLE: p= &v->u.rval_double ; n=sizeof(double) ;break ; -+ case CTK_PTR: p= &v->u.rval_ptr ; n=sizeof(ttarget_ptr) ;break ; -+ case CTK_ARRAY: /* the lvalue becomes an rvalue, a real pointer! */ -+ duel_assert(v->val_kind==VK_LVALUE); /* duel exp rules */ -+ v->val_kind=VK_RVALUE ; -+ v->ctype=duel_mkctype_ptr(v->ctype->u.kid) ; -+ v->u.rval_ptr=v->u.lvalue ; -+ return TRUE; -+ case CTK_FUNC: /* makes it a pointer to a func*/ -+ duel_assert(v->val_kind==VK_LVALUE); /* duel exp rules */ -+ v->val_kind=VK_RVALUE ; -+ v->ctype=duel_mkctype_ptr(v->ctype) ; -+ v->u.rval_ptr=v->u.lvalue ; -+ return TRUE; -+ -+ case CTK_STRUCT: /* can't have an rval from struct? */ -+ case CTK_UNION: -+ /* enums were eliminated above */ -+ default: duel_assert(0); -+ } -+ if(v->val_kind == VK_BVALUE) { /* bitfield: lvalue+bitpos/len */ -+ tbvalue_info bv; -+ bv=v->u.bvalue ; -+ ok=duel_get_target_bitfield(bv.lvalue, bv.bitpos, bv.bitlen, p, -+ v->ctype->type_kind); -+ if(!ok) { v->u.bvalue=bv ; return FALSE ; } -+ } -+ else { -+ ttarget_ptr lv=v->u.lvalue ; -+ ok=duel_get_target_bytes(lv,p,n); /*fetch n debuggee bytes*/ -+ if(!ok) { v->u.lvalue=lv ; return FALSE ; } -+ } -+ -+ v->val_kind=VK_RVALUE ; -+ /* in remote debugging, one might need to swap byte order at this -+ * point. [remote debugging is not supported by duel v1.0] -+ */ -+ return TRUE ; -+} -+ -+ -+/* -+ * safe get_rvalue - produce error messages on memory access failer. -+ */ -+ -+LPROC get_rvalue(tvalue *v,char *op) -+{ -+ bool ok=duel_try_get_rvalue(v,op); -+ if(!ok) duel_op_error("illegal address for operand x of '%s'",op,v,0); -+} -+ -+/* put_rvalue: put the rvalue of v2 into the location in v1. -+ * types are assumed to be the same. -+ */ -+ -+LPROC put_rvalue(tvalue *v1,tvalue *v2,char *op) -+{ -+ void *p ; -+ int n ; -+ duel_assert(v1->val_kind!=VK_RVALUE); -+ duel_assert(v1->val_kind!=VK_FVALUE); -+ duel_assert(v2->val_kind==VK_RVALUE); -+ duel_assert(v1->ctype->size == v2->ctype->size); -+ switch(get_storage_type_kind(v2->ctype)) { -+ case CTK_CHAR: p= &v2->u.rval_char ; n=sizeof(char) ;break ; -+ case CTK_SCHAR: p= &v2->u.rval_schar ; n=sizeof(tschar) ;break ; -+ case CTK_UCHAR: p= &v2->u.rval_uchar ; n=sizeof(tuchar) ;break ; -+ case CTK_USHORT: p= &v2->u.rval_ushort ; n=sizeof(tushort) ;break ; -+ case CTK_SHORT: p= &v2->u.rval_short ; n=sizeof(short) ;break ; -+ case CTK_INT: p= &v2->u.rval_int ; n=sizeof(int) ;break ; -+ case CTK_UINT: p= &v2->u.rval_uint ; n=sizeof(tuint) ;break ; -+ case CTK_LONG: p= &v2->u.rval_long ; n=sizeof(long) ;break ; -+ case CTK_ULONG: p= &v2->u.rval_ulong ; n=sizeof(tulong) ;break ; -+ case CTK_LONGLONG: p= &v2->u.rval_longlong ; n=sizeof(long long);break ; -+ case CTK_ULONGLONG: p= &v2->u.rval_ulonglong ; n=sizeof(tulonglong);break ; -+ case CTK_FLOAT: p= &v2->u.rval_float ; n=sizeof(float) ;break ; -+ case CTK_DOUBLE: p= &v2->u.rval_double ; n=sizeof(double) ;break ; -+ case CTK_PTR: p= &v2->u.rval_ptr ; n=sizeof(ttarget_ptr) ;break ; -+ default: duel_assert(0); /* other types not supported as rvalues */ -+ } -+ if(v1->val_kind == VK_BVALUE) -+ duel_gen_error("assignment to bitfields is not yet supported",0); -+ else -+ if(!duel_put_target_bytes(v1->u.lvalue,p,n)) /*store n debuggee bytes*/ -+ duel_op_error("cant write memory for operand x of '%s'",op,v1,0); -+} -+ -+/* set the symbolic val for tvalue. input format is a sprintf, -+ * with v1,v2 being other values that show as '%s' in the format. -+ * v1,v2 can be zero if they are unused by the format. -+ */ -+PROC duel_set_symb_val(tvalue *r,char *format,tvalue *v1,tvalue *v2) -+{ -+ char s[3*VALUE_MAX_SYMBOLIC_SIZE]; -+ sprintf(s,format,v1->symb_val,v2->symb_val); -+ s[VALUE_MAX_SYMBOLIC_SIZE-1]=0 ; /* chop as needed */ -+ strcpy(r->symb_val,s); -+} -+ -+/* given a small int type (short,char,enum) return the upgraded (int or -+ * uint) type. Else return the original type -+ */ -+LFUNC tctype* upgrade_small_int_types(tctype *t) -+{ -+ switch(t->type_kind) { -+ case CTK_ENUM: -+ case CTK_CHAR: -+ case CTK_SCHAR: -+ case CTK_UCHAR: -+ case CTK_SHORT: -+ return ctype_int ; -+ case CTK_USHORT: -+ if(sizeof(tushort)==sizeof(int)) return ctype_uint ; -+ else return ctype_int ; -+ default: -+ return t ; -+ } -+} -+ -+/* find the type of the result of a generic numeric operation on -+ * v1,v2. This applies the standard C type upgrade rules. -+ * The type of the result is returned. -+ * r is setup so it can receive the result: an RVALUE of the specified -+ * type. Its symbolic value is also setup based on the symbolic value -+ * of v1 v2 and the operation op. -+ * Note: op is not used to figure out the numeric result, only -+ * the types of v1 and v2. As a side effect, the answer for x|y where -+ * y is a double will be given as double. it is up to the caller to -+ * verify that v1,v2 have meaningful types of this operation -+ * -+ */ -+ -+LFUNC tctype* find_numeric_result_type(tvalue *v1,tvalue *v2, -+ tvalue *r,char *op) -+{ -+ tctype *t1=upgrade_small_int_types(v1->ctype); /* upgrade to int etc */ -+ tctype *t2=upgrade_small_int_types(v2->ctype); -+ char s[80] ; -+ r->val_kind=VK_RVALUE ; -+ sprintf(s,"%%s%s%%s",op) ; /* eg, if op=">>" then s becomes "%s>>%s" */ -+ duel_set_symb_val(r,s,v1,v2); -+ -+ if(t1==ctype_double || t2==ctype_double) return r->ctype=ctype_double ; -+ if(t1==ctype_float || t2==ctype_float) return r->ctype=ctype_float ; -+ if(t1==ctype_ulonglong || t2==ctype_ulonglong) return r->ctype=ctype_ulonglong ; -+ if(t1==ctype_longlong || t2==ctype_longlong) return r->ctype=ctype_longlong ; -+ if(t1==ctype_ulong || t2==ctype_ulong) return r->ctype=ctype_ulong ; -+ if(sizeof(unsigned)==sizeof(long) && -+ (t1==ctype_long && t2==ctype_uint || -+ t1==ctype_uint && t2==ctype_long)) return r->ctype=ctype_ulong ; -+ if(t1==ctype_long || t2==ctype_long) return r->ctype=ctype_long ; -+ if(t1==ctype_uint || t2==ctype_uint) return r->ctype=ctype_uint ; -+ return r->ctype=ctype_int ; -+} -+ -+/* convert_to_fix assisting-macro: takes the val stored in v and put it -+ * into w. w is an lvalue with a 'fixed' type (t). -+ */ -+ -+#define convert_to_fix(v,w) \ -+ switch(get_storage_type_kind(v->ctype)) { \ -+ case CTK_CHAR: w (v->u.rval_char) ; break ; \ -+ case CTK_SCHAR: w (v->u.rval_schar) ; break ; \ -+ case CTK_UCHAR: w (v->u.rval_uchar) ; break ; \ -+ case CTK_USHORT: w (v->u.rval_ushort) ; break ; \ -+ case CTK_SHORT: w (v->u.rval_short) ; break ; \ -+ case CTK_INT: w (v->u.rval_int) ; break ; \ -+ case CTK_UINT: w (v->u.rval_uint) ; break ; \ -+ case CTK_LONG: w (v->u.rval_long) ; break ; \ -+ case CTK_ULONG: w (v->u.rval_ulong) ; break ; \ -+ case CTK_LONGLONG: w (v->u.rval_longlong) ; break ; \ -+ case CTK_ULONGLONG: w (v->u.rval_ulonglong) ; break ; \ -+ case CTK_FLOAT: w (v->u.rval_float) ; break ; \ -+ case CTK_DOUBLE: w (v->u.rval_double) ; break ; \ -+ case CTK_PTR: w (tptrsize_int) (v->u.rval_ptr) ; break ; \ -+ default: duel_assert(0); \ -+ } -+ -+ -+/* convert_scalar_type -- convert rvalue v to type t. -+ * uses convert_to_fix macro. In effect, this is a huge switch for -+ * all possible combinations of basic C types. -+ */ -+ -+LPROC convert_scalar_type(tvalue *v,tctype *t,char *op) -+{ -+ get_rvalue(v,op); -+ switch(get_storage_type_kind(t)) { -+ case CTK_CHAR: convert_to_fix(v,v->u.rval_char=(char)) ; break ; -+ case CTK_SCHAR: convert_to_fix(v,v->u.rval_schar=(tschar)) ; break ; -+ case CTK_UCHAR: convert_to_fix(v,v->u.rval_uchar=(tuchar)) ; break ; -+ case CTK_SHORT: convert_to_fix(v,v->u.rval_short=(short)) ; break ; -+ case CTK_USHORT: convert_to_fix(v,v->u.rval_ushort=(tushort)) ; break ; -+ case CTK_INT: convert_to_fix(v,v->u.rval_int=(int)) ; break ; -+ case CTK_UINT: convert_to_fix(v,v->u.rval_uint=(tuint)) ; break ; -+ case CTK_LONG: convert_to_fix(v,v->u.rval_long=(long)) ; break ; -+ case CTK_ULONG: convert_to_fix(v,v->u.rval_ulong=(tulong)) ; break ; -+ case CTK_LONGLONG: convert_to_fix(v,v->u.rval_longlong=(long long)) ; break ; -+ case CTK_ULONGLONG: convert_to_fix(v,v->u.rval_ulonglong=(tulonglong)) ; break ; -+ case CTK_FLOAT: convert_to_fix(v,v->u.rval_float=(float)) ; break ; -+ case CTK_DOUBLE: convert_to_fix(v,v->u.rval_double=(double)) ; break ; -+ case CTK_PTR: convert_to_fix(v, -+ v->u.rval_ptr=(ttarget_ptr)(tptrsize_int)) ; break ; -+ default: duel_assert(0); -+ } -+ v->ctype=t ; -+} -+ -+ -+/* verify v is numeric, get its rvalue converted to type tout or at least int*/ -+LPROC get_numeric_val(tvalue *v,char *op,tctype *tout) -+{ -+ if(!ctype_kind_numeric(v->ctype)) -+ duel_op_error("operand x of '%s' is not numeric",op,v,0); -+ if(!tout) tout=upgrade_small_int_types(v->ctype); /* upgrade to int etc */ -+ convert_scalar_type(v,tout,op); -+} -+ -+/*verify v is integral, get its rvalue converted to type tout or at least int*/ -+LPROC get_integral_val(tvalue *v,char *op,tctype *tout) -+{ -+ if(!ctype_kind_integral(v->ctype)) -+ duel_op_error("operand x of '%s' is not integral",op,v,0); -+ if(!tout) tout=upgrade_small_int_types(v->ctype); /* upgrade to int etc */ -+ convert_scalar_type(v,tout,op); -+} -+ -+/* verify v is integral, return its actual value as 'int' */ -+FUNC int duel_get_int_val(tvalue *v,char *op) -+{ -+ get_integral_val(v,op,ctype_int); -+ return v->u.rval_int ; -+} -+ -+/* verify v is numeric or pointer/array, upgrade type to at least int or ptr -+ and get the rvalue */ -+LPROC get_scalar_val(tvalue *v,char *op) -+{ -+ if(ctype_kind_ptr_like(v->ctype)) get_rvalue(v,op); -+ else { -+ tctype *t=upgrade_small_int_types(v->ctype); /* upgrade to int */ -+ if(!ctype_kind_numeric(v->ctype)) -+ duel_op_error("operand x of '%s' is not a scalar",op,v,0); -+ convert_scalar_type(v,t,op); -+ } -+} -+ -+LPROC get_pointer_val(tvalue *v,char *op,bool zero_ok) -+{ -+ if(ctype_kind_ptr_like(v->ctype)) get_rvalue(v,op); -+ else -+ if(zero_ok && v->ctype->type_kind==CTK_INT && -+ v->val_kind==VK_RVALUE && v->u.rval_int==0) { -+ v->ctype=ctype_voidptr ; -+ v->u.rval_ptr=0 ; -+ } -+ else duel_op_error("operand x of '%s' is not a pointer",op,v,0); -+} -+ -+/* copy one lvalue over the other. This copy is used for assignment, -+ * including the assignment of structures and unions. -+ * supports unlimited size and error reports when memory access fails. -+ */ -+ -+LPROC copy_lvalues(tvalue *v1,tvalue *v2,char *op) -+{ -+ size_t size ; -+ ttarget_ptr to=v1->u.lvalue,from=v2->u.lvalue ; -+ char buf[BUFSIZ] ; -+ duel_assert(v1->val_kind==VK_LVALUE && v2->val_kind==VK_LVALUE); -+ size=v1->ctype->size ; -+ duel_assert(v2->ctype->size==size); -+ while(size!=0) { -+ size_t chunk_size=((size>BUFSIZ)? BUFSIZ:size) ; -+ if(!duel_get_target_bytes(from,buf,chunk_size)) -+ duel_op_error("error reading memory (copy) in '%s'",op,v1,v2); -+ if(!duel_put_target_bytes(to,buf,chunk_size)) -+ duel_op_error("error writing memory (copy) in '%s'",op,v1,v2); -+ size-=chunk_size ; -+ to+=chunk_size ; -+ from+=chunk_size ; -+ } -+} -+ -+/* -+ * check that two values have "compatible" types. -+ * since structs compiled in different modules are each unique, -+ * we settle for comparing the number of references (array/ptr) -+ * and then make sure the same type-kind is used, with the same -+ * physical size. -+ * this allows, e.g. struct {short x,y } and struct {int x} -+ * to be considered equal. Possibly one could compare struct/union -+ * for member sizes (but not names?!). this however requires to keep -+ * track of self references and is not implemented here. -+ */ -+ -+LPROC duel_check_type_eq(tvalue *v1,tvalue *v2,char *op) -+{ -+ tctype *t1=v1->ctype, *t2=v2->ctype ; -+ if(ctype_kind_ptr_like(t1) && ctype_kind_ptr_like(t2) && /*(void*) match*/ -+ (t1->u.kid==ctype_void || t2->u.kid==ctype_void)) return; -+ -+ while(ctype_kind_ptr_like(t1) && ctype_kind_ptr_like(t2)) -+ t1=t1->u.kid, t2=t2->u.kid ; -+ if(t1==t2) return ; /* exact same type */ -+ if(t1->type_kind != t2->type_kind || t1->size != t2->size) -+ duel_op_error("incompatible types for op %s",op,v1,v2); -+} -+ -+ -+/************************************************************************** -+ a set of mid-level functions follow. These actually apply duel/C -+ operators to values -+ **************************************************************************/ -+ -+/* these do pointer+int addition/subtraction of v1,v2 and store result in r. -+ * NOTE: r's symbolic value is not set. -+ */ -+ -+LPROC add_offset_to_ptr(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ size_t len ; -+ get_pointer_val(v1,"x+y (ptr add)",FALSE); -+ get_integral_val(v2,"y+x (ptr add)",NULL); -+ r->val_kind=VK_RVALUE ; -+ r->ctype=v1->ctype ; -+ len=v1->ctype->u.kid->size ; -+ if(len==0) duel_op_error("unknown pointer object size for '+' op",0,v1,0); -+ switch(v2->ctype->type_kind) { -+ case CTK_INT: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_int ;break ; -+ case CTK_UINT: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_uint ;break ; -+ case CTK_LONG: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_long ;break ; -+ case CTK_ULONG: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_ulong;break ; -+ case CTK_LONGLONG: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_longlong ;break ; -+ case CTK_ULONGLONG: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_ulonglong;break ; -+ default: duel_assert(0); -+ } -+} -+ -+LPROC sub_offset_from_ptr(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ size_t len ; -+ get_pointer_val(v1,"x-y (ptr sub)",FALSE); -+ get_integral_val(v2,"y-x (ptr sub)",NULL); -+ r->val_kind=VK_RVALUE ; -+ r->ctype=v1->ctype ; -+ len=v1->ctype->u.kid->size ; -+ if(len==0) duel_op_error("unknown pointer object size for '-' op",0,v1,0); -+ switch(v2->ctype->type_kind) { -+ case CTK_INT: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_int ;break ; -+ case CTK_UINT: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_uint ;break ; -+ case CTK_LONG: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_long ;break ; -+ case CTK_ULONG: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_ulong;break ; -+ case CTK_LONGLONG: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_longlong ;break ; -+ case CTK_ULONGLONG: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_ulonglong;break ; -+ default: duel_assert(0); -+ } -+} -+ -+ -+/* do addition of v1,v2 and store result in r. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_add(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tctype *t=find_numeric_result_type(v1,v2,r,"+"); -+ if(ctype_kind_ptr_like(v1->ctype)) { -+ get_integral_val(v2,"pointer+x",NULL); -+ add_offset_to_ptr(v1,v2,r); -+ return ; -+ } -+ if(ctype_kind_ptr_like(v2->ctype)) { -+ get_integral_val(v1,"x+pointer",NULL); -+ add_offset_to_ptr(v2,v1,r); -+ return ; -+ } -+ get_numeric_val(v1,"x+y",t); -+ get_numeric_val(v2,"y+x",t); -+ r->val_kind=VK_RVALUE ; -+ r->ctype=t ; -+ duel_set_symb_val(r,"%s+%s",v1,v2); -+ switch(t->type_kind) { -+ case CTK_INT: r->u.rval_int =v1->u.rval_int +v2->u.rval_int ;break ; -+ case CTK_UINT: r->u.rval_uint =v1->u.rval_uint +v2->u.rval_uint ;break ; -+ case CTK_LONG: r->u.rval_long =v1->u.rval_long +v2->u.rval_long ;break ; -+ case CTK_ULONG: r->u.rval_ulong=v1->u.rval_ulong +v2->u.rval_ulong ;break ; -+ case CTK_LONGLONG: r->u.rval_longlong =v1->u.rval_longlong +v2->u.rval_longlong ;break ; -+ case CTK_ULONGLONG: r->u.rval_ulonglong=v1->u.rval_ulonglong +v2->u.rval_ulonglong ;break ; -+ case CTK_FLOAT: r->u.rval_float=v1->u.rval_float +v2->u.rval_float ;break ; -+ case CTK_DOUBLE:r->u.rval_double=v1->u.rval_double+v2->u.rval_double;break; -+ default: duel_assert(0); -+ } -+} -+ -+/* do arithmeric subtraction of v1,v2 and store result in r. -+ * v1 and v2 should be of numeric type to begin with. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_subtract(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tctype *t=find_numeric_result_type(v1,v2,r,"-"); -+ if(ctype_kind_ptr_like(v1->ctype)) { -+ if(ctype_kind_ptr_like(v2->ctype)) { -+ long len ; /* length must be signed to allow signed p-q result*/ -+ get_pointer_val(v1,"x-y",FALSE); -+ get_pointer_val(v2,"x-y",FALSE); -+ duel_check_type_eq(v1,v2,"- (ptr)"); -+ /* should compare pointer types */ -+ len=v1->ctype->u.kid->size ; -+ if(len<=0) -+ duel_op_error("illegal object size for op %s","- (ptr)",v1,v2); -+ r->ctype=ctype_ptrdiff_t ; -+ r->u.rval_ptrdiff_t= (v1->u.rval_ptr - v2->u.rval_ptr)/len ; -+ return ; -+ } -+ get_integral_val(v2,"pointer-x",NULL); -+ sub_offset_from_ptr(v1,v2,r); -+ return ; -+ } -+ get_numeric_val(v1,"x-y",t); -+ get_numeric_val(v2,"y-x",t); -+ switch(t->type_kind) { -+ case CTK_INT: r->u.rval_int =v1->u.rval_int - v2->u.rval_int ;break; -+ case CTK_UINT: r->u.rval_uint =v1->u.rval_uint - v2->u.rval_uint ;break; -+ case CTK_LONG: r->u.rval_long =v1->u.rval_long - v2->u.rval_long ;break; -+ case CTK_ULONG: r->u.rval_ulong=v1->u.rval_ulong - v2->u.rval_ulong ;break; -+ case CTK_LONGLONG: r->u.rval_longlong =v1->u.rval_longlong - v2->u.rval_longlong ;break; -+ case CTK_ULONGLONG: r->u.rval_ulonglong=v1->u.rval_ulonglong - v2->u.rval_ulonglong ;break; -+ case CTK_FLOAT: r->u.rval_float=v1->u.rval_float - v2->u.rval_float ;break; -+ case CTK_DOUBLE:r->u.rval_double=v1->u.rval_double-v2->u.rval_double;break; -+ default: duel_assert(0); -+ } -+} -+ -+/* compare values of v1 and v2, knowing that at least one is a frame-value -+ * type. Allows two fvals to be compared, or an fval to be compared -+ * to a func (this compares the func at the frame to the given func) -+ */ -+ -+LFUNC bool comp_bin_op_eq_fvals(tvalue *v1,tvalue *v2) -+{ -+ bool v1f=v1->val_kind == VK_FVALUE ; -+ bool v2f=v2->val_kind == VK_FVALUE ; -+ int frame_no ; -+ ttarget_ptr frame_func,p ; -+ if(v1f && v2f) return v1->u.fvalue == v2->u.fvalue ; /*cmp frames */ -+ if(v1f) { -+ frame_no = v1->u.fvalue ; -+ get_pointer_val(v2,"frame==x",FALSE) ; -+ if(v2->ctype->u.kid->type_kind!=CTK_FUNC) -+ duel_op_error("operand x of 'frame=x' not a func pointer",0,v2,0); -+ p=v2->u.rval_ptr ; -+ } -+ else { -+ frame_no = v2->u.fvalue ; -+ get_pointer_val(v1,"x==frame",FALSE) ; -+ if(v1->ctype->u.kid->type_kind!=CTK_FUNC) -+ duel_op_error("operand x of 'x==frame' not a func pointer",0,v1,0); -+ p=v1->u.rval_ptr ; -+ } -+ frame_func = duel_get_function_for_frame(frame_no); -+ return frame_func == p ; -+} -+ -+ -+/* compares of v1,v2 and store result in r. -+ * v1 and v2 should be of numeric/pointer type to begin with. -+ * NOTE: v1, v2 are destroyed! -+ */ -+ -+LPROC do_op_eq(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tctype *t=find_numeric_result_type(v1,v2,r,"=="); -+ r->ctype=ctype_int ; -+ if(v1->val_kind==VK_FVALUE || v2->val_kind==VK_FVALUE) { -+ r->u.rval_int = comp_bin_op_eq_fvals(v1,v2); -+ return ; -+ } -+ if(ctype_kind_ptr_like(v1->ctype) || ctype_kind_ptr_like(v2->ctype)) { -+ get_pointer_val(v1,"x==y",TRUE); -+ get_pointer_val(v2,"y==x",TRUE); -+ duel_check_type_eq(v1,v2,"=="); -+ r->u.rval_int = v1->u.rval_ptr == v2->u.rval_ptr ; -+ return ; -+ } -+ get_numeric_val(v1,"x==y",t); -+ get_numeric_val(v2,"y==x",t); -+ switch(t->type_kind) { -+ case CTK_INT: r->u.rval_int=v1->u.rval_int == v2->u.rval_int ;break; -+ case CTK_UINT: r->u.rval_int=v1->u.rval_uint == v2->u.rval_uint ;break; -+ case CTK_LONG: r->u.rval_int=v1->u.rval_long == v2->u.rval_long ;break; -+ case CTK_ULONG: r->u.rval_int=v1->u.rval_ulong == v2->u.rval_ulong ;break; -+ case CTK_LONGLONG: r->u.rval_int=v1->u.rval_longlong == v2->u.rval_longlong ;break; -+ case CTK_ULONGLONG: r->u.rval_int=v1->u.rval_ulonglong == v2->u.rval_ulonglong ;break; -+ case CTK_FLOAT: r->u.rval_int=v1->u.rval_float == v2->u.rval_float ;break; -+ case CTK_DOUBLE:r->u.rval_int=v1->u.rval_double == v2->u.rval_double;break; -+ default: duel_assert(0); -+ } -+} -+ -+ -+/* compares of v1,v2 and store result in r. -+ * v1 and v2 should be of numeric/pointer type to begin with. -+ * NOTE: v1, v2 are destroyed! -+ */ -+#define mk_func_compare(func,op,sop,xysop,yxsop,nullok) \ -+LPROC func(tvalue *v1,tvalue *v2,tvalue *r) \ -+{ \ -+ tctype *t=find_numeric_result_type(v1,v2,r,sop); \ -+ r->ctype=ctype_int ; \ -+ \ -+ if(ctype_kind_ptr_like(v1->ctype) || ctype_kind_ptr_like(v2->ctype)) { \ -+ get_pointer_val(v1,xysop,nullok); \ -+ get_pointer_val(v2,yxsop,nullok); \ -+ duel_check_type_eq(v1,v2,sop); \ -+ r->u.rval_int = v1->u.rval_ptr op v2->u.rval_ptr ; \ -+ return ; \ -+ } \ -+ get_numeric_val(v1,xysop,t); \ -+ get_numeric_val(v2,yxsop,t); \ -+ switch(t->type_kind) { \ -+ case CTK_INT: r->u.rval_int=v1->u.rval_int op v2->u.rval_int ;break;\ -+ case CTK_UINT: r->u.rval_int=v1->u.rval_uint op v2->u.rval_uint ;break;\ -+ case CTK_LONG: r->u.rval_int=v1->u.rval_long op v2->u.rval_long ;break;\ -+ case CTK_ULONG: r->u.rval_int=v1->u.rval_ulong op v2->u.rval_ulong ;break;\ -+ case CTK_LONGLONG: r->u.rval_int=v1->u.rval_longlong op v2->u.rval_longlong ;break;\ -+ case CTK_ULONGLONG: r->u.rval_int=v1->u.rval_ulonglong op v2->u.rval_ulonglong ;break;\ -+ case CTK_FLOAT: r->u.rval_int=v1->u.rval_float op v2->u.rval_float ;break;\ -+ case CTK_DOUBLE:r->u.rval_int=v1->u.rval_double op v2->u.rval_double;break;\ -+ default: duel_assert(0); \ -+ } \ -+} -+ -+mk_func_compare(do_op_ne,!=,"!=","x!=y","y!=x",TRUE) -+mk_func_compare(do_op_ge,>=,">=","x>=y","y>=x",FALSE) -+mk_func_compare(do_op_le,<=,"<=","x<=y","y<=x",FALSE) -+mk_func_compare(do_op_ls,<, "<", "x<y", "y<x",FALSE) -+mk_func_compare(do_op_gt,>, ">", "x>y", "y>x",FALSE) -+#undef mk_func_compare -+ -+ -+/* do_compare_questionmark -- handle the <? >? etc ops */ -+ -+LFUNC bool do_compare_questionmark(topcode op,tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tvalue tmp ; -+ tmp= *v1 ; -+ switch(op) { -+ case OP_EQQ: do_op_eq(v1,v2,r); break ; -+ case OP_NEQ: do_op_ne(v1,v2,r); break ; -+ case OP_GEQ: do_op_ge(v1,v2,r); break ; -+ case OP_LEQ: do_op_le(v1,v2,r); break ; -+ case OP_LSQ: do_op_ls(v1,v2,r); break ; -+ case OP_GTQ: do_op_gt(v1,v2,r); break ; -+ } -+ if(r->u.rval_int==0) return FALSE ; -+ *r=tmp ; -+ return TRUE ; -+} -+ -+ -+ -+/* apply indirection of a pointer. -+ * this is easy, you just force the value to be an rvalue pointer, then -+ * make it into an lvalue with the pointed-to type. -+ * useful for (*x x[y] x->y etc) -+ * does not setup a symbolic value! -+ */ -+ -+ -+LPROC follow_pointer(tvalue *v,char *op,bool nonull) -+{ -+ get_pointer_val(v,op,FALSE); -+ if(nonull && v->u.rval_ptr == NULL) -+ duel_op_error("dereference NULL pointer x in '%s'",op,v,0); -+ v->val_kind=VK_LVALUE ; -+ v->u.lvalue=v->u.rval_ptr ; -+ v->ctype=v->ctype->u.kid ; -+} -+ -+PROC duel_get_struct_val(tvalue *v,char *op) -+{ -+ if(!ctype_kind_struct_like(v->ctype)) -+ duel_op_error("operand x of '%s' not a sturct/union",op,v,0); -+ duel_assert(v->val_kind==VK_LVALUE); -+} -+ -+PROC duel_get_struct_ptr_val(tvalue *v,char *op) -+{ -+ follow_pointer(v,op,FALSE); -+ if(!ctype_kind_struct_like(v->ctype)) -+ duel_op_error("operand x of '%s' not a pointer to sturct/union",op,v,0); -+} -+ -+FUNC int duel_get_posint_val(tvalue *v,char *op) -+{ -+ int x ; -+ x=duel_get_int_val(v,op); -+ if(x<0) duel_op_error("operand x of '%s' can not be negative",op,v,0); -+ return x ; -+} -+ -+/* indirection operator (*x) */ -+ -+LPROC do_op_indirection(tvalue *v) -+{ -+ follow_pointer(v,"*x",TRUE); -+ duel_set_symb_val(v,"*%s",v,0); -+} -+ -+/* address operator (&x) -+ * x must be an lvalue. it is converted into a pointer to the given type, -+ * an rvalue. -+ */ -+ -+LPROC do_op_address(tvalue *v) -+{ -+ if(v->val_kind != VK_LVALUE) -+ duel_op_error("operand x of '&x' is not a lvalue",0,v,0); -+ v->val_kind=VK_RVALUE ; -+ v->u.rval_ptr=v->u.lvalue ; -+ v->ctype=duel_mkctype_ptr(v->ctype); -+ duel_set_symb_val(v,"&%s",v,0); -+} -+ -+LPROC do_op_index(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ get_pointer_val(v1,"x[y]",FALSE); -+ get_integral_val(v2,"y[x]",NULL); -+ add_offset_to_ptr(v1,v2,r); -+ follow_pointer(r,"[]",TRUE); -+ duel_set_symb_val(r,"%s[%s]",v1,v2); -+} -+ -+ -+/* do arithmeric multiply of v1,v2 and store result in r. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_multiply(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tctype *t=find_numeric_result_type(v1,v2,r,"*"); -+ get_numeric_val(v1,"x*y",t); -+ get_numeric_val(v2,"y*x",t); -+ r->val_kind=VK_RVALUE ; -+ r->ctype=t ; -+ duel_set_symb_val(r,"%s*%s",v1,v2); -+ switch(t->type_kind) { -+ case CTK_INT: r->u.rval_int =v1->u.rval_int * v2->u.rval_int ;break; -+ case CTK_UINT: r->u.rval_uint =v1->u.rval_uint * v2->u.rval_uint ;break; -+ case CTK_LONG: r->u.rval_long =v1->u.rval_long * v2->u.rval_long ;break; -+ case CTK_ULONG: r->u.rval_ulong =v1->u.rval_ulong * v2->u.rval_ulong;break; -+ case CTK_LONGLONG: r->u.rval_longlong =v1->u.rval_longlong * v2->u.rval_longlong ;break; -+ case CTK_ULONGLONG: r->u.rval_ulonglong =v1->u.rval_ulonglong * v2->u.rval_ulonglong;break; -+ case CTK_FLOAT: r->u.rval_float =v1->u.rval_float * v2->u.rval_float;break; -+ case CTK_DOUBLE:r->u.rval_double=v1->u.rval_double*v2->u.rval_double;break; -+ default: duel_assert(0); -+ } -+} -+ -+/* do numeric divide of v1,v2 and store result in r. -+ * v1 and v2 should be of numeric type to begin with. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_divide(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tctype *t=find_numeric_result_type(v1,v2,r,"/"); -+ get_numeric_val(v1,"x/y",t); -+ get_numeric_val(v2,"y/x",t); -+ switch(t->type_kind) { -+ case CTK_INT: if(v2->u.rval_int==0) goto div_err; -+ r->u.rval_int =v1->u.rval_int / v2->u.rval_int ;break; -+ case CTK_UINT: if(v2->u.rval_uint==0) goto div_err; -+ r->u.rval_uint =v1->u.rval_uint / v2->u.rval_uint ;break; -+ case CTK_LONG: if(v2->u.rval_long==0) goto div_err; -+ r->u.rval_long =v1->u.rval_long / v2->u.rval_long ;break; -+ case CTK_ULONG: if(v2->u.rval_ulong==0) goto div_err; -+ r->u.rval_ulong =v1->u.rval_ulong/ v2->u.rval_ulong ;break; -+ case CTK_LONGLONG: if(v2->u.rval_longlong==0) goto div_err; -+ r->u.rval_longlong =v1->u.rval_longlong / v2->u.rval_longlong ;break; -+ case CTK_ULONGLONG: if(v2->u.rval_ulonglong==0) goto div_err; -+ r->u.rval_ulonglong =v1->u.rval_ulonglong/ v2->u.rval_ulonglong ;break; -+ case CTK_FLOAT: if(v2->u.rval_float==0.0) goto div_err; -+ r->u.rval_float =v1->u.rval_float/ v2->u.rval_float ;break; -+ case CTK_DOUBLE:if(v2->u.rval_double==0.0) goto div_err; -+ r->u.rval_double=v1->u.rval_double/v2->u.rval_double;break; -+ default: duel_assert(0); -+ } -+ return ; -+div_err: duel_op_error("division by zero",0,v1,v2); -+} -+ -+ -+/* do arithmeric reminder of v1,v2 and store result in r. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_reminder(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tctype *t=find_numeric_result_type(v1,v2,r,"%"); -+ get_integral_val(v1,"x%y",t); -+ get_integral_val(v2,"y%x",t); -+ switch(t->type_kind) { -+ case CTK_INT: if(v2->u.rval_int==0) goto div_err; -+ r->u.rval_int = v1->u.rval_int % v2->u.rval_int ; break ; -+ case CTK_UINT: if(v2->u.rval_uint==0) goto div_err; -+ r->u.rval_uint = v1->u.rval_uint % v2->u.rval_uint ; break ; -+ case CTK_LONG: if(v2->u.rval_long==0) goto div_err; -+ r->u.rval_long = v1->u.rval_long % v2->u.rval_long ; break ; -+ case CTK_ULONG: if(v2->u.rval_ulong==0) goto div_err; -+ r->u.rval_ulong = v1->u.rval_ulong % v2->u.rval_ulong ; break ; -+ case CTK_LONGLONG: if(v2->u.rval_longlong==0) goto div_err; -+ r->u.rval_longlong = v1->u.rval_longlong % v2->u.rval_longlong ; break ; -+ case CTK_ULONGLONG: if(v2->u.rval_ulonglong==0) goto div_err; -+ r->u.rval_ulonglong = v1->u.rval_ulonglong % v2->u.rval_ulonglong ; break ; -+ default: duel_assert(0); -+ } -+ return ; -+div_err: duel_op_error("reminder modulo zero",0,v1,v2); -+} -+ -+/* do arithmeric or (bitwise) of v1,v2 and store result in r. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_or(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tctype *t=find_numeric_result_type(v1,v2,r,"|"); -+ get_integral_val(v1,"x|y",t); -+ get_integral_val(v2,"y|x",t); -+ switch(t->type_kind) { -+ case CTK_INT: r->u.rval_int = v1->u.rval_int | v2->u.rval_int ; break; -+ case CTK_UINT: r->u.rval_uint = v1->u.rval_uint | v2->u.rval_uint ; break; -+ case CTK_LONG: r->u.rval_long = v1->u.rval_long | v2->u.rval_long ; break; -+ case CTK_ULONG:r->u.rval_ulong= v1->u.rval_ulong | v2->u.rval_ulong; break; -+ case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong | v2->u.rval_longlong ; break; -+ case CTK_ULONGLONG:r->u.rval_ulonglong= v1->u.rval_ulonglong | v2->u.rval_ulonglong; break; -+ default: duel_assert(0); -+ } -+ return ; -+} -+ -+/* do arithmeric and (bitwise) of v1,v2 and store result in r. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_and(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ tctype *t=find_numeric_result_type(v1,v2,r,"&"); -+ get_integral_val(v1,"x&y",t); -+ get_integral_val(v2,"y&x",t); -+ switch(t->type_kind) { -+ case CTK_INT: r->u.rval_int = v1->u.rval_int & v2->u.rval_int ; break; -+ case CTK_UINT: r->u.rval_uint = v1->u.rval_uint & v2->u.rval_uint ; break; -+ case CTK_LONG: r->u.rval_long = v1->u.rval_long & v2->u.rval_long ; break; -+ case CTK_ULONG:r->u.rval_ulong= v1->u.rval_ulong & v2->u.rval_ulong; break; -+ case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong & v2->u.rval_longlong ; break; -+ case CTK_ULONGLONG:r->u.rval_ulonglong= v1->u.rval_ulonglong & v2->u.rval_ulonglong; break; -+ default: duel_assert(0); -+ } -+} -+ -+/* do arithmeric xor (bitwise) of v1,v2 and store result in r. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_xor(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ -+ tctype *t=find_numeric_result_type(v1,v2,r,"^"); -+ get_integral_val(v1,"x^y",t); -+ get_integral_val(v2,"y^x",t); -+ switch(t->type_kind) { -+ case CTK_INT: r->u.rval_int = v1->u.rval_int ^ v2->u.rval_int ; break ; -+ case CTK_UINT: r->u.rval_uint = v1->u.rval_uint ^ v2->u.rval_uint ; break ; -+ case CTK_LONG: r->u.rval_long = v1->u.rval_long ^ v2->u.rval_long ; break ; -+ case CTK_ULONG:r->u.rval_ulong= v1->u.rval_ulong^ v2->u.rval_ulong; break ; -+ case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong ^ v2->u.rval_longlong ; break ; -+ case CTK_ULONGLONG:r->u.rval_ulonglong= v1->u.rval_ulonglong ^ v2->u.rval_ulonglong; break ; -+ default: duel_assert(0); -+ } -+ return ; -+} -+ -+/* do arithmeric leftshift of v1,v2 and store result in r. -+ * v1 and v2 should be of numeric type to begin with. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_leftshift(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ int by; -+ get_integral_val(v1,"x<<y",NULL); -+ by=duel_get_int_val(v2,"y<<x"); -+ r->val_kind=VK_RVALUE ; -+ r->ctype=v1->ctype ; -+ duel_set_symb_val(r,"%s<<%s",v1,v2); -+ switch(v1->ctype->type_kind) { -+ case CTK_INT: r->u.rval_int = v1->u.rval_int << by ; break ; -+ case CTK_UINT: r->u.rval_uint = v1->u.rval_uint << by ; break ; -+ case CTK_LONG: r->u.rval_long = v1->u.rval_long << by ; break ; -+ case CTK_ULONG: r->u.rval_ulong = v1->u.rval_ulong << by ; break ; -+ case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong << by ; break ; -+ case CTK_ULONGLONG: r->u.rval_ulonglong = v1->u.rval_ulonglong << by ; break ; -+ default: duel_assert(0); -+ } -+} -+ -+/* do arithmeric rightshift of v1,v2 and store result in r. -+ * v1 and v2 should be of numeric type to begin with. -+ * NOTE: v1, v2 are destroyed! -+ */ -+LPROC do_op_rightshift(tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ int by ; -+ get_integral_val(v1,"x>>y",NULL); -+ by=duel_get_int_val(v2,"y>>x"); -+ r->val_kind=VK_RVALUE ; -+ r->ctype=v1->ctype ; -+ duel_set_symb_val(r,"%s>>%s",v1,v2); -+ switch(v1->ctype->type_kind) { -+ case CTK_INT: r->u.rval_int = v1->u.rval_int >> by ; break ; -+ case CTK_UINT: r->u.rval_uint = v1->u.rval_uint >> by ; break ; -+ case CTK_LONG: r->u.rval_long = v1->u.rval_long >> by ; break ; -+ case CTK_ULONG: r->u.rval_ulong = v1->u.rval_ulong >> by ; break ; -+ case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong >> by ; break ; -+ case CTK_ULONGLONG: r->u.rval_ulonglong = v1->u.rval_ulonglong >> by ; break ; -+ default: duel_assert(0); -+ } -+} -+ -+/* do arithmeric not of v (!v) */ -+LPROC do_op_not(tvalue *v) -+{ -+ get_scalar_val(v,"!x"); -+ duel_set_symb_val(v,"!%s",v,0); -+ switch(v->ctype->type_kind) { -+ case CTK_PTR: v->u.rval_int = ! v->u.rval_ptr ; break ; -+ case CTK_INT: v->u.rval_int = ! v->u.rval_int ; break ; -+ case CTK_UINT: v->u.rval_int = ! v->u.rval_uint ; break ; -+ case CTK_LONG: v->u.rval_int = ! v->u.rval_long ; break ; -+ case CTK_ULONG: v->u.rval_int = ! v->u.rval_ulong ; break ; -+ case CTK_LONGLONG: v->u.rval_int = ! v->u.rval_longlong ; break ; -+ case CTK_ULONGLONG: v->u.rval_int = ! v->u.rval_ulonglong ; break ; -+ case CTK_FLOAT: v->u.rval_int = ! v->u.rval_float ; break ; -+ case CTK_DOUBLE: v->u.rval_int = ! v->u.rval_double ; break ; -+ default: duel_assert(0); -+ } -+ v->ctype=ctype_int ; /* always returns an int */ -+} -+ -+/* do bit-complement of v (~v) */ -+LPROC do_op_complement(tvalue *v) -+{ -+ get_integral_val(v,"~x",NULL); -+ duel_set_symb_val(v,"~%s",v,0); -+ switch(v->ctype->type_kind) { -+ case CTK_INT: v->u.rval_int = ~ v->u.rval_int ; break ; -+ case CTK_UINT: v->u.rval_uint = ~ v->u.rval_uint ; break ; -+ case CTK_LONG: v->u.rval_long = ~ v->u.rval_long ; break ; -+ case CTK_ULONG: v->u.rval_ulong = ~ v->u.rval_ulong ; break ; -+ case CTK_LONGLONG: v->u.rval_longlong = ~ v->u.rval_longlong ; break ; -+ case CTK_ULONGLONG: v->u.rval_ulonglong = ~ v->u.rval_ulonglong ; break ; -+ default: duel_assert(0); -+ } -+} -+ -+ /* do arithmeric minus of v (-v) */ -+LPROC do_op_minus(tvalue *v) -+{ -+ get_numeric_val(v,"-x",NULL); -+ duel_set_symb_val(v,"-%s",v,0); -+ switch(v->ctype->type_kind) { -+ case CTK_INT: v->u.rval_int = - v->u.rval_int ; break ; -+ case CTK_UINT: v->u.rval_uint = - v->u.rval_uint ; break ; -+ case CTK_LONG: v->u.rval_long = - v->u.rval_long ; break ; -+ case CTK_ULONG: v->u.rval_ulong = - v->u.rval_ulong ; break ; -+ case CTK_LONGLONG: v->u.rval_longlong = - v->u.rval_longlong ; break ; -+ case CTK_ULONGLONG: v->u.rval_ulonglong = - v->u.rval_ulonglong ; break ; -+ case CTK_FLOAT: v->u.rval_float = - v->u.rval_float ; break ; -+ case CTK_DOUBLE: v->u.rval_double= - v->u.rval_double ; break ; -+ default: duel_assert(0); -+ } -+} -+ -+/* do sizeif(exp) - simply return the size of the exp's type */ -+LPROC do_op_sizeofexp(tvalue *v) -+{ -+ v->val_kind=VK_RVALUE ; -+ v->u.rval_size_t=v->ctype->size ; -+ v->ctype=ctype_size_t ; -+ duel_set_symb_val(v,"sizeof(%s)",v,0); -+} -+ -+LPROC do_op_assignment(tvalue *v1,tvalue *v2,tvalue *r,char *op) -+{ -+ char xopy[10],yopx[10] ; -+ sprintf(xopy,"x%sy",op); -+ sprintf(yopx,"y%sx",op); -+ if(v1->val_kind!=VK_LVALUE && v1->val_kind!=VK_BVALUE) -+ duel_op_error("operand x is not an lvalue for operator '%s'",xopy,v1,0); -+ -+ if(ctype_kind_struct_like(v1->ctype)) { -+ duel_check_type_eq(v1,v2,xopy); -+ copy_lvalues(v1,v2,xopy); -+ *r= *v2 ; /* return the result as an lvalue. this means (x1=x2)=x3 -+ is legal for struct, unlike ansi-c. */ -+ return ; -+ } -+ if(ctype_kind_numeric(v1->ctype)) get_numeric_val(v2,yopx,v1->ctype); -+ else -+ if(v1->ctype->type_kind==CTK_PTR) { -+ get_pointer_val(v2,yopx,TRUE); -+ duel_check_type_eq(v1,v2,xopy); -+ } -+ else duel_op_error("bad operand x type for operator '%s'",xopy,v1,0); -+ put_rvalue(v1,v2,xopy); -+ *r= *v2 ; -+} -+ -+LPROC do_op_increment(tvalue *v,char *op,int inc,bool postfix) -+{ -+ tvalue lvalue_v,oldv ; -+ char s[80] ; -+ if(v->val_kind!=VK_LVALUE) -+ duel_op_error("operand of '%s' must be an lvalue",op,v,0); -+ lvalue_v= *v ; -+ if(v->ctype->type_kind==CTK_PTR) get_pointer_val(v,op,FALSE); -+ else get_integral_val(v,op,0); -+ oldv= *v ; -+ -+ switch(v->ctype->type_kind) { -+ case CTK_INT: v->u.rval_int += inc ; break ; -+ case CTK_UINT: v->u.rval_uint += inc ; break ; -+ case CTK_LONG: v->u.rval_long += inc ; break ; -+ case CTK_ULONG: v->u.rval_ulong += inc ; break ; -+ case CTK_LONGLONG: v->u.rval_longlong += inc ; break ; -+ case CTK_ULONGLONG: v->u.rval_ulonglong += inc ; break ; -+ case CTK_PTR: v->u.rval_ptr += inc*v->ctype->u.kid->size ; break; -+ default: duel_assert(0); -+ } -+ convert_scalar_type(v,lvalue_v.ctype,op); /* back to the original type */ -+ put_rvalue(&lvalue_v,v,op); -+ if(postfix) { /* if prefix, keep v and its sym val*/ -+ *v= oldv ; -+ convert_scalar_type(v,lvalue_v.ctype,op); /* back to original type */ -+ sprintf(s,"%%s%s",op); -+ duel_set_symb_val(v,s,v,0); -+ } -+} -+ -+/* unary op 'frame(n)' converts int n to a "frame type" */ -+LPROC do_op_frame(tvalue *v) -+{ -+ int f=duel_get_int_val(v,"frame(x)"); -+ if(f<0 || f>=duel_get_frames_number()) -+ duel_gen_error("Frame number too big",0); -+ v->val_kind=VK_FVALUE ; -+ v->ctype=ctype_int ; -+ v->u.fvalue=f ; -+ duel_set_symb_val(v,"frame(%s)",v,0); -+} -+ -+/* unary op '(x)'. this only add parenthesis to the symbolic value, if needed*/ -+ -+LPROC do_op_parenthesis(tvalue *v) -+{ -+ char *s=v->symb_val ; -+ int l=strlen(s); -+ if(s[0]=='(' && s[l-1]==')') return ; /* val is (x) dont make it ((x)) */ -+ while(*s!=0 && (isalnum(*s) || *s=='_')) s++ ; /* find first non alnum*/ -+ if(*s==0) return ; /* no need for (x) if x is a name or constant number */ -+ duel_set_symb_val(v,"(%s)",v,0); -+} -+ -+/*********************************************************************** -+ High-level functions, major entries to this module, evaluate a node -+ with a standard (single value) result -+ ***********************************************************************/ -+ -+ -+/* standardize a paramater to a function call according to the standard rules. -+ * we currently don't support union/struct paramater passing -+ */ -+ -+PROC duel_standardize_func_parm(tvalue *p) -+{ -+ /* convert paramater into "standard" function calling */ -+ if(ctype_kind_integral(p->ctype)) get_integral_val(p,"f()",NULL); -+ else -+ if(ctype_kind_numeric(p->ctype)) /* float, double to double */ -+ convert_scalar_type(p,ctype_double,"f()"); -+ else -+ if(ctype_kind_ptr_like(p->ctype)) get_pointer_val(p,"f()",FALSE); -+ else -+ duel_op_error("unsupported paramater type",0,p,0); -+} -+ -+ -+/* given a function (or pointer), find the first (top-most) frame that -+ * the function is active in, and return the FVALUE for it -+ */ -+PROC duel_find_func_frame(tvalue *v,char *op) -+{ -+ int i, frames_no=duel_get_frames_number(); -+ get_pointer_val(v,op,FALSE); -+ -+ for(i=0 ; i<frames_no ; i++) { -+ ttarget_ptr frame_func = duel_get_function_for_frame(i); -+ if(frame_func==v->u.rval_ptr) { -+ v->val_kind=VK_FVALUE ; -+ v->ctype=ctype_int ; -+ v->u.rval_int=i ; -+ return ; -+ } -+ } -+ duel_op_error("func x is not on the call stack for operator '%s'",op,v,0); -+} -+ -+ -+/* compute the n'th result of v1..v2 operator. -+ * result is returned in r, returns false if there isnt an nth result -+ * v1,v2 are converted to integer values (but can be used to call this -+ * function again. errors are reported if they arenot integral. -+ */ -+ -+FUNC bool duel_do_op_to(tvalue *v1,tvalue *v2,int n,tvalue *r) -+{ -+ int a,b,inc,x ; -+ char *p,*fmt ; -+ -+ if(!v1) { a=0 ; b=duel_get_int_val(v2,"..x")-1 ; } -+ else if(!v2) { a=duel_get_int_val(v1,"x.."); b=INT_MAX ; } -+ else { a=duel_get_int_val(v1,"x..y"); b=duel_get_int_val(v2,"x..y"); } -+ if(a<=b) inc=1 ; -+ else inc= -1 ; -+ x=a+n*inc ; -+ if(inc>0 && x>b || inc<0 && x<b) return FALSE ; -+ -+ r->val_kind=VK_RVALUE ; -+ r->ctype=ctype_int ; -+ r->u.rval_int=x ; -+ if(v1) p=v1->symb_val ; -+ else p=v2->symb_val ; -+ if( *p=='0' && p[1]=='x' || p[1]=='X') fmt="0x%x" ; -+ else if(*p=='0' && p[1]>='0' && p[1]<='7') fmt="0%o" ; -+ else if(*p=='\'' && isascii(x) && isprint(x)) fmt="'%c'" ; -+ else fmt="%d" ; -+ sprintf(r->symb_val,fmt,x); -+ return TRUE ; -+} -+ -+/* convert value to True/False and return it -+ * in case of an illegal operand, indicateds the operator is (op) -+ * main use: in operators '&&' '||' and 'if' -+ */ -+ -+FUNC bool duel_mk_logical(tvalue *v,char *op) -+{ -+ get_scalar_val(v,op); /* verify v is scalar */ -+ do_op_not(v); /* convert and force 0 or 1 */ -+ v->u.rval_int = !v->u.rval_int ; -+ sprintf(v->symb_val,"%d",v->u.rval_int); -+ return(v->u.rval_int); -+} -+ -+/* cast the value v into type t. */ -+ -+PROC duel_do_cast(tctype *tout,tvalue *v) -+{ -+ tctype *t=v->ctype ; -+ if(ctype_kind_scalar(t) && ctype_kind_scalar(tout)) { -+ if(tout->type_kind==CTK_ARRAY) -+ duel_gen_error("casting to an array type is illegal",0); -+ else convert_scalar_type(v,tout,"(cast) x"); -+ } -+ else duel_op_error("illegal type conversion in cast op",0,v,0); -+} -+ -+ -+/* apply unary oprand op to the given value. The original value is -+ * destoryed (of course) -+ */ -+ -+PROC duel_apply_unary_op(topcode op,tvalue *v) -+{ -+ switch(op) { -+ case '(': do_op_parenthesis(v); break ; -+ case '{': duel_sprint_scalar_value(v->symb_val,v);break ; -+ case '-': do_op_minus(v); break ; -+ case '!': do_op_not(v); break ; -+ case '*': do_op_indirection(v); break ; -+ case '~': do_op_complement(v); break ; -+ case '&': do_op_address(v); break ; -+ case OP_SIZ: do_op_sizeofexp(v); break ; -+ case OP_INC: do_op_increment(v,"++",1,FALSE); break ; -+ case OP_DEC: do_op_increment(v,"--",-1,FALSE); break ; -+ case OP_FRAME: do_op_frame(v); break ; -+ default: duel_assert(0); -+ } -+} -+ -+PROC duel_apply_post_unary_op(topcode op,tvalue *v) -+{ -+ switch(op) { -+ case OP_INC: do_op_increment(v,"++",1,TRUE); break ; -+ case OP_DEC: do_op_increment(v,"--",-1,TRUE); break ; -+ default: duel_assert(0); -+ } -+} -+ -+ -+/* apply_bin_op -- apply the operator op to the values v1 v2 and return -+ * the result in r. the bin op is a 'regular' one, like -+ * '+', '*', etc. in the C language. -+ * note: v1,v2 are destroyed -+ * returns: true if a value has been produced, false otherwise. -+ * (ops like '+' always return true. ops like '<=?' also return false) -+ */ -+ -+FUNC bool duel_apply_bin_op(topcode op,tvalue *v1,tvalue *v2,tvalue *r) -+{ -+ switch(op) { -+ case '[': do_op_index(v1,v2,r); break ; -+ case '+': do_op_add(v1,v2,r); break ; -+ case '-': do_op_subtract(v1,v2,r); break ; -+ case '*': do_op_multiply(v1,v2,r); break ; -+ case '/': do_op_divide(v1,v2,r); break ; -+ case '%': do_op_reminder(v1,v2,r); break ; -+ case '|': do_op_or(v1,v2,r); break; -+ case '&': do_op_and(v1,v2,r); break ; -+ case '^': do_op_xor(v1,v2,r); break ; -+ case OP_LSH: do_op_leftshift(v1,v2,r); break ; -+ case OP_RSH: do_op_rightshift(v1,v2,r); break ; -+ case OP_EQ: do_op_eq(v1,v2,r); break ; -+ case OP_NE: do_op_ne(v1,v2,r); break ; -+ case OP_GE: do_op_ge(v1,v2,r); break ; -+ case OP_LE: do_op_le(v1,v2,r); break ; -+ case '<': do_op_ls(v1,v2,r); break ; -+ case '>': do_op_gt(v1,v2,r); break ; -+ case OP_EQQ: -+ case OP_NEQ: -+ case OP_GEQ: -+ case OP_LEQ: -+ case OP_LSQ: -+ case OP_GTQ: return do_compare_questionmark(op,v1,v2,r); -+ case '=': do_op_assignment(v1,v2,r,"="); break ; -+ default: duel_assert(0); -+ } -+ return TRUE ; -+} ---- gdb/duel/global.h -+++ gdb/duel/global.h -@@ -0,0 +1,450 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* this include file contains global definitions for duel. All global info -+ * is shared thru this single file. -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.12 93/03/12 05:50:35 mg -+ * uses tuint instead of uint, etc. -+ * -+ * Revision 1.11 93/02/27 06:03:26 mg -+ * added HP9000 support by not defining uint etc -+ * clean annoying enum {x,y,} warnings -+ * -+ * Revision 1.10 93/02/03 21:49:32 mg -+ * support "signed char" -+ * -+ * Revision 1.9 93/01/12 21:52:11 mg -+ * cleanup and set for release -+ * -+ * Revision 1.8 93/01/07 00:10:53 mg -+ * macros for func ptr auto-convert -+ * -+ * Revision 1.7 93/01/03 07:30:23 mg -+ * *** empty log message *** -+ * -+ * Revision 1.6 92/12/24 23:49:25 mg -+ * *** empty log message *** -+ * -+ * Revision 1.5 92/10/19 15:07:58 mg -+ * fvalue added (not ready yet), svalues dropped -+ * -+ * Revision 1.4 92/10/14 02:05:37 mg -+ * misc -+ * -+ * Revision 1.3 92/09/16 11:11:54 mg -+ * add builtin ctype_charptr -+ * -+ * Revision 1.2 92/09/15 05:47:49 mg -+ * some ops added -+ * -+ */ -+ -+ -+/* The following definitions are common programming tricks that I use -+ * in every program I write. I hope they are obvious. the FUNC/PROC -+ * constants are useful mainly when editing (to find a function def.) -+ * or when grep'ing on source files. DEF is set to "extern" by default, -+ * allowing declaration and definition of globals in one source. only -+ * duel.c should have #define DEF before including duel.h -+ */ -+ -+#define FUNC -+#define PROC void -+#define LPROC static void -+#define LFUNC static -+ -+#ifndef DEF -+#define DEF extern /* declare only, 'int x' become 'extern int x'*/ -+#endif -+ -+/* use simpler names for unsigned types, very common, -+ * too common, indeed, so I forced 't' as a prefix. -+ */ -+ -+typedef unsigned int tuint ; -+typedef unsigned char tuchar ; -+typedef unsigned short tushort ; -+typedef unsigned long tulong ; -+typedef unsigned long long tulonglong ; -+ -+typedef signed char tschar ; /* explicit signed char */ -+typedef int bool ; /* suppose to be just 0,1 */ -+#define FALSE 0 -+#define TRUE 1 -+ -+ /* these should be inline functions, they replace common lib func which -+ * change from system to system. -+ * duel_assert can be modified to call duel_fatal, so gdb itself isn't -+ * aborted because on an internal duel error. -+ */ -+ -+#define duel_assert(x) assert(x) -+#define duel_bzero(x,y) memset(x,0,y) -+#define duel_bcopy(x,y,s) memcpy(x,y,s) -+ -+ -+ -+/************* -+ Parsing: the expression is converted into a tree. -+ Each node of this tree is of 'tnode' type. -+ Nodes can be: -+ An operator (like '+', or ':=' or 'for') -+ A constant (numbers. Strings are pointers to space!) -+ A symbol. -+ A regular expression (really a symbol extention) -+ -+ The evaluation of any node results in: -+ 1. 'Environment': duel variables and their values -+ 2. symbolic expression which describe the computation -+ meaning: keep the parentethis. in the expression a<<(3+b) (even if not needed!) -+ 3. A type & value -+ -+ Values: -+ Values are always a fixed length area of bytes; Any C type is like that. -+**************/ -+ -+ -+/****** TYPES ******* -+ A type is described in the typical compiler's way, which is also gdb's -+ way. That is, a type is made of 'atomic' types, like 'pointer to', -+ 'array of', etc. Each atomic type is described by a 'ctype' node. Ctype -+ node points to other ctype nodes as required. For example, a ctype node -+ of 'array of' will point to the node 'int' for the 'C' type array of int. -+ [The name ctype is used to indicate the C language type; 'type' is too -+ generic a term] -+ Example: -+ char *(*f[])() ; -+ Here, f is an array of pointers to functions returning a pointer to char. -+ The type is described with the top node being of CTK_ARRAY type. It -+ points to a 'CTK_PTR' node, which points to a 'CTK_FUNC' node which -+ points to a 'CTK_PTR' node which points to a 'CTK_CHAR' node which has, -+ as size, 1. -+ -+ The size of a type is the number of bytes occupied by it. it is zero -+ for types like 'function'. An array of 10 integers will have as size -+ 10*sizeof(int) -+ -+ A note on UCHAR vs CHAR vs SCHAR: -+ Internally, duel supports all three forums (for aritmetic). -+ For output, only "char" types are considered ASCII, and will be displayed -+ as 'A' instead of "65", etc. The same is true for char[] and char*. -+ GDB doesn't really support "signed char", but some compilers do; -+ we convert "signed char" into just a "char" when the default char is signed. -+ This is only significant for output. -+ Maybe duel shouldn't support "char" at all, and force everything to be -+ "schar" or "uchar". I'm not sure. I prefer "char" as a distinct type -+ which implies "string" and uchar/schar as "integral". -+ ********************/ -+ -+typedef enum { /* 'C' Type atomic primitive Kinds (CTK_) */ -+ CTK_VOID, /* void type 'void' */ -+ CTK_CHAR, /* primitive types */ -+ CTK_SCHAR, /* signed char (ansi c) */ -+ CTK_UCHAR, /* note order is used in some macros */ -+ CTK_SHORT, -+ CTK_USHORT, -+ CTK_INT, -+ CTK_UINT, -+ CTK_LONG, -+ CTK_ULONG, -+ CTK_LONGLONG, -+ CTK_ULONGLONG, -+ CTK_FLOAT, -+ CTK_DOUBLE, -+ CTK_PTR, /* pointer '*' */ -+ CTK_ARRAY, /* array '[]' */ -+ CTK_FUNC, /* a function '()' */ -+ CTK_STRUCT, /* a sturcture 'struct{}' */ -+ CTK_UNION, /* a union 'union{}' */ -+ CTK_ENUM /* enum type 'enum{}' */ -+ } tctype_kind ; -+ -+typedef struct { /* a field (of struct) info */ -+ char *name ; /* field name */ -+ struct sctype *ctype ; /* field type */ -+ int bitpos, bitlen ; /* for bit fields only */ -+} tctype_field ; -+ -+typedef struct { /* an enumerator (constant of an enum) info */ -+ char *name ; /* enumerator name */ -+ int val ; /* value assigned to the name */ -+ /* question: ansi-C say cosnt fit in int?*/ -+} tctype_enumerator ; -+ -+ -+typedef struct sctype { /* a 'C' type description */ -+ tctype_kind type_kind ; -+ char *name ; /* named of this type, if any */ -+ size_t size ; /* size (total bytes) for this type */ -+ union { -+ struct sctype *kid ; /* pointer to next atomic type */ -+ struct { -+ int fields_no ; -+ tctype_field *fields ; /* union/struct fields */ -+ } f ; -+ struct { -+ tctype_kind real_type_kind ; /* the type used for storage of the enum */ -+ int enumerators_no ; -+ tctype_enumerator *enumerators ; /* enum's type enumerators list */ -+ } e; -+ } u ; -+ } tctype ; -+ -+ -+/**** BASIC C TYPES -+ these are initialized at run type to point to the basic C types. -+ basic types are never created again, e.g. pointer comparison with -+ these is sufficient to check type equality. -+ the voidptr is (void*) which is a basic type (what zero is converted -+ to when it is a pointer). -+ ptrdiff_t and size_t are actually pointing to their actualy types, -+ ie. normally point to ctype_int. -+ ****/ -+ -+DEF tctype *ctype_int, *ctype_uint, *ctype_short, *ctype_ushort, -+ *ctype_char, *ctype_schar, *ctype_uchar, -+ *ctype_long, *ctype_ulong, *ctype_longlong, *ctype_ulonglong, -+ *ctype_float, *ctype_double, -+ *ctype_void, *ctype_charptr, -+ *ctype_voidptr,*ctype_ptrdiff_t,*ctype_size_t ; -+ -+/* type checking macros */ -+ -+/** tell if type is a struct or union */ -+#define ctype_kind_struct_like(t) ((t)->type_kind==CTK_STRUCT || \ -+ (t)->type_kind==CTK_UNION) -+ -+/** tell if type is a pointer or can be made one (array, func) */ -+#define ctype_kind_ptr_like(t) ((t)->type_kind==CTK_PTR || \ -+ (t)->type_kind==CTK_ARRAY || (t)->type_kind==CTK_FUNC) -+/* tell if type is numeric */ -+#define ctype_kind_numeric(t) (((t)->type_kind>=CTK_CHAR && \ -+ (t)->type_kind<=CTK_DOUBLE) || (t)->type_kind==CTK_ENUM) -+ -+/* tell if type is integral */ -+#define ctype_kind_integral(t) ((t)->type_kind>=CTK_CHAR && \ -+ (t)->type_kind<=CTK_ULONG || (t)->type_kind==CTK_ENUM) -+ -+/* tell if type fits into fixed memory size (void not included) */ -+#define ctype_kind_scalar(t) (ctype_kind_numeric(t) || ctype_kind_ptr_like(t)) -+ -+/* tell if type is a "base" ie can't have kids */ -+ -+#define ctype_kind_base(t) ((t)->type_kind>=CTK_VOID && \ -+ (t)->type_kind<=CTK_DOUBLE) -+ -+/* tell if a type is a function pointer or like a func ptr (ie a func!) */ -+#define ctype_kind_func_ptr_like(t) ((t)->type_kind==CTK_FUNC || \ -+ (t)->type_kind==CTK_PTR && t->u.kid->type_kind==CTK_FUNC) -+ -+ -+/***** VALUES -+ used to keep information when evaluating an expression. A value is -+ either: -+ 1) a right-value, which is represented in a fixed number of bytes that -+ actually contain its value. Example: result of '+' operation. -+ 2) a left-value. This is a reference to the actual value, which -+ resides in the debuggee's address space. -+ 3) a special-value. This contains a long value specifying a special -+ target location (e.g. register) from which values can be fetched -+ or written to. However, special-values can not be manipulated (i.e -+ have an offset added to them, as done to an lvalue struct). -+ -+ Note that the operation '*x' starts with x as an lvalue - a pointer to -+ x is kept. Then, '*x' is executed, fetching the value of x and creating -+ another lvalue, which points to where x has pointed to! This allows -+ &*x to be executed, as well as *x=1 or &x[1] ... -+ When the value of an lvalue is actually needed, it must be fetched -+ from the debugge's space. -+ *****/ -+ -+#define VALUE_MAX_CONST_SIZE 8 -+#define VALUE_MAX_SYMBOLIC_SIZE 128 -+ -+typedef long tptrsize_int ; /* type so that -+ tptrsize x; char *p ; -+ p == (char*) (tptrsize) p -+ */ -+ -+ /* type that represent a target address space location. */ -+ -+typedef char* ttarget_ptr ; /* pointer to target's address */ -+ -+typedef struct { -+ ttarget_ptr lvalue ; /* pointer to target's location of struct*/ -+ int bitpos,bitlen ; /* as specified in the field info of stuct*/ -+ } tbvalue_info ; -+ -+typedef enum { -+ VK_RVALUE, /* this value represent a constant, in the rval_ union */ -+ VK_LVALUE, /* this value represent a left-value. address in lvalue*/ -+ VK_BVALUE, /* a bit-field lvalue, given as point and bitpos/bitlen*/ -+ VK_FVALUE /* a frame, fvalue contains it number */ -+ } tval_kind ; -+ -+typedef struct { -+ tval_kind val_kind ; -+ tctype *ctype ; /* type of this value */ -+ union { -+ ttarget_ptr lvalue ; /* location in target of the value */ -+ tbvalue_info bvalue ; /* location in target of a bitfield */ -+ int fvalue ; /* a frame number (0 = top of stack) */ -+ char rval_char ; -+ tschar rval_schar ; -+ tuchar rval_uchar ; -+ short rval_short ; -+ tushort rval_ushort ; -+ int rval_int ; -+ tuint rval_uint ; -+ long rval_long ; -+ tulong rval_ulong ; -+ long long rval_longlong ; -+ tulonglong rval_ulonglong ; -+ float rval_float ; -+ double rval_double ; -+ ttarget_ptr rval_ptr ; -+ ptrdiff_t rval_ptrdiff_t ; /* Synonyms to one of the above fields! */ -+ size_t rval_size_t ; /* normally these are simply = rval_int */ -+ } u ; -+ char symb_val[VALUE_MAX_SYMBOLIC_SIZE]; -+ } tvalue ; -+ -+ -+typedef struct sval_lcell { /* a cell on a linked-list containing a tvalue*/ -+ tvalue val ; -+ struct sval_lcell *next ; -+ } tval_lcell ; -+ -+typedef struct { /* a linked list of tvalue's */ -+ tval_lcell *head ; -+ tval_lcell *tail ; -+} tval_list ; -+ -+/**** OP CODES **** -+ Opcodes are divided into groups, or 'kinds'. For example, all the -+ C regular unary operators, binary operators, etc. -+ An opcode is defined by its 'kind' and actual value. The value is, -+ in most cases, a single char. For example, the C plus operator is -+ defined as op_kind=OPK_BIN and op='+'. The C operator '+=' is -+ defined as op_kind=OPK_ASSIGN and op='+'. -+ some operators are uniquely identified by type alone (e.g. func call). -+ In the lexer there is a table of actual operators as tokens, and -+ the kind & value assigned to each. -+ Several opertors use more than one char, and are defined below. -+ the OPK_SBIN, etc kinds are special in the sense that A op B isn't -+ computed in the normal way of the C language (i.e. compute both sides, -+ then apply the operator). Such operators include ',' '&&', etc. -+ **********/ -+typedef enum { -+ /* '+' '-' etc are used directly and have their ascii value */ -+ OP_LSH = 300, /* '<<' */ -+ OP_RSH = 301, /* '>>' */ -+ OP_INC = 302, /* '++' */ -+ OP_DEC = 303, /* '--' */ -+ OP_ARR = 304, /* '->' */ -+ OP_AND = 305, /* '&&' */ -+ OP_OR = 306, /* '||' */ -+ OP_EQ = 307, /* '==' */ -+ OP_GE = 308, /* '>=' */ -+ OP_LE = 309, /* '<=' */ -+ OP_NE = 310, /* '!=' */ -+ OP_SIZ = 311, /* 'sizeof' */ -+ OP_TO = 312, /* '..' */ -+ OP_EQQ = 313, /* '==?' */ -+ OP_NEQ = 314, /* '!=?' */ -+ OP_GEQ = 315, /* '>=?' */ -+ OP_LEQ = 316, /* '<=?' */ -+ OP_GTQ = 317, /* '>?' */ -+ OP_LSQ = 318, /* '<?' */ -+ OP_IMP = 319, /* '=>' */ -+ OP_IF = 320, /* if() */ -+ OP_DEF = 321, /* ':=' */ -+ OP_DFS = 322, /* '-->' */ -+ OP_BFS = 323, /* '->>' */ -+ OP_POS = 324, /* '>--' */ -+ OP_IOS = 325, /* '->-' */ -+ OP_SEL = 326, /*'x[[y]]'*/ -+ OP_FOR = 327, /*for(;;)'*/ -+ OP_WHILE= 328, /*while() */ -+ OP_DECL = 329, /* var decl*/ -+ OP_FRAME= 330 /* frame(i)*/ -+ } topcode ; -+ -+/**** OPCODE KINDS ****/ -+ -+typedef enum { /* the kind of the opcode, 'OPK_' = OPcode Kind */ -+ OPK_UNARY =0, /* regular unary operator */ -+ OPK_SUNARY =1, /* special unary operator (sizeof) */ -+ OPK_POST_UNARY =2, /* post unary operator (x++ etc) */ -+ OPK_BIN =3, /* regular binary operator */ -+ OPK_SBIN =4, /* special binary operator */ -+ OPK_TRI =5, /* trinary (eg ?:) operator */ -+ OPK_QUAD =6, /* quad (e.g.for(;;)) operator */ -+ OPK_ASSIGN =7, /* assignment ie =, +=, -= etc */ -+ OPK_FUNC =8, /* function call. 2nd kid made of ',' kids for parms */ -+ OPK_CAST =9, /* type cast. 2nd kid convert to type in 1st kid */ -+ OPK_NUM_OF =10 /* number of OPK_* op kinds */ -+ } top_kind ; -+ -+ -+/**** NODE KINDS ****/ -+ -+typedef enum { /* the kind of node */ -+ NK_OP, /* contain an operator */ -+ NK_CONST, /* contains a constant */ -+ NK_NAME, /* contains a name/symbol */ -+ NK_CTYPE /* contain a 'C' type */ -+ } tnode_kind ; -+ -+#define NODE_MAX_KIDS 4 /* maximum no of kids per node */ -+#define NODE_MAX_SYM_LEN 50 /* maximum length for a symbol */ -+ -+/* the following structure is used to store one node of the expression tree. -+ * It contains two parts: (a) information to describe the node and (b) -+ * information used during the evaluation of the node. -+ * -+ * This structure could/should be optimized with ugly unions (e.g., for -+ * a node describing a constant(node_kind==NK_CONST) there is no need for -+ * the op, kids or any eval stuff!). However, only few nodes (less than 100?) -+ * are expected to be in memory at any time (how complex can a user -+ * expression be?). Hence, for clarity, no unions where used. -+ * -+ * All nodes have kids in the typical way. the opcode OPK_FUNC node is tricky: -+ * see parsing - the commas are handled as operators and not as part of the -+ * syntax. when a func call is evaluated, the top comma nodes are used to -+ * separate the arguments (this hack prevents complex parsing and complex tnode -+ * with variable num of kids, which would force the kids[] to be malloc etc.) -+ */ -+ -+typedef struct snode { /* a single node on an expression tree */ -+ tnode_kind node_kind ; /* what kind of note this is */ -+ /* NK_OP node info: op_kind,op,kids */ -+ int src_pos ; /* starting source code location (op etc) */ -+ top_kind op_kind ; /* opcode type (unary,bin etc) */ -+ topcode op ; /* actual opcode: '-' for both unary&bin '-'*/ -+ struct snode *kids[NODE_MAX_KIDS] ; /* pointers to node's kids */ -+ tvalue cnst ; /* NK_CONST info - constant value */ -+ char *name ; /* NK_NAME info - variable name */ -+ tctype *ctype ; /* NK_CTYPE info - a type */ -+ -+ struct { /* information used during node evaluation */ -+ int level ; /* evaluation level (0=none, 1=left in x etc)*/ -+ tvalue v1,v2 ; /* keep last computed operands, etc */ -+ tval_list vlist ; /* value list for node (used in --> etc ops) */ -+ int counter ; /* used for counting */ -+ } eval ; -+ } tnode ; -+ -+ -+DEF bool duel_debug ; /* debugging duel-itself mode */ -+DEF bool duel_output_pipe_style ; /* pipe-style output of values */ -+ -+/* this things are machine dependent stuff */ -+ -+#define BITS_PER_BYTE 8 /* no of bits in (char) (right. try '9' :-) */ ---- gdb/duel/internals.doc -+++ gdb/duel/internals.doc -@@ -0,0 +1,129 @@ -+DUEL 1.0x INTERNALS -+This documents some of the basics internal info, and might help porting -+duel. Incomplete and probably badly written. sorry. -+ -+Entry points and modules -+-------------------------- -+duel_eval_and_parse is entry point into duel, in duel.c -+duel_parse in parse.y does all parsing -+duel_eval in eval.c makes the evaluation -+evalop.c contains low-level evaluation -+misc.c contains misc stuff -+types.c type create/manage -+output.c all output goes thru duel_printf -+output2.c same as output, but support sending eval output to a pipe, -+ like the duel.pipe perl script. -+print.c all output of values is done here -+eval.c high level evaluation code (generators) -+evalops.c low level evaluation code (operators) -+error.c handle erros, display error info "nicely" -+ -+start reading the code from duel.c, then global.h, then eval.c. -+eval.c is hairy, especially the state-keeping code. The goto's are -+intentional, they convey control better than other constructs. -+ -+Types -+------ -+A relatively straight-forward system, if you have read code of real C -+compilers. A type is a "graph" with each node being a base type or -+a composition of other types. see global.h and types.c -+ -+Value system -+------------- -+also pretty simple, either an LVALUE, which have u.lvalue point to it, -+or an RVALUE, so u.rval_type contains the actual value. There is also -+a special BVALUE hack to hold lvalued bitfields, which is only useful -+is someone implements modifying a bitfield. and there is an FVALUE, which -+is just stored in u.rval_int but has the special value type (it was either -+this or add a new TYPE, i preferred a new value). -+Note the there is no "register" type support. You must read register variables -+as rvalues (duelgdb.c does that). I don't think it is essential, since -+gdb can be used directly to modify such values (this might be a -+problem in watchpoint/cond.breaks however). Also cc -g don't usually keep -+stuff in registers. We could add "SVALUE" for these. -+Bitfields are a pain, but bvalue is really needed, eg for x[..100].bitfield=0 -+ -+Memory allocation -+----------------- -+go through duel_malloc/duel_free. -+Memory is allocated only for (a) a new node, while parsing, (b) a value pushed -+on stack for x-->y operator (c) duel aliases. -+It is always safe to call duel_free_nodes which free everything except -+for aliases. -+Memory spill can occur in asynchronous interrupts (^C), but they at most -+reflect items moved from one list to another. This isn't too bad. -+ -+Interrupts -+---------- -+Duel ignores the issues of interrupts, but is written so it can be -+interrupted at any time. Naturally, some memory could be lost if an -+operation is interrupted, since Duel does not setup critical sections. -+However, interrupts will no result in bad internal structures, so it is -+safe to call duel_free_nodes after an interrupt. -+duelgdb.c implements exactly that - interrupts at all times, and cleanup -+using duel_free_nodes. -+ -+Parsing -+-------- -+yacc is pretty weak, especially when I tried complex ops like x\y#z -+(as a single, 3 val op!). I have up on such things and the syntax is -+pretty clean. Things to watch for are the semicolon nonsense, -+especially with optional-expressions (as in for(a;b;c);), the T hack -+for user types (only fix is to delay decision on (x)(y) till runtime -+or make clearer rules (consider something; (x)(y), do you parse x as a type -+and ignore the possible x:=printf in "something", etc), and the use of "," -+regular op and nodes for function parameters (the parser knows only about -+a single parameter, an exp!). -+ -+Search ops -+----------- -+Straight forward stacking in dfs_... in eval.c -+Note things are put in reversed, so root-->(left,right) does what you -+expect. Also linked-lists could be greatly optimized. -+The functionality for ->> (BFS) is already in, all you need is to -+make the stack into a queue by pushing from the other side (really append) -+ -+Multi-expressions -+-------------------- -+As far as I know, you could save root (in duel.h) and use it to evaluate -+as often as needed (e.g for breakpoints/watchpoints), the internals -+of the nodes hold all eval info. You must reset the expression -+with eval_stop, if u dont eval it to the last value. Also make sure you -+cleanup the dot stack. Aliases (in misc.c) could become scoped, of course. -+ -+Interface to the debugger -+------------------------- -+ -+What DUEL needs: -+1. A way to access the symbol table for variable names, types, etc. -+2. A way to access the value of a variable, both for read and writes. -+3. A way to call debuggee functions. -+4. A way to get locals of frame n -+5. misc functions, eg memory alloc, entery/exit code -+ -+In practice, you will probably take duelgdb.c and modify it until you -+get the "right thing" for your debugger. -+NOTE: duelgdb.c was written from scratch and has *no* GNU code in it. -+ -+The most complex issue is types - you must pass names in a tvalue, -+which include a tctype (the C reminds one of a "C" type, not just 'type' -+which is ambiguous). The code to convert gdb types into duel types is -+typical. Watch out for recursive struct pointers (the hash table handles -+these problems), and for partial types, e.g. pointer to struct which -+contains no fields (size zero!). -+ -+You can return a BVALUE an LVALUE (preferred) or an RVALUE for a name -+lookup. use RVALUE for names found in registers, and return the actual -+value. -+ -+if a frame number is given for symbol lookup, only local variables -+allocated in that frame should be returned. (else return none. don't -+return a global if it exist with the same name, this will make the dot -+stack compute things wrong). -+ -+Node that this doesnt help with scoping problems (for duel)- e.g. -+you can't do myfunc.x if x is a static variable in myfunc. There needs to -+be a more complex & general way in the language to specify this (i.e. -+specify a source location in which the variable is visible, AND a frame -+to use if the value is kept on a frame) frame(n).(scope(file,line).x)? -+ ---- gdb/duel/misc.c -+++ gdb/duel/misc.c -@@ -0,0 +1,142 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* misc function/library-like */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.5 93/03/12 05:51:00 mg -+ * support output redirection -+ * -+ * Revision 1.4 93/01/13 16:22:09 mg -+ * allow malloc to return int (is a mini symbol on SUN) -+ * -+ * Revision 1.3 93/01/12 21:52:43 mg -+ * moved aliases mgmt here -+ * cleanup and set for release -+ * -+ */ -+ -+#include "duel.h" -+ -+/* like strncpy, but put a zero at to[len] anyway. -+ * are copied (hence taking len+1 bytes -+ */ -+ -+FUNC char* strncpyz(char *to,char *from,size_t len) -+{ -+ strncpy(to,from,len); -+ to[len]=0 ; -+ return to ; -+} -+ -+/* allocate n bytes in the target's space. Used for storing constant -+ * strings when they are parsed, and for variables declaration -+ * note: on SUN (and others?) gdb claims malloc to return an integer. we -+ * accept this (silly but probably no harm done) -+ */ -+ -+FUNC ttarget_ptr duel_alloc_target_space(size_t n) -+{ -+ tvalue p,f,r,*parms[1] ; -+ -+ p.val_kind=VK_RVALUE ; /* mk n into a value, to pass as parm */ -+ p.ctype=ctype_int ; -+ p.u.rval_int=n ; -+ parms[0]= &p ; -+ -+ if(!duel_get_target_variable("malloc",-1,&f) || -+ f.ctype->type_kind!=CTK_FUNC || -+ f.ctype->u.kid->type_kind!=CTK_INT && f.ctype->u.kid->type_kind!=CTK_PTR) -+ duel_fatal("malloc() function returning a pointer required in target"); -+ -+ duel_target_func_call(&f,parms,1,&r); -+ if(r.u.rval_ptr==NULL) duel_fatal("target's malloc() failed"); -+ return r.u.rval_ptr ; -+} -+ -+PROC duel_free_val_list(tval_list *l) /*free a val list and mark list empty */ -+{ -+ tval_lcell *cell,*next ; -+ for(cell=l->head ; cell!=NULL ; cell=next ) { -+ next=cell->next ; -+ duel_free(cell); -+ } -+ l->head=l->tail=NULL ; -+} -+ -+/* free all the memory allocated in the parse tree from node */ -+ -+PROC duel_free_nodes(tnode *n) -+{ -+ int i; -+ if(!n) return ; -+ for(i=0 ; i<NODE_MAX_KIDS ; i++) -+ duel_free_nodes(n->kids[i]); -+ duel_free_val_list(&n->eval.vlist); -+ duel_free(n); -+} -+ -+ -+ -+/* Aliases management */ -+ -+typedef struct sduel_var { /* an alias */ -+ char *name ; -+ tvalue val ; -+ struct sduel_var *next ; -+ } tduel_var ; -+tduel_var *duel_vars_head ; -+ -+/* find the value of a duel variable, if exist (else return null */ -+ -+FUNC tvalue* duel_find_alias(char *name) -+{ -+ tduel_var *p ; -+ for(p=duel_vars_head ; p ; p=p->next) { -+ if(strcmp(name,p->name)==0) return(&p->val); -+ } -+ return NULL ; -+} -+ -+/* set a value of a duel alias. Create var as needed */ -+ -+PROC duel_set_alias(char *name,tvalue *v) -+{ -+ tduel_var *p ; -+ tvalue *found = duel_find_alias(name) ; -+ if(found!=NULL) *found= *v ; -+ else { -+ p=duel_malloc(sizeof(tduel_var)) ; -+ p->next=duel_vars_head ; -+ p->val= *v ; -+ p->name=name ; -+ duel_vars_head=p ; -+ } -+} -+ -+PROC duel_clear_aliases(void) /* clear all defined aliases */ -+{ -+ tduel_var *p=duel_vars_head ; -+ while(p) { -+ tduel_var *q=p ; -+ p=p->next ; -+ duel_free(q); -+ } -+ duel_vars_head=0 ; -+} -+ -+PROC duel_show_aliases(void) -+{ -+ tduel_var *p ; -+ if(!duel_vars_head) duel_printf("No aliases defined\n"); -+ else { -+ duel_printf("Aliases table:\n"); -+ for(p=duel_vars_head ; p ; p=p->next) { -+ duel_printf("%s: ",p->name); -+ duel_print_value(&p->val); -+ } -+ } -+} ---- gdb/duel/output.c -+++ gdb/duel/output.c -@@ -0,0 +1,53 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* This module supports i/o for duel. Normally output goes to stdout, -+ * but it could be piped out instead. -+ * this module support minimal duel output w/o pipes. output2.c which -+ * support piped i/o is still an alpha version. -+ */ -+ -+#include <stdarg.h> /* for duel_printf */ -+#include "duel.h" -+ -+/* output functions: -+ * duel_printf all duel output goes thru this - like printf() -+ * duel_flush used by duel to flush the output. -+ */ -+ -+PROC duel_printf(char *fmt, ...) /* like printf, but for duel output */ -+{ -+ va_list args; -+ va_start(args, fmt); -+ vfprintf(stdout,fmt,args); -+ va_end(args); -+} -+ -+PROC duel_flush(void) /* flush out output from duel */ -+{ -+ fflush(stdout); -+} -+ -+/* tells us the output is "directable" now. s is the expression -+ * being evaluated for this */ -+ -+PROC duel_redirectable_output_start(char *s) -+{ -+ if(s) duel_flush(); /* if(s) is always true. prevents warnings ...*/ -+} -+ -+PROC duel_redirectable_output_end(void) -+{ -+ duel_flush(); -+} -+ -+PROC duel_redirectable_output_abort(void) -+{ -+ duel_flush(); -+} -+ -+PROC duel_redirectable_output_init(void) -+{ -+} ---- gdb/duel/output2.c -+++ gdb/duel/output2.c -@@ -0,0 +1,141 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* This module supports i/o for duel. Normally output goes to stdout, -+ * but it could be piped out instead. -+ * Still alpha version. -+ * HOW: if file duel.pipe exists, it is opened with stdin/out piped -+ * here. results of expressions evaluations are sent to the pipe -+ * with $$$START $$$END $$$ABORT and $$$SYM/$$$VAL. The pipe's -+ * output is passed back here and is printed to stdout until -+ * a $$$DONE is received. The pipe is normally a perl script, -+ * that can processes the output at a symbolic level. -+ */ -+ -+#include <stdarg.h> /* for duel_printf */ -+#include <sys/types.h> /* for stat() */ -+#include <sys/stat.h> /* " */ -+#include <fcntl.h> /* for popen impl. */ -+#include <signal.h> /* " */ -+ -+#include "duel.h" -+ -+/* output functions: -+ * duel_printf all duel output goes thru this - like printf() -+ * duel_flush used by duel to flush the output. -+ * duel_redirectable_output_start(s) - indicate start of output for exp s that -+ * can be redirected to a pipe. -+ * duel_redirectable_output_end() - indicate end of that output. -+ * duel_redirectable_output_abort() - indicate output was aborted (error,intr) -+ * -+ * duel_redirectable_output_init() - called to init at first duel use. -+ */ -+ -+static FILE *duel_outf = stdout ; /* current output stream */ -+static FILE *poutf,*pinf ; /* pipe i/o streams */ -+ -+#define PIPE_CMD "./duel.pipe" /* command to pipe into */ -+ -+bool bidir_popen(void) -+{ -+ int pout[2],pin[2]; /* pin[0] is my input, pout[1] my output */ -+ int pid; -+ struct stat s ; -+ -+ if(stat(PIPE_CMD,&s)!=0 || !(s.st_mode & S_IEXEC)) return FALSE; -+ if (pipe(pout) < 0 || pipe(pin) < 0) return FALSE ; -+ -+ if ((pid = fork()) == 0) { -+ signal(SIGINT, SIG_IGN); -+ signal(SIGQUIT, SIG_IGN); -+ dup2(pout[0],0); dup2(pin[1],1); -+ close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); -+ execl(PIPE_CMD, PIPE_CMD, NULL); -+ _exit(127); -+ } -+ close(pout[0]); close(pin[1]); -+ if (pid == -1) return FALSE; -+ pinf =fdopen(pin[0], "r"); -+ poutf=fdopen(pout[1],"w"); -+ if(fcntl(pin[0],F_SETFL,O_NDELAY) < 0) return FALSE ; -+ return pinf!=NULL && poutf!=NULL ; -+} -+ -+ -+PROC duel_printf(char *fmt, ...) /* like printf, but for duel output */ -+{ -+ va_list args; -+ va_start(args, fmt); -+ vfprintf(duel_outf,fmt,args); -+ va_end(args); -+} -+ -+PROC duel_flush(void) /* flush out output from duel */ -+{ -+ char s[256]; -+ fflush(duel_outf); -+ while(pinf && fgets(s,sizeof(s),pinf)) /* note pinf is non blocking */ -+ printf("%s",s); -+} -+ -+LPROC duel_waitpipe(bool abort) /* wait for pipe to finish working */ -+{ -+ char s[256]; -+ if(abort) duel_printf("$$$ABORT\n"); /* write termination mesg */ -+ else duel_printf("$$$DONE\n"); -+ fflush(duel_outf); -+ fcntl(fileno(pinf),F_SETFL,0); /* restore blocking for pipe */ -+ while(fgets(s,sizeof(s),pinf)!=NULL && strcmp(s,"$$$DONE\n")!=0) -+ if(!abort) printf("%s",s); -+ fcntl(fileno(pinf),F_SETFL,O_NDELAY); -+ if(abort) printf("\n"); -+} -+ -+/* tells us the output is "directable" now. s is the expression -+ * being evaluated for this */ -+ -+PROC duel_redirectable_output_start(char *s) -+{ -+ duel_flush(); -+ if(poutf) { -+ duel_flush(); -+ duel_outf=poutf ; -+ duel_output_pipe_style=1 ; -+ duel_printf("$$$START: %s\n",s); -+ duel_flush(); -+ } -+} -+ -+PROC duel_redirectable_output_end(void) -+{ -+ duel_flush(); -+ if(poutf && duel_outf == poutf) { -+ duel_waitpipe(FALSE); -+ duel_outf=stdout ; -+ duel_output_pipe_style=0 ; -+ } -+} -+ -+PROC duel_redirectable_output_abort(void) -+{ -+ if(poutf && duel_outf == poutf) { -+ duel_waitpipe(TRUE); -+ duel_outf=stdout ; -+ duel_output_pipe_style=0 ; -+ } -+ duel_flush(); -+} -+ -+PROC duel_redirectable_output_init(void) -+{ -+ /* open the duel pipe, if available. Verify that duel.pipe -+ * as an existing executable, because popen() does not, and can -+ * later fail with pipe signal! -+ */ -+ if(bidir_popen()) { -+ duel_printf("Duel results directed to pipe \"duel.pipe\"\n"); -+ } -+ else poutf=pinf=NULL ; -+} ---- gdb/duel/parse.c -+++ gdb/duel/parse.c -@@ -0,0 +1,3326 @@ -+/* A Bison parser, made by GNU Bison 2.3. */ -+ -+/* Skeleton implementation for Bison's Yacc-like parsers in C -+ -+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 -+ Free Software Foundation, Inc. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2, or (at your option) -+ any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street, Fifth Floor, -+ Boston, MA 02110-1301, USA. */ -+ -+/* As a special exception, you may create a larger work that contains -+ part or all of the Bison parser skeleton and distribute that work -+ under terms of your choice, so long as that work isn't itself a -+ parser generator using the skeleton or a modified version thereof -+ as a parser skeleton. Alternatively, if you modify or redistribute -+ the parser skeleton itself, you may (at your option) remove this -+ special exception, which will cause the skeleton and the resulting -+ Bison output files to be licensed under the GNU General Public -+ License without this special exception. -+ -+ This special exception was added by the Free Software Foundation in -+ version 2.2 of Bison. */ -+ -+/* C LALR(1) parser skeleton written by Richard Stallman, by -+ simplifying the original so-called "semantic" parser. */ -+ -+/* All symbols defined below should begin with yy or YY, to avoid -+ infringing on user name space. This should be done even for local -+ variables, as they might otherwise be expanded by user macros. -+ There are some unavoidable exceptions within include files to -+ define necessary library symbols; they are noted "INFRINGES ON -+ USER NAME SPACE" below. */ -+ -+/* Identify Bison output. */ -+#define YYBISON 1 -+ -+/* Bison version. */ -+#define YYBISON_VERSION "2.3" -+ -+/* Skeleton name. */ -+#define YYSKELETON_NAME "yacc.c" -+ -+/* Pure parsers. */ -+#define YYPURE 0 -+ -+/* Using locations. */ -+#define YYLSP_NEEDED 0 -+ -+ -+ -+/* Tokens. */ -+#ifndef YYTOKENTYPE -+# define YYTOKENTYPE -+ /* Put the tokens into the symbol table, so that GDB and other debuggers -+ know about them. */ -+ enum yytokentype { -+ T_CONST = 258, -+ T_SYM = 259, -+ T_ASSIGN = 260, -+ T_DEFVAR = 261, -+ T_CHAR = 262, -+ T_INT = 263, -+ T_SHORT = 264, -+ T_LONG = 265, -+ T_UNSIGNED = 266, -+ T_FLOAT = 267, -+ T_DOUBLE = 268, -+ T_VOID = 269, -+ T_STRUCT = 270, -+ T_UNION = 271, -+ T_ENUM = 272, -+ T_SIZEOF = 273, -+ T_TYPEDEF_INDICATOR = 274, -+ T_SIGNED = 275, -+ T_IF = 276, -+ T_ELSE = 277, -+ T_FOR = 278, -+ T_WHILE = 279, -+ T_OR = 280, -+ T_AND = 281, -+ T_RSH = 282, -+ T_LSH = 283, -+ T_INC = 284, -+ T_DEC = 285, -+ T_COUNT = 286, -+ T_FRAME = 287, -+ T_TO = 288, -+ T_DFS = 289, -+ T_BFS = 290, -+ T_ARROW = 291, -+ T_OSEL = 292, -+ T_CSEL = 293, -+ T_IMP = 294, -+ T_ANDL = 295, -+ T_ORL = 296, -+ T_EQ = 297, -+ T_NE = 298, -+ T_EQQ = 299, -+ T_NEQ = 300, -+ T_LE = 301, -+ T_GE = 302, -+ T_LSQ = 303, -+ T_GTQ = 304, -+ T_LEQ = 305, -+ T_GEQ = 306, -+ STMT = 307, -+ UNARY = 308, -+ T_POS = 309 -+ }; -+#endif -+/* Tokens. */ -+#define T_CONST 258 -+#define T_SYM 259 -+#define T_ASSIGN 260 -+#define T_DEFVAR 261 -+#define T_CHAR 262 -+#define T_INT 263 -+#define T_SHORT 264 -+#define T_LONG 265 -+#define T_UNSIGNED 266 -+#define T_FLOAT 267 -+#define T_DOUBLE 268 -+#define T_VOID 269 -+#define T_STRUCT 270 -+#define T_UNION 271 -+#define T_ENUM 272 -+#define T_SIZEOF 273 -+#define T_TYPEDEF_INDICATOR 274 -+#define T_SIGNED 275 -+#define T_IF 276 -+#define T_ELSE 277 -+#define T_FOR 278 -+#define T_WHILE 279 -+#define T_OR 280 -+#define T_AND 281 -+#define T_RSH 282 -+#define T_LSH 283 -+#define T_INC 284 -+#define T_DEC 285 -+#define T_COUNT 286 -+#define T_FRAME 287 -+#define T_TO 288 -+#define T_DFS 289 -+#define T_BFS 290 -+#define T_ARROW 291 -+#define T_OSEL 292 -+#define T_CSEL 293 -+#define T_IMP 294 -+#define T_ANDL 295 -+#define T_ORL 296 -+#define T_EQ 297 -+#define T_NE 298 -+#define T_EQQ 299 -+#define T_NEQ 300 -+#define T_LE 301 -+#define T_GE 302 -+#define T_LSQ 303 -+#define T_GTQ 304 -+#define T_LEQ 305 -+#define T_GEQ 306 -+#define STMT 307 -+#define UNARY 308 -+#define T_POS 309 -+ -+ -+ -+ -+/* Copy the first part of user declarations. */ -+#line 1 "parse.y" -+ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* this module contains the duel parser, in yacc, plus a simple lexer. -+ * the lexer is slow, but duel expressions are tiny. -+ * the parsing generate an AST with essentially no type checking. -+ * names are only looked up when the refer explicitly to types. This forces -+ * the use of "T" before user types. You can't parse (x)(y) correctly, if -+ * you want the node to contain "cast" or "func", without knowing the x is -+ * not a type. (It is interesting to note that (x *)(y) is clearly a cast, -+ * but it can not be parsed without a context sensitive grammer!). -+ * -+ * Version 1.1 now accept (x) as a type cast, so (print)("hi") fails, but -+ * (uint)z is ok. Also accepted is (uint*)z. T is still required in sizeof -+ * and in variable declarations. A side effect was making "sizeof x" illegal -+ * (since then sizeof(x)-1 was parsed sizeof((x)-1) with (x) a cast), so -+ * now sizeof(x) must be used. Note that in C, sizoef(x)++ is acceptable, -+ * and the '++' operate on x (which is optimized out!) This can be confusing. -+ * -+ * yacc is also not smart enough to recognize e.g. "if(e) e ; else e" as -+ * a special case (redundent ';'). I hacked this in the lexer. It should -+ * reduce the trouble with C->duel coding. (It can also be done for {e1}e2, -+ * in some speical cases, e.g. if e2 is a keyword, or a name or a unary op, -+ * but this can confuse some people, e.g. in {i}[5], so I left it alone.) -+ * Finally, the %/ operator is accepted as "#/" and "%%" as "#", to those -+ * who wish to keep gdb with # comments. -+ * memory: nodes are alloc'ed dynamically. a parsing error loose so-far -+ * allocated nodes, which is normally acceptable (yyerror can probably hack -+ * into the yacc stack to release them.) -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.14 93/03/17 11:04:12 mg -+ * fixed (t*)x bug, was parsed as (t**)x -+ * -+ * Revision 1.13 93/03/12 06:15:09 mg -+ * modified unary's a bit - cosmetics -+ * support (x)y as type cast -+ * support (x*)y as type cast -+ * replace sizeof exp with sizeof(exp) to prevent clash with above -+ * more cosmetics, including yyerror abort, tuint for uint. -+ * takes anything after |> to be comment (pipe command really) -+ * -+ * -+ * Revision 1.12 93/02/27 06:06:09 mg -+ * added signed char parsing. -+ * -+ * Revision 1.11 93/02/23 19:15:38 mg -+ * improved escaped char support -+ * -+ * Revision 1.10 93/02/03 21:49:34 mg -+ * bug fix - yyerror calls now abort parsing (eg called from lex) -+ * -+ * Revision 1.9 93/01/12 21:53:07 mg -+ * cleanup and set for release -+ * -+ * Revision 1.8 93/01/07 00:14:33 mg -+ * add &&/ ||/ -+ * fixed parsing of trailing ';' was a mess. -+ * ignore ';' before 'else' and '}' w/warning. -+ * -+ * Revision 1.7 93/01/03 07:31:01 mg -+ * error reporting -+ * -+ * Revision 1.6 92/12/24 23:35:50 mg -+ * began src pos support -+ * -+ * Revision 1.5 92/10/19 15:08:02 mg -+ * frames() added; bug fixed -+ * -+ * Revision 1.4 92/10/14 02:06:32 mg -+ * misc/change casting parsing/variable def. -+ * -+ * Revision 1.3 92/09/16 11:09:39 mg -+ * add typedef/struct support, const strings -+ * cleanup s/r conflict by setting ELSE to a token. explained some stuff in -+ * comments. -+ * -+ * Revision 1.2 92/09/15 06:10:46 mg -+ * cosmetics and new ops: x@y, for() while() ..x and x.. -+ * generic '.' and '_' support. x@y. '..x' and 'x..'. while(), for(), ?: -+ * -+ */ -+ -+#include "duel.h" -+ -+static char *inputstr ; /* pointer to string being parsed */ -+static char *lexptr ; /* current lexer pointer into input str */ -+static tnode *root ; /* result of parsing stored here */ -+ -+/* pick unique names for globals of yacc. gdb has other parsers! */ -+#define yyparse duel_yyparse -+#define yylex duel_yylex -+#define yyerror duel_yyerror -+#define yylval duel_yylval -+#define yychar duel_yychar -+#define yydebug duel_yydebug -+#define yypact duel_yypact -+#define yyr1 duel_yyr1 -+#define yyr2 duel_yyr2 -+#define yydef duel_yydef -+#define yychk duel_yychk -+#define yypgo duel_yypgo -+#define yyact duel_yyact -+#define yyexca duel_yyexca -+#define yyerrflag duel_yyerrflag -+#define yynerrs duel_yynerrs -+#define yyps duel_yyps -+#define yypv duel_yypv -+#define yys duel_yys -+#define yystate duel_yystate -+#define yytmp duel_yytmp -+#define yyv duel_yyv -+#define yyval duel_yyval -+#define yylloc duel_yylloc -+ -+typedef struct { /* token info for operators */ -+ int src_pos ; /* source position */ -+ topcode opcode ; /* opcode */ -+ } topinfo ; -+ -+typedef struct { /* token info for symbols */ -+ int src_pos ; /* source position */ -+ char *name ; /* symbol */ -+ } tnameinfo ; -+ -+/* these are used as operators to mknode_... when source location is unknown*/ -+static topinfo seq_op = { -1,';' } ; /* sequencing operator, src pos unkown */ -+static topinfo decl_op = { -1,OP_DECL } ; /* declare var op, src pos unkown */ -+ -+/* local prototypes. */ -+LPROC yyerror(char *msg); -+LFUNC int yylex (void); -+ -+LPROC push_type(char desc) ; -+LPROC push_type_int(char desc,tnode *n) ; -+LFUNC bool pop_type(char *desc,int *size); -+ -+LFUNC tnode* mknode_op(top_kind,topinfo opinfo,tnode*,tnode*,tnode*,tnode*); -+LFUNC tnode* mknode_const(int src_pos,tctype *ctype); -+LFUNC tnode* mknode_ctype(tctype *ctype); -+LFUNC tnode* mknode_name(tnameinfo nameinfo); -+LFUNC tnode* mknode_modified_ctype(tctype *base); -+ -+#define mknode_post_unary(op,n) (mknode_op(OPK_POST_UNARY,op,n, 0, 0,0)) -+#define mknode_unary(op,n) (mknode_op(OPK_UNARY, op,n, 0, 0,0)) -+#define mknode_sunary(op,n) (mknode_op(OPK_SUNARY, op,n, 0, 0,0)) -+#define mknode_bin(op,n1,n2) (mknode_op(OPK_BIN, op,n1,n2,0,0)) -+#define mknode_sbin(op,n1,n2) (mknode_op(OPK_SBIN, op,n1,n2,0,0)) -+#define mknode_tri(op,n1,n2,n3) (mknode_op(OPK_TRI, op,n1,n2,n3,0)) -+ -+static tctype *decl_tbase ; /* used for variables decl */ -+ -+/* #define YYDEBUG 1 */ -+ -+ -+ -+/* Enabling traces. */ -+#ifndef YYDEBUG -+# define YYDEBUG 0 -+#endif -+ -+/* Enabling verbose error messages. */ -+#ifdef YYERROR_VERBOSE -+# undef YYERROR_VERBOSE -+# define YYERROR_VERBOSE 1 -+#else -+# define YYERROR_VERBOSE 0 -+#endif -+ -+/* Enabling the token table. */ -+#ifndef YYTOKEN_TABLE -+# define YYTOKEN_TABLE 0 -+#endif -+ -+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -+typedef union YYSTYPE -+#line 163 "parse.y" -+{ -+ tnode *node ; /* node pointer for constructed exp tree */ -+ tctype *ctype; /* type for type nodes */ -+ tnameinfo nameinfo ; /* a name/symbol + src position */ -+ topinfo opinfo; /* keyword/operator + source position */ -+ } -+/* Line 187 of yacc.c. */ -+#line 372 "parse.c" -+ YYSTYPE; -+# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -+# define YYSTYPE_IS_DECLARED 1 -+# define YYSTYPE_IS_TRIVIAL 1 -+#endif -+ -+ -+ -+/* Copy the second part of user declarations. */ -+ -+ -+/* Line 216 of yacc.c. */ -+#line 385 "parse.c" -+ -+#ifdef short -+# undef short -+#endif -+ -+#ifdef YYTYPE_UINT8 -+typedef YYTYPE_UINT8 yytype_uint8; -+#else -+typedef unsigned char yytype_uint8; -+#endif -+ -+#ifdef YYTYPE_INT8 -+typedef YYTYPE_INT8 yytype_int8; -+#elif (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+typedef signed char yytype_int8; -+#else -+typedef short int yytype_int8; -+#endif -+ -+#ifdef YYTYPE_UINT16 -+typedef YYTYPE_UINT16 yytype_uint16; -+#else -+typedef unsigned short int yytype_uint16; -+#endif -+ -+#ifdef YYTYPE_INT16 -+typedef YYTYPE_INT16 yytype_int16; -+#else -+typedef short int yytype_int16; -+#endif -+ -+#ifndef YYSIZE_T -+# ifdef __SIZE_TYPE__ -+# define YYSIZE_T __SIZE_TYPE__ -+# elif defined size_t -+# define YYSIZE_T size_t -+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ -+# define YYSIZE_T size_t -+# else -+# define YYSIZE_T unsigned int -+# endif -+#endif -+ -+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) -+ -+#ifndef YY_ -+# if YYENABLE_NLS -+# if ENABLE_NLS -+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ -+# define YY_(msgid) dgettext ("bison-runtime", msgid) -+# endif -+# endif -+# ifndef YY_ -+# define YY_(msgid) msgid -+# endif -+#endif -+ -+/* Suppress unused-variable warnings by "using" E. */ -+#if ! defined lint || defined __GNUC__ -+# define YYUSE(e) ((void) (e)) -+#else -+# define YYUSE(e) /* empty */ -+#endif -+ -+/* Identity function, used to suppress warnings about constant conditions. */ -+#ifndef lint -+# define YYID(n) (n) -+#else -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+static int -+YYID (int i) -+#else -+static int -+YYID (i) -+ int i; -+#endif -+{ -+ return i; -+} -+#endif -+ -+#if ! defined yyoverflow || YYERROR_VERBOSE -+ -+/* The parser invokes alloca or malloc; define the necessary symbols. */ -+ -+# ifdef YYSTACK_USE_ALLOCA -+# if YYSTACK_USE_ALLOCA -+# ifdef __GNUC__ -+# define YYSTACK_ALLOC __builtin_alloca -+# elif defined __BUILTIN_VA_ARG_INCR -+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ -+# elif defined _AIX -+# define YYSTACK_ALLOC __alloca -+# elif defined _MSC_VER -+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ -+# define alloca _alloca -+# else -+# define YYSTACK_ALLOC alloca -+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -+# ifndef _STDLIB_H -+# define _STDLIB_H 1 -+# endif -+# endif -+# endif -+# endif -+# endif -+ -+# ifdef YYSTACK_ALLOC -+ /* Pacify GCC's `empty if-body' warning. */ -+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) -+# ifndef YYSTACK_ALLOC_MAXIMUM -+ /* The OS might guarantee only one guard page at the bottom of the stack, -+ and a page size can be as small as 4096 bytes. So we cannot safely -+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number -+ to allow for a few compiler-allocated temporary stack slots. */ -+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -+# endif -+# else -+# define YYSTACK_ALLOC YYMALLOC -+# define YYSTACK_FREE YYFREE -+# ifndef YYSTACK_ALLOC_MAXIMUM -+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -+# endif -+# if (defined __cplusplus && ! defined _STDLIB_H \ -+ && ! ((defined YYMALLOC || defined malloc) \ -+ && (defined YYFREE || defined free))) -+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -+# ifndef _STDLIB_H -+# define _STDLIB_H 1 -+# endif -+# endif -+# ifndef YYMALLOC -+# define YYMALLOC malloc -+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -+# endif -+# endif -+# ifndef YYFREE -+# define YYFREE free -+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+void free (void *); /* INFRINGES ON USER NAME SPACE */ -+# endif -+# endif -+# endif -+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ -+ -+ -+#if (! defined yyoverflow \ -+ && (! defined __cplusplus \ -+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) -+ -+/* A type that is properly aligned for any stack member. */ -+union yyalloc -+{ -+ yytype_int16 yyss; -+ YYSTYPE yyvs; -+ }; -+ -+/* The size of the maximum gap between one aligned stack and the next. */ -+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) -+ -+/* The size of an array large to enough to hold all stacks, each with -+ N elements. */ -+# define YYSTACK_BYTES(N) \ -+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ -+ + YYSTACK_GAP_MAXIMUM) -+ -+/* Copy COUNT objects from FROM to TO. The source and destination do -+ not overlap. */ -+# ifndef YYCOPY -+# if defined __GNUC__ && 1 < __GNUC__ -+# define YYCOPY(To, From, Count) \ -+ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -+# else -+# define YYCOPY(To, From, Count) \ -+ do \ -+ { \ -+ YYSIZE_T yyi; \ -+ for (yyi = 0; yyi < (Count); yyi++) \ -+ (To)[yyi] = (From)[yyi]; \ -+ } \ -+ while (YYID (0)) -+# endif -+# endif -+ -+/* Relocate STACK from its old location to the new one. The -+ local variables YYSIZE and YYSTACKSIZE give the old and new number of -+ elements in the stack, and YYPTR gives the new location of the -+ stack. Advance YYPTR to a properly aligned location for the next -+ stack. */ -+# define YYSTACK_RELOCATE(Stack) \ -+ do \ -+ { \ -+ YYSIZE_T yynewbytes; \ -+ YYCOPY (&yyptr->Stack, Stack, yysize); \ -+ Stack = &yyptr->Stack; \ -+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ -+ yyptr += yynewbytes / sizeof (*yyptr); \ -+ } \ -+ while (YYID (0)) -+ -+#endif -+ -+/* YYFINAL -- State number of the termination state. */ -+#define YYFINAL 77 -+/* YYLAST -- Last index in YYTABLE. */ -+#define YYLAST 1420 -+ -+/* YYNTOKENS -- Number of terminals. */ -+#define YYNTOKENS 81 -+/* YYNNTS -- Number of nonterminals. */ -+#define YYNNTS 18 -+/* YYNRULES -- Number of rules. */ -+#define YYNRULES 129 -+/* YYNRULES -- Number of states. */ -+#define YYNSTATES 238 -+ -+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -+#define YYUNDEFTOK 2 -+#define YYMAXUTOK 309 -+ -+#define YYTRANSLATE(YYX) \ -+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -+ -+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -+static const yytype_uint8 yytranslate[] = -+{ -+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 48, 2, 46, 2, 38, 31, 2, -+ 42, 43, 36, 34, 26, 35, 39, 37, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 80, 25, -+ 32, 27, 33, 28, 47, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 40, 2, 41, 30, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 44, 29, 45, 49, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, -+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, -+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 -+}; -+ -+#if YYDEBUG -+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in -+ YYRHS. */ -+static const yytype_uint16 yyprhs[] = -+{ -+ 0, 0, 3, 5, 7, 10, 14, 16, 18, 21, -+ 23, 27, 28, 32, 34, 38, 40, 44, 50, 53, -+ 58, 60, 66, 73, 80, 88, 98, 107, 113, 118, -+ 121, 124, 127, 130, 133, 136, 139, 142, 145, 148, -+ 151, 154, 159, 164, 169, 173, 177, 181, 185, 189, -+ 193, 198, 203, 208, 212, 216, 221, 226, 233, 237, -+ 241, 245, 249, 253, 257, 261, 265, 269, 273, 277, -+ 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, -+ 321, 325, 329, 335, 339, 343, 347, 351, 354, 357, -+ 361, 365, 369, 371, 373, 374, 376, 378, 380, 383, -+ 387, 393, 396, 401, 402, 405, 407, 410, 413, 415, -+ 417, 420, 422, 425, 428, 432, 435, 439, 443, 448, -+ 450, 453, 456, 460, 462, 464, 466, 469, 472, 475 -+}; -+ -+/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -+static const yytype_int8 yyrhs[] = -+{ -+ 82, 0, -1, 83, -1, 85, -1, 85, 25, -1, -+ 85, 25, 84, -1, 84, -1, 92, -1, 92, 25, -+ -1, 86, -1, 85, 25, 86, -1, -1, 97, 87, -+ 88, -1, 89, -1, 88, 26, 89, -1, 90, -1, -+ 42, 90, 43, -1, 42, 90, 43, 42, 43, -1, -+ 36, 90, -1, 90, 40, 3, 41, -1, 94, -1, -+ 21, 42, 91, 43, 91, -1, 21, 42, 91, 43, -+ 91, 22, -1, 21, 42, 91, 43, 22, 91, -1, -+ 21, 42, 91, 43, 91, 22, 91, -1, 23, 42, -+ 93, 25, 91, 25, 93, 43, 91, -1, 23, 42, -+ 93, 25, 91, 25, 93, 43, -1, 24, 42, 91, -+ 43, 91, -1, 24, 42, 91, 43, -1, 36, 91, -+ -1, 31, 91, -1, 35, 91, -1, 48, 91, -1, -+ 49, 91, -1, 56, 91, -1, 65, 91, -1, 66, -+ 91, -1, 54, 91, -1, 55, 91, -1, 91, 54, -+ -1, 91, 55, -1, 18, 42, 95, 43, -1, 18, -+ 42, 91, 43, -1, 57, 42, 91, 43, -1, 91, -+ 59, 91, -1, 91, 60, 91, -1, 91, 46, 94, -+ -1, 91, 47, 91, -1, 91, 61, 91, -1, 91, -+ 39, 91, -1, 91, 40, 91, 41, -1, 91, 62, -+ 91, 63, -1, 91, 42, 93, 43, -1, 42, 92, -+ 43, -1, 44, 92, 45, -1, 42, 95, 43, 91, -+ -1, 42, 98, 43, 91, -1, 42, 98, 36, 96, -+ 43, 91, -1, 91, 36, 91, -1, 91, 37, 91, -+ -1, 91, 38, 91, -1, 91, 34, 91, -1, 91, -+ 35, 91, -1, 91, 53, 91, -1, 91, 52, 91, -+ -1, 91, 67, 91, -1, 91, 68, 91, -1, 91, -+ 69, 91, -1, 91, 70, 91, -1, 91, 71, 91, -+ -1, 91, 72, 91, -1, 91, 75, 91, -1, 91, -+ 76, 91, -1, 91, 32, 91, -1, 91, 33, 91, -+ -1, 91, 73, 91, -1, 91, 74, 91, -1, 91, -+ 31, 91, -1, 91, 29, 91, -1, 91, 30, 91, -+ -1, 91, 51, 91, -1, 91, 50, 91, -1, 91, -+ 28, 91, 80, 91, -1, 91, 27, 91, -1, 91, -+ 5, 91, -1, 94, 6, 91, -1, 91, 58, 91, -+ -1, 58, 91, -1, 91, 58, -1, 91, 26, 91, -+ -1, 91, 64, 91, -1, 92, 25, 91, -1, 91, -+ -1, 91, -1, -1, 3, -1, 94, -1, 98, -1, -+ 97, 96, -1, 42, 96, 43, -1, 42, 96, 43, -+ 42, 43, -1, 36, 96, -1, 96, 40, 3, 41, -+ -1, -1, 19, 98, -1, 7, -1, 20, 7, -1, -+ 11, 7, -1, 8, -1, 11, -1, 11, 8, -1, -+ 10, -1, 10, 8, -1, 11, 10, -1, 11, 10, -+ 8, -1, 10, 10, -1, 10, 10, 8, -1, 11, -+ 10, 10, -1, 11, 10, 10, 8, -1, 9, -1, -+ 9, 8, -1, 11, 9, -1, 11, 9, 8, -1, -+ 12, -1, 13, -1, 14, -1, 15, 98, -1, 16, -+ 98, -1, 17, 98, -1, 4, -1 -+}; -+ -+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -+static const yytype_uint16 yyrline[] = -+{ -+ 0, 211, 211, 214, 215, 216, 217, 219, 220, 222, -+ 223, 226, 226, 228, 229, 232, 236, 237, 238, 239, -+ 240, 251, 252, 254, 256, 259, 261, 263, 265, 271, -+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, -+ 282, 283, 284, 285, 288, 289, 291, 292, 293, 294, -+ 295, 296, 297, 298, 299, 302, 313, 317, 326, 327, -+ 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, -+ 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, -+ 348, 349, 352, 356, 357, 358, 363, 364, 365, 366, -+ 367, 370, 371, 374, 375, 378, 379, 385, 387, 392, -+ 393, 394, 395, 396, 413, 423, 424, 425, 426, 427, -+ 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, -+ 438, 439, 440, 441, 442, 443, 444, 447, 450, 455 -+}; -+#endif -+ -+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE -+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. -+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -+static const char *const yytname[] = -+{ -+ "$end", "error", "$undefined", "T_CONST", "T_SYM", "T_ASSIGN", -+ "T_DEFVAR", "T_CHAR", "T_INT", "T_SHORT", "T_LONG", "T_UNSIGNED", -+ "T_FLOAT", "T_DOUBLE", "T_VOID", "T_STRUCT", "T_UNION", "T_ENUM", -+ "T_SIZEOF", "T_TYPEDEF_INDICATOR", "T_SIGNED", "T_IF", "T_ELSE", "T_FOR", -+ "T_WHILE", "';'", "','", "'='", "'?'", "'|'", "'^'", "'&'", "'<'", "'>'", -+ "'+'", "'-'", "'*'", "'/'", "'%'", "'.'", "'['", "']'", "'('", "')'", -+ "'{'", "'}'", "'#'", "'@'", "'!'", "'~'", "T_OR", "T_AND", "T_RSH", -+ "T_LSH", "T_INC", "T_DEC", "T_COUNT", "T_FRAME", "T_TO", "T_DFS", -+ "T_BFS", "T_ARROW", "T_OSEL", "T_CSEL", "T_IMP", "T_ANDL", "T_ORL", -+ "T_EQ", "T_NE", "T_EQQ", "T_NEQ", "T_LE", "T_GE", "T_LSQ", "T_GTQ", -+ "T_LEQ", "T_GEQ", "STMT", "UNARY", "T_POS", "':'", "$accept", "start", -+ "duel_inp", "duel_exp", "all_decls", "vars_decl", "@1", "var_decl", -+ "name_decl1", "name_decl", "exp", "sm_exp", "oexp", "nameexp", "type", -+ "type_mod", "typebase", "name", 0 -+}; -+#endif -+ -+# ifdef YYPRINT -+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to -+ token YYLEX-NUM. */ -+static const yytype_uint16 yytoknum[] = -+{ -+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, -+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, -+ 275, 276, 277, 278, 279, 59, 44, 61, 63, 124, -+ 94, 38, 60, 62, 43, 45, 42, 47, 37, 46, -+ 91, 93, 40, 41, 123, 125, 35, 64, 33, 126, -+ 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, -+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, -+ 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, -+ 58 -+}; -+# endif -+ -+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -+static const yytype_uint8 yyr1[] = -+{ -+ 0, 81, 82, 83, 83, 83, 83, 84, 84, 85, -+ 85, 87, 86, 88, 88, 89, 90, 90, 90, 90, -+ 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 92, 92, 93, 93, 91, 91, 94, 95, 96, -+ 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, -+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, -+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 98 -+}; -+ -+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -+static const yytype_uint8 yyr2[] = -+{ -+ 0, 2, 1, 1, 2, 3, 1, 1, 2, 1, -+ 3, 0, 3, 1, 3, 1, 3, 5, 2, 4, -+ 1, 5, 6, 6, 7, 9, 8, 5, 4, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 4, 4, 4, 3, 3, 3, 3, 3, 3, -+ 4, 4, 4, 3, 3, 4, 4, 6, 3, 3, -+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ 3, 3, 5, 3, 3, 3, 3, 2, 2, 3, -+ 3, 3, 1, 1, 0, 1, 1, 1, 2, 3, -+ 5, 2, 4, 0, 2, 1, 2, 2, 1, 1, -+ 2, 1, 2, 2, 3, 2, 3, 3, 4, 1, -+ 2, 2, 3, 1, 1, 1, 2, 2, 2, 1 -+}; -+ -+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state -+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero -+ means the default is an error. */ -+static const yytype_uint8 yydefact[] = -+{ -+ 0, 95, 129, 105, 108, 119, 111, 109, 123, 124, -+ 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 2, 6, 3, 9, 92, -+ 7, 96, 11, 97, 120, 112, 115, 107, 110, 121, -+ 113, 126, 127, 128, 0, 104, 106, 0, 94, 0, -+ 30, 31, 29, 0, 0, 103, 97, 0, 32, 33, -+ 37, 38, 34, 0, 87, 35, 36, 1, 4, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, -+ 0, 0, 39, 40, 88, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 8, 0, 0, 116, 122, 114, 117, 0, 0, 0, -+ 93, 0, 0, 0, 53, 0, 103, 103, 98, 103, -+ 0, 54, 0, 5, 10, 84, 89, 83, 0, 78, -+ 79, 77, 73, 74, 61, 62, 58, 59, 60, 49, -+ 0, 0, 46, 47, 81, 80, 64, 63, 86, 44, -+ 45, 48, 0, 90, 65, 66, 67, 68, 69, 70, -+ 75, 76, 71, 72, 91, 85, 0, 0, 12, 13, -+ 15, 20, 118, 42, 41, 0, 0, 28, 55, 101, -+ 0, 0, 0, 56, 43, 0, 50, 52, 51, 18, -+ 0, 0, 0, 0, 21, 0, 27, 99, 0, 0, -+ 82, 16, 14, 0, 23, 22, 94, 0, 102, 57, -+ 0, 19, 24, 0, 100, 17, 26, 25 -+}; -+ -+/* YYDEFGOTO[NTERM-NUM]. */ -+static const yytype_int16 yydefgoto[] = -+{ -+ -1, 34, 35, 36, 37, 38, 122, 188, 189, 190, -+ 39, 40, 131, 41, 64, 138, 42, 43 -+}; -+ -+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing -+ STATE-NUM. */ -+#define YYPACT_NINF -105 -+static const yytype_int16 yypact[] = -+{ -+ 843, -105, -105, -105, -105, 15, 46, 23, -105, -105, -+ -105, 39, 39, 39, -15, 39, 44, 16, 34, 64, -+ 892, 892, 892, 843, 892, 892, 892, 892, 892, 892, -+ 67, 892, 892, 892, 110, -105, -105, 86, -105, 667, -+ 87, 108, -105, -105, -105, -105, 109, -105, -105, 111, -+ 47, -105, -105, -105, 843, -105, -105, 892, 892, 892, -+ 148, 148, 148, 1, 73, -17, -14, -10, 148, 148, -+ 148, 148, 148, 892, 1302, 1076, 1028, -105, 843, 892, -+ 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, -+ 892, 892, 892, 892, 892, 892, 39, 892, 892, 892, -+ 892, 892, -105, -105, 941, 892, 892, 892, 892, 892, -+ 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, -+ 892, 892, 0, -105, -105, -105, 113, 249, 75, 300, -+ 667, 98, 351, 892, -105, 892, -17, -17, 84, -17, -+ 892, -105, 402, -105, -105, 769, 718, 769, 191, 1123, -+ 1169, 1214, 1331, 1331, 1358, 1358, 148, 148, 148, -105, -+ 453, 88, -105, -105, 1028, 1076, 932, 932, 1302, -105, -+ -105, -105, 504, 667, 1259, 1259, 1259, 1259, 1331, 1331, -+ 1331, 1331, 1331, 1331, 667, 769, 0, 0, 106, -105, -+ 90, -105, -105, -105, -105, 104, 892, 892, 148, 84, -+ -19, 130, 7, 148, -105, 892, -105, -105, -105, 90, -+ 9, 0, 133, 892, 564, 616, 667, 95, 97, 892, -+ 980, 99, -105, 101, 667, 892, 892, 100, -105, 148, -+ 102, -105, 667, 107, -105, -105, 892, 667 -+}; -+ -+/* YYPGOTO[NTERM-NUM]. */ -+static const yytype_int8 yypgoto[] = -+{ -+ -105, -105, -105, 66, -105, 69, -105, -105, -62, -104, -+ -20, 79, -92, -82, 103, -91, -13, 5 -+}; -+ -+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If -+ positive, shift that token. If negative, reduce the rule which -+ number is the opposite. If zero, do what YYDEFACT says. -+ If YYTABLE_NINF, syntax error. */ -+#define YYTABLE_NINF -1 -+static const yytype_int16 yytable[] = -+{ -+ 60, 61, 62, 161, 2, 68, 69, 70, 71, 72, -+ 65, 74, 75, 76, 162, 133, 51, 52, 53, 136, -+ 55, 201, 139, 44, 217, 137, 133, 54, 66, 140, -+ 47, 48, 49, 50, 127, 141, 186, 129, 130, 132, -+ 191, 65, 187, 2, 134, 199, 200, 201, 202, 212, -+ 219, 56, 221, 142, 45, 125, 46, 126, 57, 145, -+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, -+ 156, 157, 158, 159, 160, 130, 58, 163, 164, 165, -+ 166, 167, 209, 210, 168, 169, 170, 171, 172, 173, -+ 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, -+ 184, 185, 63, 67, 191, 191, 59, 1, 2, 73, -+ 77, 78, 120, 184, 121, 198, 135, 123, 194, 124, -+ 203, 192, 14, 196, 201, 17, 213, 18, 19, 191, -+ 212, 207, 211, 218, 233, 20, 223, 227, 228, 21, -+ 22, 230, 231, 234, 143, 235, 23, 144, 24, 222, -+ 236, 0, 25, 26, 0, 0, 0, 128, 27, 28, -+ 29, 30, 31, 0, 0, 0, 0, 0, 0, 32, -+ 33, 0, 0, 0, 0, 214, 215, 216, 0, 0, -+ 0, 0, 0, 0, 0, 220, 0, 93, 94, 0, -+ 95, 0, 0, 224, 96, 97, 79, 0, 0, 229, -+ 0, 0, 102, 103, 0, 232, 130, 105, 106, 107, -+ 108, 0, 0, 0, 0, 0, 237, 80, 81, 82, -+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -+ 93, 94, 0, 95, 0, 0, 0, 96, 97, 0, -+ 0, 98, 99, 100, 101, 102, 103, 0, 0, 104, -+ 105, 106, 107, 108, 79, 109, 0, 0, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, 0, 0, -+ 0, 205, 0, 0, 0, 80, 81, 82, 83, 84, -+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, -+ 0, 95, 193, 0, 0, 96, 97, 0, 0, 98, -+ 99, 100, 101, 102, 103, 79, 0, 104, 105, 106, -+ 107, 108, 0, 109, 0, 0, 110, 111, 112, 113, -+ 114, 115, 116, 117, 118, 119, 80, 81, 82, 83, -+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, -+ 94, 0, 95, 195, 0, 0, 96, 97, 0, 0, -+ 98, 99, 100, 101, 102, 103, 79, 0, 104, 105, -+ 106, 107, 108, 0, 109, 0, 0, 110, 111, 112, -+ 113, 114, 115, 116, 117, 118, 119, 80, 81, 82, -+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -+ 93, 94, 0, 95, 197, 0, 0, 96, 97, 0, -+ 0, 98, 99, 100, 101, 102, 103, 79, 0, 104, -+ 105, 106, 107, 108, 0, 109, 0, 0, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, 80, 81, -+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, -+ 92, 93, 94, 0, 95, 204, 0, 0, 96, 97, -+ 0, 0, 98, 99, 100, 101, 102, 103, 79, 0, -+ 104, 105, 106, 107, 108, 0, 109, 0, 0, 110, -+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 80, -+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, -+ 91, 92, 93, 94, 206, 95, 0, 0, 0, 96, -+ 97, 0, 0, 98, 99, 100, 101, 102, 103, 79, -+ 0, 104, 105, 106, 107, 108, 0, 109, 0, 0, -+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, -+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -+ 90, 91, 92, 93, 94, 0, 95, 0, 0, 0, -+ 96, 97, 0, 0, 98, 99, 100, 101, 102, 103, -+ 0, 0, 104, 105, 106, 107, 108, 208, 109, 79, -+ 0, 110, 111, 112, 113, 114, 115, 116, 117, 118, -+ 119, 0, 0, 0, 0, 0, 225, 0, 0, 0, -+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -+ 90, 91, 92, 93, 94, 0, 95, 0, 0, 0, -+ 96, 97, 0, 0, 98, 99, 100, 101, 102, 103, -+ 0, 79, 104, 105, 106, 107, 108, 0, 109, 0, -+ 0, 110, 111, 112, 113, 114, 115, 116, 117, 118, -+ 119, 226, 80, 81, 82, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 92, 93, 94, 0, 95, 0, -+ 0, 0, 96, 97, 0, 0, 98, 99, 100, 101, -+ 102, 103, 79, 0, 104, 105, 106, 107, 108, 0, -+ 109, 0, 0, 110, 111, 112, 113, 114, 115, 116, -+ 117, 118, 119, 80, 81, 82, 83, 84, 85, 86, -+ 87, 88, 89, 90, 91, 92, 93, 94, 0, 95, -+ 0, 0, 0, 96, 97, 0, 0, 98, 99, 100, -+ 101, 102, 103, 79, 0, 104, 105, 106, 107, 108, -+ 0, 109, 0, 0, 110, 111, 112, 113, 114, 115, -+ 116, 117, 118, 119, 80, 81, 82, 83, 84, 85, -+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 0, -+ 95, 0, 0, 0, 96, 97, 0, 0, 98, 99, -+ 100, 101, 102, 103, 79, 0, 104, 105, 106, 107, -+ 108, 0, 0, 0, 0, 110, 111, 112, 113, 114, -+ 115, 116, 117, 118, 119, 0, 81, 82, 83, 84, -+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, -+ 0, 95, 0, 0, 0, 96, 97, 0, 0, 98, -+ 99, 100, 101, 102, 103, 0, 0, 104, 105, 106, -+ 107, 108, 0, 0, 0, 0, 110, 111, 112, 113, -+ 114, 115, 116, 117, 118, 119, 1, 2, 0, 0, -+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -+ 13, 14, 15, 16, 17, 0, 18, 19, 0, 0, -+ 0, 0, 0, 0, 20, 0, 0, 0, 21, 22, -+ 0, 0, 0, 0, 0, 23, 0, 24, 0, 0, -+ 0, 25, 26, 0, 0, 1, 2, 27, 28, 29, -+ 30, 31, 0, 0, 0, 0, 0, 0, 32, 33, -+ 14, 0, 0, 17, 0, 18, 19, 0, 0, 0, -+ 0, 0, 0, 20, 0, 0, 0, 21, 22, 0, -+ 0, 0, 0, 0, 23, 0, 24, 0, 0, 0, -+ 25, 26, 0, 0, 1, 2, 27, 28, 29, 30, -+ 31, 0, 0, 0, 0, 0, 0, 32, 33, 14, -+ 0, 0, 17, 0, 18, 19, 88, 89, 90, 91, -+ 92, 93, 94, 0, 95, 0, 21, 22, 96, 97, -+ 0, 0, 0, 23, 0, 24, 102, 103, 0, 25, -+ 26, 105, 106, 107, 108, 27, 28, 29, 30, -1, -+ 0, 0, 0, 0, 0, 0, 32, 33, 82, 83, -+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, -+ 94, 0, 95, 0, 0, 0, 96, 97, 0, 0, -+ 98, 99, 100, 101, 102, 103, 0, 0, 104, 105, -+ 106, 107, 108, 0, 0, 0, 0, 110, 111, 112, -+ 113, 114, 115, 116, 117, 118, 119, 83, 84, 85, -+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 0, -+ 95, 0, 0, 0, 96, 97, 0, 0, 0, 99, -+ 100, 101, 102, 103, 0, 0, 104, 105, 106, 107, -+ 108, 0, 0, 0, 0, 110, 111, 112, 113, 114, -+ 115, 116, 117, 118, 119, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 92, 93, 94, 0, 95, 0, -+ 0, 0, 96, 97, 0, 0, 0, 0, 100, 101, -+ 102, 103, 0, 0, 104, 105, 106, 107, 108, 0, -+ 0, 0, 0, 110, 111, 112, 113, 114, 115, 116, -+ 117, 118, 119, 84, 85, 86, 87, 88, 89, 90, -+ 91, 92, 93, 94, 0, 95, 0, 0, 0, 96, -+ 97, 0, 0, 0, 0, 100, 101, 102, 103, 0, -+ 0, 104, 105, 106, 107, 108, 0, 0, 0, 0, -+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, -+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, -+ 0, 95, 0, 0, 0, 96, 97, 0, 0, 0, -+ 0, 100, 101, 102, 103, 0, 0, 104, 105, 106, -+ 107, 108, 0, 0, 0, 0, 110, 111, 112, 113, -+ 114, 115, 116, 117, 118, 119, 86, 87, 88, 89, -+ 90, 91, 92, 93, 94, 0, 95, 0, 0, 0, -+ 96, 97, 0, 0, 0, 0, 100, 101, 102, 103, -+ 0, 0, 104, 105, 106, 107, 108, 0, 0, 0, -+ 0, 110, 111, 112, 113, 114, 115, 116, 117, 118, -+ 119, 86, 87, 88, 89, 90, 91, 92, 93, 94, -+ 0, 95, 0, 0, 0, 96, 97, 0, 0, 0, -+ 0, 100, 101, 102, 103, 0, 0, 104, 105, 106, -+ 107, 108, 0, 0, 0, 0, 0, 0, 0, 0, -+ 114, 115, 116, 117, 118, 119, 88, 89, 90, 91, -+ 92, 93, 94, 0, 95, 0, 0, 0, 96, 97, -+ 0, 0, 0, 0, 100, 101, 102, 103, 0, 0, -+ -1, 105, 106, 107, 108, 88, 89, 90, 91, 92, -+ 93, 94, 0, 95, 0, 0, 0, 96, 97, 0, -+ 0, 0, 0, 100, 101, 102, 103, 0, 0, 104, -+ 105, 106, 107, 108, 90, 91, 92, 93, 94, 0, -+ 95, 0, 0, 0, 96, 97, 0, 0, 0, 0, -+ 0, 0, 102, 103, 0, 0, 0, 105, 106, 107, -+ 108 -+}; -+ -+static const yytype_int16 yycheck[] = -+{ -+ 20, 21, 22, 95, 4, 25, 26, 27, 28, 29, -+ 23, 31, 32, 33, 96, 25, 11, 12, 13, 36, -+ 15, 40, 36, 8, 43, 42, 25, 42, 23, 43, -+ 7, 8, 9, 10, 54, 45, 36, 57, 58, 59, -+ 122, 54, 42, 4, 43, 136, 137, 40, 139, 40, -+ 43, 7, 43, 73, 8, 8, 10, 10, 42, 79, -+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -+ 90, 91, 92, 93, 94, 95, 42, 97, 98, 99, -+ 100, 101, 186, 187, 104, 105, 106, 107, 108, 109, -+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, -+ 120, 121, 23, 24, 186, 187, 42, 3, 4, 42, -+ 0, 25, 25, 133, 6, 135, 43, 8, 43, 8, -+ 140, 8, 18, 25, 40, 21, 22, 23, 24, 211, -+ 40, 43, 26, 3, 226, 31, 3, 42, 41, 35, -+ 36, 42, 41, 43, 78, 43, 42, 78, 44, 211, -+ 43, -1, 48, 49, -1, -1, -1, 54, 54, 55, -+ 56, 57, 58, -1, -1, -1, -1, -1, -1, 65, -+ 66, -1, -1, -1, -1, 195, 196, 197, -1, -1, -+ -1, -1, -1, -1, -1, 205, -1, 39, 40, -1, -+ 42, -1, -1, 213, 46, 47, 5, -1, -1, 219, -+ -1, -1, 54, 55, -1, 225, 226, 59, 60, 61, -+ 62, -1, -1, -1, -1, -1, 236, 26, 27, 28, -+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -+ 39, 40, -1, 42, -1, -1, -1, 46, 47, -1, -+ -1, 50, 51, 52, 53, 54, 55, -1, -1, 58, -+ 59, 60, 61, 62, 5, 64, -1, -1, 67, 68, -+ 69, 70, 71, 72, 73, 74, 75, 76, -1, -1, -+ -1, 80, -1, -1, -1, 26, 27, 28, 29, 30, -+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -+ -1, 42, 43, -1, -1, 46, 47, -1, -1, 50, -+ 51, 52, 53, 54, 55, 5, -1, 58, 59, 60, -+ 61, 62, -1, 64, -1, -1, 67, 68, 69, 70, -+ 71, 72, 73, 74, 75, 76, 26, 27, 28, 29, -+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, -1, 42, 43, -1, -1, 46, 47, -1, -1, -+ 50, 51, 52, 53, 54, 55, 5, -1, 58, 59, -+ 60, 61, 62, -1, 64, -1, -1, 67, 68, 69, -+ 70, 71, 72, 73, 74, 75, 76, 26, 27, 28, -+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -+ 39, 40, -1, 42, 43, -1, -1, 46, 47, -1, -+ -1, 50, 51, 52, 53, 54, 55, 5, -1, 58, -+ 59, 60, 61, 62, -1, 64, -1, -1, 67, 68, -+ 69, 70, 71, 72, 73, 74, 75, 76, 26, 27, -+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, -+ 38, 39, 40, -1, 42, 43, -1, -1, 46, 47, -+ -1, -1, 50, 51, 52, 53, 54, 55, 5, -1, -+ 58, 59, 60, 61, 62, -1, 64, -1, -1, 67, -+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 26, -+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -+ 37, 38, 39, 40, 41, 42, -1, -1, -1, 46, -+ 47, -1, -1, 50, 51, 52, 53, 54, 55, 5, -+ -1, 58, 59, 60, 61, 62, -1, 64, -1, -1, -+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, -+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -+ 36, 37, 38, 39, 40, -1, 42, -1, -1, -1, -+ 46, 47, -1, -1, 50, 51, 52, 53, 54, 55, -+ -1, -1, 58, 59, 60, 61, 62, 63, 64, 5, -+ -1, 67, 68, 69, 70, 71, 72, 73, 74, 75, -+ 76, -1, -1, -1, -1, -1, 22, -1, -1, -1, -+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -+ 36, 37, 38, 39, 40, -1, 42, -1, -1, -1, -+ 46, 47, -1, -1, 50, 51, 52, 53, 54, 55, -+ -1, 5, 58, 59, 60, 61, 62, -1, 64, -1, -+ -1, 67, 68, 69, 70, 71, 72, 73, 74, 75, -+ 76, 25, 26, 27, 28, 29, 30, 31, 32, 33, -+ 34, 35, 36, 37, 38, 39, 40, -1, 42, -1, -+ -1, -1, 46, 47, -1, -1, 50, 51, 52, 53, -+ 54, 55, 5, -1, 58, 59, 60, 61, 62, -1, -+ 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, -+ 74, 75, 76, 26, 27, 28, 29, 30, 31, 32, -+ 33, 34, 35, 36, 37, 38, 39, 40, -1, 42, -+ -1, -1, -1, 46, 47, -1, -1, 50, 51, 52, -+ 53, 54, 55, 5, -1, 58, 59, 60, 61, 62, -+ -1, 64, -1, -1, 67, 68, 69, 70, 71, 72, -+ 73, 74, 75, 76, 26, 27, 28, 29, 30, 31, -+ 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -+ 42, -1, -1, -1, 46, 47, -1, -1, 50, 51, -+ 52, 53, 54, 55, 5, -1, 58, 59, 60, 61, -+ 62, -1, -1, -1, -1, 67, 68, 69, 70, 71, -+ 72, 73, 74, 75, 76, -1, 27, 28, 29, 30, -+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -+ -1, 42, -1, -1, -1, 46, 47, -1, -1, 50, -+ 51, 52, 53, 54, 55, -1, -1, 58, 59, 60, -+ 61, 62, -1, -1, -1, -1, 67, 68, 69, 70, -+ 71, 72, 73, 74, 75, 76, 3, 4, -1, -1, -+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -+ 17, 18, 19, 20, 21, -1, 23, 24, -1, -1, -+ -1, -1, -1, -1, 31, -1, -1, -1, 35, 36, -+ -1, -1, -1, -1, -1, 42, -1, 44, -1, -1, -+ -1, 48, 49, -1, -1, 3, 4, 54, 55, 56, -+ 57, 58, -1, -1, -1, -1, -1, -1, 65, 66, -+ 18, -1, -1, 21, -1, 23, 24, -1, -1, -1, -+ -1, -1, -1, 31, -1, -1, -1, 35, 36, -1, -+ -1, -1, -1, -1, 42, -1, 44, -1, -1, -1, -+ 48, 49, -1, -1, 3, 4, 54, 55, 56, 57, -+ 58, -1, -1, -1, -1, -1, -1, 65, 66, 18, -+ -1, -1, 21, -1, 23, 24, 34, 35, 36, 37, -+ 38, 39, 40, -1, 42, -1, 35, 36, 46, 47, -+ -1, -1, -1, 42, -1, 44, 54, 55, -1, 48, -+ 49, 59, 60, 61, 62, 54, 55, 56, 57, 58, -+ -1, -1, -1, -1, -1, -1, 65, 66, 28, 29, -+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, -1, 42, -1, -1, -1, 46, 47, -1, -1, -+ 50, 51, 52, 53, 54, 55, -1, -1, 58, 59, -+ 60, 61, 62, -1, -1, -1, -1, 67, 68, 69, -+ 70, 71, 72, 73, 74, 75, 76, 29, 30, 31, -+ 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, -+ 42, -1, -1, -1, 46, 47, -1, -1, -1, 51, -+ 52, 53, 54, 55, -1, -1, 58, 59, 60, 61, -+ 62, -1, -1, -1, -1, 67, 68, 69, 70, 71, -+ 72, 73, 74, 75, 76, 29, 30, 31, 32, 33, -+ 34, 35, 36, 37, 38, 39, 40, -1, 42, -1, -+ -1, -1, 46, 47, -1, -1, -1, -1, 52, 53, -+ 54, 55, -1, -1, 58, 59, 60, 61, 62, -1, -+ -1, -1, -1, 67, 68, 69, 70, 71, 72, 73, -+ 74, 75, 76, 30, 31, 32, 33, 34, 35, 36, -+ 37, 38, 39, 40, -1, 42, -1, -1, -1, 46, -+ 47, -1, -1, -1, -1, 52, 53, 54, 55, -1, -+ -1, 58, 59, 60, 61, 62, -1, -1, -1, -1, -+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, -+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -+ -1, 42, -1, -1, -1, 46, 47, -1, -1, -1, -+ -1, 52, 53, 54, 55, -1, -1, 58, 59, 60, -+ 61, 62, -1, -1, -1, -1, 67, 68, 69, 70, -+ 71, 72, 73, 74, 75, 76, 32, 33, 34, 35, -+ 36, 37, 38, 39, 40, -1, 42, -1, -1, -1, -+ 46, 47, -1, -1, -1, -1, 52, 53, 54, 55, -+ -1, -1, 58, 59, 60, 61, 62, -1, -1, -1, -+ -1, 67, 68, 69, 70, 71, 72, 73, 74, 75, -+ 76, 32, 33, 34, 35, 36, 37, 38, 39, 40, -+ -1, 42, -1, -1, -1, 46, 47, -1, -1, -1, -+ -1, 52, 53, 54, 55, -1, -1, 58, 59, 60, -+ 61, 62, -1, -1, -1, -1, -1, -1, -1, -1, -+ 71, 72, 73, 74, 75, 76, 34, 35, 36, 37, -+ 38, 39, 40, -1, 42, -1, -1, -1, 46, 47, -+ -1, -1, -1, -1, 52, 53, 54, 55, -1, -1, -+ 58, 59, 60, 61, 62, 34, 35, 36, 37, 38, -+ 39, 40, -1, 42, -1, -1, -1, 46, 47, -1, -+ -1, -1, -1, 52, 53, 54, 55, -1, -1, 58, -+ 59, 60, 61, 62, 36, 37, 38, 39, 40, -1, -+ 42, -1, -1, -1, 46, 47, -1, -1, -1, -1, -+ -1, -1, 54, 55, -1, -1, -1, 59, 60, 61, -+ 62 -+}; -+ -+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing -+ symbol of state STATE-NUM. */ -+static const yytype_uint8 yystos[] = -+{ -+ 0, 3, 4, 7, 8, 9, 10, 11, 12, 13, -+ 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, -+ 31, 35, 36, 42, 44, 48, 49, 54, 55, 56, -+ 57, 58, 65, 66, 82, 83, 84, 85, 86, 91, -+ 92, 94, 97, 98, 8, 8, 10, 7, 8, 9, -+ 10, 98, 98, 98, 42, 98, 7, 42, 42, 42, -+ 91, 91, 91, 92, 95, 97, 98, 92, 91, 91, -+ 91, 91, 91, 42, 91, 91, 91, 0, 25, 5, -+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -+ 36, 37, 38, 39, 40, 42, 46, 47, 50, 51, -+ 52, 53, 54, 55, 58, 59, 60, 61, 62, 64, -+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, -+ 25, 6, 87, 8, 8, 8, 10, 91, 95, 91, -+ 91, 93, 91, 25, 43, 43, 36, 42, 96, 36, -+ 43, 45, 91, 84, 86, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 93, 94, 91, 91, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, -+ 91, 91, 91, 91, 91, 91, 36, 42, 88, 89, -+ 90, 94, 8, 43, 43, 43, 25, 43, 91, 96, -+ 96, 40, 96, 91, 43, 80, 41, 43, 63, 90, -+ 90, 26, 40, 22, 91, 91, 91, 43, 3, 43, -+ 91, 43, 89, 3, 91, 22, 25, 42, 41, 91, -+ 42, 41, 91, 93, 43, 43, 43, 91 -+}; -+ -+#define yyerrok (yyerrstatus = 0) -+#define yyclearin (yychar = YYEMPTY) -+#define YYEMPTY (-2) -+#define YYEOF 0 -+ -+#define YYACCEPT goto yyacceptlab -+#define YYABORT goto yyabortlab -+#define YYERROR goto yyerrorlab -+ -+ -+/* Like YYERROR except do call yyerror. This remains here temporarily -+ to ease the transition to the new meaning of YYERROR, for GCC. -+ Once GCC version 2 has supplanted version 1, this can go. */ -+ -+#define YYFAIL goto yyerrlab -+ -+#define YYRECOVERING() (!!yyerrstatus) -+ -+#define YYBACKUP(Token, Value) \ -+do \ -+ if (yychar == YYEMPTY && yylen == 1) \ -+ { \ -+ yychar = (Token); \ -+ yylval = (Value); \ -+ yytoken = YYTRANSLATE (yychar); \ -+ YYPOPSTACK (1); \ -+ goto yybackup; \ -+ } \ -+ else \ -+ { \ -+ yyerror (YY_("syntax error: cannot back up")); \ -+ YYERROR; \ -+ } \ -+while (YYID (0)) -+ -+ -+#define YYTERROR 1 -+#define YYERRCODE 256 -+ -+ -+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. -+ If N is 0, then set CURRENT to the empty location which ends -+ the previous symbol: RHS[0] (always defined). */ -+ -+#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -+#ifndef YYLLOC_DEFAULT -+# define YYLLOC_DEFAULT(Current, Rhs, N) \ -+ do \ -+ if (YYID (N)) \ -+ { \ -+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ -+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ -+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ -+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ -+ } \ -+ else \ -+ { \ -+ (Current).first_line = (Current).last_line = \ -+ YYRHSLOC (Rhs, 0).last_line; \ -+ (Current).first_column = (Current).last_column = \ -+ YYRHSLOC (Rhs, 0).last_column; \ -+ } \ -+ while (YYID (0)) -+#endif -+ -+ -+/* YY_LOCATION_PRINT -- Print the location on the stream. -+ This macro was not mandated originally: define only if we know -+ we won't break user code: when these are the locations we know. */ -+ -+#ifndef YY_LOCATION_PRINT -+# if YYLTYPE_IS_TRIVIAL -+# define YY_LOCATION_PRINT(File, Loc) \ -+ fprintf (File, "%d.%d-%d.%d", \ -+ (Loc).first_line, (Loc).first_column, \ -+ (Loc).last_line, (Loc).last_column) -+# else -+# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -+# endif -+#endif -+ -+ -+/* YYLEX -- calling `yylex' with the right arguments. */ -+ -+#ifdef YYLEX_PARAM -+# define YYLEX yylex (YYLEX_PARAM) -+#else -+# define YYLEX yylex () -+#endif -+ -+/* Enable debugging if requested. */ -+#if YYDEBUG -+ -+# ifndef YYFPRINTF -+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ -+# define YYFPRINTF fprintf -+# endif -+ -+# define YYDPRINTF(Args) \ -+do { \ -+ if (yydebug) \ -+ YYFPRINTF Args; \ -+} while (YYID (0)) -+ -+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -+do { \ -+ if (yydebug) \ -+ { \ -+ YYFPRINTF (stderr, "%s ", Title); \ -+ yy_symbol_print (stderr, \ -+ Type, Value); \ -+ YYFPRINTF (stderr, "\n"); \ -+ } \ -+} while (YYID (0)) -+ -+ -+/*--------------------------------. -+| Print this symbol on YYOUTPUT. | -+`--------------------------------*/ -+ -+/*ARGSUSED*/ -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+static void -+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -+#else -+static void -+yy_symbol_value_print (yyoutput, yytype, yyvaluep) -+ FILE *yyoutput; -+ int yytype; -+ YYSTYPE const * const yyvaluep; -+#endif -+{ -+ if (!yyvaluep) -+ return; -+# ifdef YYPRINT -+ if (yytype < YYNTOKENS) -+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -+# else -+ YYUSE (yyoutput); -+# endif -+ switch (yytype) -+ { -+ default: -+ break; -+ } -+} -+ -+ -+/*--------------------------------. -+| Print this symbol on YYOUTPUT. | -+`--------------------------------*/ -+ -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+static void -+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -+#else -+static void -+yy_symbol_print (yyoutput, yytype, yyvaluep) -+ FILE *yyoutput; -+ int yytype; -+ YYSTYPE const * const yyvaluep; -+#endif -+{ -+ if (yytype < YYNTOKENS) -+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); -+ else -+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); -+ -+ yy_symbol_value_print (yyoutput, yytype, yyvaluep); -+ YYFPRINTF (yyoutput, ")"); -+} -+ -+/*------------------------------------------------------------------. -+| yy_stack_print -- Print the state stack from its BOTTOM up to its | -+| TOP (included). | -+`------------------------------------------------------------------*/ -+ -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+static void -+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) -+#else -+static void -+yy_stack_print (bottom, top) -+ yytype_int16 *bottom; -+ yytype_int16 *top; -+#endif -+{ -+ YYFPRINTF (stderr, "Stack now"); -+ for (; bottom <= top; ++bottom) -+ YYFPRINTF (stderr, " %d", *bottom); -+ YYFPRINTF (stderr, "\n"); -+} -+ -+# define YY_STACK_PRINT(Bottom, Top) \ -+do { \ -+ if (yydebug) \ -+ yy_stack_print ((Bottom), (Top)); \ -+} while (YYID (0)) -+ -+ -+/*------------------------------------------------. -+| Report that the YYRULE is going to be reduced. | -+`------------------------------------------------*/ -+ -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+static void -+yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -+#else -+static void -+yy_reduce_print (yyvsp, yyrule) -+ YYSTYPE *yyvsp; -+ int yyrule; -+#endif -+{ -+ int yynrhs = yyr2[yyrule]; -+ int yyi; -+ unsigned long int yylno = yyrline[yyrule]; -+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", -+ yyrule - 1, yylno); -+ /* The symbols being reduced. */ -+ for (yyi = 0; yyi < yynrhs; yyi++) -+ { -+ fprintf (stderr, " $%d = ", yyi + 1); -+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], -+ &(yyvsp[(yyi + 1) - (yynrhs)]) -+ ); -+ fprintf (stderr, "\n"); -+ } -+} -+ -+# define YY_REDUCE_PRINT(Rule) \ -+do { \ -+ if (yydebug) \ -+ yy_reduce_print (yyvsp, Rule); \ -+} while (YYID (0)) -+ -+/* Nonzero means print parse trace. It is left uninitialized so that -+ multiple parsers can coexist. */ -+int yydebug; -+#else /* !YYDEBUG */ -+# define YYDPRINTF(Args) -+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -+# define YY_STACK_PRINT(Bottom, Top) -+# define YY_REDUCE_PRINT(Rule) -+#endif /* !YYDEBUG */ -+ -+ -+/* YYINITDEPTH -- initial size of the parser's stacks. */ -+#ifndef YYINITDEPTH -+# define YYINITDEPTH 200 -+#endif -+ -+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only -+ if the built-in stack extension method is used). -+ -+ Do not make this value too large; the results are undefined if -+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) -+ evaluated with infinite-precision integer arithmetic. */ -+ -+#ifndef YYMAXDEPTH -+# define YYMAXDEPTH 10000 -+#endif -+ -+ -+ -+#if YYERROR_VERBOSE -+ -+# ifndef yystrlen -+# if defined __GLIBC__ && defined _STRING_H -+# define yystrlen strlen -+# else -+/* Return the length of YYSTR. */ -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+static YYSIZE_T -+yystrlen (const char *yystr) -+#else -+static YYSIZE_T -+yystrlen (yystr) -+ const char *yystr; -+#endif -+{ -+ YYSIZE_T yylen; -+ for (yylen = 0; yystr[yylen]; yylen++) -+ continue; -+ return yylen; -+} -+# endif -+# endif -+ -+# ifndef yystpcpy -+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -+# define yystpcpy stpcpy -+# else -+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in -+ YYDEST. */ -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+static char * -+yystpcpy (char *yydest, const char *yysrc) -+#else -+static char * -+yystpcpy (yydest, yysrc) -+ char *yydest; -+ const char *yysrc; -+#endif -+{ -+ char *yyd = yydest; -+ const char *yys = yysrc; -+ -+ while ((*yyd++ = *yys++) != '\0') -+ continue; -+ -+ return yyd - 1; -+} -+# endif -+# endif -+ -+# ifndef yytnamerr -+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary -+ quotes and backslashes, so that it's suitable for yyerror. The -+ heuristic is that double-quoting is unnecessary unless the string -+ contains an apostrophe, a comma, or backslash (other than -+ backslash-backslash). YYSTR is taken from yytname. If YYRES is -+ null, do not copy; instead, return the length of what the result -+ would have been. */ -+static YYSIZE_T -+yytnamerr (char *yyres, const char *yystr) -+{ -+ if (*yystr == '"') -+ { -+ YYSIZE_T yyn = 0; -+ char const *yyp = yystr; -+ -+ for (;;) -+ switch (*++yyp) -+ { -+ case '\'': -+ case ',': -+ goto do_not_strip_quotes; -+ -+ case '\\': -+ if (*++yyp != '\\') -+ goto do_not_strip_quotes; -+ /* Fall through. */ -+ default: -+ if (yyres) -+ yyres[yyn] = *yyp; -+ yyn++; -+ break; -+ -+ case '"': -+ if (yyres) -+ yyres[yyn] = '\0'; -+ return yyn; -+ } -+ do_not_strip_quotes: ; -+ } -+ -+ if (! yyres) -+ return yystrlen (yystr); -+ -+ return yystpcpy (yyres, yystr) - yyres; -+} -+# endif -+ -+/* Copy into YYRESULT an error message about the unexpected token -+ YYCHAR while in state YYSTATE. Return the number of bytes copied, -+ including the terminating null byte. If YYRESULT is null, do not -+ copy anything; just return the number of bytes that would be -+ copied. As a special case, return 0 if an ordinary "syntax error" -+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during -+ size calculation. */ -+static YYSIZE_T -+yysyntax_error (char *yyresult, int yystate, int yychar) -+{ -+ int yyn = yypact[yystate]; -+ -+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) -+ return 0; -+ else -+ { -+ int yytype = YYTRANSLATE (yychar); -+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); -+ YYSIZE_T yysize = yysize0; -+ YYSIZE_T yysize1; -+ int yysize_overflow = 0; -+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; -+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; -+ int yyx; -+ -+# if 0 -+ /* This is so xgettext sees the translatable formats that are -+ constructed on the fly. */ -+ YY_("syntax error, unexpected %s"); -+ YY_("syntax error, unexpected %s, expecting %s"); -+ YY_("syntax error, unexpected %s, expecting %s or %s"); -+ YY_("syntax error, unexpected %s, expecting %s or %s or %s"); -+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -+# endif -+ char *yyfmt; -+ char const *yyf; -+ static char const yyunexpected[] = "syntax error, unexpected %s"; -+ static char const yyexpecting[] = ", expecting %s"; -+ static char const yyor[] = " or %s"; -+ char yyformat[sizeof yyunexpected -+ + sizeof yyexpecting - 1 -+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) -+ * (sizeof yyor - 1))]; -+ char const *yyprefix = yyexpecting; -+ -+ /* Start YYX at -YYN if negative to avoid negative indexes in -+ YYCHECK. */ -+ int yyxbegin = yyn < 0 ? -yyn : 0; -+ -+ /* Stay within bounds of both yycheck and yytname. */ -+ int yychecklim = YYLAST - yyn + 1; -+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; -+ int yycount = 1; -+ -+ yyarg[0] = yytname[yytype]; -+ yyfmt = yystpcpy (yyformat, yyunexpected); -+ -+ for (yyx = yyxbegin; yyx < yyxend; ++yyx) -+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) -+ { -+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) -+ { -+ yycount = 1; -+ yysize = yysize0; -+ yyformat[sizeof yyunexpected - 1] = '\0'; -+ break; -+ } -+ yyarg[yycount++] = yytname[yyx]; -+ yysize1 = yysize + yytnamerr (0, yytname[yyx]); -+ yysize_overflow |= (yysize1 < yysize); -+ yysize = yysize1; -+ yyfmt = yystpcpy (yyfmt, yyprefix); -+ yyprefix = yyor; -+ } -+ -+ yyf = YY_(yyformat); -+ yysize1 = yysize + yystrlen (yyf); -+ yysize_overflow |= (yysize1 < yysize); -+ yysize = yysize1; -+ -+ if (yysize_overflow) -+ return YYSIZE_MAXIMUM; -+ -+ if (yyresult) -+ { -+ /* Avoid sprintf, as that infringes on the user's name space. -+ Don't have undefined behavior even if the translation -+ produced a string with the wrong number of "%s"s. */ -+ char *yyp = yyresult; -+ int yyi = 0; -+ while ((*yyp = *yyf) != '\0') -+ { -+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) -+ { -+ yyp += yytnamerr (yyp, yyarg[yyi++]); -+ yyf += 2; -+ } -+ else -+ { -+ yyp++; -+ yyf++; -+ } -+ } -+ } -+ return yysize; -+ } -+} -+#endif /* YYERROR_VERBOSE */ -+ -+ -+/*-----------------------------------------------. -+| Release the memory associated to this symbol. | -+`-----------------------------------------------*/ -+ -+/*ARGSUSED*/ -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+static void -+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -+#else -+static void -+yydestruct (yymsg, yytype, yyvaluep) -+ const char *yymsg; -+ int yytype; -+ YYSTYPE *yyvaluep; -+#endif -+{ -+ YYUSE (yyvaluep); -+ -+ if (!yymsg) -+ yymsg = "Deleting"; -+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); -+ -+ switch (yytype) -+ { -+ -+ default: -+ break; -+ } -+} -+ -+ -+/* Prevent warnings from -Wmissing-prototypes. */ -+ -+#ifdef YYPARSE_PARAM -+#if defined __STDC__ || defined __cplusplus -+int yyparse (void *YYPARSE_PARAM); -+#else -+int yyparse (); -+#endif -+#else /* ! YYPARSE_PARAM */ -+#if defined __STDC__ || defined __cplusplus -+int yyparse (void); -+#else -+int yyparse (); -+#endif -+#endif /* ! YYPARSE_PARAM */ -+ -+ -+ -+/* The look-ahead symbol. */ -+int yychar; -+ -+/* The semantic value of the look-ahead symbol. */ -+YYSTYPE yylval; -+ -+/* Number of syntax errors so far. */ -+int yynerrs; -+ -+ -+ -+/*----------. -+| yyparse. | -+`----------*/ -+ -+#ifdef YYPARSE_PARAM -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+int -+yyparse (void *YYPARSE_PARAM) -+#else -+int -+yyparse (YYPARSE_PARAM) -+ void *YYPARSE_PARAM; -+#endif -+#else /* ! YYPARSE_PARAM */ -+#if (defined __STDC__ || defined __C99__FUNC__ \ -+ || defined __cplusplus || defined _MSC_VER) -+int -+yyparse (void) -+#else -+int -+yyparse () -+ -+#endif -+#endif -+{ -+ -+ int yystate; -+ int yyn; -+ int yyresult; -+ /* Number of tokens to shift before error messages enabled. */ -+ int yyerrstatus; -+ /* Look-ahead token as an internal (translated) token number. */ -+ int yytoken = 0; -+#if YYERROR_VERBOSE -+ /* Buffer for error messages, and its allocated size. */ -+ char yymsgbuf[128]; -+ char *yymsg = yymsgbuf; -+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -+#endif -+ -+ /* Three stacks and their tools: -+ `yyss': related to states, -+ `yyvs': related to semantic values, -+ `yyls': related to locations. -+ -+ Refer to the stacks thru separate pointers, to allow yyoverflow -+ to reallocate them elsewhere. */ -+ -+ /* The state stack. */ -+ yytype_int16 yyssa[YYINITDEPTH]; -+ yytype_int16 *yyss = yyssa; -+ yytype_int16 *yyssp; -+ -+ /* The semantic value stack. */ -+ YYSTYPE yyvsa[YYINITDEPTH]; -+ YYSTYPE *yyvs = yyvsa; -+ YYSTYPE *yyvsp; -+ -+ -+ -+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) -+ -+ YYSIZE_T yystacksize = YYINITDEPTH; -+ -+ /* The variables used to return semantic value and location from the -+ action routines. */ -+ YYSTYPE yyval; -+ -+ -+ /* The number of symbols on the RHS of the reduced rule. -+ Keep to zero when no symbol should be popped. */ -+ int yylen = 0; -+ -+ YYDPRINTF ((stderr, "Starting parse\n")); -+ -+ yystate = 0; -+ yyerrstatus = 0; -+ yynerrs = 0; -+ yychar = YYEMPTY; /* Cause a token to be read. */ -+ -+ /* Initialize stack pointers. -+ Waste one element of value and location stack -+ so that they stay on the same level as the state stack. -+ The wasted elements are never initialized. */ -+ -+ yyssp = yyss; -+ yyvsp = yyvs; -+ -+ goto yysetstate; -+ -+/*------------------------------------------------------------. -+| yynewstate -- Push a new state, which is found in yystate. | -+`------------------------------------------------------------*/ -+ yynewstate: -+ /* In all cases, when you get here, the value and location stacks -+ have just been pushed. So pushing a state here evens the stacks. */ -+ yyssp++; -+ -+ yysetstate: -+ *yyssp = yystate; -+ -+ if (yyss + yystacksize - 1 <= yyssp) -+ { -+ /* Get the current used size of the three stacks, in elements. */ -+ YYSIZE_T yysize = yyssp - yyss + 1; -+ -+#ifdef yyoverflow -+ { -+ /* Give user a chance to reallocate the stack. Use copies of -+ these so that the &'s don't force the real ones into -+ memory. */ -+ YYSTYPE *yyvs1 = yyvs; -+ yytype_int16 *yyss1 = yyss; -+ -+ -+ /* Each stack pointer address is followed by the size of the -+ data in use in that stack, in bytes. This used to be a -+ conditional around just the two extra args, but that might -+ be undefined if yyoverflow is a macro. */ -+ yyoverflow (YY_("memory exhausted"), -+ &yyss1, yysize * sizeof (*yyssp), -+ &yyvs1, yysize * sizeof (*yyvsp), -+ -+ &yystacksize); -+ -+ yyss = yyss1; -+ yyvs = yyvs1; -+ } -+#else /* no yyoverflow */ -+# ifndef YYSTACK_RELOCATE -+ goto yyexhaustedlab; -+# else -+ /* Extend the stack our own way. */ -+ if (YYMAXDEPTH <= yystacksize) -+ goto yyexhaustedlab; -+ yystacksize *= 2; -+ if (YYMAXDEPTH < yystacksize) -+ yystacksize = YYMAXDEPTH; -+ -+ { -+ yytype_int16 *yyss1 = yyss; -+ union yyalloc *yyptr = -+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); -+ if (! yyptr) -+ goto yyexhaustedlab; -+ YYSTACK_RELOCATE (yyss); -+ YYSTACK_RELOCATE (yyvs); -+ -+# undef YYSTACK_RELOCATE -+ if (yyss1 != yyssa) -+ YYSTACK_FREE (yyss1); -+ } -+# endif -+#endif /* no yyoverflow */ -+ -+ yyssp = yyss + yysize - 1; -+ yyvsp = yyvs + yysize - 1; -+ -+ -+ YYDPRINTF ((stderr, "Stack size increased to %lu\n", -+ (unsigned long int) yystacksize)); -+ -+ if (yyss + yystacksize - 1 <= yyssp) -+ YYABORT; -+ } -+ -+ YYDPRINTF ((stderr, "Entering state %d\n", yystate)); -+ -+ goto yybackup; -+ -+/*-----------. -+| yybackup. | -+`-----------*/ -+yybackup: -+ -+ /* Do appropriate processing given the current state. Read a -+ look-ahead token if we need one and don't already have one. */ -+ -+ /* First try to decide what to do without reference to look-ahead token. */ -+ yyn = yypact[yystate]; -+ if (yyn == YYPACT_NINF) -+ goto yydefault; -+ -+ /* Not known => get a look-ahead token if don't already have one. */ -+ -+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ -+ if (yychar == YYEMPTY) -+ { -+ YYDPRINTF ((stderr, "Reading a token: ")); -+ yychar = YYLEX; -+ } -+ -+ if (yychar <= YYEOF) -+ { -+ yychar = yytoken = YYEOF; -+ YYDPRINTF ((stderr, "Now at end of input.\n")); -+ } -+ else -+ { -+ yytoken = YYTRANSLATE (yychar); -+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); -+ } -+ -+ /* If the proper action on seeing token YYTOKEN is to reduce or to -+ detect an error, take that action. */ -+ yyn += yytoken; -+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) -+ goto yydefault; -+ yyn = yytable[yyn]; -+ if (yyn <= 0) -+ { -+ if (yyn == 0 || yyn == YYTABLE_NINF) -+ goto yyerrlab; -+ yyn = -yyn; -+ goto yyreduce; -+ } -+ -+ if (yyn == YYFINAL) -+ YYACCEPT; -+ -+ /* Count tokens shifted since error; after three, turn off error -+ status. */ -+ if (yyerrstatus) -+ yyerrstatus--; -+ -+ /* Shift the look-ahead token. */ -+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); -+ -+ /* Discard the shifted token unless it is eof. */ -+ if (yychar != YYEOF) -+ yychar = YYEMPTY; -+ -+ yystate = yyn; -+ *++yyvsp = yylval; -+ -+ goto yynewstate; -+ -+ -+/*-----------------------------------------------------------. -+| yydefault -- do the default action for the current state. | -+`-----------------------------------------------------------*/ -+yydefault: -+ yyn = yydefact[yystate]; -+ if (yyn == 0) -+ goto yyerrlab; -+ goto yyreduce; -+ -+ -+/*-----------------------------. -+| yyreduce -- Do a reduction. | -+`-----------------------------*/ -+yyreduce: -+ /* yyn is the number of a rule to reduce with. */ -+ yylen = yyr2[yyn]; -+ -+ /* If YYLEN is nonzero, implement the default value of the action: -+ `$$ = $1'. -+ -+ Otherwise, the following line sets YYVAL to garbage. -+ This behavior is undocumented and Bison -+ users should not rely upon it. Assigning to YYVAL -+ unconditionally makes the parser a bit smaller, and it avoids a -+ GCC warning that YYVAL may be used uninitialized. */ -+ yyval = yyvsp[1-yylen]; -+ -+ -+ YY_REDUCE_PRINT (yyn); -+ switch (yyn) -+ { -+ case 2: -+#line 211 "parse.y" -+ { root=(yyvsp[(1) - (1)].node) ; ;} -+ break; -+ -+ case 5: -+#line 216 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node));;} -+ break; -+ -+ case 8: -+#line 220 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (2)].opinfo),(yyvsp[(1) - (2)].node),0); ;} -+ break; -+ -+ case 10: -+#line 223 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 11: -+#line 226 "parse.y" -+ { decl_tbase=(yyvsp[(1) - (1)].ctype) ; ;} -+ break; -+ -+ case 12: -+#line 226 "parse.y" -+ { (yyval.node)=(yyvsp[(3) - (3)].node) ; ;} -+ break; -+ -+ case 14: -+#line 229 "parse.y" -+ { (yyval.node)=mknode_sbin(seq_op,(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 15: -+#line 232 "parse.y" -+ { (yyval.node)=mknode_sbin(decl_op,(yyvsp[(1) - (1)].node), -+ mknode_modified_ctype(decl_tbase)); ;} -+ break; -+ -+ case 16: -+#line 236 "parse.y" -+ { (yyval.node)=(yyvsp[(2) - (3)].node) ; ;} -+ break; -+ -+ case 17: -+#line 237 "parse.y" -+ { (yyval.node)=(yyvsp[(2) - (5)].node) ; push_type('('); ;} -+ break; -+ -+ case 18: -+#line 238 "parse.y" -+ { (yyval.node)=(yyvsp[(2) - (2)].node) ; push_type('*'); ;} -+ break; -+ -+ case 19: -+#line 239 "parse.y" -+ { (yyval.node)=(yyvsp[(1) - (4)].node) ; push_type_int('[',(yyvsp[(3) - (4)].node)); ;} -+ break; -+ -+ case 21: -+#line 251 "parse.y" -+ { (yyval.node)=mknode_tri((yyvsp[(1) - (5)].opinfo),(yyvsp[(3) - (5)].node),(yyvsp[(5) - (5)].node),0); ;} -+ break; -+ -+ case 22: -+#line 253 "parse.y" -+ { (yyval.node)=mknode_tri((yyvsp[(1) - (6)].opinfo),(yyvsp[(3) - (6)].node),(yyvsp[(5) - (6)].node),0); ;} -+ break; -+ -+ case 23: -+#line 255 "parse.y" -+ { (yyval.node)=mknode_tri((yyvsp[(1) - (6)].opinfo),(yyvsp[(3) - (6)].node),0,(yyvsp[(6) - (6)].node)); ;} -+ break; -+ -+ case 24: -+#line 257 "parse.y" -+ { (yyval.node)=mknode_tri((yyvsp[(1) - (7)].opinfo),(yyvsp[(3) - (7)].node),(yyvsp[(5) - (7)].node),(yyvsp[(7) - (7)].node)); ;} -+ break; -+ -+ case 25: -+#line 260 "parse.y" -+ { (yyval.node)=mknode_op(OPK_QUAD,(yyvsp[(1) - (9)].opinfo),(yyvsp[(3) - (9)].node),(yyvsp[(5) - (9)].node),(yyvsp[(7) - (9)].node),(yyvsp[(9) - (9)].node)); ;} -+ break; -+ -+ case 26: -+#line 262 "parse.y" -+ { (yyval.node)=mknode_op(OPK_QUAD,(yyvsp[(1) - (8)].opinfo),(yyvsp[(3) - (8)].node),(yyvsp[(5) - (8)].node),(yyvsp[(7) - (8)].node),0); ;} -+ break; -+ -+ case 27: -+#line 264 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(1) - (5)].opinfo),(yyvsp[(3) - (5)].node),(yyvsp[(5) - (5)].node)); ;} -+ break; -+ -+ case 28: -+#line 266 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(1) - (4)].opinfo),(yyvsp[(3) - (4)].node),0); ;} -+ break; -+ -+ case 29: -+#line 271 "parse.y" -+ { (yyval.node)=mknode_unary( (yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 30: -+#line 272 "parse.y" -+ { (yyval.node)=mknode_unary( (yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 31: -+#line 273 "parse.y" -+ { (yyval.node)=mknode_unary( (yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 32: -+#line 274 "parse.y" -+ { (yyval.node)=mknode_unary( (yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 33: -+#line 275 "parse.y" -+ { (yyval.node)=mknode_unary( (yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 34: -+#line 276 "parse.y" -+ { (yyval.node)=mknode_sunary((yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 35: -+#line 277 "parse.y" -+ { (yyval.node)=mknode_sunary((yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 36: -+#line 278 "parse.y" -+ { (yyval.node)=mknode_sunary((yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 37: -+#line 279 "parse.y" -+ { (yyval.node)=mknode_unary( (yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 38: -+#line 280 "parse.y" -+ { (yyval.node)=mknode_unary( (yyvsp[(1) - (2)].opinfo),(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 39: -+#line 281 "parse.y" -+ { (yyval.node)=mknode_post_unary((yyvsp[(2) - (2)].opinfo),(yyvsp[(1) - (2)].node)); ;} -+ break; -+ -+ case 40: -+#line 282 "parse.y" -+ { (yyval.node)=mknode_post_unary((yyvsp[(2) - (2)].opinfo),(yyvsp[(1) - (2)].node)); ;} -+ break; -+ -+ case 41: -+#line 283 "parse.y" -+ { (yyval.node)=mknode_sunary((yyvsp[(1) - (4)].opinfo),(yyvsp[(3) - (4)].node)); ;} -+ break; -+ -+ case 42: -+#line 284 "parse.y" -+ { (yyval.node)=mknode_unary((yyvsp[(1) - (4)].opinfo),(yyvsp[(3) - (4)].node)); ;} -+ break; -+ -+ case 43: -+#line 285 "parse.y" -+ { (yyval.node)=mknode_unary( (yyvsp[(1) - (4)].opinfo),(yyvsp[(3) - (4)].node)); ;} -+ break; -+ -+ case 44: -+#line 288 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 45: -+#line 289 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 46: -+#line 291 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 47: -+#line 292 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 48: -+#line 293 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 49: -+#line 294 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 50: -+#line 295 "parse.y" -+ { (yyval.node)=mknode_bin( (yyvsp[(2) - (4)].opinfo),(yyvsp[(1) - (4)].node),(yyvsp[(3) - (4)].node)); ;} -+ break; -+ -+ case 51: -+#line 296 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (4)].opinfo),(yyvsp[(1) - (4)].node),(yyvsp[(3) - (4)].node)); ;} -+ break; -+ -+ case 52: -+#line 297 "parse.y" -+ { (yyval.node)=mknode_op(OPK_FUNC,(yyvsp[(2) - (4)].opinfo),(yyvsp[(1) - (4)].node),(yyvsp[(3) - (4)].node),0,0); ;} -+ break; -+ -+ case 53: -+#line 298 "parse.y" -+ { (yyval.node)=mknode_unary((yyvsp[(1) - (3)].opinfo),(yyvsp[(2) - (3)].node)); ;} -+ break; -+ -+ case 54: -+#line 299 "parse.y" -+ { (yyval.node)=mknode_unary((yyvsp[(1) - (3)].opinfo),(yyvsp[(2) - (3)].node)); ;} -+ break; -+ -+ case 55: -+#line 303 "parse.y" -+ { (yyval.node)=mknode_op(OPK_CAST,(yyvsp[(1) - (4)].opinfo),(yyvsp[(2) - (4)].node),(yyvsp[(4) - (4)].node),0,0); ;} -+ break; -+ -+ case 56: -+#line 313 "parse.y" -+ { -+ tctype *t=duel_get_target_typedef((yyvsp[(2) - (4)].nameinfo).name); -+ if(t==NULL) yyerror("not a typedef name"); -+ (yyval.node)=mknode_op(OPK_CAST,(yyvsp[(1) - (4)].opinfo),mknode_ctype(t),(yyvsp[(4) - (4)].node),0,0); ;} -+ break; -+ -+ case 57: -+#line 317 "parse.y" -+ { -+ tctype *t=duel_get_target_typedef((yyvsp[(2) - (6)].nameinfo).name); -+ if(t==NULL) yyerror("not a typedef name"); -+ push_type('*'); -+ (yyval.node)=mknode_op(OPK_CAST,(yyvsp[(1) - (6)].opinfo),mknode_modified_ctype(t),(yyvsp[(6) - (6)].node),0,0); ;} -+ break; -+ -+ case 58: -+#line 326 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 59: -+#line 327 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 60: -+#line 328 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 61: -+#line 329 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 62: -+#line 330 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 63: -+#line 331 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 64: -+#line 332 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 65: -+#line 333 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 66: -+#line 334 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 67: -+#line 335 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 68: -+#line 336 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 69: -+#line 337 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 70: -+#line 338 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 71: -+#line 339 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 72: -+#line 340 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 73: -+#line 341 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 74: -+#line 342 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 75: -+#line 343 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 76: -+#line 344 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 77: -+#line 345 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 78: -+#line 346 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 79: -+#line 347 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 80: -+#line 348 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 81: -+#line 349 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 82: -+#line 353 "parse.y" -+ { (yyval.node)=mknode_tri((yyvsp[(2) - (5)].opinfo),(yyvsp[(1) - (5)].node),(yyvsp[(3) - (5)].node),(yyvsp[(5) - (5)].node)); ;} -+ break; -+ -+ case 83: -+#line 356 "parse.y" -+ { (yyval.node)=mknode_bin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 84: -+#line 357 "parse.y" -+ { (yyval.node)=mknode_op(OPK_ASSIGN,(yyvsp[(2) - (3)].opinfo), (yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node),0,0); ;} -+ break; -+ -+ case 85: -+#line 358 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 86: -+#line 363 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 87: -+#line 364 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(1) - (2)].opinfo), 0,(yyvsp[(2) - (2)].node)); ;} -+ break; -+ -+ case 88: -+#line 365 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (2)].opinfo),(yyvsp[(1) - (2)].node), 0); ;} -+ break; -+ -+ case 89: -+#line 366 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 90: -+#line 367 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 91: -+#line 370 "parse.y" -+ { (yyval.node)=mknode_sbin((yyvsp[(2) - (3)].opinfo),(yyvsp[(1) - (3)].node),(yyvsp[(3) - (3)].node)); ;} -+ break; -+ -+ case 94: -+#line 375 "parse.y" -+ { (yyval.node)=0 ; ;} -+ break; -+ -+ case 97: -+#line 385 "parse.y" -+ { (yyval.node)=mknode_name((yyvsp[(1) - (1)].nameinfo)) ; ;} -+ break; -+ -+ case 98: -+#line 387 "parse.y" -+ { (yyval.node)=mknode_modified_ctype((yyvsp[(1) - (2)].ctype)); ;} -+ break; -+ -+ case 100: -+#line 393 "parse.y" -+ { push_type('('); ;} -+ break; -+ -+ case 101: -+#line 394 "parse.y" -+ { push_type('*'); ;} -+ break; -+ -+ case 102: -+#line 395 "parse.y" -+ { push_type_int('[',(yyvsp[(3) - (4)].node)); ;} -+ break; -+ -+ case 104: -+#line 413 "parse.y" -+ { -+ (yyval.ctype)=duel_get_target_typedef((yyvsp[(2) - (2)].nameinfo).name); -+ if((yyval.ctype)==NULL) { -+ tvalue v; -+ if(duel_get_target_variable((yyvsp[(2) - (2)].nameinfo).name,-1,&v)) (yyval.ctype)=v.ctype; -+ else yyerror("not a typedef name"); -+ } -+ ;} -+ break; -+ -+ case 105: -+#line 423 "parse.y" -+ { (yyval.ctype) = ctype_char; ;} -+ break; -+ -+ case 106: -+#line 424 "parse.y" -+ { (yyval.ctype) = ctype_schar; ;} -+ break; -+ -+ case 107: -+#line 425 "parse.y" -+ { (yyval.ctype) = ctype_uchar; ;} -+ break; -+ -+ case 108: -+#line 426 "parse.y" -+ { (yyval.ctype) = ctype_int; ;} -+ break; -+ -+ case 109: -+#line 427 "parse.y" -+ { (yyval.ctype) = ctype_uint; ;} -+ break; -+ -+ case 110: -+#line 428 "parse.y" -+ { (yyval.ctype) = ctype_uint; ;} -+ break; -+ -+ case 111: -+#line 429 "parse.y" -+ { (yyval.ctype) = ctype_long; ;} -+ break; -+ -+ case 112: -+#line 430 "parse.y" -+ { (yyval.ctype) = ctype_long; ;} -+ break; -+ -+ case 113: -+#line 431 "parse.y" -+ { (yyval.ctype) = ctype_ulong; ;} -+ break; -+ -+ case 114: -+#line 432 "parse.y" -+ { (yyval.ctype) = ctype_ulong; ;} -+ break; -+ -+ case 115: -+#line 433 "parse.y" -+ { (yyval.ctype) = ctype_longlong; ;} -+ break; -+ -+ case 116: -+#line 434 "parse.y" -+ { (yyval.ctype) = ctype_longlong; ;} -+ break; -+ -+ case 117: -+#line 435 "parse.y" -+ { (yyval.ctype) = ctype_ulonglong; ;} -+ break; -+ -+ case 118: -+#line 436 "parse.y" -+ { (yyval.ctype) = ctype_ulonglong; ;} -+ break; -+ -+ case 119: -+#line 437 "parse.y" -+ { (yyval.ctype) = ctype_short; ;} -+ break; -+ -+ case 120: -+#line 438 "parse.y" -+ { (yyval.ctype) = ctype_short; ;} -+ break; -+ -+ case 121: -+#line 439 "parse.y" -+ { (yyval.ctype) = ctype_ushort; ;} -+ break; -+ -+ case 122: -+#line 440 "parse.y" -+ { (yyval.ctype) = ctype_ushort; ;} -+ break; -+ -+ case 123: -+#line 441 "parse.y" -+ { (yyval.ctype) = ctype_float ; ;} -+ break; -+ -+ case 124: -+#line 442 "parse.y" -+ { (yyval.ctype) = ctype_double; ;} -+ break; -+ -+ case 125: -+#line 443 "parse.y" -+ { (yyval.ctype) = ctype_void; ;} -+ break; -+ -+ case 126: -+#line 445 "parse.y" -+ { (yyval.ctype) = duel_get_target_struct_tag((yyvsp[(2) - (2)].nameinfo).name); -+ if((yyval.ctype)==NULL) yyerror("not a struct tag"); ;} -+ break; -+ -+ case 127: -+#line 448 "parse.y" -+ { (yyval.ctype) = duel_get_target_union_tag((yyvsp[(2) - (2)].nameinfo).name); -+ if((yyval.ctype)==NULL) yyerror("not a union tag"); ;} -+ break; -+ -+ case 128: -+#line 451 "parse.y" -+ { (yyval.ctype) = duel_get_target_enum_tag((yyvsp[(2) - (2)].nameinfo).name); -+ if((yyval.ctype)==NULL) yyerror("not an enum tag"); ;} -+ break; -+ -+ -+/* Line 1267 of yacc.c. */ -+#line 2627 "parse.c" -+ default: break; -+ } -+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); -+ -+ YYPOPSTACK (yylen); -+ yylen = 0; -+ YY_STACK_PRINT (yyss, yyssp); -+ -+ *++yyvsp = yyval; -+ -+ -+ /* Now `shift' the result of the reduction. Determine what state -+ that goes to, based on the state we popped back to and the rule -+ number reduced by. */ -+ -+ yyn = yyr1[yyn]; -+ -+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; -+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) -+ yystate = yytable[yystate]; -+ else -+ yystate = yydefgoto[yyn - YYNTOKENS]; -+ -+ goto yynewstate; -+ -+ -+/*------------------------------------. -+| yyerrlab -- here on detecting error | -+`------------------------------------*/ -+yyerrlab: -+ /* If not already recovering from an error, report this error. */ -+ if (!yyerrstatus) -+ { -+ ++yynerrs; -+#if ! YYERROR_VERBOSE -+ yyerror (YY_("syntax error")); -+#else -+ { -+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); -+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) -+ { -+ YYSIZE_T yyalloc = 2 * yysize; -+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) -+ yyalloc = YYSTACK_ALLOC_MAXIMUM; -+ if (yymsg != yymsgbuf) -+ YYSTACK_FREE (yymsg); -+ yymsg = (char *) YYSTACK_ALLOC (yyalloc); -+ if (yymsg) -+ yymsg_alloc = yyalloc; -+ else -+ { -+ yymsg = yymsgbuf; -+ yymsg_alloc = sizeof yymsgbuf; -+ } -+ } -+ -+ if (0 < yysize && yysize <= yymsg_alloc) -+ { -+ (void) yysyntax_error (yymsg, yystate, yychar); -+ yyerror (yymsg); -+ } -+ else -+ { -+ yyerror (YY_("syntax error")); -+ if (yysize != 0) -+ goto yyexhaustedlab; -+ } -+ } -+#endif -+ } -+ -+ -+ -+ if (yyerrstatus == 3) -+ { -+ /* If just tried and failed to reuse look-ahead token after an -+ error, discard it. */ -+ -+ if (yychar <= YYEOF) -+ { -+ /* Return failure if at end of input. */ -+ if (yychar == YYEOF) -+ YYABORT; -+ } -+ else -+ { -+ yydestruct ("Error: discarding", -+ yytoken, &yylval); -+ yychar = YYEMPTY; -+ } -+ } -+ -+ /* Else will try to reuse look-ahead token after shifting the error -+ token. */ -+ goto yyerrlab1; -+ -+ -+/*---------------------------------------------------. -+| yyerrorlab -- error raised explicitly by YYERROR. | -+`---------------------------------------------------*/ -+yyerrorlab: -+ -+ /* Pacify compilers like GCC when the user code never invokes -+ YYERROR and the label yyerrorlab therefore never appears in user -+ code. */ -+ if (/*CONSTCOND*/ 0) -+ goto yyerrorlab; -+ -+ /* Do not reclaim the symbols of the rule which action triggered -+ this YYERROR. */ -+ YYPOPSTACK (yylen); -+ yylen = 0; -+ YY_STACK_PRINT (yyss, yyssp); -+ yystate = *yyssp; -+ goto yyerrlab1; -+ -+ -+/*-------------------------------------------------------------. -+| yyerrlab1 -- common code for both syntax error and YYERROR. | -+`-------------------------------------------------------------*/ -+yyerrlab1: -+ yyerrstatus = 3; /* Each real token shifted decrements this. */ -+ -+ for (;;) -+ { -+ yyn = yypact[yystate]; -+ if (yyn != YYPACT_NINF) -+ { -+ yyn += YYTERROR; -+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) -+ { -+ yyn = yytable[yyn]; -+ if (0 < yyn) -+ break; -+ } -+ } -+ -+ /* Pop the current state because it cannot handle the error token. */ -+ if (yyssp == yyss) -+ YYABORT; -+ -+ -+ yydestruct ("Error: popping", -+ yystos[yystate], yyvsp); -+ YYPOPSTACK (1); -+ yystate = *yyssp; -+ YY_STACK_PRINT (yyss, yyssp); -+ } -+ -+ if (yyn == YYFINAL) -+ YYACCEPT; -+ -+ *++yyvsp = yylval; -+ -+ -+ /* Shift the error token. */ -+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); -+ -+ yystate = yyn; -+ goto yynewstate; -+ -+ -+/*-------------------------------------. -+| yyacceptlab -- YYACCEPT comes here. | -+`-------------------------------------*/ -+yyacceptlab: -+ yyresult = 0; -+ goto yyreturn; -+ -+/*-----------------------------------. -+| yyabortlab -- YYABORT comes here. | -+`-----------------------------------*/ -+yyabortlab: -+ yyresult = 1; -+ goto yyreturn; -+ -+#ifndef yyoverflow -+/*-------------------------------------------------. -+| yyexhaustedlab -- memory exhaustion comes here. | -+`-------------------------------------------------*/ -+yyexhaustedlab: -+ yyerror (YY_("memory exhausted")); -+ yyresult = 2; -+ /* Fall through. */ -+#endif -+ -+yyreturn: -+ if (yychar != YYEOF && yychar != YYEMPTY) -+ yydestruct ("Cleanup: discarding lookahead", -+ yytoken, &yylval); -+ /* Do not reclaim the symbols of the rule which action triggered -+ this YYABORT or YYACCEPT. */ -+ YYPOPSTACK (yylen); -+ YY_STACK_PRINT (yyss, yyssp); -+ while (yyssp != yyss) -+ { -+ yydestruct ("Cleanup: popping", -+ yystos[*yyssp], yyvsp); -+ YYPOPSTACK (1); -+ } -+#ifndef yyoverflow -+ if (yyss != yyssa) -+ YYSTACK_FREE (yyss); -+#endif -+#if YYERROR_VERBOSE -+ if (yymsg != yymsgbuf) -+ YYSTACK_FREE (yymsg); -+#endif -+ /* Make sure YYID is used. */ -+ return YYID (yyresult); -+} -+ -+ -+#line 456 "parse.y" -+ -+ -+static struct stoken { /* all opcodes we recognize */ -+ char *opstr ; /* op code as a string */ -+ int token ; /* token to return to yacc */ -+ int opcode ; /* opcode value associated with the token */ -+ } tokens[] = { /* the special tokens, longer ones 1st! */ -+ {">>=",T_ASSIGN, OP_RSH}, -+ {"<<=",T_ASSIGN, OP_LSH}, -+ {"-->",T_DFS, OP_DFS}, -+ {"->>",T_BFS, OP_BFS}, -+ {"==?", T_EQQ, OP_EQQ}, -+ {"!=?", T_NEQ, OP_NEQ}, -+ {"<=?", T_LEQ, OP_LEQ}, -+ {">=?", T_GEQ, OP_GEQ}, -+ {"&&/", T_ANDL, OP_AND}, -+ {"||/", T_ORL, OP_OR}, -+ -+ {"<?", T_LSQ, OP_LSQ}, -+ {">?", T_GTQ, OP_GTQ}, -+ {"#/", T_COUNT, '#' }, -+ {"%/", T_COUNT, '#' }, /* gdb insists to recognize # as start of comma!*/ -+ {"%%", '#', '#' }, /* same. so %/ for #/ and %% for #. not doc!*/ -+ {"+=", T_ASSIGN, '+'}, -+ {"-=", T_ASSIGN, '-'}, -+ {"*=", T_ASSIGN, '*'}, -+ {"/=", T_ASSIGN, '/'}, -+ {"%=", T_ASSIGN, '%'}, -+ {"|=", T_ASSIGN, '|'}, -+ {"&=", T_ASSIGN, '&'}, -+ {"^=", T_ASSIGN, '^'}, -+ {":=", T_DEFVAR,OP_DEF}, -+ {"++", T_INC, OP_INC }, -+ {"--", T_DEC, OP_DEC }, -+ {"->", T_ARROW, OP_ARR }, -+ {"&&", T_AND, OP_AND }, -+ {"||", T_OR, OP_OR }, -+ {"<<", T_LSH, OP_LSH }, -+ {">>", T_RSH, OP_RSH }, -+ {"==", T_EQ, OP_EQ }, -+ {"!=", T_NE, OP_NE }, -+ {"<=", T_LE, OP_LE }, -+ {">=", T_GE, OP_GE }, -+ {"..", T_TO, OP_TO }, -+ {"=>", T_IMP, OP_IMP }, -+ {"[[", T_OSEL, OP_SEL }, -+ {"]]", T_CSEL, OP_SEL }, -+ }; -+ -+static struct skeyword { /* all keywords we recognize */ -+ char *keyword_str ; /* keyword as a string */ -+ int token ; /* token to return to yacc */ -+ topcode opcode ; /* opcode associated w/keyword */ -+ } keywords[] = { -+ {"if", T_IF , OP_IF}, -+ {"else", T_ELSE }, -+ {"for", T_FOR , OP_FOR}, -+ {"while", T_WHILE , OP_WHILE}, -+ {"sizeof", T_SIZEOF , OP_SIZ}, -+ {"frame", T_FRAME , OP_FRAME}, -+ -+ {"T", T_TYPEDEF_INDICATOR }, -+ {"struct", T_STRUCT }, -+ {"union", T_UNION }, -+ {"enum", T_ENUM }, -+ -+ {"unsigned",T_UNSIGNED }, -+ {"signed", T_SIGNED }, -+ {"short", T_SHORT }, -+ {"long", T_LONG }, -+ {"char", T_CHAR }, -+ {"int", T_INT }, -+ {"double", T_DOUBLE }, -+ {"float", T_FLOAT }, -+ {"void", T_VOID }, -+ } ; -+ -+ -+LFUNC tnode* duel_lex_int(void) /* parse next token as integer num */ -+{ -+ tnode *n ; -+ tulonglong val=0 ; -+ char *p=lexptr ; -+ bool is_l=0,is_u=0 ; -+ int base=10 ; -+ int src_pos=lexptr-inputstr ; -+ -+ if(*p=='0') { /* figure out the base */ -+ p++ ; -+ if(*p=='x' || *p=='X') base=16,p++ ; -+ else -+ if(isdigit(*p)) base=8 ; /* avoid having '0' as a base 8 (uint) */ -+ } -+ -+ while(isdigit(*p) || base==16 && isxdigit(*p)) { /* get the value */ -+ val*=base ; -+ if(isupper(*p)) val+= *p-'A'+10 ; -+ else if(islower(*p)) val+= *p-'a'+10 ; -+ else val+= *p-'0' ; -+ p++ ; -+ } -+ for (;*p;p++) { /* yuk. figure 0L etc */ -+ if (*p == 'l' || *p == 'L') is_l++; -+ else if(*p == 'u' || *p == 'U') is_u++; -+ else break; -+ } -+ is_u=is_u || base!=10 ; -+ -+ if((is_l>1 && is_u) || (long long) val < 0 || ((tulong) val != val && is_u)) { -+ n=mknode_const(src_pos,ctype_ulonglong); -+ n->cnst.u.rval_ulonglong=val ; -+ } -+ else -+ if(is_l>1 || (tulong) val != val) { -+ n=mknode_const(src_pos,ctype_longlong) ; -+ n->cnst.u.rval_longlong=(long long) val ; -+ } -+ else -+ if((is_l && is_u) || (long) val < 0 || ((tuint) val != val && is_u)) { -+ n=mknode_const(src_pos,ctype_ulong); -+ n->cnst.u.rval_ulong=val ; -+ } -+ else -+ if(is_l || (tuint) val != val) { -+ n=mknode_const(src_pos,ctype_long) ; -+ n->cnst.u.rval_long=(long) val ; -+ } -+ else -+ if(is_u || (int) val < 0) { -+ n=mknode_const(src_pos,ctype_uint) ; -+ n->cnst.u.rval_uint=(tuint) val ; -+ } -+ else { -+ n=mknode_const(src_pos,ctype_int) ; -+ n->cnst.u.rval_int=(int) val ; -+ } -+ strncpyz(n->cnst.symb_val,lexptr,p-lexptr); /* save the symbolic val*/ -+ lexptr=p ; -+ return n ; -+} -+ -+LFUNC tnode* duel_lex_float(void) /* parse next token as float num */ -+{ -+ tnode *n=0 ; -+ char *p=lexptr ; -+ double val ; -+ char c,tmpc ; -+ bool ok=TRUE; -+ int src_pos = lexptr - inputstr ; -+ -+ /* this is disgusting.. why isnt there a lib call to recognize floats?! */ -+ while(isdigit(*p)) p++ ; -+ if(*p=='.') p++ ; -+ while(isdigit(*p)) p++ ; -+ if(*p=='e' || *p=='E') { -+ p++ ; -+ if(*p=='+' || *p=='-') p++ ; -+ if(!isdigit(*p)) ok=FALSE ; /* force digit (scanf allows 1e-.2 ?!) */ -+ while(isdigit(*p)) p++ ; -+ } -+ tmpc= *p ; *p=0 ; -+ ok=ok && sscanf(lexptr,"%lf%c",&val,&c)==1 ; -+ *p=tmpc ; -+ if(!ok) yyerror("Invalid float constant."); -+ -+ n=mknode_const(src_pos,ctype_double); -+ n->cnst.u.rval_double=val ; -+ strncpyz(n->cnst.symb_val,lexptr,p-lexptr); /* save the symbolic val*/ -+ lexptr=p ; -+ return(n); -+} -+ -+/* parse_escaped_char -- parse an escaped char (e.g. '\n'). -+ * lexptr expected to point to text right after the '\'. -+ * return: actual char value (e.g. 012 if 'n' or '012' is found.) -+ * lexptr is advanced after the espaced char. -+ */ -+ -+LFUNC char parse_escaped_char(void) -+{ -+ char retc ; -+ switch(lexptr[0]) { -+ /*case 'a': retc='\a' ; break ; /* some compilers don't support it. */ -+ case 'b': retc='\b' ; break ; -+ case 'f': retc='\f' ; break ; -+ case 'n': retc='\n' ; break ; -+ case 'r': retc='\r' ; break ; -+ case 't': retc='\t' ; break ; -+ case 'v': retc='\v' ; break ; -+ case 'x': yyerror("hex char const not yet suppported"); -+ case '0': case '1': case '2': case '3': -+ retc= lexptr[0] - '0' ; -+ if(lexptr[1]>='0' && lexptr[1]<='7') -+ retc= retc* 010 + *++lexptr - '0' ; -+ if(lexptr[1]>='0' && lexptr[1]<='7') -+ retc= retc* 010 + *++lexptr - '0' ; -+ break ; -+ default: retc=lexptr[0] ; /* default also takes care of '\'' '\\' */ -+ } -+ lexptr++ ; -+ return retc ; -+} -+ -+/* FUNC yylex -- return the next token to yacc. -+ * GLOBALS: lexptr point to the string we are parsing next. it is updated. -+ */ -+ -+LFUNC int yylex (void) -+{ -+ int c,i,src_pos ; -+ char *p ; -+ -+ for(c= *lexptr; c==' ' || c=='\t' || c=='\n' ; c= *++lexptr); /* skip blank*/ -+ -+ src_pos = lexptr - inputstr ; /* current char being parsed */ -+ yylval.opinfo.src_pos = src_pos ; -+ -+ if(*lexptr=='\0' || strncmp(lexptr,"|>",2)==0) return 0 ; /* end of expr */ -+ -+ for (i = 0; i < sizeof(tokens)/sizeof(struct stoken) ; i++) { -+ int l=strlen(tokens[i].opstr) ; /* check next token vs table */ -+ if(strncmp(lexptr,tokens[i].opstr,l)==0) { -+ lexptr+=l ; -+ yylval.opinfo.opcode = tokens[i].opcode; -+ return tokens[i].token ; -+ } -+ } -+ -+ switch (c = *lexptr) { -+ case '\'': /* char constant, but stored as int (ansi-c) */ -+ p=lexptr++ ; -+ c = *lexptr++ ; -+ if (c == '\\') c=parse_escaped_char(); -+ if( *lexptr++ != '\'') yyerror("Invalid character constant."); -+ yylval.node=mknode_const(src_pos,ctype_int) ; -+ yylval.node->cnst.u.rval_int=c ; -+ strncpyz(yylval.node->cnst.symb_val,p,lexptr-p); /*save the symbol. val*/ -+ return T_CONST ; -+ -+ case '0': /* chk hex */ -+ if(lexptr[1]=='x' || lexptr[1]=='X') { -+ yylval.node=duel_lex_int(); -+ return T_CONST ; -+ } -+ /* fall thru for other numbers */ -+ case '1': case '2': case '3': /* decimal or floating point number */ -+ case '4': case '5': case '6': case '7': case '8': case '9': -+ for(p=lexptr ; *p>='0' && *p<='9' ; p++ ) ; /*find next non digit*/ -+ if(*p=='.' && p[1]!='.' || *p=='e' || *p=='E') -+ yylval.node=duel_lex_float(); -+ else yylval.node=duel_lex_int(); -+ return T_CONST ; -+ -+ case '(': case ')': -+ case '<': case '>': -+ case '[': case ']': -+ case '{': case '}': -+ case '+': case '-': case '*': case '/': case '%': -+ case '|': case '&': case '^': case '~': case '!': -+ case ',': case '?': case ':': case '=': -+ case '.': case '@': case '$': case '#': case '`': case '\\': -+ lexptr++; -+ yylval.opinfo.opcode=c ; -+ return c; -+ case ';': { /* hack, ignore ';' before '}' and else. for C compatability*/ -+ char *save_lexptr= ++lexptr ; -+ int tok=yylex() ; /* hack, call myself for next token */ -+ if(tok=='}' || tok==T_ELSE) { -+ duel_printf("warning: useless ';' ignored\n"); -+ return tok ; -+ } -+ /* else restore position and return the ';' */ -+ lexptr=save_lexptr ; -+ yylval.opinfo.opcode=';' ; -+ yylval.opinfo.src_pos = src_pos ; -+ return ';'; -+ } -+ case '"': { -+ char s[512] ; -+ size_t len=0 ; -+ ttarget_ptr dptr ; -+ tnode *n ; -+ -+ p=lexptr++ ; -+ while((c= *lexptr++)!='"') { -+ if (c == '\\') c=parse_escaped_char(); -+ s[len++]=c ; -+ } -+ s[len++]=0 ; -+ dptr=duel_alloc_target_space(len); -+ duel_put_target_bytes(dptr,s,len); -+ -+ n=mknode_const(src_pos,ctype_charptr); -+ n->cnst.u.rval_ptr=dptr ; -+ len=lexptr-p ; -+ if(len>60) len=60 ; -+ strncpyz(n->cnst.symb_val,p,len); /* save the symbolic val*/ -+ yylval.node=n ; -+ return T_CONST ; -+ } -+ } -+ -+ if(c != '_' && !isalpha(c)) -+ yyerror ("Invalid character in expression."); -+ -+ p=lexptr ; -+ do { c= *++lexptr ; } while(c=='_' || isalnum(c)); -+ -+ for (i = 0; i < sizeof(keywords)/sizeof(struct skeyword) ; i++) { -+ int l=strlen(keywords[i].keyword_str) ; /* check next token vs keywords*/ -+ if(l==lexptr-p && strncmp(p,keywords[i].keyword_str,l)==0) { -+ yylval.opinfo.opcode=keywords[i].opcode ; -+ return keywords[i].token ; -+ } -+ } -+ -+ /* the symbol/name found is not a reserved word, so return it as a T_SYM -+ */ -+ -+ i=lexptr-p ; /* length of string found (symbol/name) */ -+ yylval.nameinfo.src_pos=src_pos ; -+ yylval.nameinfo.name=duel_malloc(i+1); -+ strncpyz(yylval.nameinfo.name,p,i); -+ return T_SYM; -+} -+ -+LPROC yyerror(char *msg) -+{ -+ int i,n=lexptr-inputstr ; -+ duel_printf("%s\n",inputstr); -+ for(i=0 ; i<n ; i++) duel_printf("-"); -+ duel_printf("^ %s\n",msg); -+ duel_abort(); /* terminate parsing. some callers depend on this*/ -+} -+ -+/*************************************************************************/ -+/* utility functions used to parse the expression and build it as a tree */ -+/*************************************************************************/ -+ -+/* mknode_op -- make a tree node of type op with given opcode and kids -+ */ -+ -+LFUNC tnode* mknode_op(top_kind op_kind,topinfo opinfo, -+ tnode *k1,tnode *k2,tnode *k3,tnode *k4) -+{ -+ tnode *n ; -+ duel_assert(opinfo.opcode>' '); -+ n=(tnode *) duel_malloc(sizeof(tnode)); -+ duel_bzero((char*) n,sizeof(tnode)); -+ n->node_kind=NK_OP ; -+ n->op_kind=op_kind ; -+ n->op=opinfo.opcode ; -+ n->src_pos=opinfo.src_pos ; -+ n->kids[0]=k1 ; n->kids[1]=k2 ; n->kids[2]=k3 ; n->kids[3]=k4 ; -+ return n ; -+} -+ -+ -+ /* mknode_const -- make a constant node for the given type. -+ */ -+ -+LFUNC tnode* mknode_const(int src_pos,tctype *ctype) -+{ -+ tnode *n ; -+ n=(tnode *) duel_malloc(sizeof(tnode)); -+ duel_bzero((char*) n,sizeof(tnode)); -+ n->node_kind=NK_CONST ; -+ n->src_pos=src_pos ; -+ n->cnst.val_kind=VK_RVALUE ; -+ n->cnst.ctype=ctype ; -+ return n ; -+} -+ -+ /* mknode_ctype -- make a node of the given c-type. -+ */ -+ -+LFUNC tnode* mknode_ctype(tctype *ctype) -+{ -+ tnode *n ; -+ n=(tnode *) duel_malloc(sizeof(tnode)); -+ duel_bzero((char*) n,sizeof(tnode)); -+ n->node_kind=NK_CTYPE ; -+ n->ctype=ctype ; -+ return n ; -+} -+ -+ /* mknode_name -- make a node of the given name/symbol. -+ * input is pointer to the saved name (on heap) -+ */ -+ -+LFUNC tnode* mknode_name(tnameinfo nameinfo) -+{ -+ tnode *n ; -+ n=(tnode *) duel_malloc(sizeof(tnode)); -+ duel_bzero((char*) n,sizeof(tnode)); -+ n->node_kind=NK_NAME ; -+ n->name=nameinfo.name ; -+ n->src_pos=nameinfo.src_pos ; -+ return n ; -+} -+ -+/* In order to parse C types, which are 'reversed' in the parser, a stack -+ * is used to push abstract declarators, e.g. in (*)() we first push a func -+ * indicator '(' and then push a pointer indicator '*'. for arrays we push -+ * a '[' and the array size. -+ * This stack is popped and a ctype is constructed at the end of the -+ * abstract type parsing. The following functions implement the stack -+ */ -+ -+typedef struct stype_desc { /* stack of type descriptors is made of these */ -+ char desc ; -+ int size ; -+ struct stype_desc *next ; /* next on stack */ -+ } ttype_desc ; -+ -+ttype_desc *top = 0 ; -+ -+ -+LPROC push_type(char desc) /* put desc on the types stack */ -+{ -+ ttype_desc *p = (ttype_desc* ) duel_malloc(sizeof(ttype_desc)); -+ p->desc=desc ; -+ p->size=0 ; -+ p->next=top ; -+ top=p ; -+} -+ -+/* push_type_int -- same as push_type but also set the size parameter, which -+ * is given as a constant node (which is expected to be int) -+ */ -+ -+LPROC push_type_int(char desc,tnode *n) -+{ -+ duel_assert(n->node_kind==NK_CONST); -+ if(n->cnst.ctype != ctype_int || -+ n->cnst.u.rval_int <=0 ) duel_gen_error("Illegal array size",0); -+ push_type(desc); -+ top->size=n->cnst.u.rval_int ; -+} -+ -+LFUNC bool pop_type(char *desc,int *size) /* pop item from stack. */ -+{ -+ ttype_desc *p = top ; -+ if(p==0) return FALSE ; -+ *desc=p->desc ; -+ *size=p->size ; -+ top=p->next ; -+ duel_free(p) ; -+ return TRUE ; -+} -+ -+ -+/* abstract type-modifiers were pushed on a stack. Retrieve -+ * them (reversed) creating type nodes as we go -+ * input: base type (e.g. 'long'). -+ * returns: node of the modified type. -+ * modification is based on the stack of things pushed while parsing. -+ */ -+ -+LFUNC tnode* mknode_modified_ctype(tctype *base) -+{ -+ int size; -+ char tdesc ; /* descriptor of abs decl eg '*' */ -+ tctype *t=base ; /* type under construction */ -+ -+ while(pop_type(&tdesc,&size)) /* pop next abs decl */ -+ switch (tdesc) { -+ case '*': t=duel_mkctype_ptr(t); break ; -+ case '(': t=duel_mkctype_func(t); break ; -+ case '[': t=duel_mkctype_array(t,size); break ; -+ } -+ return mknode_ctype(t) ; -+} -+ -+/* entry point for parsing. the given expression is parsed into the given -+ * node as root. -+ */ -+ -+FUNC tnode* duel_parse(char *s) -+{ -+ lexptr=inputstr=s ; -+ top=0 ; /* reset the types stack */ -+ if(duel_yyparse()) root=NULL ; -+ return root ; -+} -+ ---- gdb/duel/parse.y -+++ gdb/duel/parse.y -@@ -0,0 +1,940 @@ -+%{ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* this module contains the duel parser, in yacc, plus a simple lexer. -+ * the lexer is slow, but duel expressions are tiny. -+ * the parsing generate an AST with essentially no type checking. -+ * names are only looked up when the refer explicitly to types. This forces -+ * the use of "T" before user types. You can't parse (x)(y) correctly, if -+ * you want the node to contain "cast" or "func", without knowing the x is -+ * not a type. (It is interesting to note that (x *)(y) is clearly a cast, -+ * but it can not be parsed without a context sensitive grammer!). -+ * -+ * Version 1.1 now accept (x) as a type cast, so (print)("hi") fails, but -+ * (uint)z is ok. Also accepted is (uint*)z. T is still required in sizeof -+ * and in variable declarations. A side effect was making "sizeof x" illegal -+ * (since then sizeof(x)-1 was parsed sizeof((x)-1) with (x) a cast), so -+ * now sizeof(x) must be used. Note that in C, sizoef(x)++ is acceptable, -+ * and the '++' operate on x (which is optimized out!) This can be confusing. -+ * -+ * yacc is also not smart enough to recognize e.g. "if(e) e ; else e" as -+ * a special case (redundent ';'). I hacked this in the lexer. It should -+ * reduce the trouble with C->duel coding. (It can also be done for {e1}e2, -+ * in some speical cases, e.g. if e2 is a keyword, or a name or a unary op, -+ * but this can confuse some people, e.g. in {i}[5], so I left it alone.) -+ * Finally, the %/ operator is accepted as "#/" and "%%" as "#", to those -+ * who wish to keep gdb with # comments. -+ * memory: nodes are alloc'ed dynamically. a parsing error loose so-far -+ * allocated nodes, which is normally acceptable (yyerror can probably hack -+ * into the yacc stack to release them.) -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.14 93/03/17 11:04:12 mg -+ * fixed (t*)x bug, was parsed as (t**)x -+ * -+ * Revision 1.13 93/03/12 06:15:09 mg -+ * modified unary's a bit - cosmetics -+ * support (x)y as type cast -+ * support (x*)y as type cast -+ * replace sizeof exp with sizeof(exp) to prevent clash with above -+ * more cosmetics, including yyerror abort, tuint for uint. -+ * takes anything after |> to be comment (pipe command really) -+ * -+ * -+ * Revision 1.12 93/02/27 06:06:09 mg -+ * added signed char parsing. -+ * -+ * Revision 1.11 93/02/23 19:15:38 mg -+ * improved escaped char support -+ * -+ * Revision 1.10 93/02/03 21:49:34 mg -+ * bug fix - yyerror calls now abort parsing (eg called from lex) -+ * -+ * Revision 1.9 93/01/12 21:53:07 mg -+ * cleanup and set for release -+ * -+ * Revision 1.8 93/01/07 00:14:33 mg -+ * add &&/ ||/ -+ * fixed parsing of trailing ';' was a mess. -+ * ignore ';' before 'else' and '}' w/warning. -+ * -+ * Revision 1.7 93/01/03 07:31:01 mg -+ * error reporting -+ * -+ * Revision 1.6 92/12/24 23:35:50 mg -+ * began src pos support -+ * -+ * Revision 1.5 92/10/19 15:08:02 mg -+ * frames() added; bug fixed -+ * -+ * Revision 1.4 92/10/14 02:06:32 mg -+ * misc/change casting parsing/variable def. -+ * -+ * Revision 1.3 92/09/16 11:09:39 mg -+ * add typedef/struct support, const strings -+ * cleanup s/r conflict by setting ELSE to a token. explained some stuff in -+ * comments. -+ * -+ * Revision 1.2 92/09/15 06:10:46 mg -+ * cosmetics and new ops: x@y, for() while() ..x and x.. -+ * generic '.' and '_' support. x@y. '..x' and 'x..'. while(), for(), ?: -+ * -+ */ -+ -+#include "duel.h" -+ -+static char *inputstr ; /* pointer to string being parsed */ -+static char *lexptr ; /* current lexer pointer into input str */ -+static tnode *root ; /* result of parsing stored here */ -+ -+/* pick unique names for globals of yacc. gdb has other parsers! */ -+#define yyparse duel_yyparse -+#define yylex duel_yylex -+#define yyerror duel_yyerror -+#define yylval duel_yylval -+#define yychar duel_yychar -+#define yydebug duel_yydebug -+#define yypact duel_yypact -+#define yyr1 duel_yyr1 -+#define yyr2 duel_yyr2 -+#define yydef duel_yydef -+#define yychk duel_yychk -+#define yypgo duel_yypgo -+#define yyact duel_yyact -+#define yyexca duel_yyexca -+#define yyerrflag duel_yyerrflag -+#define yynerrs duel_yynerrs -+#define yyps duel_yyps -+#define yypv duel_yypv -+#define yys duel_yys -+#define yystate duel_yystate -+#define yytmp duel_yytmp -+#define yyv duel_yyv -+#define yyval duel_yyval -+#define yylloc duel_yylloc -+ -+typedef struct { /* token info for operators */ -+ int src_pos ; /* source position */ -+ topcode opcode ; /* opcode */ -+ } topinfo ; -+ -+typedef struct { /* token info for symbols */ -+ int src_pos ; /* source position */ -+ char *name ; /* symbol */ -+ } tnameinfo ; -+ -+/* these are used as operators to mknode_... when source location is unknown*/ -+static topinfo seq_op = { -1,';' } ; /* sequencing operator, src pos unkown */ -+static topinfo decl_op = { -1,OP_DECL } ; /* declare var op, src pos unkown */ -+ -+/* local prototypes. */ -+LPROC yyerror(char *msg); -+LFUNC int yylex (void); -+ -+LPROC push_type(char desc) ; -+LPROC push_type_int(char desc,tnode *n) ; -+LFUNC bool pop_type(char *desc,int *size); -+ -+LFUNC tnode* mknode_op(top_kind,topinfo opinfo,tnode*,tnode*,tnode*,tnode*); -+LFUNC tnode* mknode_const(int src_pos,tctype *ctype); -+LFUNC tnode* mknode_ctype(tctype *ctype); -+LFUNC tnode* mknode_name(tnameinfo nameinfo); -+LFUNC tnode* mknode_modified_ctype(tctype *base); -+ -+#define mknode_post_unary(op,n) (mknode_op(OPK_POST_UNARY,op,n, 0, 0,0)) -+#define mknode_unary(op,n) (mknode_op(OPK_UNARY, op,n, 0, 0,0)) -+#define mknode_sunary(op,n) (mknode_op(OPK_SUNARY, op,n, 0, 0,0)) -+#define mknode_bin(op,n1,n2) (mknode_op(OPK_BIN, op,n1,n2,0,0)) -+#define mknode_sbin(op,n1,n2) (mknode_op(OPK_SBIN, op,n1,n2,0,0)) -+#define mknode_tri(op,n1,n2,n3) (mknode_op(OPK_TRI, op,n1,n2,n3,0)) -+ -+static tctype *decl_tbase ; /* used for variables decl */ -+ -+/* #define YYDEBUG 1 */ -+ -+%} -+ -+%union -+ { -+ tnode *node ; /* node pointer for constructed exp tree */ -+ tctype *ctype; /* type for type nodes */ -+ tnameinfo nameinfo ; /* a name/symbol + src position */ -+ topinfo opinfo; /* keyword/operator + source position */ -+ } -+ -+%type <node> start duel_inp duel_exp exp type nameexp sm_exp oexp -+%type <node> all_decls vars_decl var_decl name_decl1 name_decl -+%type <ctype> typebase -+%type <nameinfo> name -+ -+%token <node> T_CONST -+%token <nameinfo> T_SYM -+%token <opinfo> T_ASSIGN T_DEFVAR -+ -+ -+%token <opinfo> T_CHAR T_INT T_SHORT T_LONG T_UNSIGNED T_FLOAT T_DOUBLE T_VOID -+%token <opinfo> T_STRUCT T_UNION T_ENUM T_SIZEOF T_TYPEDEF_INDICATOR T_SIGNED -+ -+%token <opinfo> T_IF T_ELSE T_FOR T_WHILE -+%token <opinfo> ';' ',' '=' '?' '|' '^' '&' '<' '>' '+' '-' '*' '/' '%' -+%token <opinfo> '.' '[' ']' '(' ')' '{' '}' '#' '@' '!' '~' -+%token <opinfo> T_OR T_AND T_RSH T_LSH T_INC T_DEC T_COUNT T_FRAME T_TO -+%token <opinfo> T_DFS T_BFS T_ARROW T_OSEL T_CSEL T_IMP T_ANDL T_ORL -+%token <opinfo> T_EQ T_NE T_EQQ T_NEQ T_LE T_GE T_LSQ T_GTQ T_LEQ T_GEQ -+ -+%left ';' -+%right STMT T_ELSE -+%right T_IMP -+%right ',' -+%right '=' T_ASSIGN T_DEFVAR -+%right '?' -+%left T_OR T_ORL -+%left T_AND T_ANDL -+%left '|' -+%left '^' -+%left '&' -+%left T_EQ T_NE T_EQQ T_NEQ -+%left '<' '>' T_LE T_GE T_LSQ T_GTQ T_LEQ T_GEQ -+%nonassoc T_TO -+%left T_LSH T_RSH -+%left '+' '-' -+%left '*' '/' '%' -+%right UNARY '!' '~' T_INC T_DEC T_COUNT T_FRAME -+%left T_DFS T_BFS T_POS T_ARROW '.' '[' ']' '(' ')' '{' '}' '#' '@' T_OSEL T_CSEL -+%% -+ -+start : duel_inp { root=$1 ; } -+ ; -+ -+duel_inp : all_decls -+ | all_decls ';' -+ | all_decls ';' duel_exp { $$=mknode_sbin($2,$1,$3);} -+ | duel_exp -+ ; -+duel_exp : sm_exp -+ | sm_exp ';' { $$=mknode_sbin($2,$1,0); } -+ ; -+all_decls: vars_decl -+ | all_decls ';' vars_decl { $$=mknode_sbin($2,$1,$3); } -+ ; -+ -+vars_decl: typebase { decl_tbase=$1 ; } var_decl { $$=$3 ; } -+ ; -+var_decl : name_decl1 -+ | var_decl ',' name_decl1 { $$=mknode_sbin(seq_op,$1,$3); } -+ ; -+ -+name_decl1: name_decl { $$=mknode_sbin(decl_op,$1, -+ mknode_modified_ctype(decl_tbase)); } -+ ; -+ -+name_decl : '(' name_decl ')' { $$=$2 ; } -+ | '(' name_decl ')' '(' ')' { $$=$2 ; push_type('('); } -+ | '*' name_decl { $$=$2 ; push_type('*'); } -+ | name_decl '[' T_CONST ']' { $$=$1 ; push_type_int('[',$3); } -+ | nameexp -+ ; -+ -+/* Statements - not really, these are expressions too! -+ Notes: for(;;) oexp - will create lots of shift/reduce conflicts, -+ 'for(;;;)' and 'for(;;) exp' are specified -+ instead and yacc handle this as a "standard" s/r. -+ the only diff is yacc dont complain on these! -+ if() - same comments as above, plus, we prevent meaningless -+ if's like in C: ' if(x); else;' - a useless statement. -+ */ -+exp : T_IF '(' exp ')' exp %prec STMT { $$=mknode_tri($1,$3,$5,0); } -+ | T_IF '(' exp ')' exp T_ELSE %prec STMT -+ { $$=mknode_tri($1,$3,$5,0); } -+ | T_IF '(' exp ')' T_ELSE exp %prec STMT -+ { $$=mknode_tri($1,$3,0,$6); } -+ | T_IF '(' exp ')' exp T_ELSE exp %prec STMT -+ { $$=mknode_tri($1,$3,$5,$7); } -+ -+ | T_FOR '(' oexp ';' exp ';' oexp ')' exp %prec STMT -+ { $$=mknode_op(OPK_QUAD,$1,$3,$5,$7,$9); } -+ | T_FOR '(' oexp ';' exp ';' oexp ')' %prec STMT -+ { $$=mknode_op(OPK_QUAD,$1,$3,$5,$7,0); } -+ | T_WHILE '(' exp ')' exp %prec STMT -+ { $$=mknode_sbin($1,$3,$5); } -+ | T_WHILE '(' exp ')' %prec STMT -+ { $$=mknode_sbin($1,$3,0); } -+ ; -+ -+/* Expressions */ -+ -+exp : '*' exp %prec UNARY { $$=mknode_unary( $1,$2); } -+ | '&' exp %prec UNARY { $$=mknode_unary( $1,$2); } -+ | '-' exp %prec UNARY { $$=mknode_unary( $1,$2); } -+ | '!' exp { $$=mknode_unary( $1,$2); } -+ | '~' exp { $$=mknode_unary( $1,$2); } -+ | T_COUNT exp { $$=mknode_sunary($1,$2); } -+ | T_ANDL exp { $$=mknode_sunary($1,$2); } -+ | T_ORL exp { $$=mknode_sunary($1,$2); } -+ | T_INC exp { $$=mknode_unary( $1,$2); } -+ | T_DEC exp { $$=mknode_unary( $1,$2); } -+ | exp T_INC { $$=mknode_post_unary($2,$1); } -+ | exp T_DEC { $$=mknode_post_unary($2,$1); } -+ | T_SIZEOF '(' type ')' { $$=mknode_sunary($1,$3); } -+ | T_SIZEOF '(' exp ')' { $$=mknode_unary($1,$3); } -+ | T_FRAME '(' exp ')' %prec UNARY { $$=mknode_unary( $1,$3); } -+ ; -+ -+exp : exp T_DFS exp { $$=mknode_sbin($2,$1,$3); } -+ | exp T_BFS exp { $$=mknode_sbin($2,$1,$3); } -+ -+ | exp '#' nameexp { $$=mknode_sbin($2,$1,$3); } -+ | exp '@' exp { $$=mknode_sbin($2,$1,$3); } -+ | exp T_ARROW exp { $$=mknode_sbin($2,$1,$3); } -+ | exp '.' exp { $$=mknode_sbin($2,$1,$3); } -+ | exp '[' exp ']' { $$=mknode_bin( $2,$1,$3); } -+ | exp T_OSEL exp T_CSEL { $$=mknode_sbin($2,$1,$3); } -+ | exp '(' oexp ')' %prec '.' { $$=mknode_op(OPK_FUNC,$2,$1,$3,0,0); } -+ | '(' sm_exp ')' { $$=mknode_unary($1,$2); } -+ | '{' sm_exp '}' { $$=mknode_unary($1,$2); } -+ ; -+ -+exp : '(' type ')' exp %prec UNARY -+ { $$=mknode_op(OPK_CAST,$1,$2,$4,0,0); } -+/* HACKS to handle the most common cast cases with a typedef, without -+ * requiring a 'T'. This code breaks (printf)("hi"), which returns the -+ * error "printf not a typedef", but otherwise it works ok. -+ * It might be confusing since "(uint *)p" works but "(uint (*)())p" wont, -+ * but it seems that (uint*)p, (uint)x are the most common, and users get -+ * confused w/o them. -+ * The code below works essentially with context-sensitive parsing! -+ * see the hacked %prec for nameexp which prevents yacc s/r warning! -+ */ -+ | '(' name ')' exp %prec UNARY { -+ tctype *t=duel_get_target_typedef($2.name); -+ if(t==NULL) yyerror("not a typedef name"); -+ $$=mknode_op(OPK_CAST,$1,mknode_ctype(t),$4,0,0); } -+ | '(' name '*' type_mod ')' exp %prec UNARY { -+ tctype *t=duel_get_target_typedef($2.name); -+ if(t==NULL) yyerror("not a typedef name"); -+ push_type('*'); -+ $$=mknode_op(OPK_CAST,$1,mknode_modified_ctype(t),$6,0,0); } -+ ; -+ -+ /* Bin ops in decreasing precedence order: */ -+ -+exp : exp '*' exp { $$=mknode_bin($2,$1,$3); } -+ | exp '/' exp { $$=mknode_bin($2,$1,$3); } -+ | exp '%' exp { $$=mknode_bin($2,$1,$3); } -+ | exp '+' exp { $$=mknode_bin($2,$1,$3); } -+ | exp '-' exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_LSH exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_RSH exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_EQ exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_NE exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_EQQ exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_NEQ exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_LE exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_GE exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_LEQ exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_GEQ exp { $$=mknode_bin($2,$1,$3); } -+ | exp '<' exp { $$=mknode_bin($2,$1,$3); } -+ | exp '>' exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_LSQ exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_GTQ exp { $$=mknode_bin($2,$1,$3); } -+ | exp '&' exp { $$=mknode_bin($2,$1,$3); } -+ | exp '|' exp { $$=mknode_bin($2,$1,$3); } -+ | exp '^' exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_AND exp { $$=mknode_sbin($2,$1,$3); } -+ | exp T_OR exp { $$=mknode_sbin($2,$1,$3); } -+ ; -+ -+exp : exp '?' exp ':' exp %prec '?' -+ { $$=mknode_tri($2,$1,$3,$5); } -+ ; -+ -+exp : exp '=' exp { $$=mknode_bin($2,$1,$3); } -+ | exp T_ASSIGN exp { $$=mknode_op(OPK_ASSIGN,$2, $1,$3,0,0); } -+ |nameexp T_DEFVAR exp { $$=mknode_sbin($2,$1,$3); } -+ ; -+ -+ /* generating expressions */ -+ -+exp : exp T_TO exp { $$=mknode_sbin($2,$1,$3); } -+ | T_TO exp { $$=mknode_sbin($1, 0,$2); } -+ | exp T_TO { $$=mknode_sbin($2,$1, 0); } -+ | exp ',' exp { $$=mknode_sbin($2,$1,$3); } -+ | exp T_IMP exp { $$=mknode_sbin($2,$1,$3); } -+ ; -+ -+sm_exp : sm_exp ';' exp { $$=mknode_sbin($2,$1,$3); } -+ | exp -+ ; -+ -+oexp : exp /* optional expression, eg in for() */ -+ | { $$=0 ; } -+ ; -+ -+exp : T_CONST ; -+exp : nameexp ; -+ /* convert a string input (name) into an expression. -+ * precedence of '+' is a hack to make the special case -+ * of (x*)(y) parsed as a cast, without shift/reduce conflict -+ *(this would work the same w/o the '+' but gives warning) -+ */ -+nameexp : name %prec '+' { $$=mknode_name($1) ; } ; -+ -+type : typebase type_mod { $$=mknode_modified_ctype($1); } -+ ; -+/* type_mod has no value. bison warning is meaningless. I cant find a way -+ * to shut it up -+ */ -+type_mod: '(' type_mod ')' -+ | '(' type_mod ')' '(' ')' { push_type('('); } -+ | '*' type_mod { push_type('*'); } -+ | type_mod '[' T_CONST ']' { push_type_int('[',$3); } -+ | -+ ; -+ -+ -+/* note that names are evaluated at runtime. hence (name)(x) is ambigious -+ * as either a function call or a cast. -+ * We could identify a typedef 'name' as such and return a special token from -+ * the lexr, but this will make 'x.(5+y)' illegal if y is both a field and -+ * a typedef (Note that gdb's own code include such things). -+ * -+ * there is a complex solution, that keeps the the casting as a syntax tree, -+ * and compute ctype at runtime, too. However, we want to compute all types at -+ * parse time. Out solution forces the reserved word T_TYPEDEF_INDICATOR to -+ * appear before any typedef name. (the reserved word is normally just 'T') -+ * example: instead of '(list *) x' use in duel: '(T list *) x' -+ */ -+ -+typebase: T_TYPEDEF_INDICATOR name { -+ $$=duel_get_target_typedef($2.name); -+ if($$==NULL) { -+ tvalue v; -+ if(duel_get_target_variable($2.name,-1,&v)) $$=v.ctype; -+ else yyerror("not a typedef name"); -+ } -+ } -+ ; -+ -+typebase: T_CHAR { $$ = ctype_char; } -+ | T_SIGNED T_CHAR { $$ = ctype_schar; } -+ | T_UNSIGNED T_CHAR { $$ = ctype_uchar; } -+ | T_INT { $$ = ctype_int; } -+ | T_UNSIGNED { $$ = ctype_uint; } -+ | T_UNSIGNED T_INT { $$ = ctype_uint; } -+ | T_LONG { $$ = ctype_long; } -+ | T_LONG T_INT { $$ = ctype_long; } -+ | T_UNSIGNED T_LONG { $$ = ctype_ulong; } -+ | T_UNSIGNED T_LONG T_INT { $$ = ctype_ulong; } -+ | T_LONG T_LONG { $$ = ctype_longlong; } -+ | T_LONG T_LONG T_INT { $$ = ctype_longlong; } -+ | T_UNSIGNED T_LONG T_LONG { $$ = ctype_ulonglong; } -+ | T_UNSIGNED T_LONG T_LONG T_INT { $$ = ctype_ulonglong; } -+ | T_SHORT { $$ = ctype_short; } -+ | T_SHORT T_INT { $$ = ctype_short; } -+ | T_UNSIGNED T_SHORT { $$ = ctype_ushort; } -+ | T_UNSIGNED T_SHORT T_INT { $$ = ctype_ushort; } -+ | T_FLOAT { $$ = ctype_float ; } -+ | T_DOUBLE { $$ = ctype_double; } -+ | T_VOID { $$ = ctype_void; } -+ | T_STRUCT name -+ { $$ = duel_get_target_struct_tag($2.name); -+ if($$==NULL) yyerror("not a struct tag"); } -+ | T_UNION name -+ { $$ = duel_get_target_union_tag($2.name); -+ if($$==NULL) yyerror("not a union tag"); } -+ | T_ENUM name -+ { $$ = duel_get_target_enum_tag($2.name); -+ if($$==NULL) yyerror("not an enum tag"); } -+ ; -+ -+name : T_SYM ; -+%% -+ -+static struct stoken { /* all opcodes we recognize */ -+ char *opstr ; /* op code as a string */ -+ int token ; /* token to return to yacc */ -+ int opcode ; /* opcode value associated with the token */ -+ } tokens[] = { /* the special tokens, longer ones 1st! */ -+ {">>=",T_ASSIGN, OP_RSH}, -+ {"<<=",T_ASSIGN, OP_LSH}, -+ {"-->",T_DFS, OP_DFS}, -+ {"->>",T_BFS, OP_BFS}, -+ {"==?", T_EQQ, OP_EQQ}, -+ {"!=?", T_NEQ, OP_NEQ}, -+ {"<=?", T_LEQ, OP_LEQ}, -+ {">=?", T_GEQ, OP_GEQ}, -+ {"&&/", T_ANDL, OP_AND}, -+ {"||/", T_ORL, OP_OR}, -+ -+ {"<?", T_LSQ, OP_LSQ}, -+ {">?", T_GTQ, OP_GTQ}, -+ {"#/", T_COUNT, '#' }, -+ {"%/", T_COUNT, '#' }, /* gdb insists to recognize # as start of comma!*/ -+ {"%%", '#', '#' }, /* same. so %/ for #/ and %% for #. not doc!*/ -+ {"+=", T_ASSIGN, '+'}, -+ {"-=", T_ASSIGN, '-'}, -+ {"*=", T_ASSIGN, '*'}, -+ {"/=", T_ASSIGN, '/'}, -+ {"%=", T_ASSIGN, '%'}, -+ {"|=", T_ASSIGN, '|'}, -+ {"&=", T_ASSIGN, '&'}, -+ {"^=", T_ASSIGN, '^'}, -+ {":=", T_DEFVAR,OP_DEF}, -+ {"++", T_INC, OP_INC }, -+ {"--", T_DEC, OP_DEC }, -+ {"->", T_ARROW, OP_ARR }, -+ {"&&", T_AND, OP_AND }, -+ {"||", T_OR, OP_OR }, -+ {"<<", T_LSH, OP_LSH }, -+ {">>", T_RSH, OP_RSH }, -+ {"==", T_EQ, OP_EQ }, -+ {"!=", T_NE, OP_NE }, -+ {"<=", T_LE, OP_LE }, -+ {">=", T_GE, OP_GE }, -+ {"..", T_TO, OP_TO }, -+ {"=>", T_IMP, OP_IMP }, -+ {"[[", T_OSEL, OP_SEL }, -+ {"]]", T_CSEL, OP_SEL }, -+ }; -+ -+static struct skeyword { /* all keywords we recognize */ -+ char *keyword_str ; /* keyword as a string */ -+ int token ; /* token to return to yacc */ -+ topcode opcode ; /* opcode associated w/keyword */ -+ } keywords[] = { -+ {"if", T_IF , OP_IF}, -+ {"else", T_ELSE }, -+ {"for", T_FOR , OP_FOR}, -+ {"while", T_WHILE , OP_WHILE}, -+ {"sizeof", T_SIZEOF , OP_SIZ}, -+ {"frame", T_FRAME , OP_FRAME}, -+ -+ {"T", T_TYPEDEF_INDICATOR }, -+ {"struct", T_STRUCT }, -+ {"union", T_UNION }, -+ {"enum", T_ENUM }, -+ -+ {"unsigned",T_UNSIGNED }, -+ {"signed", T_SIGNED }, -+ {"short", T_SHORT }, -+ {"long", T_LONG }, -+ {"char", T_CHAR }, -+ {"int", T_INT }, -+ {"double", T_DOUBLE }, -+ {"float", T_FLOAT }, -+ {"void", T_VOID }, -+ } ; -+ -+ -+LFUNC tnode* duel_lex_int(void) /* parse next token as integer num */ -+{ -+ tnode *n ; -+ tulonglong val=0 ; -+ char *p=lexptr ; -+ bool is_l=0,is_u=0 ; -+ int base=10 ; -+ int src_pos=lexptr-inputstr ; -+ -+ if(*p=='0') { /* figure out the base */ -+ p++ ; -+ if(*p=='x' || *p=='X') base=16,p++ ; -+ else -+ if(isdigit(*p)) base=8 ; /* avoid having '0' as a base 8 (uint) */ -+ } -+ -+ while(isdigit(*p) || base==16 && isxdigit(*p)) { /* get the value */ -+ val*=base ; -+ if(isupper(*p)) val+= *p-'A'+10 ; -+ else if(islower(*p)) val+= *p-'a'+10 ; -+ else val+= *p-'0' ; -+ p++ ; -+ } -+ for (;*p;p++) { /* yuk. figure 0L etc */ -+ if (*p == 'l' || *p == 'L') is_l++; -+ else if(*p == 'u' || *p == 'U') is_u++; -+ else break; -+ } -+ is_u=is_u || base!=10 ; -+ -+ if((is_l>1 && is_u) || (long long) val < 0 || ((tulong) val != val && is_u)) { -+ n=mknode_const(src_pos,ctype_ulonglong); -+ n->cnst.u.rval_ulonglong=val ; -+ } -+ else -+ if(is_l>1 || (tulong) val != val) { -+ n=mknode_const(src_pos,ctype_longlong) ; -+ n->cnst.u.rval_longlong=(long long) val ; -+ } -+ else -+ if((is_l && is_u) || (long) val < 0 || ((tuint) val != val && is_u)) { -+ n=mknode_const(src_pos,ctype_ulong); -+ n->cnst.u.rval_ulong=val ; -+ } -+ else -+ if(is_l || (tuint) val != val) { -+ n=mknode_const(src_pos,ctype_long) ; -+ n->cnst.u.rval_long=(long) val ; -+ } -+ else -+ if(is_u || (int) val < 0) { -+ n=mknode_const(src_pos,ctype_uint) ; -+ n->cnst.u.rval_uint=(tuint) val ; -+ } -+ else { -+ n=mknode_const(src_pos,ctype_int) ; -+ n->cnst.u.rval_int=(int) val ; -+ } -+ strncpyz(n->cnst.symb_val,lexptr,p-lexptr); /* save the symbolic val*/ -+ lexptr=p ; -+ return n ; -+} -+ -+LFUNC tnode* duel_lex_float(void) /* parse next token as float num */ -+{ -+ tnode *n=0 ; -+ char *p=lexptr ; -+ double val ; -+ char c,tmpc ; -+ bool ok=TRUE; -+ int src_pos = lexptr - inputstr ; -+ -+ /* this is disgusting.. why isnt there a lib call to recognize floats?! */ -+ while(isdigit(*p)) p++ ; -+ if(*p=='.') p++ ; -+ while(isdigit(*p)) p++ ; -+ if(*p=='e' || *p=='E') { -+ p++ ; -+ if(*p=='+' || *p=='-') p++ ; -+ if(!isdigit(*p)) ok=FALSE ; /* force digit (scanf allows 1e-.2 ?!) */ -+ while(isdigit(*p)) p++ ; -+ } -+ tmpc= *p ; *p=0 ; -+ ok=ok && sscanf(lexptr,"%lf%c",&val,&c)==1 ; -+ *p=tmpc ; -+ if(!ok) yyerror("Invalid float constant."); -+ -+ n=mknode_const(src_pos,ctype_double); -+ n->cnst.u.rval_double=val ; -+ strncpyz(n->cnst.symb_val,lexptr,p-lexptr); /* save the symbolic val*/ -+ lexptr=p ; -+ return(n); -+} -+ -+/* parse_escaped_char -- parse an escaped char (e.g. '\n'). -+ * lexptr expected to point to text right after the '\'. -+ * return: actual char value (e.g. 012 if 'n' or '012' is found.) -+ * lexptr is advanced after the espaced char. -+ */ -+ -+LFUNC char parse_escaped_char(void) -+{ -+ char retc ; -+ switch(lexptr[0]) { -+ /*case 'a': retc='\a' ; break ; /* some compilers don't support it. */ -+ case 'b': retc='\b' ; break ; -+ case 'f': retc='\f' ; break ; -+ case 'n': retc='\n' ; break ; -+ case 'r': retc='\r' ; break ; -+ case 't': retc='\t' ; break ; -+ case 'v': retc='\v' ; break ; -+ case 'x': yyerror("hex char const not yet suppported"); -+ case '0': case '1': case '2': case '3': -+ retc= lexptr[0] - '0' ; -+ if(lexptr[1]>='0' && lexptr[1]<='7') -+ retc= retc* 010 + *++lexptr - '0' ; -+ if(lexptr[1]>='0' && lexptr[1]<='7') -+ retc= retc* 010 + *++lexptr - '0' ; -+ break ; -+ default: retc=lexptr[0] ; /* default also takes care of '\'' '\\' */ -+ } -+ lexptr++ ; -+ return retc ; -+} -+ -+/* FUNC yylex -- return the next token to yacc. -+ * GLOBALS: lexptr point to the string we are parsing next. it is updated. -+ */ -+ -+LFUNC int yylex (void) -+{ -+ int c,i,src_pos ; -+ char *p ; -+ -+ for(c= *lexptr; c==' ' || c=='\t' || c=='\n' ; c= *++lexptr); /* skip blank*/ -+ -+ src_pos = lexptr - inputstr ; /* current char being parsed */ -+ yylval.opinfo.src_pos = src_pos ; -+ -+ if(*lexptr=='\0' || strncmp(lexptr,"|>",2)==0) return 0 ; /* end of expr */ -+ -+ for (i = 0; i < sizeof(tokens)/sizeof(struct stoken) ; i++) { -+ int l=strlen(tokens[i].opstr) ; /* check next token vs table */ -+ if(strncmp(lexptr,tokens[i].opstr,l)==0) { -+ lexptr+=l ; -+ yylval.opinfo.opcode = tokens[i].opcode; -+ return tokens[i].token ; -+ } -+ } -+ -+ switch (c = *lexptr) { -+ case '\'': /* char constant, but stored as int (ansi-c) */ -+ p=lexptr++ ; -+ c = *lexptr++ ; -+ if (c == '\\') c=parse_escaped_char(); -+ if( *lexptr++ != '\'') yyerror("Invalid character constant."); -+ yylval.node=mknode_const(src_pos,ctype_int) ; -+ yylval.node->cnst.u.rval_int=c ; -+ strncpyz(yylval.node->cnst.symb_val,p,lexptr-p); /*save the symbol. val*/ -+ return T_CONST ; -+ -+ case '0': /* chk hex */ -+ if(lexptr[1]=='x' || lexptr[1]=='X') { -+ yylval.node=duel_lex_int(); -+ return T_CONST ; -+ } -+ /* fall thru for other numbers */ -+ case '1': case '2': case '3': /* decimal or floating point number */ -+ case '4': case '5': case '6': case '7': case '8': case '9': -+ for(p=lexptr ; *p>='0' && *p<='9' ; p++ ) ; /*find next non digit*/ -+ if(*p=='.' && p[1]!='.' || *p=='e' || *p=='E') -+ yylval.node=duel_lex_float(); -+ else yylval.node=duel_lex_int(); -+ return T_CONST ; -+ -+ case '(': case ')': -+ case '<': case '>': -+ case '[': case ']': -+ case '{': case '}': -+ case '+': case '-': case '*': case '/': case '%': -+ case '|': case '&': case '^': case '~': case '!': -+ case ',': case '?': case ':': case '=': -+ case '.': case '@': case '$': case '#': case '`': case '\\': -+ lexptr++; -+ yylval.opinfo.opcode=c ; -+ return c; -+ case ';': { /* hack, ignore ';' before '}' and else. for C compatability*/ -+ char *save_lexptr= ++lexptr ; -+ int tok=yylex() ; /* hack, call myself for next token */ -+ if(tok=='}' || tok==T_ELSE) { -+ duel_printf("warning: useless ';' ignored\n"); -+ return tok ; -+ } -+ /* else restore position and return the ';' */ -+ lexptr=save_lexptr ; -+ yylval.opinfo.opcode=';' ; -+ yylval.opinfo.src_pos = src_pos ; -+ return ';'; -+ } -+ case '"': { -+ char s[512] ; -+ size_t len=0 ; -+ ttarget_ptr dptr ; -+ tnode *n ; -+ -+ p=lexptr++ ; -+ while((c= *lexptr++)!='"') { -+ if (c == '\\') c=parse_escaped_char(); -+ s[len++]=c ; -+ } -+ s[len++]=0 ; -+ dptr=duel_alloc_target_space(len); -+ duel_put_target_bytes(dptr,s,len); -+ -+ n=mknode_const(src_pos,ctype_charptr); -+ n->cnst.u.rval_ptr=dptr ; -+ len=lexptr-p ; -+ if(len>60) len=60 ; -+ strncpyz(n->cnst.symb_val,p,len); /* save the symbolic val*/ -+ yylval.node=n ; -+ return T_CONST ; -+ } -+ } -+ -+ if(c != '_' && !isalpha(c)) -+ yyerror ("Invalid character in expression."); -+ -+ p=lexptr ; -+ do { c= *++lexptr ; } while(c=='_' || isalnum(c)); -+ -+ for (i = 0; i < sizeof(keywords)/sizeof(struct skeyword) ; i++) { -+ int l=strlen(keywords[i].keyword_str) ; /* check next token vs keywords*/ -+ if(l==lexptr-p && strncmp(p,keywords[i].keyword_str,l)==0) { -+ yylval.opinfo.opcode=keywords[i].opcode ; -+ return keywords[i].token ; -+ } -+ } -+ -+ /* the symbol/name found is not a reserved word, so return it as a T_SYM -+ */ -+ -+ i=lexptr-p ; /* length of string found (symbol/name) */ -+ yylval.nameinfo.src_pos=src_pos ; -+ yylval.nameinfo.name=duel_malloc(i+1); -+ strncpyz(yylval.nameinfo.name,p,i); -+ return T_SYM; -+} -+ -+LPROC yyerror(char *msg) -+{ -+ int i,n=lexptr-inputstr ; -+ duel_printf("%s\n",inputstr); -+ for(i=0 ; i<n ; i++) duel_printf("-"); -+ duel_printf("^ %s\n",msg); -+ duel_abort(); /* terminate parsing. some callers depend on this*/ -+} -+ -+/*************************************************************************/ -+/* utility functions used to parse the expression and build it as a tree */ -+/*************************************************************************/ -+ -+/* mknode_op -- make a tree node of type op with given opcode and kids -+ */ -+ -+LFUNC tnode* mknode_op(top_kind op_kind,topinfo opinfo, -+ tnode *k1,tnode *k2,tnode *k3,tnode *k4) -+{ -+ tnode *n ; -+ duel_assert(opinfo.opcode>' '); -+ n=(tnode *) duel_malloc(sizeof(tnode)); -+ duel_bzero((char*) n,sizeof(tnode)); -+ n->node_kind=NK_OP ; -+ n->op_kind=op_kind ; -+ n->op=opinfo.opcode ; -+ n->src_pos=opinfo.src_pos ; -+ n->kids[0]=k1 ; n->kids[1]=k2 ; n->kids[2]=k3 ; n->kids[3]=k4 ; -+ return n ; -+} -+ -+ -+ /* mknode_const -- make a constant node for the given type. -+ */ -+ -+LFUNC tnode* mknode_const(int src_pos,tctype *ctype) -+{ -+ tnode *n ; -+ n=(tnode *) duel_malloc(sizeof(tnode)); -+ duel_bzero((char*) n,sizeof(tnode)); -+ n->node_kind=NK_CONST ; -+ n->src_pos=src_pos ; -+ n->cnst.val_kind=VK_RVALUE ; -+ n->cnst.ctype=ctype ; -+ return n ; -+} -+ -+ /* mknode_ctype -- make a node of the given c-type. -+ */ -+ -+LFUNC tnode* mknode_ctype(tctype *ctype) -+{ -+ tnode *n ; -+ n=(tnode *) duel_malloc(sizeof(tnode)); -+ duel_bzero((char*) n,sizeof(tnode)); -+ n->node_kind=NK_CTYPE ; -+ n->ctype=ctype ; -+ return n ; -+} -+ -+ /* mknode_name -- make a node of the given name/symbol. -+ * input is pointer to the saved name (on heap) -+ */ -+ -+LFUNC tnode* mknode_name(tnameinfo nameinfo) -+{ -+ tnode *n ; -+ n=(tnode *) duel_malloc(sizeof(tnode)); -+ duel_bzero((char*) n,sizeof(tnode)); -+ n->node_kind=NK_NAME ; -+ n->name=nameinfo.name ; -+ n->src_pos=nameinfo.src_pos ; -+ return n ; -+} -+ -+/* In order to parse C types, which are 'reversed' in the parser, a stack -+ * is used to push abstract declarators, e.g. in (*)() we first push a func -+ * indicator '(' and then push a pointer indicator '*'. for arrays we push -+ * a '[' and the array size. -+ * This stack is popped and a ctype is constructed at the end of the -+ * abstract type parsing. The following functions implement the stack -+ */ -+ -+typedef struct stype_desc { /* stack of type descriptors is made of these */ -+ char desc ; -+ int size ; -+ struct stype_desc *next ; /* next on stack */ -+ } ttype_desc ; -+ -+ttype_desc *top = 0 ; -+ -+ -+LPROC push_type(char desc) /* put desc on the types stack */ -+{ -+ ttype_desc *p = (ttype_desc* ) duel_malloc(sizeof(ttype_desc)); -+ p->desc=desc ; -+ p->size=0 ; -+ p->next=top ; -+ top=p ; -+} -+ -+/* push_type_int -- same as push_type but also set the size parameter, which -+ * is given as a constant node (which is expected to be int) -+ */ -+ -+LPROC push_type_int(char desc,tnode *n) -+{ -+ duel_assert(n->node_kind==NK_CONST); -+ if(n->cnst.ctype != ctype_int || -+ n->cnst.u.rval_int <=0 ) duel_gen_error("Illegal array size",0); -+ push_type(desc); -+ top->size=n->cnst.u.rval_int ; -+} -+ -+LFUNC bool pop_type(char *desc,int *size) /* pop item from stack. */ -+{ -+ ttype_desc *p = top ; -+ if(p==0) return FALSE ; -+ *desc=p->desc ; -+ *size=p->size ; -+ top=p->next ; -+ duel_free(p) ; -+ return TRUE ; -+} -+ -+ -+/* abstract type-modifiers were pushed on a stack. Retrieve -+ * them (reversed) creating type nodes as we go -+ * input: base type (e.g. 'long'). -+ * returns: node of the modified type. -+ * modification is based on the stack of things pushed while parsing. -+ */ -+ -+LFUNC tnode* mknode_modified_ctype(tctype *base) -+{ -+ int size; -+ char tdesc ; /* descriptor of abs decl eg '*' */ -+ tctype *t=base ; /* type under construction */ -+ -+ while(pop_type(&tdesc,&size)) /* pop next abs decl */ -+ switch (tdesc) { -+ case '*': t=duel_mkctype_ptr(t); break ; -+ case '(': t=duel_mkctype_func(t); break ; -+ case '[': t=duel_mkctype_array(t,size); break ; -+ } -+ return mknode_ctype(t) ; -+} -+ -+/* entry point for parsing. the given expression is parsed into the given -+ * node as root. -+ */ -+ -+FUNC tnode* duel_parse(char *s) -+{ -+ lexptr=inputstr=s ; -+ top=0 ; /* reset the types stack */ -+ if(duel_yyparse()) root=NULL ; -+ return root ; -+} ---- gdb/duel/patchlevel.h -+++ gdb/duel/patchlevel.h -@@ -0,0 +1,7 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+#define PATCHLEVEL 4 -+#define VERSION "DUEL 1.20" ---- gdb/duel/print.c -+++ gdb/duel/print.c -@@ -0,0 +1,299 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* handle value/type printing */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.9 93/03/12 06:01:00 mg -+ * cosmetics: tuint for uint, etc. -+ * display union like structs -+ * suport piped output -+ * note for all pointers if illegal, better handling of string bad pointers -+ * -+ * Revision 1.8 93/02/27 06:06:50 mg -+ * removed usage of fabs() so -lm is not required in gdb's linking (HP9000) -+ * -+ * Revision 1.7 93/02/26 05:00:42 mg -+ * fixed display of *p for void *p -+ * -+ * Revision 1.6 93/02/23 20:57:56 mg -+ * *** empty log message *** -+ * -+ * Revision 1.5 93/02/23 19:16:00 mg -+ * improved escaped char support -+ * -+ * Revision 1.4 93/02/03 21:54:49 mg -+ * support "signed char" -+ * -+ * Revision 1.3 93/01/12 21:53:45 mg -+ * cleanup and set for release -+ * -+ * Revision 1.2 93/01/07 00:14:34 mg -+ * print union name -+ * -+ * Revision 1.1 93/01/03 07:31:55 mg -+ * Initial revision -+ * -+ */ -+ -+#include "duel.h" -+ -+/* print type information (no new lines) -+ * parm 'expand' controls expansion level for structs & unions. normally 1. -+ */ -+ -+PROC duel_print_type(tctype *t,int expand) -+{ -+ int i ; -+ tctype *kid=t->u.kid ; -+ -+ switch(t->type_kind) { -+ case CTK_VOID: duel_printf("void ") ; break ; -+ case CTK_CHAR: duel_printf("char ") ; break ; -+ case CTK_SCHAR: duel_printf("schar ") ; break ; -+ case CTK_UCHAR: duel_printf("uchar ") ; break ; -+ case CTK_USHORT: duel_printf("ushort ") ; break ; -+ case CTK_SHORT: duel_printf("short ") ; break ; -+ case CTK_INT: duel_printf("int ") ; break ; -+ case CTK_UINT: duel_printf("uint ") ; break ; -+ case CTK_LONG: duel_printf("long ") ; break ; -+ case CTK_ULONG: duel_printf("ulong ") ; break ; -+ case CTK_LONGLONG: duel_printf("longong ") ; break ; -+ case CTK_ULONGLONG: duel_printf("ulonglong ") ; break ; -+ case CTK_FLOAT: duel_printf("float ") ; break ; -+ case CTK_DOUBLE: duel_printf("double ") ; break ; -+ case CTK_ENUM: duel_printf("enum %s ",t->name); break ; -+ -+ case CTK_PTR: -+ if(ctype_kind_base(kid)) { -+ duel_print_type(kid,0); -+ duel_printf("* "); -+ } -+ else { -+ duel_printf("ptr to "); -+ duel_print_type(kid,expand-1) ; -+ } -+ break ; -+ case CTK_ARRAY: { -+ int n=t->size ; -+ if(kid->size>0) n/=kid->size ; -+ -+ if(ctype_kind_base(kid)) { -+ duel_print_type(kid,0); -+ duel_printf("[%d] ",n); -+ } -+ else { -+ duel_printf("array [%d] of ",n); -+ duel_print_type(kid,expand) ; -+ } -+ } -+ break ; -+ case CTK_FUNC: duel_printf("func returning "); -+ duel_print_type(kid,expand); -+ break ; -+ case CTK_STRUCT: -+ if(expand <= 0) { -+ duel_printf("struct %s ",t->name); -+ break ; -+ } -+ duel_printf("struct %s { ",t->name) ; -+ for(i=0 ; i<t->u.f.fields_no ; i++) { -+ tctype_field *f= &t->u.f.fields[i] ; -+ duel_print_type(f->ctype,expand-1); -+ duel_printf("%s ",f->name); -+ if(f->bitlen != 0) duel_printf(":%d ",f->bitlen); -+ duel_printf("; "); -+ } -+ duel_printf("} ; "); -+ break ; -+ case CTK_UNION: duel_printf("union %s",t->name) ; break ; -+ default: duel_assert(0); -+ } -+} -+ -+/* display char 'c' in a "neat" way, e.g. c='\n' is displayed as such, -+ * etc. Special case for c==quote (normally ' or "), we add '\\' -+ * return a pointer to a static string which is overriden each call etc -+ */ -+char *neat_char(char c,char quote) -+{ -+ static char s[8] ; -+ switch(c) { -+ case '\0': strcpy(s,"\\0"); break ; -+ case '\n': strcpy(s,"\\n"); break ; -+ case '\r': strcpy(s,"\\r"); break ; -+ case '\t': strcpy(s,"\\t"); break ; -+ case '\\': strcpy(s,"\\\\"); break ; -+ default: -+ if(!isprint(c) || !isascii(c)) sprintf(s,"\\%3.3o",c & 0377); -+ else -+ if(c==quote) sprintf(s,"\\%c",c); -+ else sprintf(s,"%c",c); -+ } -+ return s ; -+} -+ -+/* print the given scalar value into string s. -+ * for none-scalar values, print the lval's address. -+ * note: v's value is not modified. -+ */ -+ -+PROC duel_sprint_scalar_value(char *s,tvalue *v) -+{ -+ bool ok ; -+ tvalue rval ; /* copy of v, but as an rval */ -+ rval = *v ; -+ if(v->val_kind==VK_FVALUE) { -+ sprintf(s,"frame(%d)",v->u.fvalue); -+ return ; -+ } -+ if(v->val_kind==VK_LVALUE) { -+ char tmpstr[256],*m="" ; /* tmpstr= temporary for check, m= message */ -+ int sz = v->ctype->size ; /* size of object ref. */ -+ if(sz<1) sz=1 ; -+ if(sz>256) sz=256 ; -+ /* check for null and bad (try read sz bytes at addr ) references */ -+ if(v->u.lvalue==NULL || -+ !duel_get_target_bytes(v->u.lvalue,tmpstr,sz)) m=" [ILLEGAL]" ; -+ -+ switch(v->ctype->type_kind) { -+ case CTK_VOID: sprintf(s,"void @%p%s",v->u.lvalue,m); return; -+ case CTK_STRUCT: sprintf(s,"struct @%p%s",v->u.lvalue,m); return; -+ case CTK_UNION: sprintf(s,"union @%p%s",v->u.lvalue,m); return; -+ case CTK_FUNC: sprintf(s,"func @%p%s",v->u.lvalue,m) ; return; -+ case CTK_ARRAY: -+ if(*m!='\0' || v->ctype->u.kid!=ctype_char) { -+ sprintf(s,"array @%p%s",v->u.lvalue,m); -+ return; -+ } -+ } -+ /* convert scalar type to rvalue */ -+ if(!duel_try_get_rvalue(&rval,"")) { -+ sprintf(s,"ref @%p [ILLEGAL]",v->u.lvalue,m); -+ return ; -+ } -+ } -+ else -+ if(v->val_kind==VK_BVALUE) { -+ if(!duel_try_get_rvalue(&rval,"")) { -+ sprintf(s,"ref @%p [ILLEGAL]",v->u.bvalue.lvalue); -+ return ; -+ } -+ } -+ -+ switch(rval.ctype->type_kind) { /* handle rvalues */ -+ case CTK_VOID: sprintf(s,"void") ; break ; -+ case CTK_CHAR: sprintf(s,"'%s'",neat_char(rval.u.rval_char,'\''));break; -+ case CTK_SHORT: sprintf(s,"%d", rval.u.rval_short) ; break ; -+ case CTK_INT: sprintf(s,"%d", rval.u.rval_int) ; break ; -+ case CTK_LONG: sprintf(s,"%ldL", rval.u.rval_long) ; break ; -+ case CTK_LONGLONG: sprintf(s,"%lldLL", rval.u.rval_longlong) ; break ; -+ case CTK_SCHAR: if(rval.u.rval_schar==0) sprintf(s,"'\\0'"); -+ else sprintf(s,"%d", rval.u.rval_schar) ; break ; -+ case CTK_UCHAR: if(rval.u.rval_uchar==0) sprintf(s,"'\\0'"); -+ else sprintf(s,"'\\x%d'", rval.u.rval_uchar) ; break ; -+ case CTK_USHORT: if(rval.u.rval_ushort==0) sprintf(s,"0"); -+ else sprintf(s,"0x%x", rval.u.rval_ushort) ; break ; -+ case CTK_UINT: if(rval.u.rval_uint==0) sprintf(s,"0"); -+ else sprintf(s,"0x%x", rval.u.rval_uint) ; break ; -+ case CTK_ULONG: if(rval.u.rval_ulong==0L) sprintf(s,"0"); -+ else sprintf(s,"0x%lxUL", rval.u.rval_ulong) ; break ; -+ case CTK_ULONGLONG: if(rval.u.rval_ulonglong==0L) sprintf(s,"0"); -+ else sprintf(s,"0x%llxULL", rval.u.rval_ulonglong) ; break ; -+ case CTK_FLOAT: rval.u.rval_double=rval.u.rval_float ; -+ case CTK_DOUBLE: { double x=rval.u.rval_double ; -+ if(x >= -1e-6 && x <= 1e-6 || x >= 1e8 || x <= -1e8) -+ sprintf(s,"%.4le",x); /* standard 'e' fmt */ -+ else { /* fixed point removing trailing '0'*/ -+ int l; -+ sprintf(s,"%.8lf",x); -+ l=strlen(s)-1; -+ while(s[l]=='0' && s[l-1]!='.') s[l--]=0 ; -+ } -+ } -+ break ; -+ case CTK_PTR: -+ if(rval.u.rval_ptr==NULL) sprintf(s,"NULL"); -+ else { -+ char sval[41]; -+ bool ok=duel_get_target_bytes(rval.u.lvalue,sval,1); -+ if(ok && rval.ctype->u.kid==ctype_char) { -+ int i ; -+ duel_get_target_bytes(rval.u.lvalue,sval,41); -+ strcpy(s,"\""); -+ for(i=0 ; i<40 && sval[i]!='\0' ; i++) -+ strcat(s,neat_char(sval[i],'"')); -+ if(sval[i]=='\0') strcat(s,"\""); -+ else strcat(s,"...\""); -+ } -+ else sprintf(s,"@%p%s",rval.u.rval_ptr,ok? "":" [ILLEGAL]"); -+ } -+ break ; -+ case CTK_ENUM: { -+ int i, n=rval.ctype->u.e.enumerators_no ; -+ tctype_enumerator *e=rval.ctype->u.e.enumerators ; -+ int val=duel_get_int_val(v,""); -+ for(i=0 ; i<n ; i++) -+ if(e[i].val == val) { strcpy(s,e[i].name); return ;} -+ sprintf(s,"%d",val); -+ } -+ break ; -+ default: duel_assert(0); -+ } -+} -+ -+/* print the given value, symbolic+val. Handles structures */ -+ -+PROC duel_print_value(tvalue *v) -+{ -+ tctype *t=v->ctype ; -+ int i ; -+ bool topipe=duel_output_pipe_style ; -+ char s[160]; -+ -+ duel_printf(topipe? "$$$SYM: %s\n":"%s",v->symb_val); -+ -+ if(duel_debug && !topipe) { -+ duel_printf("`` %s '' ",v->symb_val); -+ duel_printf("{ "); -+ duel_print_type(v->ctype,2); -+ duel_printf("} "); -+ if(v->val_kind==VK_LVALUE) { -+ duel_printf("lval @%p",v->u.lvalue); -+ } -+ else -+ if(v->val_kind==VK_BVALUE) { -+ duel_printf("bval @%p [%d,%d]",v->u.bvalue.lvalue,v->u.bvalue.bitpos, -+ v->u.bvalue.bitlen); -+ } -+ duel_printf("\n"); -+ } -+ -+ duel_sprint_scalar_value(s,v); -+ if(v->val_kind==VK_LVALUE && strstr(s,"ILLEGAL")==NULL) { -+ switch(t->type_kind) { -+ case CTK_UNION: -+ case CTK_STRUCT: -+ duel_printf(topipe? "$$$VAL: { " : " = { "); -+ for(i=0 ; i<t->u.f.fields_no ; i++) { -+ tvalue u ; -+ char *name=t->u.f.fields[i].name ; -+ duel_get_dot_name(v,name,&u); -+ duel_sprint_scalar_value(s,&u); -+ duel_printf("%s = %s",name,s) ; -+ if(i < t->u.f.fields_no-1) duel_printf(", "); -+ } -+ duel_printf(" }\n"); -+ return ; -+ case CTK_ARRAY: ; /* not handled except for char[] as scalar*/ -+ } -+ } -+ -+ if(topipe) duel_printf("$$$VAL: %s",s); -+ else -+ if(strcmp(v->symb_val,s)!=0) duel_printf(" = %s",s); -+ duel_printf("\n"); -+} ---- gdb/duel/proto.h -+++ gdb/duel/proto.h -@@ -0,0 +1,101 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* prototypes for all of duel's global functions */ -+ -+FUNC tctype* duel_mkctype_ptr(tctype *t); -+FUNC tctype* duel_mkctype_func(tctype *t); -+FUNC tctype* duel_mkctype_array(tctype *t,int size); -+FUNC tctype* duel_mkctype_struct(char *name,size_t size,int fields_no, -+ bool is_union); -+PROC duel_mkctype_struct_field(tctype *t,int field_no,char *name, -+ int bitpos,int bitlen, tctype *fctype); -+FUNC tctype* duel_mkctype_enum(char *name,tctype_kind real_type_kind, -+ size_t size,int enumerators_no); -+PROC duel_mkctype_enumerator(tctype *t,int enumerator_no,char *name,int val); -+ -+PROC duel_init_basic_ctypes(void); -+ -+PROC duel_print_value(tvalue *v); -+PROC duel_print_type(tctype *t,int expand); -+PROC duel_sprint_scalar_value(char *s,tvalue *v); -+ -+ -+PROC duel_fatal(char *msg); -+PROC duel_abort(void); -+PROC duel_cleanup(void *); -+ -+FUNC tnode* duel_parse(char *s); -+ -+ -+PROC duel_reset_eval(void); -+FUNC bool duel_eval(tnode *n,tvalue *v); -+FUNC bool duel_get_dot_name(tvalue *v,char *name,tvalue *ret); -+ -+FUNC tnode* duel_set_eval_loc(tnode *n); -+FUNC char* duel_set_input_string(char *s); -+PROC duel_op_error(char *mesg,char *op,tvalue *v1,tvalue *v2); -+PROC duel_gen_error(char *mesg,char *arg1); -+ -+PROC duel_parse_and_eval(char *s); -+ -+FUNC bool duel_try_get_rvalue(tvalue *v,char *op); -+PROC duel_standardize_func_parm(tvalue *p); -+FUNC bool duel_do_op_to(tvalue *v1,tvalue *v2,int n,tvalue *r); -+PROC duel_do_cast(tctype *tout,tvalue *v); -+FUNC bool duel_mk_logical(tvalue *v,char *op); -+PROC duel_set_symb_val(tvalue *r,char *format,tvalue *v1,tvalue *v2); -+PROC duel_get_struct_val(tvalue *v,char *op); -+PROC duel_get_struct_ptr_val(tvalue *v,char *op); -+FUNC int duel_get_int_val(tvalue *v,char *op); -+FUNC int duel_get_posint_val(tvalue *v,char *op); -+PROC duel_apply_unary_op(topcode op,tvalue *v); -+PROC duel_apply_post_unary_op(topcode op,tvalue *v); -+FUNC bool duel_apply_bin_op(topcode op,tvalue *v1,tvalue *v2,tvalue *r); -+PROC duel_find_func_frame(tvalue *v,char *op); -+ -+/* output management */ -+ -+PROC duel_printf(char *fmt, ...); -+PROC duel_flush(void); -+PROC duel_redirectable_output_start(char *); -+PROC duel_redirectable_output_end(void); -+PROC duel_redirectable_output_abort(void); -+PROC duel_redirectable_output_init(void); -+ -+/* debugger dependent functions */ -+ -+FUNC void* duel_malloc(size_t size); -+PROC duel_free(void *); -+ -+FUNC bool duel_get_target_bytes(ttarget_ptr from,void *to,size_t n); -+FUNC bool duel_put_target_bytes(ttarget_ptr to,void *from,size_t n); -+ -+FUNC bool duel_get_target_bitfield(ttarget_ptr struct_at,int bitpos, -+ int bitlen,void *to,tctype_kind tkind); -+FUNC bool duel_get_target_variable(char *name, int frame_no, tvalue *v); -+FUNC tctype* duel_get_target_typedef(char *name); -+FUNC tctype* duel_get_target_struct_tag(char *name); -+FUNC tctype* duel_get_target_union_tag(char *name); -+FUNC tctype* duel_get_target_enum_tag(char *name); -+FUNC ttarget_ptr duel_alloc_target_space(size_t n); -+ -+FUNC int duel_get_frames_number(void); -+FUNC ttarget_ptr duel_get_function_for_frame(int frame_no); -+PROC duel_target_func_call(tvalue *func, tvalue *parms[], -+ int parms_no,tvalue *ret); -+ -+/* prototypes for misc functions */ -+ -+FUNC char* strncpyz(char *to,char *from,size_t len); -+ -+PROC duel_free_val_list(tval_list *l); -+PROC duel_free_nodes(tnode *); -+ -+FUNC tvalue* duel_find_alias(char *name); -+PROC duel_set_alias(char *name,tvalue *v); -+PROC duel_clear_aliases(void); -+PROC duel_show_aliases(void); -+ ---- gdb/duel/tsuite.c -+++ gdb/duel/tsuite.c -@@ -0,0 +1,64 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* this is a test program to be used with tsuite.gdb */ -+ -+#include <stdlib.h> -+#include <stdio.h> -+#include <string.h> -+ -+int gint ; -+typedef unsigned int uint ; -+ -+struct { int a,b ; char *name ; } emp[100] ; -+enum { MIKI, DAVE, ELA } us ; -+struct snode { int code ; struct snode *left,*right ; } ; -+typedef struct snode tnode ; -+ -+/* amazing, but DEC compiled strcmp such that gdb thinks it returns void */ -+int mystrcmp(s,t) char *s; char *t; { return strcmp(s,t); } -+ -+void main() -+{ -+ char *s="main string" ; -+ FILE *out=stdout ; /* stdout is not a variable on some machines */ -+ /* will use fflush(out) from debugger */ -+ int i ; -+ tnode *root,*p,**q ; -+ -+ for(i=0 ; i<100 ; i++) { -+ emp[i].a=i ; emp[i].b=i*i ; -+ emp[i].name=(char*) malloc(10); -+ sprintf(emp[i].name,"emp%3.3d",i); -+ } -+ emp[53].a=76 ; /* bug */ -+ emp[36].b-- ; /* bug */ -+ emp[74].name[3]='5' ; /* another bug */ -+ -+ root=(tnode*) malloc(sizeof(tnode)); -+ root->left=root->right=0 ; -+ root->code=5000 ; -+ for(i=1 ; i<10000 ; i++) { /* insert elements into tree */ -+ int code=((i*997*1013)>>10)%11000 ; /* "fixed" "random" generaor */ -+ if(code<0) code= -code ; -+ p=root ; -+ while(p) { -+ if(p->code==code) break ; -+ if(p->code<code) q= &p->right, p=p->right ; -+ else q= &p->left, p=p->left ; -+ } -+ if(p==0) { -+ p=(tnode*) malloc(sizeof(tnode)); -+ p->code=code ; -+ if(i>8680) p->code+=(i<9210)? 1:-1 ; /* bug */ -+ p->left=p->right=0 ; -+ *q=p ; -+ } -+ } -+ -+ printf("trivial tsuite program\n"); -+ printf("trivial tsuite program\n"); -+} -+ ---- gdb/duel/tsuite.gdb -+++ gdb/duel/tsuite.gdb -@@ -0,0 +1,126 @@ -+set prompt -+## DUEL - A Very High Level Debugging Langauge. -+## Public domain code -+## Written by Michael Golan mg@cs.princeton.edu -+##$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $ -+## -+## test suite for duel, can be used with duelself or gdb -+## -+file tsuite -+b 60 -+b 61 -+r -+## check constants -+dl (1..5)*(2,(double) 2/3) -+## declare array x, set it, search it -+dl int x[100] ; -+dl x[0..99]= -1 ; -+dl x[i:=20..40]=2+i*i ; -+dl x[20..23,38..40] -+dl x[..100] >=? 33*33 <=? 35*35 -+dl x[..100]=> ((_>=33*33) & (_<= 35*35)) ==? 1 -+dl (*(x+(7..9)))++ -+dl y:= &x[7] ; -+dl y[0..2] -+dl x+7 == y -+dl (x[..99]>?0)@(_>100) -+dl printf("%d\n",1..10); -+dl printf("x is: "); printf("%d, ",x[0..99]>? 0); printf("\n");fflush(out); -+dl int j ; for(j=0 ; j<100 ; j++) if(x[j]>37*37) printf("x[%d]=%d\n",j,x[j]);fflush(out); -+dl printf("%d\n",1..5); -+## check void type -+dl void *p -+dl p = &p -+dl p,*p -+## errors -+dl 1e+++3 -+dl i=4 ; -+dl x=6 ; -+dl x++ ; -+dl --i ; -+## cleanup -+dl alias -+dl clear -+## access some variables -+dl s -+dl s[4..8] -+dl s[6..]@0 -+dl l:=#/s[0..]@0 -+dl s[l-2..l] -+dl gint -+dl gint++ -+dl gint++ -+dl --gint -+dl gint -+dl main.s -+dl ++main.s -+dl main ==? main -+dl main == main -+dl frames_no -+dl frame(0).s -+dl frame(0).(gint+0) -+dl sizeof(gint) -+dl sizeof(T uint) -+dl sizeof(T uint*) -+dl sizeof(T emp) -+dl sizeof(emp) -+dl sizeof(emp[0]) -+dl (uint)-1 -+dl (uint*)(gint=gint-9) -+dl *(uint*)&gint -+dl T uint myuint ; myuint = -1 -+## some errors -+dl frame(0).gint -+dl frame(0).(gint) -+dl frame(0).ha -+dl sizeof(uint) -+dl sizeof gint -+dl main == printf -+dl main+1 -+dl main > printf -+dl printf+3 -+dl T int x -+dl uint y -+dl T uint z = 5 -+## finally, do some serious checks using the bugs in the programs -+dl emp[4] -+dl emp[k:=..100].a !=? k -+dl (emp[k:=..100].a !=? k)[[0]] ; emp[{k}] -+dl emp[k:=..100].if(a!=k) _ -+dl emp[k:=..100].b !=? k*k -+dl emp[k:=..100].if(b!=k*k) _,{k}*{k} -+dl emp[k:=..100]=>if(_.b!=k*k) _,{k}*{k} -+dl char s[80]; -+dl ..100 => (sprintf(s,"emp%3.3d",_) ; emp[_].name[0..]@0#j !=? s[j]) -+dl ..100 => (sprintf(s,"emp%3.3d",_) ; mystrcmp(emp[_].name,s)!=?0) -+dl ..100 => (sprintf(s,"emp%3.3d",_) ; emp[_].name=>if(mystrcmp(_,s))_) -+## now, lets try some pointers and --> stuff! -+dl root-->left[[..8]]->code -+dl root-->(left,right)[[..30]]->code -+dl #/root-->(left,right) -+dl root->(left,right) => #/_-->(left,right) -+dl root->(left->left,left->right,right->left,right->right)=> #/_-->(left,right) -+## this cause very long symbolic vals, core dump/bad results before duel 1.10.3 -+dl #/(root+0000000000000000000000000000000000000000000000000000)-->(left,right) -+## compute min, max, check for dups, no-show -+dl root-->left[[#/root-->left-1]]->code -+dl root-->right[[#/root-->right-1]]->code -+dl int codes[11000] ; codes[..11000]=0 ; codes[root-->(left,right)->code]++ ; -+dl codes[..11000] >? 1 -+dl (codes[..11000] ==? 0 )[[..10]] -+dl (..11000 => if(!codes[_]) _)[[..10]] -+## check consistency -+dl root-->(left,right)->((left!=?0)->code >=? code, (right!=?0)->code <=? code) -+dl root-->(left,right)->((left!=?0)->code>=code, (right!=?0)->code<=code)==?1 -+dl (1000..=>if(&&/( 2,3.._-1 =>__%_)) _)[[..10]] -+## enums -+dl ELA -+dl (T us) 1 -+dl us=1 ; us -+dl MIKI..ELA -+## more errors -+dl emp[0]=us -+dl emp=us -+dl us=emp -+## the end -+ ---- gdb/duel/tsuite.gdb.out -+++ gdb/duel/tsuite.gdb.out -@@ -0,0 +1,293 @@ -+GDB is free software and you are welcome to distribute copies of it -+ under certain conditions; type "show copying" to see the conditions. -+There is absolutely no warranty for GDB; type "show warranty" for details. -+GDB 4.8, Copyright 1993 Free Software Foundation, Inc. -+(gdb) Reading symbols from tsuite...done. -+ Breakpoint 1 at 0x400518: file tsuite.c, line 60. -+ Note: breakpoint 1 also set at pc 0x400518. -+Breakpoint 2 at 0x400518: file tsuite.c, line 61. -+ Starting program: /tmp_mnt/n/fs/grad2/mg/duel/tsuite/tsuite -+ -+Breakpoint 1, main () at tsuite.c:61 -+61 printf("trivial tsuite program\n"); -+ DUEL 1.10.4, public domain debugging language. "dl" for help -+1*2 = 2 -+1*(2/3) = 0.66666667 -+2*2 = 4 -+2*(2/3) = 1.33333333 -+3*2 = 6 -+3*(2/3) = 2.0 -+4*2 = 8 -+4*(2/3) = 2.66666667 -+5*2 = 10 -+5*(2/3) = 3.33333333 -+ x[20] = 402 -+x[21] = 443 -+x[22] = 486 -+x[23] = 531 -+x[38] = 1446 -+x[39] = 1523 -+x[40] = 1602 -+ x[33] = 1091 -+x[34] = 1158 -+ (x[33]>=33*33)&(x[33]<=35*35) = 1 -+(x[34]>=33*33)&(x[34]<=35*35) = 1 -+ (*(x+7))++ = -1 -+(*(x+8))++ = -1 -+(*(x+9))++ = -1 -+ y[0] = 0 -+y[1] = 0 -+y[2] = 0 -+ x+7==y = 1 -+ 1 -+2 -+3 -+4 -+5 -+6 -+7 -+8 -+9 -+10 -+x is: 402, 443, 486, 531, 578, 627, 678, 731, 786, 843, 902, 963, 1026, 1091, 1158, 1227, 1298, 1371, 1446, 1523, 1602, -+ x[37]=1371 -+x[38]=1446 -+x[39]=1523 -+x[40]=1602 -+ &p = @10020020 -+ p = @10020020 -+*p = void @10020020 -+ 1e+++3 -+^ Invalid float constant. -+ Error: i=4 ; -+ -^-- operand x is not an lvalue for operator 'x=y' -+operand ``i'' -- type: int -+ -- value: 40 -+ Error: x=6 ; -+ -^-- bad operand x type for operator 'x=y' -+operand ``x'' -- type: int [100] -+ -- value: array @1001f000 -+ Error: x++ ; -+ -^-- operand x of '++' is not integral -+operand ``x'' -- type: int [100] -+ -- value: array @1001f000 -+ Error: --i ; -+ ^-- operand of '--' must be an lvalue -+operand ``i'' -- type: int -+ -- value: 40 -+ Aliases table: -+p: p = @10020020 -+j: j = 100 -+y: &x[7] = @1001f01c -+i: 40 -+x: x = array @1001f000 -+ Aliases table cleared -+ s = "main string" -+ s[4] = ' ' -+s[5] = 's' -+s[6] = 't' -+s[7] = 'r' -+s[8] = 'i' -+ s[6] = 't' -+s[7] = 'r' -+s[8] = 'i' -+s[9] = 'n' -+s[10] = 'g' -+ #/(s[0] ...) = 11 -+ s[9] = 'n' -+s[10] = 'g' -+s[11] = '\0' -+ gint = 0 -+ gint++ = 0 -+ gint++ = 1 -+ gint = 1 -+ gint = 1 -+ main.s = "main string" -+ main.s = "ain string" -+ main = func @004001f0 -+ main==main = 1 -+ frames_no = 1 -+ frame(0).s = "ain string" -+ frame(0).(gint+0) = 1 -+ sizeof(gint) = 0x4 -+ sizeof(unsigned int) = 0x4 -+ sizeof(T) = 0x4 -+ sizeof(T) = 0x4b0 -+ sizeof(emp) = 0x4b0 -+ sizeof(emp[0]) = 0xc -+ -1 = 0xffffffff -+ (gint-9) = @fffffff8 [ILLEGAL] -+ *&gint = 0xfffffff8 -+ -1 = 0xffffffff -+ Error: frame(0).gint -+ --------^-- field not found in operator '.' -+operand ``frame(0)'' -- type: int -+ -- value: frame(0) -+ frame(0).(gint) -+---------------^ syntax error -+ Error: frame(0).ha -+ --------^-- field not found in operator '.' -+operand ``frame(0)'' -- type: int -+ -- value: frame(0) -+ Error: sizeof(uint) -+ -------^-- variable 'uint' not found -+ sizeof gint -+-----------^ syntax error -+ Error: main == printf -+ -----^-- incompatible types for op == -+operand1 ``main'' -- type: ptr to func returning void -+ -- value: @004001f0 -+operand2 ``printf'' -- type: ptr to func returning int -+ -- value: @00400ca0 -+ Error: main+1 -+ ----^-- unknown pointer object size for '+' op -+operand ``main'' -- type: ptr to func returning void -+ -- value: @004001f0 -+ Error: main > printf -+ -----^-- incompatible types for op > -+operand1 ``main'' -- type: ptr to func returning void -+ -- value: @004001f0 -+operand2 ``printf'' -- type: ptr to func returning int -+ -- value: @00400ca0 -+ Error: printf+3 -+ ------^-- unknown pointer object size for '+' op -+operand ``printf'' -- type: ptr to func returning int -+ -- value: @00400ca0 -+ T int x -+-----^ syntax error -+ uint y -+------^ syntax error -+ T uint z = 5 -+----------^ syntax error -+ emp[4] = { a = 4, b = 16, name = "emp004" } -+ emp[53].a = 76 -+ emp[53] = { a = 76, b = 2809, name = "emp053" } -+ emp[53] = { a = 76, b = 2809, name = "emp053" } -+ emp[36].b = 1295 -+ emp[36] = { a = 36, b = 1295, name = "emp036" } -+emp[36].36*36 = 1296 -+ emp[36] = { a = 36, b = 1295, name = "emp036" } -+36*36 = 1296 -+ (emp[74].name[3]) = '5' -+ (mystrcmp(emp[74].name,s)) = 5 -+ (emp[74].name) = "emp574" -+ root->code = 5000 -+root->left->code = 986 -+root-->left[[2]]->code = 835 -+root-->left[[3]]->code = 684 -+root-->left[[4]]->code = 533 -+root-->left[[5]]->code = 383 -+root-->left[[6]]->code = 232 -+root-->left[[7]]->code = 81 -+ root->code = 5000 -+root->left->code = 986 -+root-->left[[2]]->code = 835 -+root-->left[[3]]->code = 684 -+root-->left[[4]]->code = 533 -+root-->left[[5]]->code = 383 -+root-->left[[6]]->code = 232 -+root-->left[[7]]->code = 81 -+root-->left[[8]]->code = 12 -+root-->left[[9]]->code = 2 -+root-->left[[9]]->right->code = 5 -+root-->left[[9]]->right->left->code = 4 -+root-->left[[9]]-->right[[2]]->code = 11 -+root-->left[[9]]-->right[[2]]->left->code = 8 -+root-->left[[9]]-->right[[2]]-->left[[2]]->code = 7 -+root-->left[[9]]-->right[[2]]->left->right->code = 10 -+root-->left[[8]]->right->code = 24 -+root-->left[[8]]->right->left->code = 15 -+root-->left[[8]]->right-->left[[2]]->code = 14 -+root-->left[[8]]->right->left->right->code = 17 -+root-->left[[8]]->right->left->right->left->code = 16 -+root-->left[[8]]->right->left-->right[[2]]->code = 23 -+root-->left[[8]]->right->left-->right[[2]]->left->code = 20 -+root-->left[[8]]->right->left-->right[[2]]-->left[[2]]->code = 19 -+root-->left[[8]]->right->left-->right[[2]]->left->right->code = 22 -+root-->left[[8]]->right->left-->right[[2]]->left->right->left->code = 21 -+root-->left[[8]]-->right[[2]]->code = 36 -+root-->left[[8]]-->right[[2]]->left->code = 27 -+root-->left[[8]]-->right[[2]]->left->right->code = 35 -+root-->left[[8]]-->right[[2]]->left->right->left->code = 32 -+ #/(root ...) = 7144 -+ #/(root->left ...) = 3249 -+#/(root->right ...) = 3894 -+ #/(root->(left->left) ...) = 641 -+#/(root->(left->right) ...) = 2607 -+#/(root->(right->left) ...) = 595 -+#/(root->(right->right) ...) = 3298 -+ #/((root+0000000000000000000000000000000000000000000000000000) ...) = 7144 -+ root-->left[[9]]->code = 2 -+ root-->right[[14]]->code = 10999 -+ codes[2122] = 2 -+codes[2308] = 2 -+codes[5081] = 2 -+codes[5267] = 2 -+codes[8040] = 2 -+codes[9026] = 2 -+codes[9363] = 2 -+ (codes[0]) = 0 -+(codes[1]) = 0 -+(codes[3]) = 0 -+(codes[6]) = 0 -+(codes[9]) = 0 -+(codes[13]) = 0 -+(codes[18]) = 0 -+(codes[25]) = 0 -+(codes[26]) = 0 -+(codes[29]) = 0 -+ 0 -+1 -+3 -+6 -+9 -+13 -+18 -+25 -+26 -+29 -+ root->left-->right[[2]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code) = 2122 -+root->left-->right[[2]]-->left[[5]]-->right[[3]]->left->right->left->right->(left->code) = 2308 -+root->right-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code) = 5081 -+root->right-->left[[5]]-->right[[3]]->left->right->left->right->(left->code) = 5267 -+root-->right[[4]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code) = 8040 -+root-->right[[5]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code) = 9026 -+root-->right[[5]]-->left[[4]]-->right[[3]]->left->right->left->right->(left->code) = 9363 -+ root->left-->right[[2]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code<=code) = 1 -+root->left-->right[[2]]-->left[[5]]-->right[[3]]->left->right->left->right->(left->code>=code) = 1 -+root->right-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code<=code) = 1 -+root->right-->left[[5]]-->right[[3]]->left->right->left->right->(left->code>=code) = 1 -+root-->right[[4]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code<=code) = 1 -+root-->right[[5]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code<=code) = 1 -+root-->right[[5]]-->left[[4]]-->right[[3]]->left->right->left->right->(left->code>=code) = 1 -+ 1009 -+1013 -+1019 -+1021 -+1031 -+1033 -+1039 -+1049 -+1051 -+1061 -+ ELA -+ 1 = DAVE -+ us = DAVE -+ 0 -+1 -+2 -+ Error: emp[0]=us -+ ------^-- incompatible types for op x=y -+operand1 ``emp[0]'' -- type: struct .F13 { int a ; int b ; char * name ; } ; -+ -- value: struct @10001510 -+operand2 ``us'' -- type: enum .F14 -+ -- value: DAVE -+ Error: emp=us -+ ---^-- bad operand x type for operator 'x=y' -+operand ``emp'' -- type: array [100] of struct .F13 { int a ; int b ; char * name ; } ; -+ -- value: array @10001510 -+ Error: us=emp -+ --^-- operand x of 'y=x' is not numeric -+operand ``emp'' -- type: array [100] of struct .F13 { int a ; int b ; char * name ; } ; -+ -- value: array @10001510 -+ ---- gdb/duel/tsuite.self -+++ gdb/duel/tsuite.self -@@ -0,0 +1,111 @@ -+## DUEL - A Very High Level Debugging Langauge. -+## Public domain code -+## Written by Michael Golan mg@cs.princeton.edu -+## $Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $ -+ -+## -+## test suite for duel, can be used with duelself or gdb -+## -+ -+## check constants -+(1..5)*(2,(double) 2/3) -+ -+## declare array x, set it, search it -+ -+int x[100] ; -+x[0..99]= -1 ; -+x[i:=20..40]=2+i*i ; -+x[20..23,38..40] -+x[..100] >=? 33*33 <=? 35*35 -+x[..100]=> ((_>=33*33) & (_<= 35*35)) ==? 1 -+x -+x+5 -+*(x+7..9)++ -+*(x+(7..9))++ -+(*(x+(7..9)))++ -+y:= &x[7] ; -+y[0..2] -+x+7 == y -+(x[..99]>?0)@(_>500) -+ -+printf("x is: "); printf("%d, ",x[0..99]>? 0); printf("\n"); -+int j ; for(j=0 ; j<100 ; j++) if(x[j]>37*37) printf("x[%d]=%d\n",j,x[j]); -+ -+printf("%d, ",1..5); printf("\n"); -+ -+## check void type -+void *p -+p = &p -+p,*p -+ -+## errors -+ -+1e++4 -+& &x -+i=4 ; -+x=6 ; -+x++ ; -+--i ; -+ -+## cleanup -+ -+alias -+clear -+ -+## access some variables -+s -+s[3..7] -+s[5..]@0 -+l:=#/s[0..]@0 -+s[l-2..l] -+ -+gint -+gint++ -+gint++ -+--gint -+gint -+main.s -+main.s++ -+main.s++ -+ -+main -+printf -+main ==? main -+main == main -+ -+frames_no -+frame(0).s -+ -+## gint is a global, not local fro main in frame 0 -+frame(0).gint -+## but when we eval (expr) under frame 0 scope, we find it ok. -+frame(0).(gint) -+ -+T uint myuint ; myuint = -1 -+ -+sizeof(int) -+sizeof(long) -+sizeof(int *) -+sizeof(signed char*) -+sizeof() -+sizeof(gint) -+sizeof gint -+sizeof gint+1 -+## some errors -+ -+main == main -+main == printf -+ -+main+1 -+malloc[4] -+printf+3 -+ -+T int x -+int x -+uint y -+T uint y = 5 -+T uint y -+ -+## the end -+ -+ ---- gdb/duel/tsuite.self.out -+++ gdb/duel/tsuite.self.out -@@ -0,0 +1,263 @@ -+dl> ## DUEL - A Very High Level Debugging Langauge. -+dl> ## Public domain code -+dl> ## Written by Michael Golan mg@cs.princeton.edu -+dl> -+dl> ## -+dl> ## test suite for duel, can be used with duelself or gdb -+dl> ## -+dl> -+dl> ## check constants -+dl> (1..5)*(2,(double) 2/3) -+DUEL 1.10.4, public domain debugging language. "dl" for help -+1*2 = 2 -+1*(2/3) = 0.66666667 -+2*2 = 4 -+2*(2/3) = 1.33333333 -+3*2 = 6 -+3*(2/3) = 2.0 -+4*2 = 8 -+4*(2/3) = 2.66666667 -+5*2 = 10 -+5*(2/3) = 3.33333333 -+dl> -+dl> ## declare array x, set it, search it -+dl> -+dl> int x[100] ; -+dl> x[0..99]= -1 ; -+dl> x[i:=20..40]=2+i*i ; -+dl> x[20..23,38..40] -+x[20] = 402 -+x[21] = 443 -+x[22] = 486 -+x[23] = 531 -+x[38] = 1446 -+x[39] = 1523 -+x[40] = 1602 -+dl> x[..100] >=? 33*33 <=? 35*35 -+x[33] = 1091 -+x[34] = 1158 -+dl> x[..100]=> ((_>=33*33) & (_<= 35*35)) ==? 1 -+(x[33]>=33*33)&(x[33]<=35*35) = 1 -+(x[34]>=33*33)&(x[34]<=35*35) = 1 -+dl> x -+x = array @10014000 -+dl> x+5 -+x+5 = @10014014 -+dl> *(x+7..9)++ -+Error: *(x+7..9)++ -+ -----^-- operand x of 'x..y' is not integral -+operand ``x+7'' -- type: int * -+ -- value: @1001401c -+dl> *(x+(7..9))++ -+Error: *(x+(7..9))++ -+ -----------^-- operand of '++' must be an lvalue -+operand ``(x+7)'' -- type: int * -+ -- value: @1001401c -+dl> (*(x+(7..9)))++ -+(*(x+7))++ = -1 -+(*(x+8))++ = -1 -+(*(x+9))++ = -1 -+dl> y:= &x[7] ; -+dl> y[0..2] -+y[0] = 0 -+y[1] = 0 -+y[2] = 0 -+dl> x+7 == y -+x+7==y = 1 -+dl> (x[..99]>?0)@(_>500) -+(x[20]) = 402 -+(x[21]) = 443 -+(x[22]) = 486 -+dl> -+dl> printf("x is: "); printf("%d, ",x[0..99]>? 0); printf("\n"); -+x is: 402, 443, 486, 531, 578, 627, 678, 731, 786, 843, 902, 963, 1026, 1091, 1158, 1227, 1298, 1371, 1446, 1523, 1602, -+dl> int j ; for(j=0 ; j<100 ; j++) if(x[j]>37*37) printf("x[%d]=%d\n",j,x[j]); -+x[37]=1371 -+x[38]=1446 -+x[39]=1523 -+x[40]=1602 -+dl> -+dl> printf("%d, ",1..5); printf("\n"); -+1, 2, 3, 4, 5, -+dl> -+dl> ## check void type -+dl> void *p -+dl> p = &p -+&p = @10012138 -+dl> p,*p -+p = @10012138 -+*p = void @10012138 -+dl> -+dl> ## errors -+dl> -+dl> 1e++4 -+1e++4 -+^ Invalid float constant. -+dl> & &x -+Error: & &x -+ ^-- operand x of '&x' is not a lvalue -+operand ``&x'' -- type: ptr to int [100] -+ -- value: @10014000 -+dl> i=4 ; -+Error: i=4 ; -+ -^-- operand x is not an lvalue for operator 'x=y' -+operand ``i'' -- type: int -+ -- value: 40 -+dl> x=6 ; -+Error: x=6 ; -+ -^-- bad operand x type for operator 'x=y' -+operand ``x'' -- type: int [100] -+ -- value: array @10014000 -+dl> x++ ; -+Error: x++ ; -+ -^-- operand x of '++' is not integral -+operand ``x'' -- type: int [100] -+ -- value: array @10014000 -+dl> --i ; -+Error: --i ; -+ ^-- operand of '--' must be an lvalue -+operand ``i'' -- type: int -+ -- value: 40 -+dl> -+dl> ## cleanup -+dl> -+dl> alias -+Aliases table: -+p: p = @10012138 -+j: j = 100 -+y: &x[7] = @1001401c -+i: 40 -+x: x = array @10014000 -+dl> clear -+Aliases table cleared -+dl> -+dl> ## access some variables -+dl> s -+s = "main string" -+dl> s[3..7] -+s[3] = 'n' -+s[4] = ' ' -+s[5] = 's' -+s[6] = 't' -+s[7] = 'r' -+dl> s[5..]@0 -+s[5] = 's' -+s[6] = 't' -+s[7] = 'r' -+s[8] = 'i' -+s[9] = 'n' -+s[10] = 'g' -+dl> l:=#/s[0..]@0 -+#/(s[0] ...) = 11 -+dl> s[l-2..l] -+s[9] = 'n' -+s[10] = 'g' -+s[11] = '\0' -+dl> -+dl> gint -+gint = 0 -+dl> gint++ -+gint++ = 0 -+dl> gint++ -+gint++ = 1 -+dl> --gint -+gint = 1 -+dl> gint -+gint = 1 -+dl> main.s -+main.s = "main string" -+dl> main.s++ -+main.s++ = "main string" -+dl> main.s++ -+main.s++ = "ain string" -+dl> -+dl> main -+main = func @00400918 -+dl> printf -+printf = func @004112b0 -+dl> main ==? main -+main = func @00400918 -+dl> main == main -+main==main = 1 -+dl> -+dl> frames_no -+frames_no = 1 -+dl> frame(0).s -+frame(0).s = "in string" -+dl> -+dl> ## gint is a global, not local fro main in frame 0 -+dl> frame(0).gint -+Error: frame(0).gint -+ --------^-- field not found in operator '.' -+operand ``frame(0)'' -- type: int -+ -- value: frame(0) -+dl> ## but when we eval (expr) under frame 0 scope, we find it ok. -+dl> frame(0).(gint) -+frame(0).(gint) -+---------------^ syntax error -+dl> -+dl> T uint myuint ; myuint = -1 -+-1 = 0xffffffff -+dl> -+dl> sizeof(int) -+sizeof(int) = 0x4 -+dl> sizeof(long) -+sizeof(long) = 0x4 -+dl> sizeof(int *) -+sizeof(T) = 0x4 -+dl> sizeof(signed char*) -+sizeof(T) = 0x4 -+dl> sizeof() -+sizeof() -+--------^ syntax error -+dl> sizeof(gint) -+sizeof(gint) = 0x4 -+dl> sizeof gint -+sizeof gint -+-----------^ syntax error -+dl> sizeof gint+1 -+sizeof gint+1 -+-----------^ syntax error -+dl> ## some errors -+dl> -+dl> main == main -+main==main = 1 -+dl> main == printf -+Error: main == printf -+ -----^-- incompatible types for op == -+operand1 ``main'' -- type: ptr to func returning void -+ -- value: @00400918 -+operand2 ``printf'' -- type: ptr to func returning int -+ -- value: @004112b0 -+dl> -+dl> main+1 -+Error: main+1 -+ ----^-- unknown pointer object size for '+' op -+operand ``main'' -- type: ptr to func returning void -+ -- value: @00400918 -+dl> malloc[4] -+Error: malloc[4] -+ ------^-- unknown pointer object size for '+' op -+operand ``malloc'' -- type: ptr to func returning void * -+ -- value: @00411310 -+dl> printf+3 -+Error: printf+3 -+ ------^-- unknown pointer object size for '+' op -+operand ``printf'' -- type: ptr to func returning int -+ -- value: @004112b0 -+dl> -+dl> T int x -+T int x -+-----^ syntax error -+dl> int x -+dl> uint y -+uint y -+------^ syntax error -+dl> T uint y = 5 -+T uint y = 5 -+----------^ syntax error -+dl> T uint y -+dl> -+dl> ## the end -+dl> -+dl> ---- gdb/duel/types.c -+++ gdb/duel/types.c -@@ -0,0 +1,200 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* this module contains the duel type system management -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.8 93/03/12 06:01:50 mg -+ * use tuint for uint etc -+ * -+ * Revision 1.7 93/02/03 21:55:26 mg -+ * support "signed char" -+ * -+ * Revision 1.6 93/01/12 21:54:25 mg -+ * cleanup and set for release -+ * -+ * Revision 1.5 93/01/03 07:31:24 mg -+ * *** empty log message *** -+ * -+ * Revision 1.4 92/10/19 15:09:28 mg -+ * support zero fields/enumerators because gdb have them sometimes. -+ * -+ * Revision 1.3 92/10/14 02:07:00 mg -+ * misc -+ * -+ * Revision 1.2 92/09/16 11:11:43 mg -+ * added builtin charptr type -+ * -+ */ -+ -+#include "duel.h" -+ -+FUNC tctype* duel_mkctype_ptr(tctype *t) -+{ -+ tctype *n ; -+ n=(tctype *) duel_malloc(sizeof(tctype)); -+ duel_bzero((char*) n,sizeof(tctype)); -+ n->type_kind=CTK_PTR ; -+ n->size=sizeof(void*); -+ n->u.kid=t ; -+ return n ; -+} -+ -+FUNC tctype* duel_mkctype_func(tctype *t) -+{ -+ tctype *n ; -+ n=(tctype *) duel_malloc(sizeof(tctype)); -+ duel_bzero((char*) n,sizeof(tctype)); -+ n->size=0 ; -+ n->type_kind=CTK_FUNC ; -+ n->u.kid=t ; -+ return n ; -+} -+ -+/* create a struct or union type. The fields are not set here, but -+ * filled individually with the next function -+ * note the having zero fields is supported. This shouldnt be legal in C -+ * but compilers allow pointer to sturct w/o every specifying the struct. -+ * this is especially true for gdb itself! -+ */ -+ -+FUNC tctype* duel_mkctype_struct(char *name,size_t size,int fields_no, -+ bool is_union) -+{ -+ tctype *n ; -+ n=(tctype *) duel_malloc(sizeof(tctype)); -+ duel_bzero((char*) n,sizeof(tctype)); -+ n->name=name ; -+ n->size=size ; -+ if(is_union) n->type_kind=CTK_UNION ; -+ else n->type_kind=CTK_STRUCT ; -+ n->u.f.fields_no=fields_no ; -+ if(fields_no==0) n->u.f.fields=NULL ; -+ else { -+ n->u.f.fields=(tctype_field *) duel_malloc(fields_no*sizeof(tctype_field)); -+ duel_bzero((char*) n->u.f.fields,fields_no*sizeof(tctype_field)); -+ } -+ return n ; -+} -+ -+/* insert field (field_no) into sturct/union (t), with type fctype -+ */ -+PROC duel_mkctype_struct_field(tctype *t,int field_no,char *name, -+ int bitpos,int bitlen, tctype *fctype) -+{ -+ tctype_field *f ; -+ duel_assert(t->type_kind==CTK_STRUCT || t->type_kind==CTK_UNION); -+ duel_assert(field_no>=0 && field_no <= t->u.f.fields_no); -+ f= &t->u.f.fields[field_no] ; -+ f->name=name ; -+ f->bitpos=bitpos ; -+ f->bitlen=bitlen ; -+ f->ctype=fctype ; -+} -+ -+/* create an enum type. The enumerators are not set here, but -+ * filled individually with the next function -+ * again like sturct, we support zero enums. I am not sure its needed, -+ * but better safe than sorry. -+ */ -+ -+FUNC tctype* duel_mkctype_enum(char *name,tctype_kind real_type_kind, -+ size_t size,int enumerators_no) -+{ -+ tctype *n ; -+ n=(tctype *) duel_malloc(sizeof(tctype)); -+ duel_bzero((char*) n,sizeof(tctype)); -+ n->name=name ; -+ n->size=size ; -+ n->type_kind=CTK_ENUM ; -+ n->u.e.real_type_kind=real_type_kind ; -+ n->u.e.enumerators_no=enumerators_no ; -+ if(enumerators_no==0) n->u.e.enumerators=NULL ; -+ else { -+ n->u.e.enumerators= (tctype_enumerator *) -+ duel_malloc(enumerators_no*sizeof(tctype_enumerator)); -+ duel_bzero((char*) n->u.e.enumerators, -+ enumerators_no*sizeof(tctype_enumerator)); -+ } -+ return n ; -+} -+ -+ -+/* insert enumerator (enumerator_no_ into an enum type (t), with given name/val -+ */ -+PROC duel_mkctype_enumerator(tctype *t,int enumerator_no,char *name,int val) -+{ -+ tctype_enumerator *e ; -+ duel_assert(t->type_kind==CTK_ENUM); -+ duel_assert(enumerator_no>=0 && enumerator_no <= t->u.e.enumerators_no); -+ e= &t->u.e.enumerators[enumerator_no] ; -+ e->name=name ; -+ e->val=val ; -+} -+ -+FUNC tctype* duel_mkctype_array(tctype *t,int size) -+{ -+ tctype *n ; -+ if(t->size==0) duel_gen_error("array of a type of zero size is illegal",0); -+ if(size<=0) duel_gen_error("array of size zero or negative is illegal",0); -+ n=(tctype *) duel_malloc(sizeof(tctype)); -+ duel_bzero((char*) n,sizeof(tctype)); -+ n->type_kind=CTK_ARRAY ; -+ n->size=size*t->size ; -+ n->u.kid=t ; -+ return n ; -+} -+ -+ -+LFUNC tctype* init_basic_ctype(tctype_kind tk,char *name,size_t size) -+{ -+ tctype *p = duel_malloc(sizeof(tctype)); -+ p->type_kind=tk ; -+ p->name=name ; -+ p->size=size ; -+ return p ; -+} -+ -+PROC duel_init_basic_ctypes(void) -+{ -+ ctype_void= init_basic_ctype(CTK_VOID, "void", 0); -+ -+ ctype_char =init_basic_ctype(CTK_CHAR, "char", sizeof(char)); -+ ctype_short =init_basic_ctype(CTK_SHORT, "short",sizeof(short)); -+ ctype_int =init_basic_ctype(CTK_INT, "int", sizeof(int)); -+ ctype_long =init_basic_ctype(CTK_LONG, "long", sizeof(long)); -+ ctype_longlong=init_basic_ctype(CTK_LONGLONG,"long long", sizeof(long long)); -+ -+ ctype_schar =init_basic_ctype(CTK_SCHAR, "signed char", sizeof(tschar)); -+ ctype_uchar =init_basic_ctype(CTK_UCHAR, "unsigned char", sizeof(tuchar)); -+ ctype_ushort =init_basic_ctype(CTK_USHORT, "unsigned short",sizeof(tushort)); -+ ctype_uint =init_basic_ctype(CTK_UINT, "unsigned int", sizeof(tuint)); -+ ctype_ulong =init_basic_ctype(CTK_ULONG, "unsigned long", sizeof(tulong)); -+ ctype_ulonglong=init_basic_ctype(CTK_ULONG, "unsigned long long", sizeof(tulonglong)); -+ -+ ctype_double=init_basic_ctype(CTK_DOUBLE, "double", sizeof(double)); -+ ctype_float =init_basic_ctype(CTK_FLOAT, "float", sizeof(float)); -+ -+ ctype_voidptr=duel_mkctype_ptr(ctype_void); -+ ctype_charptr=duel_mkctype_ptr(ctype_char); -+ /* find and set the special types. -+ * support only a signed ptrdiff; size_t/ptrdiff must both be int or long -+ */ -+ { ptrdiff_t p ; size_t s ; -+ p= -1 ; s= -1 ; -+ if(p>0) duel_gen_error("bad ptrdiff_t - unsigned",0); -+ -+ if(sizeof(p)==sizeof(int)) ctype_ptrdiff_t=ctype_int ; -+ else if(sizeof(p)==sizeof(long)) ctype_ptrdiff_t=ctype_long ; -+ else duel_gen_error("bad ptrdiff_t size",0); -+ -+ if(sizeof(s)==sizeof(int)) ctype_size_t= (s<0)? ctype_int:ctype_uint ; -+ else -+ if(sizeof(s)==sizeof(long)) ctype_size_t= (s<0)? ctype_long:ctype_ulong ; -+ else duel_gen_error("bad size_t size",0); -+ } -+} ---- gdb/duel/wishlist.doc -+++ gdb/duel/wishlist.doc -@@ -0,0 +1,160 @@ -+ -+ += -= etc operators -+ initialize variables e.g. int x=0 , maybe even scopes -+ set declared var to zero. -+ allow x++ for aliases as a special case. -+ x->?y or x?->y to be like (x!=?0)->y OR x?? or ??x as (x!=?0) -+ -+ +/ */ &/ |/ ^/ ==/ !=/ </ >/ <=/ >=/ -+ src(location) as scope -+ istype(type,x) to check type of x -+ ?x to check for x in current scope -+ conditional break points, watchpoints -+ better type checking of structs. -+ bitfield assignment -+ better builtin commands, help -+ output formatting, duel/xodus, more general out(v) -+ duel macros/functions -+ \x and \\x -+ check array bounds -+ x->>y x->-y x>--y -+ check cycles in --> expansion -+ ..:+ ..:- -+ print types, do so better -+ -+DUEL.PIPE - make it general purpose -+------------------------------------ -+see duel.pipe for some details. -+should be made general purpose, so it is easy to modify/add functions. -+many basic functions can be writted - sort, uniq, matrix, vector, -+compress, etc. -+ -+Checking for cycles in --> expansion -+------------------------------------ -+One can easily add code to handle head-->(next!=?head), as well as -+head-->(next!=?_). If you don't know what these do, you should RTFM again :-) -+ -+You can also keep all pointers that have been expanded already, -+hence detecting any kind of cycle. However, what to do in -+such cases is debatable. Some users would like to see -+cycles terminate expansion quietly, while others will want a fatal error -+to be produced. This could be handled by an operator like x-->?y which -+would indicate that cycles are ok and expansion should terminate quietly, -+while x-->y produce an error on cycles. -+ -+Another idea is to have _cyc defined inside -->, to allow the user to -+do something about cycles, e.g. head-->(if(!_cyc) next). There are -+several ways to manage _cyc: a boolean, or equal to head; true if -+this is already a cycle, or a function cyc(next), which return true if -+next would cycle, or return next unles it would cycle, etc. -+This last one seems to handle most cases: -+head-->(cyc(left),cyc(right)) - return tree, igoring cycles -+head-->(cyc(0),left,right) - like head->(left,right), but mention of cyc -+ which by itself does nothing, cause general -+ cycle detection as errors -+as above, but left!=?_ - detect general cycles, pointer to self ok -+ -+While we adding cyc(), we can also add _depth to indicate current depth, -+e.g. head-->(if(_depth<6) (left,right)) -- expand only to depth 6 -+and also acceess to the current path with _path(i), _path(0)=_ and -+_path(_depth-1)=head -+head-->(cyc(0), if(! ||/_path(.._deapth)==left) left, ...) -+ which avoids cycles "in the path" -+ -+If you an strong opinion on this subject, or a better idea, lemme know! -+ -+Other expansions: x->>y x->-y x>--y -+------------------------------------ -+x-->y applies DFS (Depth First Search). Another useful expansion would be -+BFS (Breath First Search). It is simple to implement - y's values should -+be put on a queue instead of a stack, and the code in place has been written -+with this in mind (eval.c). -+Others will probably want a post-order or in-order search instead of preorder -+search as done by x-->y. I am not sure this is important enough to merit -+new operators, but ->- for inorder and >-- for post order are reserved. -+These, too, should be easy to implement, but it is very unclear that the -+added complexity to the language is worth it. If you really need such -+operators, lemme know. -+ -+Increment count for x..y (x..y:+z and x..y:-z) -+------------------------------------------------ -+The x..y operator could be extended to support an increment or decrement -+value. This would allow 1..n to be written as 1..n:+1 so when n==0 it -+will not produce the surprising 1,0 results. -+However, 0..10:+2 could also be written as (0..5)*2, so it is unclear -+that such operators are really needed (maybe just x..+y, x..-y to force -+the direction). -+ -+ -+Duel functions / print procedures -+------------------------------------- -+the command: dl define x expr -+will define x to be duel procedure for expression expr. -+x can then be used like an alias (indeed, it will probably be kept in -+the alias table with a special value). x evaluation returns multiple -+values. -+There is no need parameters, since emp.x would call "x" using the implicit -+parameter "_" set as emp. the expression for x is essentially put into -+the code for the execution. Having no parameters (except implicit ones) -+make it easier to document, use etc. -+ -+Such functions (macros?) are most useful for output. e.g. -+dl define empout val_type,a, u.if(val_type==0) code*6,name else code,z -+dl emp.empout -+will produce output for -+ struct { -+ int val_type,code ; -+ char a; -+ union { char *name ; double z ; } u -+ } emp ; -+ -+the empout procedure can be defined just once, and used to output such -+unions as needed. -+ -+The next step is to call such functions automatically for output and -+for expansion. We add syntax like dl define out(type) expr -+ -+then whenever an expression of the given type is to be printed, this -+code is evaluated instead, e.g.: -+dl define out(struct emp) ... -+dl emp ## this calls the above out code for the output. -+ -+We can also expand expressions by calling the right function, e.g. -+The operator "\" calls a function to expand a specific type: -+dl define \(struct list *) (_-->next) -+dl if(\head#i == \head#j && i<j) \head[[i,j]] -+ -+instead of writing this code (find non unique elements of linked list): -+ if(head-->next#i == head-->next#j && i<j) head-->next[[i,j]] -+ -+Both printing and expansion occurs automatically based on TYPE. -+It is unclear if the an array is allowed to be expanded by a pointer -+type expansion or not (i.e. is \(int *) to expand "int x[40]"). -+this might require an extension to types allowing \(int [n]) which matches -+any int array and set n for the specific bound. Types could be extended -+in a similar way, e.g. \(type **) _[0..]@0 -+which expands any array of pointers (e.g. argv). -+This can quickly require scope-nesting for local aliases/variables. -+ -+As before, it is unclear what of these is useful. Unless people depends on -+duel heavily, and write such "output/expansion" functions for the project, -+the features are useless (who is going to use this interactively?) -+ -+Regular expressions for names. $xxx and `xxx` -+---------------------------------------------- -+this allows things like emp.`value_*` to return all the value_something -+fields. it is really useful with structs, especially if a grep-style hat (^) -+is supported. Obviously extends to func.rexp, to show all locals, etc, -+which will make it possible to write a stack-trace display in duel. -+ -+exact semantics (e.g. what is matched and how) unclear. -+ -+ -+Nicer #/ -+--------- -+ -+hash[..1024] => #/_-->next >? 2 -+ -+it is probably best if #/(exp) constructed (exp) as symbolic before it -+gets the values. or maybe, yes, best is #/(e) symbolic is #/(e1..en) -+where e1 is the first return symbolc, en the last. ---- gdb/duelgdb.c -+++ gdb/duelgdb.c -@@ -0,0 +1,694 @@ -+/* DUEL - A Very High Level Debugging Langauge. */ -+/* Public domain code */ -+/* Written by Michael Golan mg@cs.princeton.edu */ -+/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.8/10_all_gdb-6.6-duel.patch,v 1.1 2008/04/06 23:59:05 vapier Exp $*/ -+ -+/* debugger dependent module, it contains all of duel's access to -+ * the outside world (debuggee, symbol table, etc) -+ */ -+ -+/* -+ * $Log: 10_all_gdb-6.6-duel.patch,v $ -+ * Revision 1.1 2008/04/06 23:59:05 vapier -+ * initial 6.8 patchset based on last 6.7.1 patchset -+ * -+ * Revision 1.30 08/11/14 23:14:00 serg -+ * ported to gdb 6.6.2, glibc 2.5 -+ * -+ * Revision 1.20 93/03/20 10:35:48 mg -+ * fixed system("date")... didnt work on OS/2 -+ * -+ * Revision 1.19 93/03/13 03:28:49 mg -+ * bug fixed frame(0).unknown_name caused a crash -+ * bug fixed duel didnt support enum of length zero but turns out gdb tables -+ * have such things (specifically, for some gdb internals!) -+ * -+ * Revision 1.18 93/03/12 05:43:22 mg -+ * Version 1.10 - tuint instead of uint etc, fixed gdb48 recognis. problem -+ * -+ * Revision 1.17 93/02/27 06:01:01 mg -+ * improved unsigned char default machines support, -+ * convert explicit uchar into "char" if they are the same. -+ * -+ * Revision 1.16 93/02/23 19:11:10 mg -+ * beauty changes + gdb4.8 support -+ * -+ * Revision 1.15 93/02/04 02:09:18 mg -+ * fixed enum enum names -+ * -+ * Revision 1.14 93/02/04 00:54:26 mg -+ * arr. fixed. -+ * -+ * Revision 1.13 93/02/03 21:54:14 mg -+ * create duel.out unless compiling with NO_DUEL_OUT -+ * -+ * Revision 1.12 93/02/03 21:46:33 mg -+ * fixed problems with null gdb type names. -+ * support "signed char" -+ * -+ * Revision 1.11 93/01/21 21:22:15 mg -+ * *** empty log message *** -+ * -+ * Revision 1.10 93/01/13 16:19:33 mg -+ * support mini symbol table lookup (malloc, printf on SUN didnt work) -+ * -+ * Revision 1.9 93/01/12 21:30:04 mg -+ * cleanup and set for release -+ * -+ * Revision 1.8 93/01/06 23:59:21 mg -+ * new memory alloc/release. moved target's malloc into duel code -+ * allow ^c to work, fixed help, fixed variable lookup for specific frame. -+ * -+ * Revision 1.7 93/01/03 07:27:11 mg -+ * support function calls! -+ * -+ * Revision 1.6 92/12/24 23:33:13 mg -+ * frames support -+ * -+ * Revision 1.5 92/10/19 15:06:29 mg -+ * made lcc happy -+ * no svalues -+ * new registers support and way of getting vars. -+ * these are temporary changes, new frames supports soon -+ * -+ * Revision 1.4 92/10/14 02:03:53 mg -+ * misc/gdb4.6/duel vars using malloc -+ * -+ * Revision 1.3 92/09/16 11:06:22 mg -+ * a lot more functions: get typedef/tags, alloc debuggee mem. +cosmetics -+ * -+ * Revision 1.2 92/09/15 05:37:28 mg -+ * fix enum size bug. added headers -+ * -+ */ -+ -+ -+#include <stddef.h> /* used for ptrdiff_t and size_t */ -+#include <stdio.h> -+#include <string.h> -+#include <time.h> /* for time/ctime stamping of duel.out */ -+#include <assert.h> -+ -+#include "defs.h" -+#include "symtab.h" -+#include "gdbtypes.h" -+#include "gdbcore.h" -+#include "frame.h" -+#include "target.h" -+#include "value.h" -+#include "symfile.h" -+#include "objfiles.h" -+#include "gdbcmd.h" -+#include "call-cmds.h" -+#include "infcall.h" -+ -+#include "duel/global.h" -+#include "duel/proto.h" -+ -+/* all output goes thru here */ -+ -+#include <stdarg.h> -+ -+PROC duel_printf(char *fmt, ...) /* like printf, but for duel output */ -+{ -+ va_list args; -+ va_start(args, fmt); -+ vprintf_filtered(fmt,args); -+ va_end(args); -+} -+ -+PROC duel_flush(void) -+{ /* not yet. only really needed for redirections */ -+} -+ -+PROC duel_redirectable_output_start(char *s) -+{ -+} -+ -+PROC duel_redirectable_output_end(void) -+{ -+} -+ -+PROC duel_redirectable_output_abort(void) -+{ -+} -+ -+PROC duel_redirectable_output_init(void) -+{ -+} -+ -+/* all duel memory allocations go thru here */ -+ -+FUNC void* duel_malloc(size_t size) -+{ -+ void *p ; -+ immediate_quit-- ; /* disable ^C while xmalloc */ -+ p=xmalloc(size); /* gdb's malloc, incl zero return chk */ -+ immediate_quit++ ; -+ QUIT ; /* check if ^C while xmalloc called */ -+ return p ; -+} -+ -+PROC duel_free(void *p) -+{ -+ immediate_quit-- ; -+ free(p); -+ immediate_quit++ ; -+ QUIT ; -+} -+ -+/* fetch n bytes from the target at the given memory address. -+ * the address to fetch from is given by (from). -+ * the value is stored at the 'to' location, which points to space for -+ * n bytes in the debugger. -+ * if the address can not be accessed, false is returned (if all ok, ret true) -+ */ -+ -+FUNC bool duel_get_target_bytes(ttarget_ptr from,void *to,size_t n) -+{ -+ return target_read_memory((CORE_ADDR)from,to,n)==0; -+} -+ -+/* store n bytes to the debuggee. reverse parms from above */ -+FUNC bool duel_put_target_bytes(ttarget_ptr to,void *from,size_t n) -+{ -+ return target_write_memory((CORE_ADDR)to,from,n)==0; -+} -+ -+/* fetch the value of a bitfield of a given structure. -+ * struct_at - a pointer to the structure -+ * bitpos - the position of the field, in bits (as given in the type) -+ * bitlen - the length of the field in bits -+ * to - pointer to tuint where value will be stored. -+ * tkind - the type kind of the field (used to do sign extention if needed) -+ * note: I'm unaware of any compiler with bitfields that are not int/tuint. -+ */ -+ -+FUNC bool duel_get_target_bitfield(ttarget_ptr struct_at,int bitpos, -+ int bitlen,void *to,tctype_kind tkind) -+{ -+ tuint bits ; -+ duel_assert(tkind==CTK_INT || tkind==CTK_UINT); -+ if(!duel_get_target_bytes(struct_at+bitpos/8,&bits,sizeof(bits))) -+ return FALSE; -+ -+ /* now, move the field to the 'bottom' of bits, by shifting right */ -+ bitpos%=8 ; /* fix it to a bit offset inside the 'bits' */ -+ if (gdbarch_bits_big_endian (current_gdbarch)) -+ bits >>= (sizeof(bits)*8-bitpos-bitlen) ; -+ else -+ bits >>= bitpos ; -+ -+ /* finally chop down 'bits' to only bitlen significant bits, -+ * or sign-extend it if output field is 'int' and the sign is 1. -+ * ~0 is all ones, shift it to have bitlen zeros. Complement to get -+ * a bitlen string of 1's in the low-order bits. Common ugly hacks. -+ * Note: this code assume 2's complement -+ */ -+ -+ if(tkind==CTK_INT && (bits & 1<<(bitlen-1))) /* int field, negative sign */ -+ bits|= ~0<<bitlen ; /*sign extend */ -+ else bits&= ~(~0<<bitlen) ; /* clear all bits above the sign bit */ -+ *(tuint*) to= bits ; -+ -+ return TRUE ; -+} -+ -+LFUNC struct type* duel_convert_type_to_gdb(tctype *ct); -+LFUNC tctype* duel_convert_type_from_gdb(struct type *gv); -+ -+/* convert gdb value into duel's. Used to fetch const, registers, func ret val -+ * and convert a symbol into a reference. -+ * otherwise, duel access target's memory directly. -+ */ -+ -+LPROC duel_convert_value_from_gdb(struct value *gv, tvalue *dv) -+{ -+ dv->ctype=duel_convert_type_from_gdb(value_type(gv)); -+ if(VALUE_LVAL(gv) == lval_memory) { -+ dv->val_kind=VK_LVALUE ; -+ dv->u.lvalue= (ttarget_ptr) VALUE_ADDRESS(gv) ; /*address of variable*/ -+ } -+ else -+ if(ctype_kind_scalar(dv->ctype) && (VALUE_LVAL(gv) == not_lval || -+ VALUE_LVAL(gv) == lval_register)) { -+ dv->val_kind=VK_RVALUE ; -+ duel_bcopy(&dv->u,value_contents_raw(gv),dv->ctype->size); -+ } -+ else -+ duel_fatal("unsupported value type returned by gdb"); -+} -+ -+ -+/* helper function converts duel values to gdb's values. used only to make -+ * function calls to the target, so current support is weak. -+ * gdb thinks long=int=pointers, so we go along with that. -+ * To support arbitrary types like struct/union, we can probably fake it -+ * by making a gdb lvalue. but i am not sure how/what -+ */ -+ -+LFUNC struct value *convert_duel_val_to_gdb_val(tvalue *v) -+{ -+ struct value *gv ; -+ if(v->val_kind!=VK_RVALUE) return 0 ; /* cant handle lvals */ -+ switch(v->ctype->type_kind) { -+/* duel standardize func parms, so this code is not required. if this -+ * function is used for more than func parms, as its name implies, we will -+ * need to do better than this. -+ * there is no gdb "builtin_type_signed_char", so we assume char -+ case CTK_CHAR: -+ gv=value_from_longest(builtin_type_char,v->u.rval_char); break; -+ case CTK_SCHAR: -+ gv=value_from_longest(builtin_type_char,v->u.rval_schar); break; -+ case CTK_UCHAR: -+ gv=value_from_longest(builtin_type_unsigned_char,v->u.rval_char); break; -+ case CTK_USHORT: -+ gv=value_from_longest(builtin_type_unsigned_short,v->u.rval_ushort);break; -+ case CTK_SHORT: -+ gv=value_from_longest(builtin_type_unsigned_short,v->u.rval_short);break; -+*/ -+ case CTK_INT: -+ gv=value_from_longest(builtin_type_int, v->u.rval_int); break; -+ case CTK_UINT: -+ gv=value_from_longest(builtin_type_unsigned_int, v->u.rval_uint) ; break ; -+ case CTK_LONG: -+ gv=value_from_longest(builtin_type_long, v->u.rval_long) ; break ; -+ case CTK_ULONG: -+ gv=value_from_longest(builtin_type_unsigned_long,v->u.rval_ulong); break ; -+ case CTK_LONGLONG: -+ gv=value_from_longest(builtin_type_long_long, v->u.rval_longlong) ; break ; -+ case CTK_ULONGLONG: -+ gv=value_from_longest(builtin_type_unsigned_long_long,v->u.rval_ulonglong); break ; -+ case CTK_FLOAT: -+ gv=value_from_double(builtin_type_float, v->u.rval_float) ; break ; -+ case CTK_DOUBLE: -+ gv=value_from_double(builtin_type_double, v->u.rval_double) ; break ; -+ case CTK_PTR: -+ gv=value_from_longest(lookup_pointer_type(builtin_type_void), -+ (long) v->u.rval_ptr) ;break ; -+ default: duel_assert(0); -+ } -+ return gv ; -+} -+ -+/* make a function call to the target. -+ * this is the only case where we convert duel tvalue into gdb's values. -+ * gdb thinks long=int=pointers, so we go along with that. -+ */ -+ -+PROC duel_target_func_call(tvalue *func, tvalue *parms[], -+ int parms_no,tvalue *rval) -+{ -+ struct value *gfunc, *grval, *gparms[20] ; -+ int i ; -+ struct type *gftype ; -+ -+ duel_assert(func->val_kind==VK_LVALUE); -+ for(i=0 ; i<parms_no ; i++) { -+ gparms[i]=convert_duel_val_to_gdb_val(parms[i]) ; -+ if(gparms[i]==NULL) -+ duel_op_error("unsupported func call parm type",0,parms[i],0); -+ } -+ gftype =duel_convert_type_to_gdb(func->ctype); -+ if(!gftype) duel_op_error("unsupported func return parm type",0,func,0); -+ gftype = lookup_pointer_type(gftype); -+ if(!gftype) -+ duel_op_error("unsupproted func return type",0,func,0); -+ -+ gfunc = value_from_longest(gftype,(LONGEST) func->u.lvalue); -+ -+ grval=call_function_by_hand(gfunc,parms_no,gparms); -+ if(func->ctype->u.kid->type_kind==CTK_VOID) return ; /* no return val*/ -+ duel_convert_value_from_gdb(grval,rval); -+} -+ -+ -+ -+#define TYPE_HASH_SIZE (1024*128) -+#define type_hash_func(t) ( (((long)t&0xffff) + (((long)t>>16)&0xffff)) \ -+ % TYPE_HASH_SIZE ) -+struct { -+ struct type *t ; /* gdb type ptr */ -+ tctype *ct ; /* duel type ptr */ -+} duel_thash[TYPE_HASH_SIZE] ; -+ -+LPROC duel_add_hash(struct type *t, tctype *ct) -+{ -+ int start,i=type_hash_func(t); -+ start=i ; -+ do { -+ if(duel_thash[i].t==0) { -+ duel_thash[i].t=t ; -+ duel_thash[i].ct=ct ; -+ return ; -+ } -+ if(duel_thash[i].t==t) { -+ if(duel_thash[i].ct==ct) return ; -+ duel_fatal("type hash table inconsistency "); -+ } -+ i= (i+1)%TYPE_HASH_SIZE ; -+ } while(i!=start); -+ duel_fatal("type hash table is full"); -+} -+ -+LFUNC tctype* duel_find_hash(struct type *t) -+{ -+ int start,i=type_hash_func(t); -+ start=i ; -+ do { -+ if(duel_thash[i].t==0) break ; -+ if(duel_thash[i].t==t) return duel_thash[i].ct ; -+ i= (i+1)%TYPE_HASH_SIZE ; -+ } while(i!=start); -+ return NULL ; -+} -+ -+/* a simple conversion back to gdb types, used only for target func calls */ -+/* this is a hack and based on the assumption that the type was first -+ * converted FROM gdb to duel. (turn out to be false for int func from -+ * minimal symbols, so we do this as a special case.) -+ */ -+LFUNC struct type* duel_convert_type_to_gdb(tctype *ct) -+{ -+ int i ; -+ for(i=0 ; i<TYPE_HASH_SIZE ; i++) -+ if(duel_thash[i].ct==ct) return duel_thash[i].t ; -+ -+ if(ct->type_kind==CTK_FUNC && ct->u.kid->type_kind==CTK_INT) -+ return lookup_function_type (builtin_type_int); -+ return NULL ; -+} -+ -+#define INTTYPE_CHAR 1 -+#define INTTYPE_SHORT 2 -+#define INTTYPE_INT 0 -+#define INTTYPE_LONG 4 -+#define INTTYPE_SIGNED 0 -+#define INTTYPE_UNSIGNED 16 -+ -+struct { char *name; int len; int codetype; } name_to_codetype[]= -+{ {"char", 4, INTTYPE_CHAR }, -+ {"short", 5, INTTYPE_SHORT }, -+ {"int", 3, INTTYPE_INT }, -+ {"long", 4, INTTYPE_LONG }, -+ {"signed", 6, INTTYPE_SIGNED }, -+ {"unsigned", 8, INTTYPE_UNSIGNED }, -+ {0,0,0} -+}; -+ -+ /* given a gdb type t, return an equivalent duel type */ -+ -+LFUNC tctype* duel_convert_type_from_gdb(struct type *t) -+{ -+ tctype *ct=duel_find_hash(t); -+ if(ct) return ct ; -+ -+ if (duel_debug) -+ duel_printf("gdb type: {%d, %s}\n", TYPE_CODE(t), TYPE_NAME(t)); -+ -+ switch (TYPE_CODE (t)) { -+ case TYPE_CODE_BOOL: -+ if(strcmp(TYPE_NAME(t),"bool")==0) ct=ctype_uchar ; /* XXX HACK */ -+ break; -+ case TYPE_CODE_INT: { -+ int i, type=0; -+ char *s=TYPE_NAME(t); -+ while (*s) -+ for (i=0; name_to_codetype[i].name; i++) { -+ if (strncmp(s,name_to_codetype[i].name,name_to_codetype[i].len) == 0) { -+ s+=name_to_codetype[i].len; -+ if (*s == ' ') s++; -+ type+= name_to_codetype[i].codetype; -+ break; -+ } -+ } -+ if(type == INTTYPE_CHAR) ct=ctype_char ; -+ else if(type == INTTYPE_CHAR + INTTYPE_UNSIGNED) ct=ctype_uchar ; -+ else if(type == INTTYPE_SHORT) ct=ctype_short ; -+ else if(type == INTTYPE_SHORT + INTTYPE_UNSIGNED) ct=ctype_ushort ; -+ else if(type == INTTYPE_INT) ct=ctype_int ; -+ else if(type == INTTYPE_UNSIGNED) ct=ctype_uint ; -+ else if(type == INTTYPE_LONG) ct=ctype_long ; -+ else if(type == INTTYPE_UNSIGNED + INTTYPE_LONG) ct=ctype_ulong ; -+ else if(type == INTTYPE_LONG + INTTYPE_LONG) ct=ctype_longlong ; -+ else if(type == INTTYPE_UNSIGNED + INTTYPE_LONG + INTTYPE_LONG) ct=ctype_ulonglong ; -+ break; -+ } -+ case TYPE_CODE_FLT: -+ if(strcmp(TYPE_NAME(t),"float")==0) ct=ctype_float ; -+ else -+ if(strcmp(TYPE_NAME(t),"double")==0) ct=ctype_double ; -+ break; -+ case TYPE_CODE_VOID: -+ if(strcmp(TYPE_NAME(t),"void")==0) ct=ctype_void ; -+ break; -+ case TYPE_CODE_PTR: -+ case TYPE_CODE_REF: -+ { -+ /* the pointer might get defined when converting the target, so -+ * check the hashing again (reason: self-referencing structs) -+ */ -+ tctype *target=duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t)); -+ if((ct=duel_find_hash(t))==NULL) ct=duel_mkctype_ptr(target); -+ } -+ break ; -+ case TYPE_CODE_FUNC: -+ ct=duel_mkctype_func(duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t))); -+ break ; -+ case TYPE_CODE_ARRAY: -+ { int n=TYPE_LENGTH(TYPE_TARGET_TYPE(t)); -+ if(n!=0) n=TYPE_LENGTH(t)/n; -+ ct=duel_mkctype_array( -+ duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t)),n); -+ } -+ break; -+ case TYPE_CODE_STRUCT: -+ case TYPE_CODE_UNION: -+ { int i,n=TYPE_NFIELDS(t); -+ char *name=TYPE_NAME(t); -+ if(name == NULL) name="" ; /* duel can't handle null ptr! */ -+ if(strncmp(name,"struct ",7)==0) name+=7 ; -+ if(strncmp(name,"union ",6)==0) name+=6 ; -+ ct=duel_mkctype_struct(name,TYPE_LENGTH(t),n, -+ TYPE_CODE(t)==TYPE_CODE_UNION); -+ duel_add_hash(t,ct); /* so a pointer to myself is recognized */ -+ for(i=0 ; i<n ; i++) -+ duel_mkctype_struct_field(ct,i,TYPE_FIELD_NAME(t,i), -+ TYPE_FIELD_BITPOS(t,i), TYPE_FIELD_BITSIZE(t,i), -+ duel_convert_type_from_gdb(TYPE_FIELD_TYPE(t,i))); -+ } -+ break ; -+ case TYPE_CODE_ENUM: -+ /* TYPE_LENGTH(t) tell how big it is. I assume signed integral types. -+ * it is unclear if gdb supports unsigned enums and how -+ * (e.g. enum { x=0,y=250 } stored in uchar -+ * FIELDS contain the tags, BITPOS is the assigned value. -+ */ -+ { int i,n=TYPE_NFIELDS(t),len=TYPE_LENGTH(t); -+ char *name=TYPE_NAME(t); -+ tctype_kind k ; -+ if(name==NULL) name="" ; /* duel can't handle null ptr */ -+ if(strncmp(name,"enum ",5)==0) name+=5 ; -+ /* select 'real' stored type. note order important if short==int. -+ * long is not allowed as far as I know ANSI C (enums are conv. to int) -+ * Amazingly, some internal gdb struct (sym) can have an enum of -+ * size zero (enum language, gdb4.8). We allow this as int but warn. -+ * gdb> p sizeof(sym->ginfo.lang_specific.language) gives zero -+ */ -+ if(len==0) { -+ duel_printf("Warning: enum %s is size zero. assumed int\n",name); -+ len=sizeof(int); -+ } -+ if(len==sizeof(int)) k=CTK_INT ; -+ else if(len==sizeof(short)) k=CTK_SHORT ; -+ else if(len==sizeof(char)) k=CTK_CHAR ; -+ else duel_assert(0); -+ -+ ct=duel_mkctype_enum(name,k,len,n); -+ for(i=0 ; i<n ; i++) -+ duel_mkctype_enumerator(ct,i,TYPE_FIELD_NAME(t,i), -+ TYPE_FIELD_BITPOS(t,i)); -+ } -+ break ; -+ case TYPE_CODE_TYPEDEF: -+ ct=duel_convert_type_from_gdb(check_typedef(t)); -+ break ; -+ case TYPE_CODE_UNDEF: -+ break; -+ } -+ if(ct==0) duel_fatal("unsupported C type returned by gdb"); -+ duel_add_hash(t,ct); -+ return ct ; -+} -+ -+/* optimize frame access so frame(100..0) doesnt start the search from 0 -+ * everytime. similar to selected_frame etc, but we dont want to mess up -+ * gdb's own frame setup (for up/down/print etc) -+ * this optimization should have been part of gdb, not here. -+ * ie. duel_select_frame should be a simple fast gdb call. -+ * we dont optimze going to frame 7 from frame 5 etc, this isn't typical. -+ * set last/tot frames to -2 to assure recomputeations (-1 is not good enuf) -+ */ -+ -+static struct frame_info * last_frame ; /* last frame pointer we used */ -+static int last_frame_no ; /* last frame number we used */ -+static int tot_frames_no ; /* tot number of frames */ -+ -+LFUNC struct frame_info * duel_select_frame(int frame_no) -+{ -+ struct frame_info * frame ; -+ if(last_frame_no==frame_no) frame=last_frame ; -+ else -+ if(last_frame_no==frame_no-1) frame=get_prev_frame(last_frame); -+ else -+ if(last_frame_no==frame_no+1) frame=get_next_frame(last_frame); -+ else { -+ int count=frame_no ; -+ frame=get_current_frame(); -+ while (frame && --count >= 0) -+ frame = get_prev_frame (frame); -+ } -+ duel_assert(frame); /* callee should have checked frames no*/ -+ last_frame = frame ; -+ last_frame_no = frame_no ; -+ return frame ; -+} -+ -+FUNC bool duel_get_target_variable(char *name, int frame_no, tvalue *v) -+{ -+ struct symbol *sym; -+ struct frame_info * frame ; -+ struct block *blk ; -+ int len ; -+ struct value *gv ; /* gdb value */ -+ -+ if(frame_no== -1) { /* use the user selected frame and block */ -+ frame = get_selected_frame("Error!") ; -+ blk = get_selected_block(0) ; -+ } -+ else { -+ frame=duel_select_frame(frame_no) ; -+ blk = get_frame_block(frame, 0); -+ } -+ sym = lookup_symbol (name, blk, VAR_DOMAIN,0,0); -+ if(!sym) { /* look up the symbol that has no debug info*/ -+ struct minimal_symbol *m ; -+ if(frame_no != -1) return FALSE ; /* only locals looked up- not found*/ -+ m=lookup_minimal_symbol (name,NULL, 0); /* find printf, malloc etc */ -+ if(m == NULL) return FALSE ; -+ v->val_kind=VK_LVALUE ; -+#ifdef SYMBOL_LANGUAGE -+ /* in gdb4.8 the mini table changed. I use the existance of the above -+ * #define symbol as hack to indicate gdb.4.8 */ -+ v->u.lvalue=(ttarget_ptr) SYMBOL_VALUE_ADDRESS(m); -+#else -+ v->u.lvalue=(ttarget_ptr) m->address ; -+#endif -+ /* guess it is an int if it is a data type, an int func if text */ -+ if(m->type == mst_data || m->type == mst_bss) v->ctype=ctype_int ; -+ else -+ if(m->type == mst_text) v->ctype=duel_mkctype_func(ctype_int); -+ else return FALSE ; -+ return TRUE ; -+ } -+ if(SYMBOL_CLASS(sym)==LOC_TYPEDEF) return FALSE ; -+ /* if frame specificed, allow only local variables to be found */ -+ if(frame_no!= -1 && (SYMBOL_CLASS(sym)==LOC_STATIC || -+ SYMBOL_CLASS(sym)==LOC_BLOCK || SYMBOL_CLASS(sym)==LOC_CONST)) return FALSE; -+ gv=read_var_value(sym,frame); -+ if(gv==0) return FALSE ; /* frame not found or illegal */ -+ duel_convert_value_from_gdb(gv,v); -+ return TRUE ; -+} -+ -+ -+/* return the total number of frames on the stack */ -+ -+FUNC int duel_get_frames_number(void) -+{ -+ int n ; -+ struct frame_info * frame ; -+ if(tot_frames_no!= -2) return tot_frames_no ; -+ frame=get_current_frame(); -+ for(n=0 ; frame ; n++) -+ frame = get_prev_frame (frame); -+ return tot_frames_no=n ; -+} -+ -+FUNC ttarget_ptr duel_get_function_for_frame(int frame_no) -+{ -+ struct frame_info * frame=duel_select_frame(frame_no); -+ struct symbol *sym = get_frame_function(frame); -+ struct value *val = read_var_value(sym,frame); -+ duel_assert(val!=0 && VALUE_LVAL(val) == lval_memory); -+ -+ return (ttarget_ptr) VALUE_ADDRESS(val) ; -+} -+ -+FUNC tctype* duel_get_target_typedef(char *name) -+{ -+ struct symbol *sym; -+ sym = lookup_symbol (name, get_selected_block(0), VAR_DOMAIN,0,0); -+ if(!sym || SYMBOL_CLASS(sym)!=LOC_TYPEDEF) { -+ sym = lookup_symbol (name, 0, VAR_DOMAIN, 0,0); -+ if(!sym || SYMBOL_CLASS(sym)!=LOC_TYPEDEF) return NULL ; -+ } -+ return duel_convert_type_from_gdb(SYMBOL_TYPE(sym)); -+} -+ -+FUNC tctype* duel_get_target_struct_tag(char *name) -+{ -+ struct symbol *sym; -+ sym = lookup_symbol (name, get_selected_block(0), STRUCT_DOMAIN,0,0); -+ if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_STRUCT) { -+ sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0,0); -+ if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_STRUCT) return NULL ; -+ } -+ return duel_convert_type_from_gdb(SYMBOL_TYPE(sym)); -+} -+ -+FUNC tctype* duel_get_target_union_tag(char *name) -+{ -+ struct symbol *sym; -+ sym = lookup_symbol (name, get_selected_block(0), STRUCT_DOMAIN,0,0); -+ if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_UNION) { -+ sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0,0); -+ if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_UNION) return NULL ; -+ } -+ return duel_convert_type_from_gdb(SYMBOL_TYPE(sym)); -+} -+ -+FUNC tctype* duel_get_target_enum_tag(char *name) -+{ -+ struct symbol *sym; -+ sym = lookup_symbol (name, get_selected_block(0), STRUCT_DOMAIN,0,0); -+ if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_ENUM) { -+ sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0,0); -+ if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_ENUM) return NULL ; -+ } -+ return duel_convert_type_from_gdb(SYMBOL_TYPE(sym)); -+} -+ -+/* -+ * entry point from gdb. -+ * produce help in gdb's format, or call duel enter point. -+ * we allow ^c to quit immidiatly, and setup memory release cleanup. -+ */ -+ -+void duel_command(char *exp,int from_tty) -+{ -+ last_frame_no = -2 ; /* recompute frame location on each dl command */ -+ tot_frames_no = -2 ; -+ -+ make_cleanup(duel_cleanup, 0); /* clear all allocated mem */ -+ immediate_quit++ ; -+ duel_parse_and_eval(exp); -+ immediate_quit-- ; -+} -+ -+void -+_initialize_duel() -+{ -+ add_com ("duel", class_vars, duel_command, -+"Evaluate Duel expressions. Duel is a very high level debugging language.\n\ -+\"dl help\" for help.\n"); -+ add_com_alias ("dl", "duel", class_vars, 1); -+ -+} diff --git a/src/patchsets/gdb/6.8/11_all_gdb-6.6-duel-integrate.patch b/src/patchsets/gdb/6.8/11_all_gdb-6.6-duel-integrate.patch deleted file mode 100644 index d639b6cbd1..0000000000 --- a/src/patchsets/gdb/6.8/11_all_gdb-6.6-duel-integrate.patch +++ /dev/null @@ -1,59 +0,0 @@ ---- gdb/Makefile.in -+++ gdb/Makefile.in -@@ -116,6 +116,9 @@ - # Where is the "-liberty" library? Typically in ../libiberty. - LIBIBERTY = ../libiberty/libiberty.a - -+# Where is the DUEL library ? Always in duel/src -+DUEL=duel/duel.a -+ - # Where is the BFD library? Typically in ../bfd. - BFD_DIR = ../bfd - BFD = $(BFD_DIR)/libbfd.a -@@ -383,9 +386,9 @@ - CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) \ - $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \ - $(LIBICONV) $(LIBEXPAT) \ -- $(LIBIBERTY) $(WIN32LIBS) -+ $(LIBIBERTY) $(WIN32LIBS) $(DUEL) - CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \ -- $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) -+ $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(DUEL) - - ADD_FILES = $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) - ADD_DEPS = $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) -@@ -561,7 +564,7 @@ - ui-out.c utils.c ui-file.h ui-file.c \ - user-regs.c \ - valarith.c valops.c valprint.c value.c varobj.c vec.c \ -- wrapper.c \ -+ wrapper.c duelgdb.c \ - xml-tdesc.c xml-support.c - - LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c -@@ -948,7 +951,7 @@ - dwarf2expr.o dwarf2loc.o dwarf2-frame.o \ - ada-lang.o c-lang.o f-lang.o objc-lang.o \ - ui-out.o cli-out.o \ -- varobj.o vec.o wrapper.o \ -+ varobj.o vec.o wrapper.o duelgdb.o \ - jv-lang.o jv-valprint.o jv-typeprint.o \ - m2-lang.o p-lang.o p-typeprint.o p-valprint.o \ - scm-exp.o scm-lang.o scm-valprint.o \ -@@ -971,7 +974,7 @@ - - TSOBS = inflow.o - --SUBDIRS = @subdirs@ -+SUBDIRS = @subdirs@ duel - - # For now, shortcut the "configure GDB for fewer languages" stuff. - YYFILES = c-exp.c \ -@@ -3238,4 +3241,7 @@ - $(gdb_curses_h) $(gdb_assert_h) - $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c - -+$(DUEL): -+ $(MAKE) $(FLAGS_TO_PASS) -C duel -+ - ### end of the gdb Makefile.in. |