Gentoo Archives: gentoo-commits

From: "Mike Frysinger (vapier)" <vapier@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo commit in src/patchsets/gdb/6.7.1: 10_all_gdb-6.6-duel.patch 11_all_gdb-6.6-duel-integrate.patch README.history
Date: Sat, 29 Dec 2007 21:06:35
Message-Id: E1J8ish-0005TP-7h@stork.gentoo.org
1 vapier 07/12/29 21:06:07
2
3 Modified: README.history
4 Added: 10_all_gdb-6.6-duel.patch
5 11_all_gdb-6.6-duel-integrate.patch
6 Log:
7 add DUEL support #199987 by Sergei Golubchik
8
9 Revision Changes Path
10 1.2 src/patchsets/gdb/6.7.1/README.history
11
12 file : http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/gdb/6.7.1/README.history?rev=1.2&view=markup
13 plain: http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/gdb/6.7.1/README.history?rev=1.2&content-type=text/plain
14 diff : http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/gdb/6.7.1/README.history?r1=1.1&r2=1.2
15
16 Index: README.history
17 ===================================================================
18 RCS file: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/README.history,v
19 retrieving revision 1.1
20 retrieving revision 1.2
21 diff -u -r1.1 -r1.2
22 --- README.history 29 Oct 2007 20:40:43 -0000 1.1
23 +++ README.history 29 Dec 2007 21:06:06 -0000 1.2
24 @@ -1,3 +1,7 @@
25 +1.1 [29.12.2007]
26 + + 10_all_gdb-6.6-duel.patch
27 + + 11_all_gdb-6.6-duel-integrate.patch
28 +
29 1.0 [29.10.2007]
30 + 35_all_gdb-6.3-security-errata-20050610.patch
31 + 45_all_gdb-hppa-offsets.patch
32
33
34
35 1.1 src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch
36
37 file : http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch?rev=1.1&view=markup
38 plain: http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch?rev=1.1&content-type=text/plain
39
40 Index: 10_all_gdb-6.6-duel.patch
41 ===================================================================
42 ftp://ftp.cs.princeton.edu/pub/duel/
43
44 --- gdb/duel/MANUAL
45 +++ gdb/duel/MANUAL
46 @@ -0,0 +1,501 @@
47 +
48 +
49 +
50 + DDDDuuuueeeellll((((1111)))) VVVVeeeerrrrssssiiiioooonnnn 1111....11110000 ((((MMMMaaaarrrr 99993333)))) DDDDuuuueeeellll((((1111))))
51 +
52 +
53 +
54 + NNNNAAAAMMMMEEEE
55 + duel - A high level C debugging language extension to gdb
56 +
57 + SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
58 + dddduuuueeeellll [gdb options] [_p_r_o_g[_c_o_r_e|_p_r_o_c_I_D]]
59 +
60 + DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
61 + Duel is a special purpose language designed for concise state
62 + exploration of debugged C programs, currently implemented under the
63 + GNU debugger _g_d_b(1). Duel is invoked by entering the shell command
64 + _d_u_e_l instead of _g_d_b. It is identical to gdb except for comments, which
65 + begin with `##' instead of `#', and the new _d_l command for Duel
66 + expressions:
67 +
68 + _g_d_b> dl x[1..10] >? 5
69 + x[3] = 14
70 + x[8] = 6
71 +
72 + prints the array elements x[1] to x[10] that are greater than 5. The
73 + output includes the values 14 and 6, as well as their symbolic
74 + representation "x[3]" and "x[8]".
75 +
76 + IIIIFFFF YYYYOOOOUUUU NNNNEEEEVVVVEEEERRRR UUUUSSSSEEEEDDDD GGGGDDDDBBBB
77 + The improved functionality added by Duel merits a fresh look even by
78 + debugger shunners. Gdb is a powerful debugger with many commands, a
79 + thick manual and various interfaces including _e_m_a_c_s(1) and _x_x_g_d_b(1).
80 + These gdb commands should help you get started:
81 +
82 + _b _l_i_n_e set a breakpoint at the line (b func to break at a function)
83 + _d _n delete breakpoint number n (gdb prints n when bp occurs)
84 + _l _l_i_n_e list the source beginning at line (l file.c:line for module)
85 + _r _p_a_r_m run/restart the program with the given parameters
86 + _s single-step to the next statement (steps into function calls)
87 + _n single-step to the next line, skipping over function calls
88 + _c continue execution
89 + _b_t show a stack trace
90 + _p _e_x_p evaluate a symbolic expression
91 + _d_l _e_x_p evaluate a Duel expression
92 + _d_l _g_d_b give a gdb command summary
93 +
94 + The most common use is `b func' followed by `r' followed by several
95 + `n' and `s', evaluating expressions in between.
96 +
97 + DDDDUUUUEEEELLLL QQQQUUUUIIIICCCCKKKK SSSSTTTTAAAARRRRTTTT
98 + Duel is implemented by adding the _d_l command to gdb. All gdb commands
99 + work as before. The dl command, however, is interpreted by duel. Gdb
100 + concepts (such as the value history) do not work in the dl command,
101 + and duel concepts are not understood by other gdb command.
102 +
103 + Duel is based on expressions which return multiple values. The x..y
104 + operator returns the integers from x to y; the x,y operator returns x
105 + and then y, e.g.
106 +
107 + _g_d_b> dl (1,9,12..15,22)
108 +
109 + prints 1, 9, 12, 13, 14, 15 and 22. Such expressions can be used
110 + wherever a single value is used, e.g.
111 +
112 + _g_d_b> dl x[0..99]=0 ;
113 +
114 + assigns zero to the first 100 elements of array x. The semantics of
115 + x[i] are the same as in C. They are applied for each of the values
116 + returned by 0..99, which can be thought of as an implied external
117 + loop. The trailing semicolon indicates evaluation for side-effects
118 + only, with no output. Duel incorporates C operators, casts C
119 + statements as expressions, and supports limited variable declaration:
120 +
121 + _g_d_b> dl int i;for(i=0;i<100;i++)
122 + if(x[i]<0) printf("x[%d]=%d\n",i,x[i]);
123 + x[7] = -4
124 +
125 + The semicolon prevents Duel output; only output from printf is
126 + printed. Aliases are defined with x:=y and provide an alternative to
127 + variable declaration. We could also return x[i] instead of using
128 + printf:
129 +
130 + _g_d_b> dl if(x[i:=0..99]<0) x[i]
131 + x[i] = -4
132 +
133 + The symbolic output "x[i]" can be fixed by surrounding i with {}, i.e.
134 +
135 + _g_d_b> dl if(x[i:=0..99]<0) x[{i}]
136 + x[7] = -4
137 +
138 + The {} are like (), but force the symbolic evaluation to use i's
139 + value, instead of "i". You can usually avoid this altogether with
140 + direct Duel operators:
141 +
142 + _g_d_b> dl x[..100] <? 0
143 + x[7] = -4
144 +
145 + The ..n operator is a shorthand for 0..n-1, i.e. ..100 is the same as
146 + 0..99. The x<?y, x==?y, x>=?y, etc., operators compare their left
147 + side operand to their right side operand as in C, but return the left
148 + side value if the comparison result is true. Otherwise, they look for
149 + the next values to compare, without returning anything.
150 +
151 + Duel's x.y and x->y allow an expression y, evaluated under x's scope:
152 +
153 + _g_d_b> dl emp[..100].(if(code>400) (code,name))
154 + emp[46].code = 682
155 + emp[46].name = "Ela"
156 +
157 + The if() expression is evaluated under the scope of each element of
158 + emp[], an array of structures. In C terms, we had to write:
159 +
160 + _g_d_b> dl int i; for(i=0; i<100 ; i++)
161 + if(emp[i].code>400) emp[{i}].code,emp[{i}].name
162 +
163 + A useful alternative to loops is the x=>y operator. It returns y for
164 + each value of x, setting `_' to reference x's value, e.g.
165 +
166 + _g_d_b> ..100 => if(emp[_].code>400) emp[_].code,emp[_].name
167 +
168 + Using `_' instead of `i' also avoids the need for {i}. Finally, the
169 + x-->y operator expands lists and other data structures. If head points
170 + to a linked list threaded through the next field, then:
171 +
172 + _g_d_b> dl head-->next->data
173 + head->data = 12
174 + head->next->data = 14
175 + head-->next[[2]]->data = 20
176 + head-->next[[3]]->data = 26
177 +
178 + produce the data field for each node in the list. x-->y returns x, x-
179 + >y, x->y->y, x->y->y->y, ... until a NULL is found. The symbolic
180 + output "x-->y[[n]]" indicates that ->y was applied n times. x[[y]] is
181 + also the selection operator:
182 +
183 + _g_d_b> dl head-->next[[50..60]]->data
184 +
185 + return the 50th through the 60th elements in the list. The #/x
186 + operator counts the number of values, so
187 +
188 + _g_d_b> dl #/( head-->next->data >? 50 )
189 +
190 + counts the number of data elements over 50 on the list. Several other
191 + operators, including x@y, x#y and active call stack access are
192 + described in the operators section.
193 +
194 + OOOOPPPPEEEERRRRAAAATTTTOOOORRRRSSSS SSSSUUUUMMMMMMMMAAAARRRRYYYY
195 + Assoc Operators Details
196 + left {} () [] -> . f() --> x-->y expands x->y x->y->y ...
197 + x[[y]] x#y x@y generate x; select, index or stop-at y
198 + right #/ - * & ! ~ ++ -- (cast) #/x number of x values
199 + frame(n) sizeof(x) reference to call stack level n
200 + left x/y x*y x%y multiply, divide, reminder
201 + left x-y x+y add, subtract
202 + left x<<y x>>y shift left/right
203 + none x..y ..y x.. ..y = 0..y-1. x..y return x, x+1...y
204 + left < > <= >= <? >? <=? >=? x>?y return x if x>y
205 + left == != ==? !=? x==?y return x if x==y
206 + left x&y bit-and
207 + left x^y bit-xor
208 + left x|y bit-or
209 + left x&&y &&/x &&/x are all x values non-zero?
210 + left x||y ||/x ||/x is any x value non-zero?
211 + right x? y:z foreach x, if(x) y else z
212 + right x:=y x=y x+=y ... x:=y set x as an alias to y
213 + left x,y return x, then y
214 + right x=>y foreach x, evaluate y with x value `_'
215 + right if() else while() for() C statements cast as operators
216 + left x;y evaluate and ignore x, return y
217 +
218 +
219 + EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS
220 + dl (0xff-0x12)*3 compute simple expression
221 + dl (1..10)*(1..10) display multiplication table
222 + dl x[10..20,22,24,40..60] display x[i] for the selected indexes
223 + dl x[9..0] display x[i] backwards
224 + dl x[..100] >? 5 display x[i] that are greater than 5
225 + dl x[..100] >? 5 <? 10 display x[i] if 5<x[i]<10
226 + dl x[..100] ==? (6..9) same
227 + dl x[0..99]=>if(_>5 && _<10) _ same
228 + dl y[x[..100] !=? 0] display y[x[i]] for each non-zero x[i]
229 + dl emp[..50].code display emp[i].code for i=0 to 49
230 + dl emp[..50].(code,name) display emp[i].code & emp[i].name
231 + dl val[..50].(is_dbl? x:y) display val[i].x or val[i].y depending
232 + on val[i].is_dbl.
233 + dl val[..50].if(is_dbl) x else y same as above
234 + dl x[..100]=0 ; assign 0 to x[i]
235 + dl x[i:=..100]=y[i] ; assign y[i] to x[i]
236 + dl x[..100]=y[..100] *ERR* assign y[99] to each x[j]
237 + dl x[i:=..3]=(4,5,9)[[i]] assign x[0]=4 x[1]=5 x[2]=9
238 + dl x[..3]=(4,5,9) *ERR* assign 9 to each element
239 + dl if(x[i:=..100]<0) x[i]=0 ; assign 0 to negative x[i]
240 + dl (hash[..1024]!=?0)->scope hash[i].scope for non-null hash[i]
241 + dl x[i:=..100] >? x[i+1] check if x[i] is not sorted
242 + dl x[i:=..100] ==? x[j:=..100]=> checks if x has non-unique elements
243 + if(i<j) x[{i,j}]
244 + dl if(x[i:=..99] == same
245 + x[j:=i+1..99]) x[{i,j}]
246 + dl (x[..100] >? 0)[[0]] the 1st (0th element) positive x[i]
247 + dl (x[..100] >? 0)[[2]] return the 3rd positive x[i]
248 + dl (x[..100] >? 0)[[..5]] return the first 5 positive x[i]
249 + dl (x[0..] >? 6)[[0]] return the first x[i]>6, no limit on i
250 + dl argv[0..]@0 argv[0] argv[1] .. until first null
251 + dl x[0..]@-1 >? 9 x[0..n]>9 where n is first x[n]== -1
252 + dl emp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0
253 +
254 + dl head-->next->val val of each element in a linked list
255 + dl head-->next[[20]] the 21st element of a linked list
256 + dl *head-->next[[20]] display above as a struct
257 + dl strcmp(head-->next->msg, search linked list for a string
258 + "testing") ==? 0
259 + dl #/head-->next count elements on a linked list
260 + dl x-->y[[#/x-->y - 1]] last element of a linked list
261 + dl x-->y[[#/x-->y - 10..1]] last 10 elements of a linked list
262 + dl head-->next-> check if the list is sorted by val
263 + if(next) val >? next->val
264 +
265 + dl head-->(next!=?head) expand cyclic linked list (tail->head)
266 + dl head-->(next!=?_) handle termination with p->next==p
267 + dl root-->(left,right)->key expand binary tree, show keys
268 + dl root-->(left,right)->( check bin tree sorted by key
269 + (left!=?0)->key>=?key, (right !=?0 )->key<=?key)
270 +
271 + dl (1000..=>if(&&/(2,3.._-1=>__%_ find first 10 primes over 1000
272 + ) _)[[..10]]
273 + dl (T mytype) x convert x to user defined type mytype
274 + dl (struct s*) x convert x to struct s pointer
275 + dl if(x) y; else z *ERR* ';' must be followed by an expression
276 + dl {x} y *ERR* '}' requires ';' if followed by exp
277 +
278 + SSSSEEEEMMMMAAAANNNNTTTTIIIICCCCSSSS
279 + Duel's semantics are modeled after the Icon programming language. The
280 + input consists of expressions which return sequences of values. C
281 + statements are cast as expressions, too. Expressions are parsed into
282 + abstract syntax trees, which are traversed during evaluation. The
283 + evaluation of most nodes (operators) recursively evaluates the next
284 + value for each operand, and then applies the operator to produce the
285 + next result. Only one value is produced each time, and Duel's eval
286 + function keeps a `state' for each node (backtracking, co-routines,
287 + consumer-producer or threads are good metaphors for the evaluation
288 + mechanism.)
289 +
290 + For example, in (5,3)+6..8, the evaluation of `+' first retrieves the
291 + operands 5 and 6, to compute and return 5+6. Then 7, the next right
292 + operand is retrieved and 5+7 is returned, followed by 5+8. Since
293 + there are no other right operand value, the next left operand, 3 is
294 + fetched. The right operand's computation is restarted returning 6, and
295 + 3+6 is returned. The final return values are 3+7 and 3+8.
296 +
297 + The computation for operators like x>?y is similar, but when x<=y, the
298 + next values are fetched instead of returning a value, forming the
299 + basis for an implicit search. Operators like `..' return a sequence of
300 + values for each pair of operands. For a better understanding of the
301 + evaluation mechanism, see the USENIX Winter/93 conference paper "DUEL
302 + - A Very High Level Debugging Language".
303 +
304 + Duel values follow the C semantics. A value is either an "lvalue" (can
305 + be used as the left hand side of assignment), or an "rvalue".
306 + Therefor, objects like arrays can not be directly manipulated
307 + (However, operators like x..y can accomplish such tasks.)
308 +
309 + Duel types also follow the C semantics, with some important
310 + differences. C types are checked statically; Duel types are checked
311 + when operators are applied, e.g., (1,1.0)/2 returns 0 (int) and 0.5
312 + (double); (x,y).z returns x.z and y.z even if x and y are of different
313 + types, as long as they both have a field z.
314 +
315 + Values and types of symbols are looked up at run-time (using gdb's
316 + lookup rules), allowing dynamic scoping and types, but causing a
317 + parsing problem: (x)(y) can be parsed as either a function call x(y)
318 + or a cast (x)y; x*y can be parsed as a declaration of y as (x*) or as
319 + multiplication.
320 +
321 + To avoid this ambiguity, the keyword T must precede a user defined
322 + type. For example, if value is a typedef, C's (value (*)()) x is
323 + written in Duel as: (T value (*)()) x. Types that begin with a
324 + reserved keyword don't need T, e.g. (struct value*) x and (long *[5])
325 + y are accepted. As special cases, (type)x and (type*)x are accepted
326 + but discouraged (it causes (printf)("hi"), which is valid in C, to
327 + fail). A side effect is that "sizeof x" must be written as sizeof(x).
328 +
329 + OOOOPPPPEEEERRRRAAAATTTTOOOORRRRSSSS
330 + _x+_y _x-_y _x*_y _x/_y _x%_y _x^_y _x|_y _x&_y _x<<_y _x>>_y
331 + _x>_y _x<_y _x>=_y _x<=_y _x==_y _x!=_y _x=_y _x[_y]
332 +
333 + These binary operators follow their C semantics. For each value of x,
334 + they are evaluated for every value of y, .e.g. (5,2)>(4,1) evaluates
335 + as 5>4, 5>1, 2>4, 2>1 returning 1, 1, 0, 1. The y values are re-
336 + evaluated for each new value of x, e.g. i=4; (4,5)>i++ evaluates as
337 + 4>4 and 5>5. Beware of multiple y values in assignment, e.g.
338 + x[..3]=(4,6,9) does not set x[0]=4, x[1]=6 and x[2]=9. It assigns 4, 6
339 + and 9 to each element, having the same effect as x[..3]=9. Use
340 + x[i:=..3]=(4,6,9)[[i]] to achieve the desired effect.
341 +
342 + -_x ~_x &_x *_x !_x ++_x --_x _x++ _x-- _s_i_z_e_o_f(_x) (_t_y_p_e)_x
343 +
344 + These unary operators follow their C semantics. They are applied to
345 + each value of x. The increment and decrement operators require an
346 + lvalue, so i:=0 ; i++ produces an error because i is an alias to 0, an
347 + rvalue. Parenthesis must be used with sizeof(x), "sizeof x" is not
348 + allowed. Cast to user defined type requires generally requires T,
349 + e.g.,
350 + (T val(*)())x, but (val)x and (val*)x are accepted as special cases.
351 +
352 + _x&&_y _x||_y
353 +
354 + These logical operators also follow their C semantics, but have non-
355 + intuitive results for multi-valued x and y, e.g. (1,0,0) || (1,0)
356 + returns 1,1,0,1,0 -- the right hand-side (1,0) is returned for each
357 + left-hand side 0. It is best to use these operators only in single
358 + value expressions.
359 +
360 + _x? _y:_z _i_f(_x)_y _i_f(_x)_y _e_l_s_e _z
361 +
362 + These expressions return the values of y for each non-zero value
363 + returned by x, and the values of z for each zero value returned by x,
364 + e.g. if(x[..100]==0) y returns y for every x[i]==0, not if all x[i]
365 + are zero (if(&&/(x[..100]==0)) y does that). Also, "if(x) y; else z"
366 + is illegal. Duel's semicolon is an expression separator, not a
367 + terminator.
368 +
369 + _w_h_i_l_e(_x)_y _f_o_r(_w;_x;_y)_z
370 +
371 + The while(x)y expression returns y as long as all values of x are
372 + non-zero. The for() expression is similar and both have the expected
373 + C semantics. For example, "for(i=0 ; i<100 ; i++) x[i]" is the same as
374 + x[..100]. Unlike the if() expression, while(x[..100]==0) continue to
375 + execute only if all elements of x are zero, i.e. the condition is
376 + evaluated into a single value using an implicit &&/x.
377 +
378 + VVVVaaaarrrriiiiaaaabbbblllleeee ddddeeeeccccllllaaaarrrraaaattttiiiioooonnnn:::: _t_y_p_e _n_a_m_e [,_n_a_m_e ...] ; ...
379 +
380 + Expressions can begin with variables declaration (but not
381 + initialization). Internally, a declaration sets an alias to space
382 + allocated in the target by calling malloc(), e.g. `int x' is the same
383 + as "x:= *(int *) malloc(sizeof(int))". This is oblivious to the user.
384 + The allocated memory is not claimed when a variable is redeclared.
385 + Declared variables addresses can be passed to functions and used in
386 + other data structures. The keyword `T' must precede user defined types
387 + (typedef), e.g. if val is a user defined type, The C code "val
388 + *p=(val*) x" becomes "T val *p; p=(T val *) x" in Duel.
389 +
390 + FFFFuuuunnnnccccttttiiiioooonnnn ccccaaaallllllllssss:::: _f_u_n_c(_p_a_r_m,...)
391 +
392 + Function calls to the debugged program can be intermixed with Duel
393 + code. Multi-valued parameters are handled as with binary operators.
394 + The call value can have multiple values, e.g. (x,y)() calls x() and
395 + y(). Currently, struct/union parameters and return values are not
396 + supported.
397 +
398 + _x,_y _x.._y .._x _x..
399 +
400 + These operators produce multiple values for single value operands. x,y
401 + returns x, then y. x..y returns the integers from x to y. When x>y the
402 + sequence is returned in descending order, i.e. 5..3 returns 5, 4, 3.
403 + The operator ..x is a shorthand for 0..x-1, e.g. ..3 returns 0, 1, 2.
404 + The x.. operator is a shorthand for x..maxint. It returns increasing
405 + integer values starting at x indefinitely, and should be bounded by
406 + [[n]] or @n operators. `,' retains its precedence level in C. The
407 + precedence of `..' is above `<' and below arithmetic operators, so
408 + 0..n-1 and x==1..9 work as expected.
409 +
410 + _x<?_y _x>?_y _x>=?_y _x<=?_y _x!=?_y _x==?_y
411 +
412 + These operators work like their C counterparts but return x if the
413 + comparison is true. If the comparison is false, the next (x,y) value
414 + is tried, forming the basis of an implicit search.
415 +
416 + (_x) {_x} _x;_y _x=>_y
417 +
418 + Both () and {} act as C parenthesis. The curly braces set the returned
419 + symbolic value as the actual value, e.g. if i=5 and x[5]=3, then x[i]
420 + produces the output "x[i] = 3", x[{i}] produces "x[5] = 3" and {x[i]}
421 + produces just "3". The semicolon is an operator. x;y evaluates x,
422 + ignoring the results, then evaluate and return y, e.g. (i:=1..3 ; i+5)
423 + sets i to 3 and return 8. The x=>y operator evaluate and return y for
424 + each value of x, e.g. (i:=1..3 => i+5) returns 6, 7 and 8. The value
425 + returned by x is also stored implicitly in `_' which can be used in y,
426 + e.g. 1..5 => z[_][_] will output z[1][1], z[2][2] etc. The symbolic
427 + value for _ is that of the left side value, hence {_} is not needed.
428 + Semicolon has the lowest precedence, so it must be used inside () or
429 + {} for compound expressions. The precedence of `=>' is just below `,'.
430 + Beware that "if(a) x; else {y;} z" is illegal; a semicolon is not
431 + allowed before '}' or 'else' and must be inserted before z.
432 +
433 + _x->_y _x._y
434 +
435 + These expression work as in C for a symbol y. If y is an expression,
436 + it is evaluated under the scope of x. e.g. x.(a+b) is the same as
437 + x.a+x.b, if a and b are field of x (if they are not, they are looked
438 + up as local or global variables). x may return multiple values of
439 + different types, e.g. (u,v).a returns u.a and v.a, even if u and v are
440 + different structures. Also, the value of x is available as `_' inside
441 + y, e.g. x[..100].(if(a) _) produces x[i] for each x[i].a!=0. Nested
442 + x.y are allowed, e.g. u.(v.(a+b)) would lookup a and b first under v,
443 + then under u.
444 +
445 + AAAAlllliiiiaaaasssseeeessss:::: _x:=_y
446 +
447 + Aliases store a reference to y in x. Any reference to x is then
448 + replaced by y. If y is a constant or an rvalue, its value is replaced
449 + for x. If y is an lvalue (e.g. a variable), a reference to same lvalue
450 + is returned. for example, x:=emp[5] ; x=9 assigns 9 to emp[5].
451 + Aliases retain their values across invocation of the "dl" command. An
452 + alias to a local variable will reference a stray address when the
453 + variable goes out of scope. The special command "dl clear" delete all
454 + the aliases, and "dl alias" show all current aliases. Symbols are
455 + looked up as aliases first, so an alias x will hide a local x.
456 +
457 + _x-->_y
458 +
459 + The expansion operator x-->y expands a data structure x following the
460 + y links. It returns x, x->y, x->y->y, until a null is found. If x is
461 + null, no values are produced. If y returns multiple values, they are
462 + stacked and each is further expanded in a depth-first notion. For
463 + example, if r is the root of a tree with children u->childs[..u-
464 + >nchilds], then u-->(childs[..nchilds]) expands the whole tree. y is
465 + an arbitrary expression, evaluated exactly like x->y (this includes
466 + `_'.)
467 +
468 + _x@_y
469 +
470 + The expression x@y produces the values of x until x.y is non-zero,
471 + e.g. for(i=0 ; x[i].code!= -1 && i<100 ; i++) x[i] can be written as
472 + x[..100]@(code==-1). The evaluation of x is stopped as soon as y
473 + evaluates to true. x->y or x=>y are used to evaluate y when x is not a
474 + struct or a union. If y is a constant,(_==y) is used. e.g. s[0..]@0
475 + produces the characters in string s up to but not including the
476 + terminating null.
477 +
478 + #/_x &&/_x ||/_x
479 +
480 + These operator return a single "summary" value for all the values
481 + returned by x. #/x returns the number of values returned by x, e.g.
482 + #/(x[..100]>?0) counts the number of positive x[i]. &&/x returns 1 if
483 + all the values produced by x are non-zero, and ||/x returns 1 if any
484 + of x's values are non-zero. Like in C, the evaluation stops as soon as
485 + possible. For example, ||/(x[..100]==0) and &&/(x[..100]==0) check if
486 + one or all of x[i] are zero, respectively.
487 +
488 + _x#_y _x[[_y]]
489 +
490 + The operator x#y produces the values of x and arranges for y to be an
491 + alias for the index of each value in x. It is commonly used with x-->y
492 + to produce the element's index, e.g. head-->next->val#i=i assigns
493 + each val field its element number in the list.
494 + The selection operator x[[y]] produces the yth result of x. If y
495 + returns multiple value, each select a value of x, e.g.
496 + (5,7,11,13)[3,0,2] returns 13, 5 and 11 (13 is the 3rd element, 5 is
497 + the 0th element). Don't use side effects in x, since its evaluation
498 + can be restarted depending on y, e.g. after (x[0..i++])[[3,5]] the
499 + value of i is unpredictable.
500 +
501 + _f_r_a_m_e(_n) _f_r_a_m_e_s__n_o _f_u_n_c._x
502 +
503 + frame(n) for an integer n returns a reference to the nth frame on the
504 + stack (0 is the inner most function and frame(frames_no-1) is main()).
505 + Frame values can be compared to function pointers, e.g.
506 + frame(3)==myfunc is true if the 4th frame is a call to myfunc, and in
507 + scope resolution, e.g. frame(3).x return the local variable x of the
508 + 4th frame. frames_no is the number of active frames on the stack,
509 + e.g. (frames(..frames_no) ==? myfunc).x displays x for all active
510 + invocations of myfunc. As a special case,
511 + (frames(..frames_no)==?f)[[0]].x can be written as f.x (x can be an
512 + expression).
513 +
514 +
515 + BBBBUUUUGGGGSSSS
516 + Both `{}' and `;' are operators, not statements or expression
517 + separators; "if(x) y; else {z;} u" is illegal; use "if(x) y else {z} ;
518 + u". Ambiguities require preceding user-defined types (typedef) with
519 + the keyword T, e.g., if value is a user type, C's "sizeof(value*)" is
520 + written "sizeof(T value*)", except for the casts "(t)x" and "(t*)x";
521 + sizeof(x) requires parenthesis for variable x.
522 +
523 + Unimplemented C idiom include: modified-assignment (x+=y), switch,
524 + break, continue, do, goto, scopes, function declarations, initializing
525 + declared variables, assignment to bit-fields and register variables,
526 + and calling functions with a struct/union parameter or return value.
527 + gdb does not store function prototypes, so parameters are not checked.
528 +
529 + Gdb itself is buggy, which shows up, especially in symbol tables and
530 + calling target functions. Before you report bug, try to do the closest
531 + thing under gdb's "print". Send bug to: mg@××××××××××××.edu.
532 +
533 + FFFFIIIILLLLEEEESSSS
534 + duel.out tracks duel commands usage. Help analyze duel's use by
535 + mailing a copy to mg@××××××××××××.edu.
536 + Duel is available by anonymous ftp at ftp.cs.princeton.edu:/duel.
537 +
538 + AAAAUUUUTTTTHHHHOOOORRRR
539 + Duel is public domain code -- no copy left or right. See the internals
540 + documentation for details on porting Duel and using its code. Duel
541 + was designed and written by Michael Golan as part of a PhD thesis in
542 + the Computer Science Department of Princeton University. I would like
543 + to thank my advisor, Dave Hanson, who helped in all phases of this
544 + project and to Matt Blaze for his support and useful insight.
545 +
546 + Duel stands for Debugging U (might) Even Like, or Don't Use this
547 + Exotic Language. Judge for yourself!
548 --- gdb/duel/Makefile
549 +++ gdb/duel/Makefile
550 @@ -0,0 +1,44 @@
551 +#
552 +# generic makefile for Duel 1.10
553 +# nothing fancy is required: yacc/bison of parse.y, compile all other modules,
554 +# and put all of the OBJ= modules into duel.a library.
555 +# gdb is compiled with its own makefile (you add duel.a and duelgdb.c)
556 +# selfduel, for testing, is compiled and linked with duel.a
557 +
558 +# NOTE:
559 +# for sunOS4.x you must use gcc or another ANSI compiler. cc doesnt
560 +# support prototypes!
561 +# Also for sunOS4.x, yacc inserts a declaration of malloc() at the first line
562 +# of y.tab.c, which is WRONG (return char*). just delete it.
563 +
564 +CFLAGS= -g
565 +CC= cc # won't work on sunOS. need ANSI C prototypes support.
566 +#CC= gcc
567 +YACC=yacc
568 +RANLIB=ranlib # for BSD-derived systems
569 +
570 +#CC = gcc -U__GNUC__ #ONLY if you get __eprintf undefined (assert.h problem)
571 +#RANLIB=echo # for System V, there is no 'ranlib'
572 +
573 +OBJ= duel.o types.o eval.o misc.o y.tab.o error.o evalops.o print.o
574 +
575 +all: duel.a duelself
576 +
577 +duelself: duel.a duelself.o output.o
578 + $(CC) duelself.o duel.a output.o -o duelself
579 +
580 +duel.a: $(OBJ)
581 + ar ru duel.a $(OBJ)
582 + $(RANLIB) duel.a
583 +
584 +y.tab.c: parse.y
585 + $(YACC) parse.y
586 +clean:
587 + rm -f $(OBJ) y.tab.c duelself.o duelself duel.a
588 +
589 +install:
590 +
591 +test: duelself
592 + duelself <tsuite.self >self.out
593 + @echo NOTE: diffs of the @xxxx values are ok
594 + diff tsuite.self.out self.out
595 --- gdb/duel/README
596 +++ gdb/duel/README
597 @@ -0,0 +1,57 @@
598 +-------------------------------------------------------------------------------
599 +README for DUEL 1.10 distribution mg@××××××××××××.edu (M. Golan) Mar 93
600 +-------------------------------------------------------------------------------
601 +see WHATNEW for what's new in version 1.10.
602 +
603 +DUEL - A high level language for debugging C programs.
604 +
605 + Duel is a special purpose language designed for concise state
606 + exploration of debugged C programs under existing debuggers.
607 + It allows you to explore your program's state better than either
608 + the debugger's commands, a C interpreter, or print statements
609 + added to your programs. The debugger is extended with the new
610 + 'dl' command for Duel expressions, e.g.,
611 +
612 + gdb> dl x[0..10].level >? 5
613 + x[3].level = 14
614 + x[8].level = 6
615 +
616 + prints the "level" fields of array elements x[0] to x[10] that are greater
617 + than 5. The output includes the values 14 and 6, as well as their
618 + symbolic representation "x[3].level" and "x[8].level". Linked list and
619 + other complex data structures are just as easy. Most of C (e.g. for, if)
620 + is also supported, e.g., int i; for(i=0; i<11; i++) if(x[i].level>5) x[i].
621 +
622 +Even if you don't normally use debuggers, but you are programming in C, give
623 +Duel a try! The man page & help even include a summary of useful gdb commands.
624 +The man page (duel.1) contains an introduction & many examples.
625 +
626 +Duel is debugger-independent, but the current distribution interface only
627 +with gdb. You will need the source for gdb-4.6, 4.7 or 4.8. Duel is public
628 +domain code. Do whatever you like with it - add it to commercial debuggers,
629 +to dbx/sdb or even make it part of the GNU project.
630 +
631 +NO PART OF THIS DISTRIBUTION CONTAINS ANY COPYRIGHT OR DERIVED CODE,
632 +(i.e. no GPL code, either). Free and public domain code need no disclaimer,
633 +which is obvious to anyone in the software business.
634 +
635 +Duel is available for anonymous ftp from ftp.cs.princeton.edu, in
636 +/duel/duel.tar.Z. "tar.Z" format means you should use the command
637 + "zcat duel.tar.Z | tar xf -" to unpack the files.
638 +
639 +The Usenix Jan/93 paper about Duel is also available as tech report 399,
640 +in /reports/1992/399.ps.Z on ftp.cs.princeton.edu, or, in it Usenix
641 +formatting, as /duel/usenix.paper.ps.Z. The software & man page are more
642 +up-to-date though.
643 +
644 +See MANIFEST for a list of files in the distribution. The file INSTALL
645 +explains how to install duel. MANUAL is a formatted version of the manual
646 +duel.1.
647 +
648 +If you are using duel and find it useful, or have any comments or suggestion,
649 +please drop me a line! duel.out is automatically produced to contain
650 +the dl commands you have used, I would appreciate it if you email it to
651 +me so that I could collect usage information. Thanks!
652 +
653 +Michael Golan
654 +mg@××××××××××××.edu
655 --- gdb/duel/WHATNEW
656 +++ gdb/duel/WHATNEW
657 @@ -0,0 +1,38 @@
658 +-------------------------------------------------------------------------------
659 +WHATNEW for DUEL 1.10 distribution mg@××××××××××××.edu (M. Golan) Mar 93
660 +-------------------------------------------------------------------------------
661 +patch 1.10.4 fix use of system("date") to support OS/2
662 +patch 1.10.3 bug fix left->left bad symbolic, long symbolics caused crash
663 +patch 1.10.2 bug fix (type*) casting was wrong
664 +patch 1.10.1 bug fix frame(0).bad_name crashed duel. enum size zero,
665 + sometimes possible in symbol tables, now allowed.
666 +
667 +What's New in version 1.10
668 +--------------------------
669 +Previously, all typedefs had to be preceded with 'T', e.g. (T uint) x.
670 +The parsing is now hacked, so that the most common cases don't require T:
671 +(type)x and (type*)x, e.g., (uint)x, *(value *)p. T is still required in
672 +complex casts like (T value (*)())p, in variable declaration "T uint x ;"
673 +and with sizeof(T uint). Side effects of this change: (printf)("hi\n")
674 +won't work, since (printf) is recognized as a cast. This shouldn't be a
675 +problem - you can use {x} for (x). Also, "sizeof x" is no longer supported,
676 +you must use sizeof(x) instead.
677 +
678 +An experimental output control through a pipe has been added. To try it,
679 +you should change duel/src/Makefile to compile output2.o instead of output.o
680 +(delete duel.a to make sure it won't have both output.o and output2.o).
681 +When output2.o is linked into duelself and/or gdb, duel fork and execute
682 +the command duel.pipe in the current directory. All the output from expression
683 +evaluation is sent to this program and its output is displayed. An example
684 +duel.pipe, a Perl script, is provided. A lot that can be done with duel.pipe
685 +to process the results symbolically, e.g., display integers in decimal,
686 +place values on the same line, fork and execute xgraph, check
687 +for unique values, etc. I would appreciate any comments on its use.
688 +
689 +A few minor bugs have been fixed. duel.man now contains a nicely formatted
690 +version of duel.1. Portability was improved. #/(x) provide a better symbolic
691 +expression.
692 +
693 +What's new in version 1.02
694 +--------------------------
695 +a few bug fixed, improved portability, gdb4.8 support.
696 --- gdb/duel/duel.1
697 +++ gdb/duel/duel.1
698 @@ -0,0 +1,547 @@
699 +'\" t
700 +.\" This document and the Duel source code are in the public domain.
701 +.\" Note that the duel executable contains GNU code and is not public domain.
702 +.TH Duel 1 "Mar 93" "Version 1.10"
703 +.SH NAME
704 +duel \- A high level C debugging language extension to gdb
705 +.SH SYNOPSIS
706 +.B duel
707 +[gdb options]
708 +.RB "[\|" \c
709 +.I prog\c
710 +.RB "[\|" \c
711 +.IR core \||\| procID\c
712 +\&\|]\&\|]
713 +.ad b
714 +.SH DESCRIPTION
715 +Duel is a special purpose language designed for concise state exploration
716 +of debugged C programs, currently implemented under the GNU debugger
717 +.IR gdb (1).
718 +Duel is invoked by entering the shell command
719 +.I duel
720 +instead of
721 +.I gdb.
722 +It is identical to gdb except for
723 +comments, which begin with `##' instead of `#', and the new
724 +.I dl
725 +command for Duel expressions:
726 +.nf
727 +
728 +\f2gdb>\f1 dl x[1..10] >? 5
729 +x[3] = 14
730 +x[8] = 6
731 +
732 +.fi
733 +prints the array elements x[1] to x[10] that are greater than 5.
734 +The output includes the values 14 and 6, as well as their
735 +symbolic representation "x[3]" and "x[8]".
736 +.SH IF YOU NEVER USED GDB
737 +The improved functionality added by Duel merits a fresh look
738 +even by debugger shunners.
739 +Gdb is a powerful debugger with many commands, a thick manual and
740 +various interfaces including
741 +.IR emacs (1)
742 +and
743 +.IR xxgdb (1).
744 +These gdb commands should help you get started:
745 +
746 +.TS
747 +l l.
748 +\f2b line\f1 set a breakpoint at the line (b func to break at a function)
749 +\f2d n\f1 delete breakpoint number n (gdb prints n when bp occurs)
750 +\f2l line\f1 list the source beginning at line (l file.c:line for module)
751 +\f2r parm\f1 run/restart the program with the given parameters
752 +\f2s\f1 single-step to the next statement (steps into function calls)
753 +\f2n\f1 single-step to the next line, skipping over function calls
754 +\f2c\f1 continue execution
755 +\f2bt\f1 show a stack trace
756 +\f2p exp\f1 evaluate a symbolic expression
757 +\f2dl exp\f1 evaluate a Duel expression
758 +\f2dl gdb\f1 give a gdb command summary
759 +.TE
760 +
761 +The most common use is `b func' followed by `r' followed by several
762 +`n' and `s', evaluating expressions in between.
763 +.SH DUEL QUICK START
764 +Duel is implemented by adding the
765 +.I dl
766 +command to gdb. All gdb commands
767 +work as before. The dl command, however, is interpreted by duel.
768 +Gdb concepts (such as the value history) do not work in the dl command,
769 +and duel concepts are not understood by other gdb command.
770 +
771 +Duel is based on expressions which return multiple values.
772 +The x..y operator returns
773 +the integers from x to y; the x,y operator returns x and then y, e.g.
774 +.sp
775 +\f2gdb>\f1 dl (1,9,12..15,22)
776 +.sp
777 +prints 1, 9, 12, 13, 14, 15 and 22. Such expressions can
778 +be used wherever a single value is used, e.g.
779 +.sp
780 +\f2gdb>\f1 dl x[0..99]=0 ;
781 +.sp
782 +assigns zero to the first 100 elements of array x. The semantics of x[i]
783 +are the same as in C. They are applied for each of the values
784 +returned by 0..99, which can be thought of as an implied external loop.
785 +The trailing semicolon indicates evaluation for side-effects only, with no
786 +output.
787 +Duel incorporates C operators, casts C statements as
788 +expressions, and supports limited variable declaration:
789 +.sp
790 +.br
791 +\f2gdb>\f1 dl int i;for(i=0;i<100;i++)
792 +.br
793 + if(x[i]<0) printf("x[%d]=%d\\n",i,x[i]);
794 +.br
795 +x[7] = -4
796 +.sp
797 +The semicolon prevents Duel output;
798 +only output from printf is printed.
799 +Aliases are defined with x:=y and provide an alternative to variable
800 +declaration. We could also return x[i] instead of using printf:
801 +.sp
802 +\f2gdb>\f1 dl if(x[i:=0..99]<0) x[i]
803 +.br
804 +x[i] = -4
805 +.sp
806 +The symbolic output "x[i]" can be fixed by surrounding i with {}, i.e.
807 +.sp
808 +\f2gdb>\f1 dl if(x[i:=0..99]<0) x[{i}]
809 +.br
810 +x[7] = -4
811 +.sp
812 +The {} are like (), but force the symbolic evaluation to use i's value,
813 +instead of "i". You can usually avoid this altogether
814 +with direct Duel operators:
815 +.sp
816 +\f2gdb>\f1 dl x[..100] <? 0
817 +.br
818 +x[7] = -4
819 +.sp
820 +The ..n operator is a shorthand for 0..n-1, i.e. ..100 is the same as 0..99.
821 +The x<?y, x==?y, x>=?y, etc., operators compare their left side operand to
822 +their right side operand as in C, but return the left side value if
823 +the comparison result is true. Otherwise, they look for the next
824 +values to compare, without returning anything.
825 +
826 +Duel's x.y and x->y allow an expression y, evaluated under x's scope:
827 +.sp
828 +\f2gdb>\f1 dl emp[..100].(if(code>400) (code,name))
829 +.br
830 +emp[46].code = 682
831 +.br
832 +emp[46].name = "Ela"
833 +.sp
834 +The if() expression is evaluated under the scope of each element
835 +of emp[], an array of structures. In C terms, we had to write:
836 +.sp
837 +\f2gdb>\f1 dl int i; for(i=0; i<100 ; i++)
838 +.br
839 + if(emp[i].code>400) emp[{i}].code,emp[{i}].name
840 +.sp
841 +A useful alternative to loops is the x=>y operator. It returns y for each
842 +value of x, setting `_' to reference x's value, e.g.
843 +.sp
844 +\f2gdb>\f1 ..100 => if(emp[_].code>400) emp[_].code,emp[_].name
845 +.sp
846 +Using `_' instead of `i' also avoids the need for {i}. Finally,
847 +the x\-\->y operator expands lists and other data structures. If head points
848 +to a linked list threaded through the next field, then:
849 +.sp
850 +\f2gdb>\f1 dl head-->next->data
851 +.br
852 +head->data = 12
853 +.br
854 +head->next->data = 14
855 +.br
856 +head-->next[[2]]->data = 20
857 +.br
858 +head-->next[[3]]->data = 26
859 +.sp
860 +produce the data field for each node in the list. x\-\->y
861 +returns x, x->y, x->y->y, x->y->y->y, ... until a NULL is found.
862 +The symbolic output "x\-\->y[[n]]"
863 +indicates that ->y was applied n times. x[[y]] is also the selection
864 +operator:
865 +.sp
866 +\f2gdb>\f1 dl head-->next[[50..60]]->data
867 +.sp
868 +return the 50th through the 60th elements in the list. The #/x operator
869 +counts the number of values, so
870 +.sp
871 +\f2gdb>\f1 dl #/( head-->next->data >? 50 )
872 +.sp
873 +counts the number of data elements over 50 on the list.
874 +Several other operators, including x@y, x#y and
875 +active call stack access are described in the operators section.
876 +.SH OPERATORS SUMMARY
877 +.\"All the C operators have the same precedence and associativity as in C. C
878 +.\"statements have precedence just below `,' and `;' has the lowest precedence.
879 +.\"Most Duel operators have the same precedence as their C counterparts. The
880 +.\"following table is in decreasing precedence:
881 +.TS
882 +l l l.
883 +Assoc Operators Details
884 +left {} () [] -> . f() --> x-->y expands x->y x->y->y ...
885 + x[[y]] x#y x@y generate x; select, index or stop-at y
886 +right #/ - * & ! ~ ++ -- (cast) #/x number of x values
887 + frame(n) sizeof(x) reference to call stack level n
888 +left x/y x*y x%y multiply, divide, reminder
889 +left x-y x+y add, subtract
890 +left x<<y x>>y shift left/right
891 +none x..y ..y x.. ..y = 0..y-1. x..y return x, x+1...y
892 +left < > <= >= <? >? <=? >=? x>?y return x if x>y
893 +left == != ==? !=? x==?y return x if x==y
894 +left x&y bit-and
895 +left x^y bit-xor
896 +left x|y bit-or
897 +left x&&y &&/x &&/x are all x values non-zero?
898 +left x||y ||/x ||/x is any x value non-zero?
899 +right x? y:z foreach x, if(x) y else z
900 +right x:=y x=y x+=y ... x:=y set x as an alias to y
901 +left x,y return x, then y
902 +right x=>y foreach x, evaluate y with x value `_'
903 +right if() else while() for() C statements cast as operators
904 +left x;y evaluate and ignore x, return y
905 +.TE
906 +
907 +.SH EXAMPLES
908 +.TS
909 +l l.
910 +dl (0xff-0x12)*3 compute simple expression
911 +dl (1..10)*(1..10) display multiplication table
912 +dl x[10..20,22,24,40..60] display x[i] for the selected indexes
913 +dl x[9..0] display x[i] backwards
914 +dl x[..100] >? 5 display x[i] that are greater than 5
915 +dl x[..100] >? 5 <? 10 display x[i] if 5<x[i]<10
916 +dl x[..100] ==? (6..9) same
917 +dl x[0..99]=>if(_>5 && _<10) _ same
918 +dl y[x[..100] !=? 0] display y[x[i]] for each non-zero x[i]
919 +dl emp[..50].code display emp[i].code for i=0 to 49
920 +dl emp[..50].(code,name) display emp[i].code & emp[i].name
921 +dl val[..50].(is_dbl? x:y) display val[i].x or val[i].y depending
922 + on val[i].is_dbl.
923 +dl val[..50].if(is_dbl) x else y same as above
924 +dl x[..100]=0 ; assign 0 to x[i]
925 +dl x[i:=..100]=y[i] ; assign y[i] to x[i]
926 +dl x[..100]=y[..100] *ERR* assign y[99] to each x[j]
927 +dl x[i:=..3]=(4,5,9)[[i]] assign x[0]=4 x[1]=5 x[2]=9
928 +dl x[..3]=(4,5,9) *ERR* assign 9 to each element
929 +dl if(x[i:=..100]<0) x[i]=0 ; assign 0 to negative x[i]
930 +dl (hash[..1024]!=?0)->scope hash[i].scope for non-null hash[i]
931 +dl x[i:=..100] >? x[i+1] check if x[i] is not sorted
932 +dl x[i:=..100] ==? x[j:=..100]=> checks if x has non-unique elements
933 + if(i<j) x[{i,j}]
934 +dl if(x[i:=..99] == same
935 + x[j:=i+1..99]) x[{i,j}]
936 +dl (x[..100] >? 0)[[0]] the 1st (0th element) positive x[i]
937 +dl (x[..100] >? 0)[[2]] return the 3rd positive x[i]
938 +dl (x[..100] >? 0)[[..5]] return the first 5 positive x[i]
939 +dl (x[0..] >? 6)[[0]] return the first x[i]>6, no limit on i
940 +dl argv[0..]@0 argv[0] argv[1] .. until first null
941 +dl x[0..]@-1 >? 9 x[0..n]>9 where n is first x[n]== -1
942 +dl emp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0
943 +
944 +dl head-->next->val val of each element in a linked list
945 +dl head-->next[[20]] the 21st element of a linked list
946 +dl *head-->next[[20]] display above as a struct
947 +dl strcmp(head-->next->msg, search linked list for a string
948 + "testing") ==? 0
949 +dl #/head-->next count elements on a linked list
950 +dl x-->y[[#/x-->y - 1]] last element of a linked list
951 +dl x-->y[[#/x-->y - 10..1]] last 10 elements of a linked list
952 +dl head-->next-> check if the list is sorted by val
953 + if(next) val >? next->val
954 +
955 +dl head-->(next!=?head) expand cyclic linked list (tail->head)
956 +dl head-->(next!=?_) handle termination with p->next==p
957 +dl root-->(left,right)->key expand binary tree, show keys
958 +dl root-->(left,right)->( check bin tree sorted by key
959 + (left!=?0)->key>=?key, (right !=?0 )->key<=?key)
960 +
961 +dl (1000..=>if(&&/(2,3.._-1=>__%_ find first 10 primes over 1000
962 + ) _)[[..10]]
963 +dl (T mytype) x convert x to user defined type mytype
964 +dl (struct s*) x convert x to struct s pointer
965 +dl if(x) y; else z *ERR* ';' must be followed by an expression
966 +dl {x} y *ERR* '}' requires ';' if followed by exp
967 +.TE
968 +.SH SEMANTICS
969 +Duel's semantics are modeled after the Icon programming language.
970 +The input consists of expressions which return sequences of values.
971 +C statements are cast as expressions, too.
972 +Expressions are parsed into abstract syntax trees, which are
973 +traversed during evaluation. The evaluation of most nodes (operators)
974 +recursively evaluates the next value for each operand, and then applies the
975 +operator to produce the next result. Only one value is produced each time,
976 +and Duel's eval function keeps a `state' for each node
977 +(backtracking, co-routines, consumer-producer or threads are good metaphors
978 +for the evaluation mechanism.)
979 +
980 +For example, in (5,3)+6..8, the
981 +evaluation of `+' first retrieves the operands 5 and 6, to compute and
982 +return 5+6. Then 7, the next right operand is retrieved
983 +and 5+7 is returned, followed by 5+8.
984 +Since there are no other right operand value, the next left operand, 3
985 +is fetched. The right operand's computation is restarted returning
986 +6, and 3+6 is returned. The final return values are 3+7 and 3+8.
987 +
988 +The computation for operators like x>?y is similar, but when x<=y,
989 +the next values are fetched instead of returning a value,
990 +forming the basis for an implicit search. Operators like `..' return a
991 +sequence of values for each pair of operands. For a better understanding
992 +of the evaluation mechanism, see the USENIX Winter/93 conference paper
993 +"DUEL - A Very High Level Debugging Language".
994 +
995 +Duel values follow the C semantics. A value is either an
996 +"lvalue" (can be used as the left hand side of assignment), or an "rvalue".
997 +Therefor, objects like arrays can not be directly manipulated (However,
998 +operators like x..y can accomplish such tasks.)
999 +
1000 +Duel types also follow the C semantics, with some important
1001 +differences. C types are checked statically; Duel types are checked
1002 +when operators are applied, e.g., (1,1.0)/2 returns 0 (int) and
1003 +0.5 (double); (x,y).z returns x.z and y.z even if
1004 +x and y are of different types, as long as they both have a field z.
1005 +
1006 +Values and types of symbols are looked up at run-time (using gdb's lookup
1007 +rules), allowing dynamic scoping and types, but causing a parsing
1008 +problem: (x)(y) can be parsed as either a function call x(y) or a
1009 +cast (x)y; x*y can be parsed as a declaration of y as (x*) or as
1010 +multiplication.
1011 +
1012 +To avoid this ambiguity, the
1013 +keyword T must precede a user defined type. For example,
1014 +if value is a typedef, C's (value (*)()) x is written in Duel as:
1015 +(T value (*)()) x. Types that begin with a reserved keyword don't
1016 +need T, e.g. (struct value*) x and (long *[5]) y are accepted.
1017 +As special cases, (type)x and (type*)x are accepted but
1018 +discouraged (it causes (printf)("hi"), which is valid in C, to fail).
1019 +A side effect is that "sizeof x" must be written as sizeof(x).
1020 +.SH OPERATORS
1021 +.sp
1022 +.I "x+y x-y x*y x/y x%y x^y x|y x&y x<<y x>>y "
1023 +.br
1024 +.I "x>y x<y x>=y x<=y x==y x!=y x=y x[y]"
1025 +.sp
1026 +These binary operators follow their C semantics. For each value of x,
1027 +they are evaluated for every value of y, .e.g. (5,2)>(4,1)
1028 +evaluates as 5>4, 5>1, 2>4, 2>1 returning 1, 1, 0, 1.
1029 +The y values are re-evaluated for each new value of x, e.g.
1030 +i=4; (4,5)>i++ evaluates as 4>4 and 5>5.
1031 +Beware of multiple y values in assignment, e.g. x[..3]=(4,6,9) does not
1032 +set x[0]=4, x[1]=6 and x[2]=9. It assigns 4, 6 and 9 to each element, having
1033 +the same effect as x[..3]=9. Use x[i:=..3]=(4,6,9)[[i]] to achieve the
1034 +desired effect.
1035 +.sp
1036 +.I "-x ~x &x *x !x ++x --x x++ x-- sizeof(x) (type)x"
1037 +.sp
1038 +These unary operators follow their C semantics. They are applied
1039 +to each value of x. The increment and decrement operators require an
1040 +lvalue, so i:=0 ; i++ produces an error because i is an alias to 0,
1041 +an rvalue. Parenthesis must be used with sizeof(x), "sizeof x" is not
1042 +allowed. Cast to user defined type requires generally requires T, e.g.,
1043 + (T val(*)())x, but (val)x and (val*)x are accepted as special cases.
1044 +.sp
1045 +.I "x&&y x||y"
1046 +.sp
1047 +These logical operators also follow their C semantics, but have non-intuitive
1048 +results for multi-valued x and y, e.g. (1,0,0) || (1,0) returns 1,1,0,1,0 --
1049 +the right hand-side (1,0) is returned for each left-hand side 0. It is best
1050 +to use these operators only in single value expressions.
1051 +.sp
1052 +.I "x? y:z if(x)y if(x)y else z"
1053 +.sp
1054 +These expressions return the values of y for each non-zero value
1055 +returned by x, and the values of z for each zero value returned by x, e.g.
1056 +if(x[..100]==0) y returns y for every x[i]==0, not if all x[i] are zero
1057 +(if(&&/(x[..100]==0)) y does that).
1058 +Also, "if(x) y; else z" is illegal. Duel's semicolon is
1059 +an expression separator, not a terminator.
1060 +.sp
1061 +.I "while(x)y for(w;x;y)z"
1062 +.sp
1063 +The while(x)y expression returns y as long as all values of x are non-zero.
1064 +The for() expression is similar and both have the expected C semantics. For
1065 +example, "for(i=0 ; i<100 ; i++) x[i]" is the same as x[..100]. Unlike
1066 +the if() expression, while(x[..100]==0) continue to execute only if all
1067 +elements of x are zero, i.e. the condition is evaluated into a single value
1068 +using an implicit &&/x.
1069 +.sp
1070 +.BI "Variable declaration: " "type name [,name ...] ; ..."
1071 +.sp
1072 +Expressions can begin with variables declaration (but not initialization).
1073 +Internally, a declaration sets an alias to space allocated
1074 +in the target by calling malloc(), e.g. `int x' is the same as
1075 +"x:= *(int *) malloc(sizeof(int))". This is oblivious to the user.
1076 +The allocated memory is not claimed when a variable is redeclared.
1077 +Declared variables addresses can be passed to functions and used in other
1078 +data structures. The keyword `T' must precede user defined types (typedef),
1079 +e.g. if val is a user defined type, The C code "val *p=(val*) x" becomes
1080 +"T val *p; p=(T val *) x" in Duel.
1081 +.sp
1082 +.BI "Function calls: " "func(parm,...)"
1083 +.sp
1084 +Function calls to the debugged program can be intermixed with Duel
1085 +code. Multi-valued parameters are handled as with binary operators.
1086 +The call value can have multiple values, e.g. (x,y)() calls x()
1087 +and y(). Currently, struct/union parameters and return values are not
1088 +supported.
1089 +.sp
1090 +.I "x,y x..y ..x x.."
1091 +.sp
1092 +These operators produce multiple values for single value operands.
1093 +x,y returns x, then y. x..y returns the integers from x to y.
1094 +When x>y the sequence is returned in descending order, i.e. 5..3
1095 +returns 5, 4, 3.
1096 +The operator ..x is a shorthand for 0..x-1, e.g. ..3 returns 0, 1, 2.
1097 +The x.. operator is a shorthand for x..maxint. It returns increasing
1098 +integer values starting at x indefinitely, and should be bounded
1099 +by [[n]] or @n operators.
1100 +`,' retains its precedence level in C. The precedence of `..'
1101 +is above `<' and below arithmetic operators, so 0..n-1 and x==1..9 work
1102 +as expected.
1103 +.sp
1104 +.I "x<?y x>?y x>=?y x<=?y x!=?y x==?y"
1105 +.sp
1106 +These operators work like their C counterparts but return x if the comparison
1107 +is true. If the comparison is false, the next (x,y) value is tried, forming
1108 +the basis of an implicit search.
1109 +.sp
1110 +.I "(x) {x} x;y x=>y"
1111 +.sp
1112 +Both () and {} act as C parenthesis.
1113 +The curly braces set the returned symbolic value
1114 +as the actual value, e.g. if i=5 and x[5]=3, then
1115 +x[i] produces the output "x[i] = 3", x[{i}] produces
1116 +"x[5] = 3" and {x[i]} produces just "3".
1117 +The semicolon is an operator. x;y evaluates x, ignoring the results,
1118 +then evaluate and return y, e.g. (i:=1..3 ; i+5) sets i to 3 and return 8.
1119 +The x=>y operator evaluate and return y for each value of x,
1120 +e.g. (i:=1..3 => i+5) returns 6, 7 and 8. The value returned by x is
1121 +also stored implicitly in `_' which can be used in y, e.g. 1..5 => z[_][_]
1122 +will output z[1][1], z[2][2] etc. The symbolic value for _ is that of the
1123 +left side value, hence {_} is not needed.
1124 +.br
1125 +Semicolon has the lowest precedence, so it must be used inside () or {}
1126 +for compound expressions. The precedence of `=>' is just below `,'.
1127 +Beware that "if(a) x; else {y;} z" is illegal; a semicolon is not allowed
1128 +before '}' or 'else' and must be inserted before z.
1129 +.sp
1130 +.IB "x->y x.y"
1131 +.sp
1132 +These expression work as in C for a symbol y. If y is an expression, it
1133 +is evaluated under the scope of x. e.g. x.(a+b) is the same as x.a+x.b,
1134 +if a and b are field of x (if they are not, they are looked up as local
1135 +or global variables). x may return multiple values of different types,
1136 +e.g. (u,v).a returns u.a and v.a, even if u and v are different structures.
1137 +Also, the value of x is available as `_' inside y, e.g. x[..100].(if(a) _)
1138 +produces x[i] for each x[i].a!=0. Nested x.y are allowed, e.g.
1139 +u.(v.(a+b)) would lookup a and b first under v, then under u.
1140 +.sp
1141 +.BI Aliases: " x:=y"
1142 +.sp
1143 +Aliases store a reference to y in x. Any reference to x is
1144 +then replaced by y. If y is a constant or an rvalue, its
1145 +value is replaced for x. If y is an lvalue (e.g. a variable), a reference
1146 +to same lvalue is returned. for example, x:=emp[5] ; x=9 assigns 9 to
1147 +emp[5].
1148 +Aliases retain their values across invocation of the "dl" command. An alias
1149 +to a local variable will reference a stray address when the variable
1150 +goes out of scope.
1151 +The special command "dl clear" delete all the aliases, and "dl alias"
1152 +show all current aliases. Symbols are looked up
1153 +as aliases first, so an alias x will hide a local x.
1154 +.sp
1155 +.I x-->y
1156 +.sp
1157 +The expansion operator x-->y expands a data structure x following the y links.
1158 +It returns x, x->y, x->y->y, until a null is found. If x is null, no values
1159 +are produced. If y returns multiple values, they are stacked and each is
1160 +further expanded in a depth-first notion. For example, if r is the root of
1161 +a tree with children u->childs[..u->nchilds], then
1162 +u-->(childs[..nchilds]) expands the whole tree. y is an arbitrary
1163 +expression, evaluated exactly like x->y (this includes `_'.)
1164 +.sp
1165 +.I x@y
1166 +.sp
1167 +The expression x@y produces the values of x until x.y is non-zero, e.g.
1168 +for(i=0 ; x[i].code!= -1 && i<100 ; i++) x[i] can be written as
1169 +x[..100]@(code==-1).
1170 +The evaluation of x is stopped as soon as y evaluates to true.
1171 +x->y or x=>y are used to evaluate y when x is not a struct or a union. If
1172 +y is a constant,(_==y) is used. e.g. s[0..]@0 produces the characters in
1173 +string s up to but not including the terminating null.
1174 +.sp
1175 +.IB "#/x &&/x ||/x"
1176 +.sp
1177 +These operator return a single "summary" value for all the values returned by
1178 +x. #/x returns the number of values returned by x, e.g.
1179 +#/(x[..100]>?0) counts the number of positive x[i]. &&/x returns 1 if all
1180 +the values produced by x are non-zero, and ||/x returns 1 if any of x's values
1181 +are non-zero. Like in C, the evaluation stops as soon as possible.
1182 +For example, ||/(x[..100]==0) and &&/(x[..100]==0) check if one or all of
1183 +x[i] are zero, respectively.
1184 +.sp
1185 +.IB "x#y x[[y]]"
1186 +.sp
1187 +The operator x#y produces the values of x and arranges for y to be an alias
1188 +for the index of each value in x. It is commonly used with x-->y to produce
1189 +the element's index, e.g. head-->next->val#i=i assigns each val field
1190 +its element number in the list.
1191 +.br
1192 +The selection operator x[[y]] produces the yth result of x. If y returns
1193 +multiple value, each select a value of x, e.g. (5,7,11,13)[3,0,2]
1194 +returns 13, 5 and 11 (13 is the 3rd element, 5 is the 0th element).
1195 +Don't use side effects in x, since its evaluation can be restarted depending
1196 +on y, e.g. after (x[0..i++])[[3,5]] the value of i is unpredictable.
1197 +.sp
1198 +.IB "frame(n) frames_no func.x"
1199 +.sp
1200 +frame(n) for an integer n returns a reference to the nth frame
1201 +on the stack (0 is the inner most function and frame(frames_no-1) is main()).
1202 +Frame values can be compared to function pointers,
1203 +e.g. frame(3)==myfunc is true if the 4th frame is a call to myfunc, and in
1204 +scope resolution, e.g. frame(3).x return the local variable x of the 4th frame.
1205 +frames_no is the number of active frames on the stack, e.g.
1206 +(frames(..frames_no) ==? myfunc).x displays x for all active
1207 +invocations of myfunc. As a special case, (frames(..frames_no)==?f)[[0]].x
1208 +can be written as f.x (x can be an expression).
1209 +.sp
1210 +.SH BUGS
1211 +Both `{}' and `;' are operators, not statements or expression separators;
1212 +"if(x) y; else {z;} u" is illegal; use "if(x) y else {z} ; u". Ambiguities
1213 +require preceding
1214 +user-defined types (typedef) with the keyword T, e.g., if
1215 +value is a user type, C's "sizeof(value*)" is written
1216 +"sizeof(T value*)", except for the casts "(t)x" and "(t*)x"; sizeof(x)
1217 +requires parenthesis for variable x.
1218 +
1219 +Unimplemented C idiom include: modified-assignment
1220 +(x+=y), switch, break, continue, do, goto, scopes, function declarations,
1221 +initializing declared variables,
1222 +assignment to bit-fields and register variables, and
1223 +calling functions with a struct/union parameter or return value.
1224 +gdb does not store function prototypes, so parameters are not checked.
1225 +
1226 +Gdb itself is buggy, which shows up, especially in symbol tables and
1227 +calling target functions. Before you report bug, try to do the closest
1228 +thing under gdb's "print". Send bug to: mg@××××××××××××.edu.
1229 +.SH FILES
1230 +duel.out tracks duel commands usage. Help analyze duel's use by mailing a
1231 +copy to mg@××××××××××××.edu.
1232 +.br
1233 +Duel is available by anonymous ftp at ftp.cs.princeton.edu:/duel.
1234 +.SH AUTHOR
1235 +Duel is public domain code -- no copy left or right. See the internals
1236 +documentation for details on porting Duel and using its code.
1237 +Duel was designed and written by Michael Golan as part of a PhD thesis
1238 +in the Computer Science Department of Princeton University.
1239 +I would like to thank my advisor, Dave Hanson, who helped in all phases
1240 +of this project and to Matt Blaze for his support and useful insight.
1241 +.sp
1242 +Duel stands for Debugging U (might) Even Like, or Don't Use this Exotic
1243 +Language. Judge for yourself!
1244 +
1245 +
1246 --- gdb/duel/duel.c
1247 +++ gdb/duel/duel.c
1248 @@ -0,0 +1,692 @@
1249 +/* DUEL - A Very High Level Debugging Langauge. */
1250 +/* Public domain code */
1251 +/* Written by Michael Golan mg@××××××××××××.edu */
1252 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
1253 +
1254 +/* this module contains the entery point to duel - duel_eval_and_pasre.
1255 + */
1256 +
1257 +/*
1258 + * $Log: 10_all_gdb-6.6-duel.patch,v $
1259 + * Revision 1.1 2007/12/29 21:06:06 vapier
1260 + * add DUEL support #199987 by Sergei Golubchik
1261 + *
1262 + * Revision 1.11 93/03/13 04:03:07 mg
1263 + * moved VERSION to patchlevel.h
1264 + *
1265 + * Revision 1.10 93/03/12 05:41:54 mg
1266 + * Version 1.10 - support (x)y cast, piped output.
1267 + *
1268 + * Revision 1.9 93/02/23 19:09:35 mg
1269 + * new version 1.02 release (support gdb4.8)
1270 + *
1271 + * Revision 1.8 93/02/03 21:56:33 mg
1272 + * version 1.01
1273 + *
1274 + * Revision 1.7 93/01/12 21:28:44 mg
1275 + * cleanup and set for release
1276 + *
1277 + * Revision 1.6 93/01/06 23:57:10 mg
1278 + * added alias, clear commands, new memory alloc/release
1279 + *
1280 + * Revision 1.5 93/01/03 07:26:47 mg
1281 + * new printing setup
1282 + *
1283 + * Revision 1.4 92/12/24 23:32:38 mg
1284 + * better struct support, misc changes
1285 + *
1286 + * Revision 1.3 92/10/19 15:02:04 mg
1287 + * lcc happy, size zero arrays
1288 + *
1289 + * Revision 1.2 92/10/14 02:03:15 mg
1290 + * misc
1291 + *
1292 + */
1293 +
1294 +#include <setjmp.h>
1295 +#define DEF /* define global variables */
1296 +#include "duel.h"
1297 +#include "patchlevel.h"
1298 +
1299 +static jmp_buf duel_abort_jmp ; /* abort current execution */
1300 +static tnode *root ; /* root of current eval node */
1301 +
1302 +
1303 +/* abort evaluation of current expression */
1304 +
1305 +PROC duel_abort(void)
1306 +{
1307 + longjmp(duel_abort_jmp,1);
1308 +}
1309 +
1310 +PROC duel_cleanup(void *unused) /* cleanup malloc, etc, when duel eval ends*/
1311 +{
1312 + duel_redirectable_output_abort();
1313 + duel_free_nodes(root);
1314 + root=NULL ;
1315 +}
1316 +
1317 +LPROC longhelp(void)
1318 +{
1319 + duel_printf(
1320 +"Duel(1) Duel(1)\n\
1321 +\n\
1322 +NAME\n\
1323 + duel - A high level C debugging language extension to gdb\n\
1324 +\n\
1325 +DESCRIPTION\n\
1326 + Duel is a special purpose language designed for concise state explo-\n\
1327 + ration of debugged C programs, currently implemented under the GNU\n\
1328 + debugger gdb(1). Duel is invoked by entering the shell command duel\n\
1329 + instead of gdb. It is identical to gdb except for comments, which\n\
1330 + begin with `##' instead of `#', and the new dl command for Duel expres-\n\
1331 + sions:\n\
1332 +\n\
1333 + gdb> dl x[1..10] >? 5\n\
1334 + x[3] = 14\n\
1335 + x[8] = 6\n\
1336 +\n\
1337 + prints the array elements x[1] to x[10] that are greater than 5. The\n\
1338 + output includes the values 14 and 6, as well as their symbolic repre-\n\
1339 + sentation \"x[3]\" and \"x[8]\".\n\
1340 +\n\
1341 +DUEL QUICK START\n\
1342 + Duel is implemented by adding the dl command to gdb. All gdb commands\n\
1343 + work as before. The dl command, however, is interpreted by duel. Gdb\n\
1344 + concepts (such as the value history) do not work in the dl command, and\n\
1345 + duel concepts are not understood by other gdb command.\n\
1346 +\n\
1347 + Duel is based on expressions which return multiple values. The x..y\n\
1348 + operator returns the integers from x to y; the x,y operator returns x\n\
1349 + and then y, e.g.\n\
1350 +\n\
1351 + gdb> dl (1,9,12..15,22)\n\
1352 +\n\
1353 + prints 1, 9, 12, 13, 14, 15 and 22. Such expressions can be used wher-\n\
1354 + ever a single value is used, e.g.\n\
1355 +\n\
1356 + gdb> dl x[0..99]=0 ;\n\
1357 +\n\
1358 + assigns zero to the first 100 elements of array x. The semantics of\n\
1359 + x[i] are the same as in C. They are applied for each of the values\n\
1360 + returned by 0..99, which can be thought of as an implied external loop.\n\
1361 + The trailing semicolon indicates evaluation for side-effects only, with\n\
1362 + no output. Duel incorporates C operators, casts C statements as\n\
1363 + expressions, and supports limited variable declaration:\n\
1364 +\n\
1365 + gdb> dl int i;for(i=0;i<100;i++)\n\
1366 + if(x[i]<0) printf(\"x[%%d]=%%d\\n\",i,x[i]);\n\
1367 + x[7] = -4\n\
1368 +\n\
1369 + The semicolon prevents Duel output; only output from printf is printed.\n\
1370 + Aliases are defined with x:=y and provide an alternative to variable\n\
1371 + declaration. We could also return x[i] instead of using printf:\n\
1372 +\n\
1373 + gdb> dl if(x[i:=0..99]<0) x[i]\n\
1374 + x[i] = -4\n\
1375 +\n\
1376 + The symbolic output \"x[i]\" can be fixed by surrounding i with {}, i.e.\n\
1377 +\n\
1378 + gdb> dl if(x[i:=0..99]<0) x[{i}]\n\
1379 + x[7] = -4\n\
1380 +\n\
1381 + The {} are like (), but force the symbolic evaluation to use i's value,\n\
1382 + instead of \"i\". You can usually avoid this altogether with direct Duel\n\
1383 + operators:\n\
1384 +\n\
1385 + gdb> dl x[..100] <? 0\n\
1386 + x[7] = -4\n\
1387 +\n\
1388 + The ..n operator is a shorthand for 0..n-1, i.e. ..100 is the same as\n\
1389 + 0..99. The x<?y, x==?y, x>=?y, etc., operators compare their left side\n\
1390 + operand to their right side operand as in C, but return the left side\n\
1391 + value if the comparison result is true. Otherwise, they look for the\n\
1392 + next values to compare, without returning anything.\n\
1393 +\n\
1394 + Duel's x.y and x->y allow an expression y, evaluated under x's scope:\n\
1395 +\n\
1396 + gdb> dl emp[..100].(if(code>400) (code,name))\n\
1397 + emp[46].code = 682\n\
1398 + emp[46].name = \"Ela\"\n\
1399 +\n\
1400 + The if() expression is evaluated under the scope of each element of\n\
1401 + emp[], an array of structures. In C terms, we had to write:\n\
1402 +\n\
1403 + gdb> dl int i; for(i=0; i<100 ; i++)\n\
1404 + if(emp[i].code>400) emp[{i}].code,emp[{i}].name\n\
1405 +\n\
1406 + A useful alternative to loops is the x=>y operator. It returns y for\n\
1407 + each value of x, setting `_' to reference x's value, e.g.\n\
1408 +\n\
1409 + gdb> ..100 => if(emp[_].code>400) emp[_].code,emp[_].name\n\
1410 +\n\
1411 + Using `_' instead of `i' also avoids the need for {i}. Finally, the\n\
1412 + x-->y operator expands lists and other data structures. If head points\n\
1413 + to a linked list threaded through the next field, then:\n\
1414 +\n\
1415 + gdb> dl head-->next->data\n\
1416 + head->data = 12\n\
1417 + head->next->data = 14\n\
1418 + head-->next[[2]]->data = 20\n\
1419 + head-->next[[3]]->data = 26\n\
1420 +\n\
1421 + produce the data field for each node in the list. x-->y returns x,\n\
1422 + x->y, x->y->y, x->y->y->y, ... until a NULL is found. The symbolic\n\
1423 + output \"x-->y[[n]]\" indicates that ->y was applied n times. x[[y]] is\n\
1424 + also the selection operator:\n\
1425 +\n\
1426 + gdb> dl head-->next[[50..60]]->data\n\
1427 +\n\
1428 + return the 50th through the 60th elements in the list. The #/x operator\n\
1429 + counts the number of values, so\n\
1430 +\n\
1431 + gdb> dl #/( head-->next->data >? 50 )\n\
1432 +\n\
1433 + counts the number of data elements over 50 on the list. Several other\n\
1434 + operators, including x@y, x#y and active call stack access are\n\
1435 + described in the operators section.\n\
1436 +\n\
1437 +OPERATORS SUMMARY\n\
1438 + Assoc Operators Details\n\
1439 + left {} () [] -> . f() --> x-->y expands x->y x->y->y ...\n\
1440 + x[[y]] x#y x@y generate x; select, index or stop-at y\n\
1441 + right #/ - * & ! ~ ++ -- (cast) #/x number of x values\n\
1442 + frame(n) sizeof(x) reference to call stack level n\n\
1443 + left x/y x*y x%%y multiply, divide, reminder\n\
1444 + left x-y x+y add, subtract\n\
1445 + left x<<y x>>y shift left/right\n\
1446 + none x..y ..y x.. ..y = 0..y-1. x..y return x, x+1...y\n\
1447 + left < > <= >= <? >? <=? >=? x>?y return x if x>y\n\
1448 + left == != ==? !=? x==?y return x if x==y\n\
1449 + left x&y bit-and\n\
1450 + left x^y bit-xor\n\
1451 + left x|y bit-or\n\
1452 + left x&&y &&/x &&/x are all x values non-zero?\n\
1453 + left x||y ||/x ||/x is any x value non-zero?\n\
1454 + right x? y:z foreach x, if(x) y else z\n\
1455 + right x:=y x=y x+=y ... x:=y set x as an alias to y\n\
1456 + left x,y return x, then y\n\
1457 + right x=>y foreach x, evaluate y with x value `_'\n\
1458 + right if() else while() for() C statements cast as operators\n\
1459 + left x;y evaluate and ignore x, return y\n\
1460 +\n\
1461 +\n\
1462 +EXAMPLES\n\
1463 + dl (0xff-0x12)*3 compute simple expression\n\
1464 + dl (1..10)*(1..10) display multiplication table\n\
1465 + dl x[10..20,22,24,40..60] display x[i] for the selected indexes\n\
1466 + dl x[9..0] display x[i] backwards\n\
1467 + dl x[..100] >? 5 display x[i] that are greater than 5\n\
1468 + dl x[..100] >? 5 <? 10 display x[i] if 5<x[i]<10\n\
1469 + dl x[..100] ==? (6..9) same\n\
1470 + dl x[0..99]=>if(_>5 && _<10) _ same\n\
1471 + dl y[x[..100] !=? 0] display y[x[i]] for each non-zero x[i]\n\
1472 + dl emp[..50].code display emp[i].code for i=0 to 49\n\
1473 + dl emp[..50].(code,name) display emp[i].code & emp[i].name\n\
1474 + dl val[..50].(is_dbl? x:y) display val[i].x or val[i].y depending\n\
1475 + on val[i].is_dbl.\n\
1476 + dl val[..50].if(is_dbl) x else y same as above\n\
1477 + dl x[..100]=0 ; assign 0 to x[i]\n\
1478 + dl x[i:=..100]=y[i] ; assign y[i] to x[i]\n\
1479 + dl x[..100]=y[..100] *ERR* assign y[99] to each x[j]\n\
1480 + dl x[i:=..3]=(4,5,9)[[i]] assign x[0]=4 x[1]=5 x[2]=9\n\
1481 + dl x[..3]=(4,5,9) *ERR* assign 9 to each element\n\
1482 + dl if(x[i:=..100]<0) x[i]=0 ; assign 0 to negative x[i]\n\
1483 + dl (hash[..1024]!=?0)->scope hash[i].scope for non-null hash[i]\n\
1484 + dl x[i:=..100] >? x[i+1] check if x[i] is not sorted\n\
1485 + dl x[i:=..100] ==? x[j:=..100]=> checks if x has non-unique elements\n\
1486 + if(i<j) x[{i,j}]\n\
1487 + dl if(x[i:=..99] == same\n\
1488 + x[j:=i+1..99]) x[{i,j}]\n\
1489 + dl (x[..100] >? 0)[[0]] the 1st (0th element) positive x[i]\n\
1490 +\n\
1491 + dl (x[..100] >? 0)[[2]] return the 3rd positive x[i]\n\
1492 + dl (x[..100] >? 0)[[..5]] return the first 5 positive x[i]\n\
1493 + dl (x[0..] >? 6)[[0]] return the first x[i]>6, no limit on i\n\
1494 + dl argv[0..]@0 argv[0] argv[1] .. until first null\n\
1495 + dl x[0..]@-1 >? 9 x[0..n]>9 where n is first x[n]== -1\n\
1496 + dl emp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0\n\
1497 +\n\
1498 + dl head-->next->val val of each element in a linked list\n\
1499 + dl head-->next[[20]] the 21st element of a linked list\n\
1500 + dl *head-->next[[20]] display above as a struct\n\
1501 + dl strcmp(head-->next->msg, search linked list for a string\n\
1502 + \"testing\") ==? 0\n\
1503 + dl #/head-->next count elements on a linked list\n\
1504 + dl x-->y[[#/x-->y - 1]] last element of a linked list\n\
1505 + dl x-->y[[#/x-->y - 10..1]] last 10 elements of a linked list\n\
1506 + dl head-->next-> check if the list is sorted by val\n\
1507 + if(next) val >? next->val\n\
1508 +\n\
1509 + dl head-->(next!=?head) expand cyclic linked list (tail->head)\n\
1510 + dl head-->(next!=?_) handle termination with p->next==p\n\
1511 + dl root-->(left,right)->key expand binary tree, show keys\n\
1512 + dl root-->(left,right)->( check bin tree sorted by key\n\
1513 + (left!=?0)->key>=?key, (right !=?0 )->key<=?key)\n\
1514 +\n\
1515 + dl (1000..=>if(&&/(2,3.._-1=>__%%_ find first 10 primes over 1000\n\
1516 + ) _)[[..10]]\n\
1517 + dl (T mytype) x convert x to user defined type mytype\n\
1518 + dl (struct s*) x convert x to struct s pointer\n\
1519 + dl if(x) y; else z *ERR* ';' must be followed by an expression\n\
1520 + dl {x} y *ERR* '}' requires ';' if followed by exp\n\
1521 +\n\
1522 +SEMANTICS\n\
1523 + Duel's semantics are modeled after the Icon programming language. The\n\
1524 + input consists of expressions which return sequences of values. C\n\
1525 + statements are cast as expressions, too. Expressions are parsed into\n\
1526 + abstract syntax trees, which are traversed during evaluation. The eval-\n\
1527 + uation of most nodes (operators) recursively evaluates the next value\n\
1528 + for each operand, and then applies the operator to produce the next\n\
1529 + result. Only one value is produced each time, and Duel's eval function\n\
1530 + keeps a `state' for each node (backtracking, co-routines, consumer-pro-\n\
1531 + ducer or threads are good metaphors for the evaluation mechanism.)\n\
1532 +\n\
1533 + For example, in (5,3)+6..8, the evaluation of `+' first retrieves the\n\
1534 + operands 5 and 6, to compute and return 5+6. Then 7, the next right op-\n\
1535 + erand is retrieved and 5+7 is returned, followed by 5+8. Since there\n\
1536 + are no other right operand value, the next left operand, 3 is fetched.\n\
1537 + The right operand's computation is restarted returning 6, and 3+6 is\n\
1538 + returned. The final return values are 3+7 and 3+8.\n\
1539 +\n\
1540 + The computation for operators like x>?y is similar, but when x<=y, the\n\
1541 + next values are fetched instead of returning a value, forming the basis\n\
1542 + for an implicit search. Operators like `..' return a sequence of values\n\
1543 + for each pair of operands. For a better understanding of the evaluation\n\
1544 + mechanism, see the USENIX Winter/93 conference paper \"DUEL - A Very\n\
1545 + High Level Debugging Language\".\n\
1546 +\n\
1547 + Duel values follow the C semantics. A value is either an \"lvalue\" (can\n\
1548 + be used as the left hand side of assignment), or an \"rvalue\". There-\n\
1549 + for, objects like arrays can not be directly manipulated (However,\n\
1550 + operators like x..y can accomplish such tasks.)\n\
1551 +\n\
1552 + Duel types also follow the C semantics, with some important differ-\n\
1553 + ences. C types are checked statically; Duel types are checked when\n\
1554 + operators are applied, e.g., (1,1.0)/2 returns 0 (int) and 0.5 (dou-\n\
1555 + ble); (x,y).z returns x.z and y.z even if x and y are of different\n\
1556 + types, as long as they both have a field z.\n\
1557 +\n\
1558 + Values and types of symbols are looked up at run-time (using gdb's\n\
1559 + lookup rules), allowing dynamic scoping and types, but causing a pars-\n\
1560 + ing problem: (x)(y) can be parsed as either a function call x(y) or a\n\
1561 + cast (x)y; x*y can be parsed as a declaration of y as (x*) or as multi-\n\
1562 + plication.\n\
1563 +\n\
1564 + To avoid this ambiguity, the keyword T must precede a user defined\n\
1565 + type. For example, if value is a typedef, C's (value (*)()) x is writ-\n\
1566 + ten in Duel as: (T value (*)()) x. Types that begin with a reserved\n\
1567 + keyword don't need T, e.g. (struct value*) x and (long *[5]) y are\n\
1568 + accepted. As special cases, (type)x and (type*)x are accepted but dis-\n\
1569 + couraged (it causes (printf)(\"hi\"), which is valid in C, to fail). A\n\
1570 + side effect is that \"sizeof x\" must be written as sizeof(x).\n\
1571 +\n\
1572 +OPERATORS\n\
1573 + x+y x-y x*y x/y x%%y x^y x|y x&y x<<y x>>y\n\
1574 + x>y x<y x>=y x<=y x==y x!=y x=y x[y]\n\
1575 +\n\
1576 + These binary operators follow their C semantics. For each value of x,\n\
1577 + they are evaluated for every value of y, .e.g. (5,2)>(4,1) evaluates as\n\
1578 + 5>4, 5>1, 2>4, 2>1 returning 1, 1, 0, 1. The y values are re-evalu-\n\
1579 + ated for each new value of x, e.g. i=4; (4,5)>i++ evaluates as 4>4 and\n\
1580 + 5>5. Beware of multiple y values in assignment, e.g. x[..3]=(4,6,9)\n\
1581 + does not set x[0]=4, x[1]=6 and x[2]=9. It assigns 4, 6 and 9 to each\n\
1582 + element, having the same effect as x[..3]=9. Use x[i:=..3]=(4,6,9)[[i]]\n\
1583 + to achieve the desired effect.\n\
1584 +\n\
1585 + -x ~x &x *x !x ++x --x x++ x-- sizeof(x) (type)x\n\
1586 +\n\
1587 + These unary operators follow their C semantics. They are applied to\n\
1588 + each value of x. The increment and decrement operators require an\n\
1589 + lvalue, so i:=0 ; i++ produces an error because i is an alias to 0, an\n\
1590 + rvalue. Parenthesis must be used with sizeof(x), \"sizeof x\" is not\n\
1591 + allowed. Cast to user defined type requires generally requires T, e.g.,\n\
1592 + (T val(*)())x, but (val)x and (val*)x are accepted as special cases.\n\
1593 +\n\
1594 + x&&y x||y\n\
1595 +\n\
1596 + These logical operators also follow their C semantics, but have non-\n\
1597 + intuitive results for multi-valued x and y, e.g. (1,0,0) || (1,0)\n\
1598 + returns 1,1,0,1,0 -- the right hand-side (1,0) is returned for each\n\
1599 + left-hand side 0. It is best to use these operators only in single\n\
1600 + value expressions.\n\
1601 +\n\
1602 + x? y:z if(x)y if(x)y else z\n\
1603 +\n\
1604 + These expressions return the values of y for each non-zero value\n\
1605 + returned by x, and the values of z for each zero value returned by x,\n\
1606 + e.g. if(x[..100]==0) y returns y for every x[i]==0, not if all x[i]\n\
1607 + are zero (if(&&/(x[..100]==0)) y does that). Also, \"if(x) y; else z\"\n\
1608 + is illegal. Duel's semicolon is an expression separator, not a termina-\n\
1609 + tor.\n\
1610 +\n\
1611 + while(x)y for(w;x;y)z\n\
1612 +\n\
1613 + The while(x)y expression returns y as long as all values of x are non-\n\
1614 + zero. The for() expression is similar and both have the expected C\n\
1615 + semantics. For example, \"for(i=0 ; i<100 ; i++) x[i]\" is the same as\n\
1616 + x[..100]. Unlike the if() expression, while(x[..100]==0) continue to\n\
1617 + execute only if all elements of x are zero, i.e. the condition is eval-\n\
1618 + uated into a single value using an implicit &&/x.\n\
1619 +\n\
1620 + Variable declaration: type name [,name ...] ; ...\n\
1621 +\n\
1622 + Expressions can begin with variables declaration (but not initializa-\n\
1623 + tion). Internally, a declaration sets an alias to space allocated in\n\
1624 + the target by calling malloc(), e.g. `int x' is the same as \"x:= *(int\n\
1625 + *) malloc(sizeof(int))\". This is oblivious to the user. The allocated\n\
1626 + memory is not claimed when a variable is redeclared. Declared vari-\n\
1627 + ables addresses can be passed to functions and used in other data\n\
1628 + structures. The keyword `T' must precede user defined types (typedef),\n\
1629 + e.g. if val is a user defined type, The C code \"val *p=(val*) x\"\n\
1630 + becomes \"T val *p; p=(T val *) x\" in Duel.\n\
1631 +\n\
1632 + Function calls: func(parm,...)\n\
1633 +\n\
1634 + Function calls to the debugged program can be intermixed with Duel\n\
1635 + code. Multi-valued parameters are handled as with binary operators.\n\
1636 + The call value can have multiple values, e.g. (x,y)() calls x() and\n\
1637 + y(). Currently, struct/union parameters and return values are not sup-\n\
1638 + ported.\n\
1639 +\n\
1640 + x,y x..y ..x x..\n\
1641 +\n\
1642 + These operators produce multiple values for single value operands. x,y\n\
1643 + returns x, then y. x..y returns the integers from x to y. When x>y the\n\
1644 + sequence is returned in descending order, i.e. 5..3 returns 5, 4, 3.\n\
1645 + The operator ..x is a shorthand for 0..x-1, e.g. ..3 returns 0, 1, 2.\n\
1646 + The x.. operator is a shorthand for x..maxint. It returns increasing\n\
1647 + integer values starting at x indefinitely, and should be bounded by\n\
1648 + [[n]] or @n operators. `,' retains its precedence level in C. The\n\
1649 + precedence of `..' is above `<' and below arithmetic operators, so\n\
1650 + 0..n-1 and x==1..9 work as expected.\n\
1651 +\n\
1652 + x<?y x>?y x>=?y x<=?y x!=?y x==?y\n\
1653 +\n\
1654 + These operators work like their C counterparts but return x if the com-\n\
1655 + parison is true. If the comparison is false, the next (x,y) value is\n\
1656 + tried, forming the basis of an implicit search.\n\
1657 +\n\
1658 + (x) {x} x;y x=>y\n\
1659 +\n\
1660 + Both () and {} act as C parenthesis. The curly braces set the returned\n\
1661 + symbolic value as the actual value, e.g. if i=5 and x[5]=3, then x[i]\n\
1662 + produces the output \"x[i] = 3\", x[{i}] produces \"x[5] = 3\" and {x[i]}\n\
1663 + produces just \"3\". The semicolon is an operator. x;y evaluates x,\n\
1664 + ignoring the results, then evaluate and return y, e.g. (i:=1..3 ; i+5)\n\
1665 + sets i to 3 and return 8. The x=>y operator evaluate and return y for\n\
1666 + each value of x, e.g. (i:=1..3 => i+5) returns 6, 7 and 8. The value\n\
1667 + returned by x is also stored implicitly in `_' which can be used in y,\n\
1668 + e.g. 1..5 => z[_][_] will output z[1][1], z[2][2] etc. The symbolic\n\
1669 + value for _ is that of the left side value, hence {_} is not needed.\n\
1670 + Semicolon has the lowest precedence, so it must be used inside () or {}\n\
1671 + for compound expressions. The precedence of `=>' is just below `,'.\n\
1672 + Beware that \"if(a) x; else {y;} z\" is illegal; a semicolon is not\n\
1673 + allowed before '}' or 'else' and must be inserted before z.\n\
1674 +\n\
1675 + x->y x.y\n\
1676 +\n\
1677 + These expression work as in C for a symbol y. If y is an expression, it\n\
1678 + is evaluated under the scope of x. e.g. x.(a+b) is the same as x.a+x.b,\n\
1679 + if a and b are field of x (if they are not, they are looked up as local\n\
1680 + or global variables). x may return multiple values of different types,\n\
1681 + e.g. (u,v).a returns u.a and v.a, even if u and v are different struc-\n\
1682 + tures. Also, the value of x is available as `_' inside y, e.g.\n\
1683 + x[..100].(if(a) _) produces x[i] for each x[i].a!=0. Nested x.y are\n\
1684 + allowed, e.g. u.(v.(a+b)) would lookup a and b first under v, then\n\
1685 + under u.\n\
1686 +\n\
1687 + Aliases: x:=y\n\
1688 +\n\
1689 + Aliases store a reference to y in x. Any reference to x is then\n\
1690 + replaced by y. If y is a constant or an rvalue, its value is replaced\n\
1691 + for x. If y is an lvalue (e.g. a variable), a reference to same lvalue\n\
1692 + is returned. for example, x:=emp[5] ; x=9 assigns 9 to emp[5]. Aliases\n\
1693 + retain their values across invocation of the \"dl\" command. An alias to\n\
1694 + a local variable will reference a stray address when the variable goes\n\
1695 + out of scope. The special command \"dl clear\" delete all the aliases,\n\
1696 + and \"dl alias\" show all current aliases. Symbols are looked up as\n\
1697 + aliases first, so an alias x will hide a local x.\n\
1698 +\n\
1699 + x-->y\n\
1700 +\n\
1701 + The expansion operator x-->y expands a data structure x following the y\n\
1702 + links. It returns x, x->y, x->y->y, until a null is found. If x is\n\
1703 + null, no values are produced. If y returns multiple values, they are\n\
1704 + stacked and each is further expanded in a depth-first notion. For exam-\n\
1705 + ple, if r is the root of a tree with children u->childs[..u->nchilds],\n\
1706 + then u-->(childs[..nchilds]) expands the whole tree. y is an arbitrary\n\
1707 + expression, evaluated exactly like x->y (this includes `_'.)\n\
1708 +\n\
1709 + x@y\n\
1710 +\n\
1711 + The expression x@y produces the values of x until x.y is non-zero, e.g.\n\
1712 + for(i=0 ; x[i].code!= -1 && i<100 ; i++) x[i] can be written as\n\
1713 + x[..100]@(code==-1). The evaluation of x is stopped as soon as y eval-\n\
1714 + uates to true. x->y or x=>y are used to evaluate y when x is not a\n\
1715 + struct or a union. If y is a constant,(_==y) is used. e.g. s[0..]@0\n\
1716 + produces the characters in string s up to but not including the termi-\n\
1717 + nating null.\n\
1718 +\n\
1719 + #/x &&/x ||/x\n\
1720 +\n\
1721 + These operator return a single \"summary\" value for all the values\n\
1722 + returned by x. #/x returns the number of values returned by x, e.g.\n\
1723 + #/(x[..100]>?0) counts the number of positive x[i]. &&/x returns 1 if\n\
1724 + all the values produced by x are non-zero, and ||/x returns 1 if any of\n\
1725 + x's values are non-zero. Like in C, the evaluation stops as soon as\n\
1726 + possible. For example, ||/(x[..100]==0) and &&/(x[..100]==0) check if\n\
1727 + one or all of x[i] are zero, respectively.\n\
1728 +\n\
1729 + x#y x[[y]]\n\
1730 +\n\
1731 + The operator x#y produces the values of x and arranges for y to be an\n\
1732 + alias for the index of each value in x. It is commonly used with x-->y\n\
1733 + to produce the element's index, e.g. head-->next->val#i=i assigns each\n\
1734 + val field its element number in the list.\n\
1735 + The selection operator x[[y]] produces the yth result of x. If y\n\
1736 + returns multiple value, each select a value of x, e.g.\n\
1737 + (5,7,11,13)[3,0,2] returns 13, 5 and 11 (13 is the 3rd element, 5 is\n\
1738 + the 0th element). Don't use side effects in x, since its evaluation\n\
1739 + can be restarted depending on y, e.g. after (x[0..i++])[[3,5]] the\n\
1740 + value of i is unpredictable.\n\
1741 +\n\
1742 + frame(n) frames_no func.x\n\
1743 +\n\
1744 + frame(n) for an integer n returns a reference to the nth frame on the\n\
1745 + stack (0 is the inner most function and frame(frames_no-1) is main()).\n\
1746 + Frame values can be compared to function pointers, e.g.\n\
1747 + frame(3)==myfunc is true if the 4th frame is a call to myfunc, and in\n\
1748 + scope resolution, e.g. frame(3).x return the local variable x of the\n\
1749 + 4th frame. frames_no is the number of active frames on the stack, e.g.\n\
1750 + (frames(..frames_no) ==? myfunc).x displays x for all active invoca-\n\
1751 + tions of myfunc. As a special case, (frames(..frames_no)==?f)[[0]].x\n\
1752 + can be written as f.x (x can be an expression).\n\
1753 +\n\
1754 +\n\
1755 +BUGS\n\
1756 + Both `{}' and `;' are operators, not statements or expression separa-\n\
1757 + tors; \"if(x) y; else {z;} u\" is illegal; use \"if(x) y else {z} ; u\".\n\
1758 + Ambiguities require preceding user-defined types (typedef) with the\n\
1759 + keyword T, e.g., if value is a user type, C's \"sizeof(value*)\" is\n\
1760 + written \"sizeof(T value*)\", except for the casts \"(t)x\" and \"(t*)x\";\n\
1761 + sizeof(x) requires parenthesis for variable x.\n\
1762 +\n\
1763 + Unimplemented C idiom include: modified-assignment (x+=y), switch,\n\
1764 + break, continue, do, goto, scopes, function declarations, initializing\n\
1765 + declared variables, assignment to bit-fields and register variables,\n\
1766 + and calling functions with a struct/union parameter or return value.\n\
1767 + gdb does not store function prototypes, so parameters are not checked.\n\
1768 +\n\
1769 + Gdb itself is buggy, which shows up, especially in symbol tables and\n\
1770 + calling target functions. Before you report bug, try to do the closest\n\
1771 + thing under gdb's \"print\". Send bug to: mg@××××××××××××.edu.\n\
1772 +\n\
1773 +FILES\n\
1774 + duel.out tracks duel commands usage. Help analyze duel's use by mailing\n\
1775 + a copy to mg@××××××××××××.edu.\n\
1776 + Duel is available by anonymous ftp at ftp.cs.princeton.edu:/duel.\n\
1777 +\n\
1778 +AUTHOR\n\
1779 + Duel is public domain code -- no copy left or right. See the internals\n\
1780 + documentation for details on porting Duel and using its code. Duel was\n\
1781 + designed and written by Michael Golan as part of a PhD thesis in the\n\
1782 + Computer Science Department of Princeton University. I would like to\n\
1783 + thank my advisor, Dave Hanson, who helped in all phases of this project\n\
1784 + and to Matt Blaze for his support and useful insight.\n\
1785 +\n\
1786 + Duel stands for Debugging U (might) Even Like, or Don't Use this Exotic\n\
1787 + Language. Judge for yourself!\n\
1788 +\n\
1789 +Version 1.10 Mar 93 Duel(1)\n\n");
1790 +}
1791 +
1792 +LPROC help(void)
1793 +{
1794 + duel_printf(
1795 +"Duel - Debugging U (might) Even Like -- A high level debugging language\n\n\
1796 +Duel was designed to overcome problems with traditional debuggers' print\n\
1797 +statement. It supports the C operators, many C constructs, and many new\n\
1798 +operators for easy exploration of the program's space, e.g.\n\
1799 +x[..100] >? 0 show positive x[i] for i=0 to 99\n\
1800 +y[10..20].code !=? 0 show non-zero y[i].code for i=10 to 20\n\
1801 +h-->next->code expand linked list h->next, h->next->next ...\n\
1802 +head-->next.if(code>0) name show name for each element with code>0\n\
1803 +x[i:=..100]=y[i]; array copy. i is an alias to vals 0..99\n\
1804 +head-->next[[10..15]] the 10th to 15th element of a linked list\n\
1805 +#/(head-->next->val==?4) count elements with val==4\n\
1806 +head-->next->if(next) val >? next->val check if list is sorted by val\n\
1807 +\n\
1808 +Duel was written by Michael Golan at Princeton University. Send email to\n\
1809 +mg@××××××××××××.edu. Duel is public domain code. No copy left or right.\n\
1810 +all but 500 lines are independent of gdb. Port it! Make it Commercial!\n\
1811 +\n\
1812 +Try \"dl ops\" for op summary; \"dl\" alone lists all commands\n");
1813 +}
1814 +
1815 +LPROC examples(void)
1816 +{
1817 + duel_printf("\
1818 +x[10..20,22,24,40..60] display x[i] for the selected indexes\n\
1819 +x[9..0] display x[i] backwards\n\
1820 +x[..100] >? 5 <? 10 display x[i] if 5<x[i]<10\n\
1821 +x[0..99]=>if(_>5 && _<10) _ same\n\
1822 +val[..50].if(is_dx) x else y \
1823 +val[i].x or val[i].y depending on val[i].is_dx\n\
1824 +emp[..50].if(is_m) _ return emp[i] if emp[i].is_m.\n\
1825 +x[i:=..100]=y[i] ; assign y[i] to x[i]\n\
1826 +x[i:=..100] >? x[i+1] check if x[i] is not sorted\n\
1827 +(x[..100] >? 0)[[2]] return the 3rd positive x[i]\n\
1828 +argv[0..]@0 argv[0] argv[1] .. until first null\n\
1829 +emp[0..]@(code==0) emp[0]..emp[n-1] where emp[n].code==0\n\
1830 +head-->next->val val of each element in a linked list\n\
1831 +*head-->next[[20]] element 20 of list, '*' display struct w/fields\n\
1832 +#/head-->next count elements on a linked list\n\
1833 +#/(head-->next-val>?5) count those over 5\n\
1834 +head-->(next!=?head) expand cyclic linked list (tail->head)\n\
1835 +T mytype x ; declare var for user defined type (need 'T')\n\
1836 +int i ; for(i=0 ;i<5 .. declare variable, use C construct.\n");
1837 +}
1838 +
1839 +LPROC operators(void)
1840 +{
1841 + duel_printf("\
1842 +DUEL operators in decreasing precedence. All C operators are accepted!\n\
1843 +note: precede typedefs by 'T', eg \"sizeof(T uint)\"\n\n\
1844 +{x} same as (x) but x's value is used for symbol emp[{i}]\n\
1845 +x-->y expands data structure from x, using y root-->(left,right)->key\n\
1846 +x.y eval y under x's scope, like pascal \"with\". x is accesible as '_'\n\
1847 +x->y same as (*x).y. hash[..50]->if(_!=0) key\n\
1848 +x[[y]] select the y'th elements of x head-->next[[..6]]\n\
1849 +x@y eval x, stop as soon as y true (_==y if y const). argv[0..]@0\n\
1850 +x#y eval x, set alias y as values counter (x-->next#n)->level==?n");
1851 + duel_printf("\n\
1852 +#/x count number of values from x #/head-->next\n\
1853 +frame(n) use with '.' to reference stack frames. frame(3).val\n\
1854 +x..y x, x+1, x+2 .. y. (if x>y, return them backwards) x[10..20]\n\
1855 +..y like 0..y-1 x[..1024]\n\
1856 +x.. like x..maxint. Caution: use only with x@y or x[[y]] name[0..]@0\n\
1857 +x>?y x if x>y else nothing. also <? <=? >=? ==? and !=? x[..10]<?0\n\
1858 +&&/x 1 or 0 if x!=0 for all x values. ||/x similar &&/x[..100]>=0\n\
1859 +x,y x, then y. head-->next->(val,key)\n\
1860 +x=>y eval y for each x, setting '_' to x's values x[..50]=>_*_\n\
1861 +if(x) y C statements are operators. Also for(), while(), if() else\n\
1862 +x;y Evaluate and ignore x's value, then return y\n");
1863 +}
1864 +
1865 +/* entry point into duel. s is the expression to evaluate */
1866 +
1867 +void duel_parse_and_eval(char *s)
1868 +{
1869 + static first=1 ;
1870 + if(first) { /* init stuff */
1871 + duel_init_basic_ctypes();
1872 + duel_printf("%s.%d, public domain debugging language. \"dl\" for help\n",
1873 + VERSION,PATCHLEVEL);
1874 + duel_redirectable_output_init();
1875 + first=0 ;
1876 + }
1877 + if(!s || *s==0) { /* no input, give some help */
1878 + duel_printf("\
1879 +Supported DUEL commands:\n\
1880 +duel help - give basic help (shortcut: dl ?)\n\
1881 +duel longhelp - give a longer help (dl ?\?)\n\
1882 +duel examples - show useful usage examples (dl ex)\n\
1883 +duel operators - operators summary (dl ops)\n\
1884 +duel aliases - show current aliases (dl alias)\n\
1885 +duel clear - clear all aliases\n\
1886 +duel debug - toggle duel debug mode\n");
1887 + return ;
1888 + }
1889 + if(strcmp(s,"?")==0 || strcmp(s,"help")==0) {
1890 + help();
1891 + return ;
1892 + }
1893 + if(strcmp(s,"?\?")==0 || strcmp(s,"longhelp")==0) {
1894 + longhelp();
1895 + return ;
1896 + }
1897 + if(strcmp(s,"examples")==0 || strcmp(s,"ex")==0 ) {
1898 + examples();
1899 + return ;
1900 + }
1901 + if(strcmp(s,"operators")==0 || strcmp(s,"ops")==0) {
1902 + operators();
1903 + return ;
1904 + }
1905 + if(strcmp(s,"debug")==0) { /* turn debugging of duel itself */
1906 + duel_debug= !duel_debug ;
1907 + duel_printf("duel debug mode %d\n",duel_debug);
1908 + return ;
1909 + }
1910 + if(strcmp(s,"clear")==0) {
1911 + duel_clear_aliases();
1912 + duel_printf("Aliases table cleared\n");
1913 + return ;
1914 + }
1915 + if(strcmp(s,"alias")==0 || strcmp(s,"aliases")==0) {
1916 + duel_show_aliases();
1917 + return ;
1918 + }
1919 + if(setjmp(duel_abort_jmp)==0) { /* set abort point */
1920 + if((root=duel_parse(s))!=NULL) {
1921 + tvalue v ;
1922 + duel_set_input_string(s); /* for src-location err management */
1923 + duel_reset_eval();
1924 + duel_redirectable_output_start(s); /* allow eval output to go to pipe */
1925 + while(duel_eval(root,&v)) {
1926 + duel_print_value(&v);
1927 + duel_flush();
1928 + }
1929 + duel_redirectable_output_end();
1930 + }
1931 + }
1932 + duel_cleanup(0);
1933 +}
1934 +
1935 +
1936 +
1937 +
1938 +
1939 +
1940 +
1941 +
1942 +
1943 +
1944 --- gdb/duel/duel.h
1945 +++ gdb/duel/duel.h
1946 @@ -0,0 +1,35 @@
1947 +/* DUEL - A Very High Level Debugging Langauge. */
1948 +/* Public domain code */
1949 +/* Written by Michael Golan mg@××××××××××××.edu */
1950 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
1951 +
1952 +/* duel.h - include file to be used with all duel source code.
1953 + * it defines important global constants & data types, as well as some
1954 + * global variables. prototypes should go in the duelprot.h file
1955 + */
1956 +
1957 +
1958 +/* common duel include files. I dunno why people don't like recursive
1959 + * includes, as long as it is consistent. Note only one level of recursion.
1960 + * the debugger module itself dont use this file, instead it includes what
1961 + * it needs directly.
1962 + * as for including "everything", unless one redefine some standard lib func,
1963 + * I feel safer including most standard lib files. It seems to prevent errors
1964 + * even if it garble the name space a bit.
1965 + */
1966 +
1967 +#include <stdio.h>
1968 +#include <stdlib.h>
1969 +#include <stddef.h>
1970 +#include <string.h>
1971 +#include <assert.h>
1972 +#include <ctype.h>
1973 +#include <limits.h>
1974 +#include <math.h>
1975 +/* global data and types */
1976 +
1977 +#include "global.h"
1978 +
1979 +/* prototypes for all global functions follows */
1980 +
1981 +#include "proto.h"
1982 --- gdb/duel/duel.pipe
1983 +++ gdb/duel/duel.pipe
1984 @@ -0,0 +1,107 @@
1985 +#!/usr/local/bin/perl
1986 +# perl script opened as a pipe by duel
1987 +#
1988 +# duel(gdb), fork this program and feed it as stdin, the output from
1989 +# evaluating expressions. the input is
1990 +# $$$START: expr where expr is the expression being evaluted
1991 +# $$$DONE end of results
1992 +# $$$ABORT end of results due to error or interrupt
1993 +# $$$SYM: s symbolic output 's'
1994 +# $$$VAL: v value for previous symbolic output
1995 +#
1996 +# the output from this program is fed back into duel, which simply display
1997 +# it. After DONE/ABORT, duel wait for a $$$DONE to get back, so it can
1998 +# return to gdb's prompt.
1999 +#
2000 +# Duel expressions terminates after '|>', the text after which should be
2001 +# processed by the pipe (a "pipe command" if you will).
2002 +# There is no limit to what this program can do. Currently all it does
2003 +# is provide all hex/ all decimal display of integers (|>hex and |>dec),
2004 +# and provide "smart" output, on the same line, when the symbolic output
2005 +# is the same as the values.
2006 +#
2007 +# Some examples of what can be done here:
2008 +# |> sort -- will sort the output
2009 +# |> sort? -- display a message if it was/wasnt sorted
2010 +# |> uniq -- display only uniq values in output
2011 +# |> uniq? -- display message if all output was uniq.
2012 +# |> vals -- only display vals, ignore symbolic
2013 +# |> syms -- only display symbolics, ignore vals
2014 +# |> matrix -- Attempt to display in a matrix format
2015 +# |> compress -- compress into single lines, eg
2016 +# x[i].val=1\n x[i].name="me"\n
2017 +# becomes: x[i] = { val=1, name="me" }
2018 +# |> vector -- attempt to display as vector, eg
2019 +# x[1]=5\bx[4]=3\nx[9]=2\nx[12]=8\n becomes:
2020 +# i 1 4 9 12
2021 +# x[i] 5 3 2 8
2022 +# |> smart -- try to figure out one of the above formats...
2023 +# |> plotxy -- plot (sym,val) using xgraph. can convert x[5]
2024 +# symbol into '5' for the x-coord, etc.
2025 +# |> stack -- output of frame(..frames_no).`*`,
2026 +# which hasnt been implemented yet (* is regex),
2027 +# to be formatted as a stack trace...
2028 +#
2029 +# the code below is very simple. A better organization will support
2030 +# adding "functions" (commands) and specify for each command if the
2031 +# function is called only after all values have been collected, or
2032 +# for every value, if the command is active until unset, or just for
2033 +# the specific line it was given on, what flags it set/reset, etc.
2034 +
2035 +
2036 +$|=1 ; # flush output on every write to the pipe
2037 +
2038 +%cmds = ("norm",1,"smart",1,"dec",1,"hex",1) ;
2039 +$smart=0;
2040 +$base=0 ;
2041 +
2042 +while(<>) {
2043 + chop; study ;
2044 + if(/^\$\$\$START: /) {
2045 + if(/\|\>\s*([^"']*)$/) { # |> pipe-command
2046 + $_ = $1 ;
2047 + s/\s+$// ; # clean trailing spaces
2048 + if($cmds{$_}) {
2049 + printf "Pipe command '$_'\n" ;
2050 + $smart=0 if /norm/ ;
2051 + $smart=1 if /smart/ ;
2052 + $base=0 if /norm/ ;
2053 + $base=10 if /dec/ ;
2054 + $base=16 if /hex/ ;
2055 + }
2056 + else { printf "BAD PIP COMMAND '$_'\n" ; }
2057 + }
2058 + $same=0 ;
2059 + }
2060 + elsif(/^\$\$\$DONE$/) {
2061 + print "\n" if $same ; # go to next line if not on same
2062 + print "\$\$\$DONE\n" ;
2063 + }
2064 + elsif(/^\$\$\$ABORT$/) {
2065 + print "\n" if $same ; # go to next line if not on same
2066 + print "\$\$\$DONE\n" ;
2067 + }
2068 + elsif(/^\$\$\$SYM: (.*)$/) {
2069 + $sym = $1 ;
2070 + }
2071 + elsif(/^\$\$\$VAL: (.*)$/) {
2072 + $_ = $val = $1 ;
2073 + $_ = oct if($base==10 && /^0x[0-9a-z]*$/) ;
2074 + $_ = sprintf("0x%2.2x",$_) if($base==16 && /^[1-9]\d*$/) ;
2075 + if($smart && ( $sym eq $_ || $sym eq $val)) {
2076 + $sz= 3 + length ;
2077 + if($same+$sz > 75) { print "\n" ; $same=0 ; }
2078 + $same+=$sz ;
2079 + print "$_, " ;
2080 + }
2081 + else {
2082 + print "\n" if $same ; # go to next line if not on same
2083 + if($sym == $val) { print "$_\n" ; }
2084 + else { print "$sym = $_\n" ; }
2085 + $same=0 ;
2086 + }
2087 + }
2088 + else {
2089 + print "bad duel input to duel.pipe ignored: $_\n" ;
2090 + }
2091 +}
2092 --- gdb/duel/duelself.c
2093 +++ gdb/duel/duelself.c
2094 @@ -0,0 +1,209 @@
2095 +/* DUEL - A Very High Level Debugging Langauge. */
2096 +/* Public domain code */
2097 +/* Written by Michael Golan mg@××××××××××××.edu */
2098 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
2099 +
2100 +/* self-debugger module, it contains all of duel's access to
2101 + * the outside world (like duelgdb.c), but is intended to work when duel
2102 + * is linked with the debuggee directly (not with the debugger!)
2103 + * if you link this with duel.a, you get a test suite of duel
2104 + * for the C program: (tsuite.c)
2105 + *
2106 + * int gint ;
2107 + * typedef unsigned int uint ;
2108 + * int main() {
2109 + * printf ; malloc ; / * include them in bin * /
2110 + * char *s="main string" ;
2111 + * }
2112 + *
2113 + * You could link this module with your own program and call it at
2114 + * "appropriate places", then ship the program with this code, and
2115 + * use duel at client's site when a crash occurs. However, reading in
2116 + * the symbol table and figuring out the active frames remains a problem.
2117 + */
2118 +
2119 +/*
2120 + * $Log: 10_all_gdb-6.6-duel.patch,v $
2121 + * Revision 1.1 2007/12/29 21:06:06 vapier
2122 + * add DUEL support #199987 by Sergei Golubchik
2123 + *
2124 + * Revision 1.6 93/03/19 16:55:35 mg
2125 + * allow execution from within make
2126 + *
2127 + * Revision 1.5 93/03/12 05:47:29 mg
2128 + * *** empty log message ***
2129 + *
2130 + * Revision 1.4 93/02/04 00:05:10 mg
2131 + * avoid Header problems in self.out
2132 + *
2133 + * Revision 1.3 93/01/13 16:21:40 mg
2134 + * made sure printf is declared
2135 + *
2136 + * Revision 1.2 93/01/12 21:31:01 mg
2137 + * brought uptodate with duelgdb.c
2138 + * cleanup and set for release
2139 + *
2140 + */
2141 +/* include system dependent stuff here */
2142 +
2143 +#include "duel.h"
2144 +
2145 +int main(int argc,char **argv);
2146 +
2147 +FUNC void* duel_malloc(size_t size)
2148 +{
2149 + void *p=malloc(size);
2150 + if(p==0) duel_fatal("out of memory.");
2151 + return p;
2152 +}
2153 +
2154 +PROC duel_free(void *p)
2155 +{
2156 + free(p);
2157 +}
2158 +/* fetch n bytes from the target at the given memory address.
2159 + * the address to fetch from is given by (from).
2160 + * the value is stored at the 'to' location, which points to space for
2161 + * n bytes in the debugger.
2162 + * if the address can not be accessed, false is returned (if all ok, ret true)
2163 + */
2164 +
2165 +FUNC bool duel_get_target_bytes(ttarget_ptr from,void *to,size_t n)
2166 +{
2167 + duel_bcopy(to,from,n);
2168 + return TRUE ;
2169 +}
2170 +
2171 +/* store n bytes to the debuggee. reverse parms from above */
2172 +FUNC bool duel_put_target_bytes(ttarget_ptr to,void *from,size_t n)
2173 +{
2174 + duel_bcopy(to,from,n);
2175 + return TRUE ;
2176 +}
2177 +
2178 +/* fetch the value of a bitfield of a given structure. */
2179 +
2180 +FUNC bool duel_get_target_bitfield(ttarget_ptr struct_at,int bitpos,
2181 + int bitlen,void *to,tctype_kind tkind)
2182 +{
2183 + return FALSE ; /* not supported in duelself */
2184 +}
2185 +
2186 +/* make a function call to the target. */
2187 +/* support only passing/returing sizeof(int) upto 5 paramaters */
2188 +PROC duel_target_func_call(tvalue *func, tvalue *parms[],
2189 + int parms_no,tvalue *rval)
2190 +{
2191 + int (*f)();
2192 + int i ;
2193 + if(parms_no>5) duel_fatal("too many parms");
2194 + if(sizeof(func->ctype->u.kid)!=sizeof(int) &&
2195 + func->ctype->u.kid!=ctype_void ) duel_fatal("unsupported func parm");
2196 + for(i=0 ; i<parms_no ; i++) {
2197 + if(parms[i]->val_kind!=VK_RVALUE || parms[i]->ctype->size!=sizeof(int))
2198 + duel_fatal("unsupported paramater");
2199 + }
2200 + f=(int (*)()) func->u.lvalue ;
2201 + switch(parms_no) {
2202 + case 0:
2203 + rval->u.rval_int= (*f)();
2204 + break ;
2205 + case 1:
2206 + rval->u.rval_int= (*f)(parms[0]->u.rval_int);
2207 + break ;
2208 + case 2:
2209 + rval->u.rval_int= (*f)(parms[0]->u.rval_int,parms[1]->u.rval_int);
2210 + break ;
2211 + case 3:
2212 + rval->u.rval_int= (*f)(parms[0]->u.rval_int,parms[1]->u.rval_int,
2213 + parms[2]->u.rval_int);
2214 + break ;
2215 + case 4:
2216 + rval->u.rval_int= (*f)(parms[0]->u.rval_int,parms[1]->u.rval_int,
2217 + parms[2]->u.rval_int,parms[3]->u.rval_int);
2218 + break ;
2219 + case 5:
2220 + rval->u.rval_int= (*f)(parms[0]->u.rval_int,parms[1]->u.rval_int,
2221 + parms[2]->u.rval_int,parms[3]->u.rval_int,parms[4]->u.rval_int);
2222 + break ;
2223 + }
2224 + rval->val_kind=VK_RVALUE ;
2225 + rval->ctype=func->ctype->u.kid ;
2226 +}
2227 +
2228 +/* find debuggee variable.
2229 + * recognize main.s, gint, malloc, printf
2230 + */
2231 +
2232 +int gint ; /* global variable recognized */
2233 +char **main_s ; /* point to main's 's' */
2234 +
2235 +FUNC bool duel_get_target_variable(char *name, int frame_no, tvalue *v)
2236 +{
2237 + v->val_kind=VK_LVALUE ;
2238 + if(frame_no<=0 && strcmp(name,"s")==0) {
2239 + v->ctype=duel_mkctype_ptr(ctype_char);
2240 + v->u.lvalue = (void*) main_s ;
2241 + return TRUE ;
2242 + }
2243 + if(frame_no != -1) return FALSE ;
2244 + if(strcmp(name,"main")==0) {
2245 + v->ctype=duel_mkctype_func(ctype_void);
2246 + v->u.lvalue = (void*) main ;
2247 + return TRUE ;
2248 + }
2249 + if(strcmp(name,"malloc")==0) {
2250 + v->ctype=duel_mkctype_func(duel_mkctype_ptr(ctype_void));
2251 + v->u.lvalue = (void*) malloc ;
2252 + return TRUE ;
2253 + }
2254 + if(strcmp(name,"printf")==0) {
2255 + if(0) printf(""); /* "declare" print */
2256 + v->ctype=duel_mkctype_func(ctype_int);
2257 + v->u.lvalue = (void*) printf ;
2258 + return TRUE ;
2259 + }
2260 + if(strcmp(name,"gint")!=0) return FALSE ;
2261 + v->ctype= ctype_int ; /* type of this variable */
2262 + v->u.lvalue= (void*) &gint ; /* address of variable */
2263 + return TRUE ;
2264 +}
2265 +
2266 +
2267 +FUNC int duel_get_frames_number(void)
2268 +{
2269 + return 1 ; /* main */
2270 +}
2271 +
2272 +
2273 +FUNC ttarget_ptr duel_get_function_for_frame(int frame_no)
2274 +{
2275 + if(frame_no==0) return (void*) main ;
2276 + else duel_fatal("bad frame number - internal err");
2277 +}
2278 +
2279 +FUNC tctype* duel_get_target_typedef(char *name)
2280 +{
2281 + if(strcmp(name,"uint")==0) return ctype_uint ;
2282 + return NULL ;
2283 +}
2284 +
2285 +FUNC tctype* duel_get_target_struct_tag(char *name) { return 0 ; }
2286 +FUNC tctype* duel_get_target_union_tag(char *name) { return 0 ; }
2287 +FUNC tctype* duel_get_target_enum_tag(char *name) { return 0 ; }
2288 +
2289 +int main(int argc,char **argv)
2290 +{
2291 + char *s="main string" ;
2292 + main_s = &s ; /* put s into the "symbol tbl" */
2293 +
2294 + while(1) {
2295 + char in[120] ;
2296 + gets(in);
2297 + if(feof(stdin)) break ;
2298 + /* output & input are RCS'ed. avoid $Header in self.out, which is
2299 + * the input header, which RCS fix... which create mis matches */
2300 + if(strncmp(in,"## $Header",10)==0) continue ;
2301 + printf("dl> %s\n",in);
2302 + if(in[0]==0 || in[0]=='#' && in[1]=='#') continue ; /* comments */
2303 + duel_parse_and_eval(in);
2304 + }
2305 + return 0 ; /* to run in make */
2306 +}
2307 --- gdb/duel/error.c
2308 +++ gdb/duel/error.c
2309 @@ -0,0 +1,114 @@
2310 +/* DUEL - A Very High Level Debugging Langauge. */
2311 +/* Public domain code */
2312 +/* Written by Michael Golan mg@××××××××××××.edu */
2313 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
2314 +
2315 +/* display errors in a neat way */
2316 +
2317 +/*
2318 + * $Log: 10_all_gdb-6.6-duel.patch,v $
2319 + * Revision 1.1 2007/12/29 21:06:06 vapier
2320 + * add DUEL support #199987 by Sergei Golubchik
2321 + *
2322 + * Revision 1.5 93/03/12 05:48:27 mg
2323 + * support output redirection
2324 + *
2325 + * Revision 1.4 93/01/12 21:35:31 mg
2326 + * cleanup and set for release
2327 + *
2328 + */
2329 +
2330 +#include "duel.h"
2331 +
2332 +static tnode *curr_eval_node ; /* current node being evaluated */
2333 +static char *curr_inputstr ; /* current input string being eval */
2334 +
2335 +/* indicate the active node where an operator is now evaluated.
2336 + * if an error occurs, this marker is used to tell the user where
2337 + * the error is located.
2338 + * return previous setup to caller, so it can be restored.
2339 + */
2340 +
2341 +FUNC tnode* duel_set_eval_loc(tnode *n)
2342 +{
2343 + tnode *prev=curr_eval_node ;
2344 + curr_eval_node=n ;
2345 + return prev ;
2346 +}
2347 +
2348 +/* indicate the current input string which is evaluated
2349 + * (intended for future versions with multiple input strings)
2350 + */
2351 +
2352 +FUNC char* duel_set_input_string(char *s)
2353 +{
2354 + char *prev=curr_inputstr ;
2355 + curr_inputstr=s ;
2356 + return prev ;
2357 +}
2358 +/* display source position for errors, based on current node being eval'ed */
2359 +
2360 +LPROC print_src_pos(void)
2361 +{
2362 + int src_pos=0 ;
2363 + int i ;
2364 + if(curr_eval_node) src_pos=curr_eval_node->src_pos ;
2365 + duel_printf("Error: %s\n",curr_inputstr) ;
2366 + duel_printf(" ") ;
2367 + for(i=0 ; i<src_pos ; i++) duel_printf("-");
2368 + duel_printf("^-- ");
2369 +}
2370 +
2371 +/* called for errors that are results of bad user input (syntax/sematics),
2372 + * e.g. an illegal variable name, etc
2373 + * the message is printed as a format string for 'op'.
2374 + * the error location in the source is printed based on the current eval node,
2375 + * and the value of the given operands are displayed.
2376 + */
2377 +
2378 +PROC duel_op_error(char *mesg,char *op,tvalue *v1,tvalue *v2)
2379 +{
2380 + char s[160] ;
2381 +
2382 + duel_redirectable_output_abort();
2383 + print_src_pos();
2384 + duel_printf(mesg,op);
2385 + duel_printf("\n");
2386 + if(v1) {
2387 + duel_printf("operand%s ``%s'' ",(v2!=0)? "1":"",v1->symb_val);
2388 + duel_printf("\t-- type: ");
2389 + duel_print_type(v1->ctype,1);
2390 + duel_sprint_scalar_value(s,v1);
2391 + duel_printf("\n\t\t-- value: %s\n",s);
2392 + }
2393 + if(v2) {
2394 + duel_printf("operand%s ``%s'' ",(v1!=0)? "2":"",v2->symb_val);
2395 + duel_printf("\t-- type: ");
2396 + duel_print_type(v2->ctype,1);
2397 + duel_sprint_scalar_value(s,v2);
2398 + duel_printf("\n\t\t-- value: %s\n",s);
2399 + }
2400 +
2401 + duel_abort();
2402 +}
2403 +
2404 +/* handle a genral error, no value (operand) is involved.
2405 + * location (node) is still displayed
2406 + */
2407 +
2408 +PROC duel_gen_error(char *mesg,char *arg1)
2409 +{
2410 + duel_redirectable_output_abort();
2411 + print_src_pos();
2412 + duel_printf(mesg,arg1);
2413 + duel_printf("\n");
2414 + duel_abort();
2415 +}
2416 +
2417 +/* handle fatal messages */
2418 +
2419 +PROC duel_fatal(char *msg)
2420 +{
2421 + duel_redirectable_output_abort();
2422 + duel_printf("Fatal Duel error: %s\n",msg);
2423 + duel_abort();
2424 +}
2425 +
2426 +
2427 --- gdb/duel/eval.c
2428 +++ gdb/duel/eval.c
2429 @@ -0,0 +1,834 @@
2430 +/* DUEL - A Very High Level Debugging Langauge. */
2431 +/* Public domain code */
2432 +/* Written by Michael Golan mg@××××××××××××.edu */
2433 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
2434 +
2435 +/* this module is the most critical code, the recursive evaluation
2436 + */
2437 +
2438 +/*
2439 + * $Log: 10_all_gdb-6.6-duel.patch,v $
2440 + * Revision 1.1 2007/12/29 21:06:06 vapier
2441 + * add DUEL support #199987 by Sergei Golubchik
2442 + *
2443 + * Revision 1.13 93/03/19 15:39:34 mg
2444 + * fixed bug in left->left symbolic, and long symbolics which caused crashes
2445 + *
2446 + * Revision 1.12 93/03/12 05:48:45 mg
2447 + * fixed sizeof(type) symbolic
2448 + *
2449 + * Revision 1.11 93/02/26 04:59:51 mg
2450 + * improved symbolic debugging of #/
2451 + *
2452 + * Revision 1.10 93/02/03 21:47:41 mg
2453 + * fixed dot stack bug; fixed func-call last parm eval bug
2454 + *
2455 + * Revision 1.9 93/01/12 21:50:26 mg
2456 + * cleanup and set for release
2457 + *
2458 + * Revision 1.8 93/01/07 00:09:34 mg
2459 + * scope stack changes a bit.
2460 + * clear/aliases commands.
2461 + * func.x support, x.y etc force existance if y field of x., x=>y w/'_'
2462 + * allow fields in y for x@y, x pointer.
2463 + * fixed eval_node setup
2464 + * added &&/ ||/
2465 + *
2466 + *
2467 + * Revision 1.7 93/01/03 07:29:23 mg
2468 + * function calls, error reporting, printing.
2469 + *
2470 + * Revision 1.6 92/12/24 23:33:48 mg
2471 + * frames support
2472 + *
2473 + * Revision 1.5 92/10/19 15:06:35 mg
2474 + * *** empty log message ***
2475 + *
2476 + * Revision 1.4 92/10/14 02:04:35 mg
2477 + * misc
2478 + *
2479 + * Revision 1.3 92/09/16 11:04:16 mg
2480 + * *** empty log message ***
2481 + *
2482 + * Revision 1.2 92/09/15 05:54:56 mg
2483 + * cosmetics and new ops:
2484 + * generic '.' and '_' support. x@y. '..x' and 'x..'. while(), for(), ?:
2485 + *
2486 + */
2487 +
2488 +#include "duel.h"
2489 +
2490 +
2491 +
2492 +#define DOT_STACK_SIZE 100 /* dot stack size, maximum no. of dots in stmt */
2493 +
2494 +/* the scope eval stack.
2495 + * used for several purposes: to push _'s values (=>), to push structs
2496 + * and unions for x.y and x->y, and to push func/frame values fro frame(i).x
2497 + * and func.x/
2498 + * realv is the real value for the left side operand. It is used for '_'.
2499 + * fieldv is the one to be used to fetch actual names. either:
2500 + * fieldv=realv (for x.y, frame(i).y), fieldv=*realv (for x->y),
2501 + * fieldv=func_frame(realv) (for func.x), or fieldv=0 (x=>y).
2502 + */
2503 +struct {
2504 + tvalue *realv ; /* actual value for x in x.y or x->y etc. used for _ */
2505 + tvalue *fieldv; /* value to use for fetching fields, *realv for x->y */
2506 + } dot_stack[DOT_STACK_SIZE] ;
2507 +int dot_stack_top= -1 ;
2508 +
2509 +PROC duel_reset_eval(void) /* reset evaluation states from previous eval */
2510 +{
2511 + dot_stack_top= -1 ; /* reset stack */
2512 +}
2513 +
2514 +/* try to find the given name on the dot_stack of structures.
2515 + * if found, return true and value in(v) else return false.
2516 + * the symbolic value is not set.
2517 + * if top_only, looks only at the top of the stack.
2518 + */
2519 +LFUNC bool find_dot_name(char *name,tvalue *v,bool top_only)
2520 +{
2521 + int i,j ;
2522 + tctype_field *f ;
2523 + tctype *t ;
2524 + tvalue *x;
2525 +
2526 + for(i=dot_stack_top ; i>=0 ; i--) { /* look at the stack[i] */
2527 + if(top_only && i!=dot_stack_top) break ; /* consider only top of stk*/
2528 + x=dot_stack[i].realv ;
2529 + if(name[0]=='_' && name[1]==0 || /* _ */
2530 + name[1]=='_' && i==dot_stack_top-1 && name[2]==0 || /* __ */
2531 + name[1]=='0'+dot_stack_top-i && name[2]==0) { /* _[0-9] */
2532 + *v = *x ;
2533 + return TRUE ;
2534 + }
2535 + x=dot_stack[i].fieldv;
2536 + if(!x) continue ;
2537 + if(x->val_kind==VK_FVALUE) {
2538 + if(!duel_get_target_variable(name,x->u.fvalue,v)) continue ;
2539 + strcpy(v->symb_val,name);
2540 + return TRUE ;
2541 + }
2542 + t=x->ctype ;
2543 + if(!ctype_kind_struct_like(t)) continue ;
2544 + duel_assert(x->val_kind==VK_LVALUE);
2545 + for(j=0 ; j<t->u.f.fields_no ; j++) { /* look at field[j] of struct*/
2546 + f= &t->u.f.fields[j] ;
2547 + if(strcmp(f->name,name)==0) goto found ;
2548 + }
2549 + }
2550 + return FALSE ;
2551 +found:
2552 + v->ctype=f->ctype ;
2553 + strcpy(v->symb_val,name);
2554 + if(f->bitlen==0) {
2555 + v->u.lvalue=x->u.lvalue+f->bitpos/BITS_PER_BYTE ;
2556 + v->val_kind=VK_LVALUE ;
2557 + return TRUE ;
2558 + }
2559 + /* special care for a bitfield */
2560 + if(f->ctype->type_kind!=CTK_INT && f->ctype->type_kind!=CTK_UINT)
2561 + duel_gen_error("bitfield '%s' must be int or unsigned",name);
2562 + v->val_kind=VK_BVALUE ;
2563 + v->u.bvalue.lvalue=x->u.lvalue ;
2564 + v->u.bvalue.bitpos=f->bitpos ;
2565 + v->u.bvalue.bitlen=f->bitlen ;
2566 + return TRUE ;
2567 +}
2568 +
2569 +/* find the value of a given symbolic name and
2570 + * return in in v
2571 + * if name is not found, aborts with an error
2572 + */
2573 +
2574 +LPROC duel_eval_name(char *name,tvalue *v)
2575 +{
2576 + tvalue *aval=duel_find_alias(name) ; /* find internal alias */
2577 + if(aval!=NULL) *v= *aval ;
2578 + else
2579 + if(find_dot_name(name,v,FALSE)) return ; /* setup name itself */
2580 + else
2581 + if(duel_get_target_variable(name,-1,v));
2582 + else
2583 + if(strcmp(name,"frames_no")==0) { /* check special variables */
2584 + v->val_kind=VK_RVALUE ;
2585 + v->ctype=ctype_int ;
2586 + v->u.rval_int=duel_get_frames_number();
2587 + }
2588 + else duel_gen_error("variable '%s' not found",name);
2589 + strcpy(v->symb_val,name);
2590 +}
2591 +
2592 +
2593 +LPROC push_val(tval_list *l,tvalue *v)
2594 +{
2595 + tval_lcell *e = duel_malloc(sizeof(tval_lcell));
2596 + e->val = *v ;
2597 + e->next=l->head ;
2598 + l->head=e ;
2599 + if(l->tail==0) l->tail=e ;
2600 +}
2601 +
2602 +LPROC append_val(tval_list *l,tvalue *v)
2603 +{
2604 + tval_lcell *e=duel_malloc(sizeof(tval_lcell)) ;
2605 + e->val = *v ;
2606 + e->next=0 ;
2607 + if(l->head==0) l->head=l->tail=e ;
2608 + else l->tail=l->tail->next=e ;
2609 +}
2610 +
2611 +/* push a whole val-list(ins) into (l) i.e. insert (ins) at the head of(l)
2612 + */
2613 +
2614 +LPROC push_val_list(tval_list *l,tval_list *ins)
2615 +{
2616 + if(ins->head==NULL) return ; /* inserted list is empty */
2617 + if(l->head==NULL) { *l= *ins ; return ; } /* insert-into is empty */
2618 + ins->tail->next=l->head ;
2619 + l->head=ins->head ;
2620 +}
2621 +
2622 +
2623 +/* remove first(top) element */
2624 +LFUNC bool pop_val(tval_list *l,tvalue *v)
2625 +{
2626 + tval_lcell *e=l->head ;
2627 + if(e==0) return(FALSE);
2628 + *v=e->val ;
2629 + l->head=e->next ;
2630 + return(TRUE);
2631 +}
2632 +/* compute the symbolic value of one iteration of a search (eg -->) operator.
2633 + * Normally, for (x) and (y) the result x->y is returned.
2634 + * But, if x === a-->next[[n]] and y === next, then we
2635 + * return a-->next[[m]] where m=n+1.
2636 + * Also, instead of returning x->y we return x-->y[[1]]
2637 + *
2638 + * note: this was not written for speed! I don't know if it takes
2639 + * a significant amount of time or not.
2640 + */
2641 +
2642 +LPROC set_search_symb_val(char *opcode,tvalue *xval,tvalue *yval)
2643 +{
2644 + char *x = xval->symb_val ;
2645 + char *y = yval->symb_val ;
2646 + int i,opl=strlen(opcode),xl=strlen(x),yl=strlen(y) ;
2647 + char s[3*VALUE_MAX_SYMBOLIC_SIZE];
2648 +
2649 + if(yl+2<xl && strcmp(x+xl-yl,y)==0 && x[xl-yl-2]=='-' && x[xl-yl-1]=='>')
2650 + sprintf(s,"%-.*s%s%s[[2]]",xl-yl-2,x,opcode,y);
2651 + else {
2652 + for(i=xl-1 ; i>0 ; i--) /* see if we have op in x */
2653 + if(strncmp(&x[i],opcode,opl)==0) break ;
2654 + if(i>0 && strncmp(&x[i+opl],y,yl)==0 &&
2655 + x[i+opl+yl]=='[' && x[i+opl+yl+1]=='[' && x[xl-2]==']' && x[xl-1]==']'){
2656 + /* x seems to be something like head-->next[1] */
2657 + int j,val=0 ;
2658 + for(j=i+opl+yl+2 ; j<xl-2 ; j++) {
2659 + if(x[j]<'0' || x[j]>'9') goto simple ;
2660 + val=10*val+x[j]-'0' ; /* compute index */
2661 + }
2662 + sprintf(s,"%-.*s[[%d]]",i+opl+yl,x,val+1); /* and re-create it */
2663 + }
2664 + else {
2665 +simple: /* we failed to find a x-->y[z] pattern, make new one */
2666 + sprintf(s,"%s->%s",x,y);
2667 + }
2668 + }
2669 + s[VALUE_MAX_SYMBOLIC_SIZE-1]=0 ; /* chop as needed */
2670 + strcpy(y,s);
2671 +}
2672 +
2673 +LPROC push_dot_stack(tvalue *realv,tvalue *fieldv)
2674 +{
2675 + if(dot_stack_top==DOT_STACK_SIZE)
2676 + duel_gen_error("expression too complex ('.' and '->' levels)",0);
2677 + dot_stack[++dot_stack_top].realv=realv ;
2678 + dot_stack[dot_stack_top].fieldv=fieldv ;
2679 +}
2680 +
2681 +LPROC pop_dot_stack(void)
2682 +{
2683 + duel_assert(dot_stack_top>=0);
2684 + dot_stack_top-- ;
2685 +}
2686 +
2687 +/* a simple fetch of a field. used mainly when printing
2688 + * v must be a struct with the given name field. value is returned in ret.
2689 + * return false if name not found.
2690 + */
2691 +
2692 +FUNC bool duel_get_dot_name(tvalue *v,char *name,tvalue *ret)
2693 +{
2694 + bool ok ;
2695 + push_dot_stack(v,v);
2696 + ok=find_dot_name(name,ret,TRUE);
2697 + pop_dot_stack();
2698 + return ok ;
2699 +}
2700 +
2701 +/* evaluate x.y and similar "with" operators. Special care when y is a
2702 + * name and not an expression -- force y to be a direct field of x.
2703 + * y is the 'y' node. v is value to return. op is opcode for error reports
2704 + * (rv,fv) are values to push on the dot stack. rv is the real 'x' value,
2705 + * fv is the value of x to use for field lookup (fv= *rv for '->')
2706 + */
2707 +
2708 +LFUNC bool eval_dot(tnode *y,tvalue *v,char *op,tvalue *rv,tvalue *fv)
2709 +{
2710 + bool ok ;
2711 + push_dot_stack(rv,fv);
2712 + if(y->node_kind!=NK_NAME) ok=duel_eval(y,v); /* "with" style */
2713 + else { /* x.y y simply name */
2714 + if(++y->eval.level>1) { y->eval.level=0 ; ok=FALSE ; }
2715 + else {
2716 + ok=find_dot_name(y->name,v,TRUE);
2717 + if(!ok) duel_op_error("field not found in operator '%s'",op,rv,0);
2718 + }
2719 + }
2720 + pop_dot_stack();
2721 + return ok ;
2722 +}
2723 +
2724 +
2725 +/* evaluate special operators like '-->' '?:' etc */
2726 +
2727 +/* get the next result of an sop val:
2728 + * DFS: init by pushing(x)
2729 + * Iterate: pop x, compute all x->y, push (reversed)
2730 + * out: x
2731 +
2732 + * POS: init by pushing(x), unmarked.
2733 + * Iterate: pop x, if marked return it. else push back, marked.
2734 + * compute all x->y, push (reversed)
2735 + * repeat until marked x is popped.
2736 + * out: poped x which is marked.
2737 +
2738 + * BFS: init by pushing(x)
2739 + * Iterate: get first(x),
2740 + * compute all x->y and put into queue.
2741 + * return x.
2742 + */
2743 +
2744 +/* fetch the next value in a DFS search on x-->y. y is given as a node
2745 + * and x is popped of the given list. Value is returned in v.
2746 + * note: the results from x->y are reversed when pushed on the list,
2747 + * this is so x-->(left,right) would return the left first (put last on
2748 + * the stack, even though it is computed first!)
2749 + * malloc problem: newl is kept locally, so in case of ^C while here, mem
2750 + * it points to will be lost. Normally only a few values
2751 + */
2752 +
2753 +LFUNC bool get_next_dfs_val(tval_list *l, tnode *y,tvalue *v)
2754 +{
2755 + tvalue child,x ;
2756 + tval_list newl ;
2757 + newl.head=0 ;
2758 + do {
2759 + if(!pop_val(l,v)) return(FALSE) ;
2760 + x= *v ;
2761 + duel_get_struct_ptr_val(&x,"x-->y");
2762 + } while(x.u.lvalue==0) ; /* ignore null pointers */
2763 + while(eval_dot(y,&child,"-->",v,&x)) {
2764 + set_search_symb_val("-->",&x,&child); /* makes x-->y[n] neatly */
2765 + append_val(&newl,&child); /* append to childs list */
2766 + }
2767 + push_val_list(l,&newl); /* append new childs to stack */
2768 + return(TRUE); /* returns the popped value in v */
2769 +}
2770 +
2771 +
2772 +/* stop the evaluation of the expression at node n.
2773 + * useful with operators like first().
2774 + * each node keeps an internal state allowing it to produce the next value.
2775 + * this function resets those states.
2776 + *
2777 + * How: the internal state is kept in n->eval.level. we reset level to zero
2778 + * for the node and the subnodes. if the level is already zero,
2779 + * the node has already gone to the 'initial state', so the subnodes
2780 + * are not visited.
2781 + */
2782 +
2783 +LPROC stop_eval(tnode *n)
2784 +{
2785 + int i;
2786 + if(n==NULL || n->eval.level==0) return ; /* done! subnodes are also ok */
2787 + n->eval.level=0 ;
2788 + for(i=0 ; i<NODE_MAX_KIDS ; i++) stop_eval(n->kids[i]);
2789 +}
2790 +
2791 +/* evaluate function paramaters. This recursive function should be called
2792 + * with the top node for the parms. Parms are parsed as "," operators.
2793 + * the function leaves the computed values "hanging" on v1 of each "," node.
2794 + * the last paramater is left at v2 of the function call itself (there isnt
2795 + * any other reasonable place!).
2796 + * 2nd paramater is the function call node, used for the last paramater.
2797 + */
2798 +
2799 +LFUNC bool eval_func_parms(tnode *n,tnode *fn)
2800 +{
2801 + tvalue *p= &n->eval.v1 ;
2802 + if(n->node_kind==NK_OP && n->op_kind==OPK_SBIN && n->op==',') {
2803 + while(n->eval.level==2 || duel_eval(n->kids[0],p)) {
2804 + n->eval.level=2 ; /* left side active parm in p */
2805 + if(eval_func_parms(n->kids[1],fn)) goto ok;
2806 + n->eval.level=1 ; /*re-eval */
2807 + }
2808 + return FALSE ;
2809 + }
2810 + else if(!duel_eval(n,p = &fn->eval.v2)) return FALSE; /* last paramater */
2811 +ok:
2812 + duel_standardize_func_parm(p);
2813 + return TRUE ;
2814 +}
2815 +
2816 +LFUNC bool eval_func_call(tnode *n,tvalue *v)
2817 +{
2818 +
2819 + tvalue *f= &n->eval.v1 ;
2820 + tvalue *parms[21];
2821 + int i,parms_no ;
2822 + tnode *p ;
2823 +
2824 +again:
2825 + if(n->kids[1]==NULL) { /* no parms */
2826 + n->eval.level=1 ;
2827 + if(!duel_eval(n->kids[0],f)) return FALSE ;
2828 + }
2829 + else {
2830 + while(n->eval.level==2 || duel_eval(n->kids[0],f)) {
2831 + n->eval.level=2 ; /* function in f */
2832 + if(eval_func_parms(n->kids[1],n)) goto ok;
2833 + n->eval.level=1 ; /*re-eval func */
2834 + }
2835 + return FALSE ;
2836 + ok: ;
2837 + }
2838 +
2839 + if(f->ctype->type_kind!=CTK_FUNC) duel_op_error("bad function call",0,f,0);
2840 +
2841 + p=n->kids[1] ; /* collect paramaters now */
2842 + parms_no=0 ;
2843 + while(p && p->node_kind==NK_OP && p->op_kind==OPK_SBIN && p->op==',') {
2844 + parms[parms_no++]= &p->eval.v1 ;
2845 + p=p->kids[1] ;
2846 + if(parms_no>=20) duel_op_error("too many paramaters",0,0,0);
2847 + }
2848 + if(p) parms[parms_no++]= &n->eval.v2 ; /* last paramater */
2849 +
2850 + duel_target_func_call(f,parms,parms_no,v);
2851 + if(f->ctype->u.kid->type_kind==CTK_VOID) goto again ; /* no return vals */
2852 + duel_set_symb_val(v,"%s(",f,0);
2853 + for(i=0 ; i<parms_no ; i++)
2854 + duel_set_symb_val(v,"%s%s,",v,parms[i]);
2855 + if(parms_no>0) v->symb_val[strlen(v->symb_val)-1]='\0' ; /*chop ',' tail*/
2856 + strcat(v->symb_val,")");
2857 + return TRUE ;
2858 +}
2859 +
2860 +
2861 +/* evaluate for special operators: those the produce more than one value,
2862 + * binary ones. ',' '..' etc
2863 + */
2864 +
2865 +LFUNC bool duel_eval_sbin(tnode *n,tvalue *v)
2866 +{
2867 + tval_list *vl = &n->eval.vlist ;
2868 + tvalue y,*v1= &n->eval.v1, *v2= &n->eval.v2 ;
2869 + tnode *kid0 = n->kids[0], *kid1 = n->kids[1] ;
2870 + int vi ;
2871 + bool ok ;
2872 +#define lev n->eval.level
2873 +
2874 + duel_assert(n->node_kind==NK_OP && n->op_kind==OPK_SBIN);
2875 + switch(n->op) {
2876 + case OP_DECL:
2877 + duel_assert(kid0->node_kind==NK_NAME && kid1->node_kind==NK_CTYPE);
2878 + if(kid1->ctype->size<=0) duel_gen_error("illegal type size",0);
2879 + v->val_kind=VK_LVALUE ;
2880 + v->ctype=kid1->ctype ;
2881 + v->u.lvalue=duel_alloc_target_space(kid1->ctype->size);
2882 + strcpy(v->symb_val,kid0->name);
2883 + duel_set_alias(kid0->name,v);
2884 + break ;
2885 + case OP_DEF:
2886 + if(kid0->node_kind!=NK_NAME)
2887 + duel_gen_error("left side of := must be a simple var",0);
2888 + if(!duel_eval(kid1,v)) return FALSE ;
2889 + duel_set_alias(kid0->name,v);
2890 + return TRUE ;
2891 + case ',':
2892 + if(lev==1 && duel_eval(kid0,v)) return TRUE ;
2893 + lev=2 ;
2894 + return duel_eval(kid1,v);
2895 + case ';':
2896 + /*note: (x;) is not allowed in syntax, but is allowed here and
2897 + *means eval x, return nothing. used by parser, e.g. terminating ';'
2898 + *produces no side effects
2899 + */
2900 +
2901 + if(lev==1) while(duel_eval(kid0,v)) ; /* eval all left size */
2902 + lev=2 ;
2903 + return duel_eval(kid1,v);
2904 + break ;
2905 + case OP_IMP: /* a=>b for each _=eval(a) return eval(b) (with _ set) */
2906 + if(lev>1) goto im2 ;
2907 + for(;;) {
2908 + if(!duel_eval(kid0,v1)) return FALSE ;
2909 + lev=2 ;
2910 + im2: push_dot_stack(v1,0);
2911 + ok=duel_eval(kid1,v);
2912 + pop_dot_stack();
2913 + if(ok) return TRUE ;
2914 + }
2915 + case OP_IF: /* if(a) b return eval(b) for each eval(a)!=0 */
2916 + if(lev>1) goto if2 ;
2917 + for(;;) {
2918 + if(!duel_eval(kid0,v)) return FALSE ;
2919 + if(!duel_mk_logical(v,"if(x)y")) continue ;
2920 + lev=2 ;
2921 + if2: if(duel_eval(kid1,v)) return TRUE ;
2922 + }
2923 + case OP_OR: /* a||b normal 'C' logical or */
2924 + if(lev>1) goto or2 ;
2925 + for(;;) {
2926 + if(!duel_eval(kid0,v)) return FALSE ;
2927 + if(duel_mk_logical(v,"x||y")) {lev=1 ; return TRUE ;}
2928 + or2: if(duel_eval(kid1,v)) {
2929 + lev=2 ;
2930 + duel_mk_logical(v,"y||x");
2931 + return TRUE ;
2932 + }
2933 + }
2934 + case OP_AND: /* a&&b normal 'C' logical and */
2935 + if(lev>1) goto an2 ;
2936 + for(;;) {
2937 + if(!duel_eval(kid0,v)) return FALSE ;
2938 + if(!duel_mk_logical(v,"x&&y")) {lev=1 ; return TRUE ;}
2939 + an2: if(duel_eval(kid1,v)) {
2940 + lev=2 ;
2941 + duel_mk_logical(v,"y&&x");
2942 + return TRUE ;
2943 + }
2944 + }
2945 + case '.':
2946 + if(lev>1) goto dt2 ;
2947 + for(;;) {
2948 + if(!duel_eval(kid0,v1)) return FALSE ;
2949 + *v2 = * v1 ; /* copy value for the lookup */
2950 + if(ctype_kind_func_ptr_like(v1->ctype)) /* func.x */
2951 + duel_find_func_frame(v2,"x.y");
2952 + else
2953 + if(v1->val_kind!=VK_FVALUE) /* type check frame or struct*/
2954 + duel_get_struct_val(v1,"x.y");
2955 + lev=2 ;
2956 + dt2: if(!eval_dot(kid1,v,".",v1,v2)) continue ;
2957 + if(v->ctype!=v1->ctype || v->val_kind!=v1->val_kind ||
2958 + v->u.lvalue != v1->u.lvalue ||
2959 + strcmp(v->symb_val,v1->symb_val)!=0) /* check for x._ */
2960 + duel_set_symb_val(v,"%s.%s",v1,v);
2961 + return TRUE ;
2962 + }
2963 + case OP_ARR:
2964 + if(lev>1) goto ar2 ;
2965 + for(;;) {
2966 + if(!duel_eval(kid0,v1)) return FALSE ;
2967 + *v2 = *v1 ; /* copy value for dereferencing */
2968 + duel_get_struct_ptr_val(v2,"x->y");
2969 + lev=2 ;
2970 + ar2: if(!eval_dot(kid1,v,"->",v1,v2)) continue ;
2971 + if(v->ctype!=v1->ctype || v->val_kind!=v1->val_kind ||
2972 + v->u.lvalue != v1->u.lvalue ||
2973 + strcmp(v->symb_val,v1->symb_val)!=0) /* check for x->_ */
2974 + duel_set_symb_val(v,"%s->%s",v1,v);
2975 + return TRUE ;
2976 + }
2977 + case OP_TO: /* a..b Is it legal to have 1..(5,6) sure! */
2978 + if(lev>1) goto to2 ;
2979 + do {
2980 + if(kid0 && !duel_eval(kid0,v1)) break ;
2981 + do {
2982 + if(kid1 && !duel_eval(kid1,v2)) break ;
2983 + to2: if(duel_do_op_to(kid0? v1:0,kid1? v2:0,++lev-2,v)) return TRUE;
2984 + } while(kid1);
2985 + } while(kid0) ; /* either one (kid0 null) or infinite iterations*/
2986 + break ;
2987 + case OP_SEL: /* x[[y]] */
2988 + if(lev==1) { lev=2 ; n->eval.counter= -1 ; }
2989 + if(!duel_eval(kid1,v1)) {
2990 + stop_eval(kid0);
2991 + return FALSE ;
2992 + }
2993 + vi=duel_get_posint_val(v1,"y[[x]]");
2994 + if(vi<=n->eval.counter) {
2995 + /* v is smaller than previous v value, so reset x and
2996 + * start over. Example: \x[1,5,3] after \x[1],
2997 + * we continue to get [5]. but to get [3] we reset
2998 + * Alternatively, we could have kept a list of old
2999 + * generated values.
3000 + */
3001 + stop_eval(kid0) ;
3002 + n->eval.counter= -1 ;
3003 + }
3004 + for( ; n->eval.counter<vi ; n->eval.counter++)
3005 + if(!duel_eval(kid0,v))
3006 + duel_op_error("operator x of y[[x]] too large",0,v1,0);
3007 + return TRUE ; /* value is the last (v) computed */
3008 + break ;
3009 + case '@': /* x@y - generate x stops when y true */
3010 + if(!duel_eval(kid0,v)) return FALSE ;
3011 + if(kid1->node_kind==NK_CONST) { /* special case y constant */
3012 + *v2=kid1->cnst ;
3013 + *v1= *v ; /* because 'apply_bin_op' destroy its args */
3014 + duel_apply_bin_op(OP_EQ,v1,v2,&y);
3015 + if(y.u.rval_int) { stop_eval(kid0); return FALSE ; }
3016 + return TRUE ;
3017 + }
3018 + *v1 = *v ; /* allow fields in y of x@y for x struct ptr */
3019 + if(ctype_kind_ptr_like(v->ctype) &&
3020 + ctype_kind_struct_like(v->ctype->u.kid))
3021 + duel_get_struct_ptr_val(v1,"x@y");
3022 +
3023 + while(eval_dot(kid1,v2,"@",v,v1)) /* check &&/y */
3024 + if(!duel_mk_logical(v2,"y@x")) { /* y==0, so dont stop x */
3025 + stop_eval(kid1);
3026 + return TRUE ;
3027 + }
3028 + stop_eval(kid0);
3029 + break ;
3030 + case '#': /* x#i define variable i as counter for gen. x*/
3031 + if(kid1->node_kind!=NK_NAME)
3032 + duel_gen_error("x#y 2rd operand must be a name",0);
3033 + if(!duel_eval(kid0,v)) return FALSE ;
3034 + if(lev==1) { lev=2 ; n->eval.counter= -1 ; } /* first time */
3035 + y.val_kind=VK_RVALUE ;
3036 + y.ctype=ctype_int ;
3037 + y.u.rval_int= ++n->eval.counter ;
3038 + sprintf(y.symb_val,"%d",n->eval.counter);
3039 + duel_set_alias(kid1->name,&y);
3040 + return TRUE ;
3041 + break ;
3042 + case OP_DFS: /* x-->y */
3043 + if(lev>1) goto df2 ;
3044 + for(;;) {
3045 + if(!duel_eval(kid0,v)) return FALSE ;
3046 + duel_free_val_list(vl);
3047 + push_val(vl,v);
3048 + lev=2 ;
3049 + df2: if(get_next_dfs_val(vl,kid1,v)) return TRUE ;
3050 + }
3051 + break ;
3052 + case OP_WHILE: /* while(a) b */
3053 + if(lev==2) goto wh2 ;
3054 + for(;;) {
3055 + while(duel_eval(kid0,v)) /* check &&/a */
3056 + if(!duel_mk_logical(v,"while(x)y")) {
3057 + stop_eval(kid0);
3058 + return FALSE ;
3059 + }
3060 + lev=2 ;
3061 + wh2: if(duel_eval(kid1,v)) return TRUE ;
3062 + }
3063 + default: duel_assert(0);
3064 + }
3065 + return FALSE ;
3066 +#undef lev
3067 +}
3068 +
3069 +
3070 +
3071 +LFUNC bool duel_eval_tri(tnode *n,tvalue *v)
3072 +{
3073 +#define lev n->eval.level
3074 + duel_assert(n->node_kind==NK_OP && n->op_kind==OPK_TRI);
3075 + switch(n->op) {
3076 + case OP_IF: /* if(a) b else c return eval(b) for each eval(a)!=0
3077 + * and eval(c) for each eval(a)==0 (usu. (a) is one result*/
3078 + if(lev>1) goto if2;
3079 + for(;;) {
3080 + if(!duel_eval(n->kids[0],v)) return FALSE ;
3081 + lev=(duel_mk_logical(v,"if(x) y else z")? 2:3) ;
3082 + if2: if(duel_eval(n->kids[lev-1],v)) return TRUE ;
3083 + }
3084 + case '?': /* a? b:c has the same semantics as if(a) b else c */
3085 + if(lev>1) goto qm2;
3086 + for(;;) {
3087 + if(!duel_eval(n->kids[0],v)) return FALSE ;
3088 + lev=(duel_mk_logical(v,"x? y:z")? 2:3) ;
3089 + qm2: if(duel_eval(n->kids[lev-1],v)) return TRUE ;
3090 + }
3091 + default: duel_assert(0);
3092 + }
3093 + return FALSE ;
3094 +#undef lev
3095 +}
3096 +
3097 +LFUNC bool duel_eval_quad(tnode *n,tvalue *v)
3098 +{
3099 +#define lev n->eval.level
3100 + duel_assert(n->node_kind==NK_OP && n->op_kind==OPK_QUAD);
3101 + switch(n->op) {
3102 + case OP_FOR: /* for(a;b;c) d ; */
3103 + if(lev==1) { lev=2 ; while(duel_eval(n->kids[0],v)); }
3104 + if(lev==3) goto fr3 ;
3105 + for(;;) {
3106 + while(duel_eval(n->kids[1],v)) /* check &&/b */
3107 + if(!duel_mk_logical(v,"for(a;x;y)z")) {
3108 + stop_eval(n->kids[1]);
3109 + return FALSE ;
3110 + }
3111 + lev=3 ;
3112 + fr3: if(duel_eval(n->kids[3],v)) return TRUE ;
3113 + while(duel_eval(n->kids[2],v));
3114 + }
3115 + default: duel_assert(0);
3116 + }
3117 + return FALSE ;
3118 +#undef lev
3119 +}
3120 +
3121 +FUNC bool duel_eval(tnode *n,tvalue *v)
3122 +{
3123 + tvalue u,tmp ;
3124 + bool ok=FALSE ;
3125 + tnode *prev_loc ;
3126 +
3127 + if(!n) return FALSE ;
3128 + prev_loc=duel_set_eval_loc(n); /* set current eval node, save prev */
3129 + if(n->eval.level==0) n->eval.level=1 ; /* indicate node is 'active' */
3130 +
3131 + switch(n->node_kind) {
3132 + case NK_CONST: /* return a 'value' node made of this constant */
3133 + if(n->eval.level==1) {
3134 + n->eval.level=2 ;
3135 + *v=n->cnst ;
3136 + ok=TRUE ;
3137 + }
3138 + break ;
3139 + case NK_NAME:
3140 + if(n->eval.level==1) {
3141 + n->eval.level=2 ;
3142 + duel_eval_name(n->name,v);
3143 + ok=TRUE ;
3144 + }
3145 + break ;
3146 + case NK_OP:
3147 + switch(n->op_kind) {
3148 + case OPK_SUNARY: /* special unary ops */
3149 + if(n->op=='#') {
3150 + int count=0 ;
3151 + if(n->eval.level==1) {
3152 + while(duel_eval(n->kids[0],&u))
3153 + if(count++ == 0) duel_set_symb_val(v,"#/(%s ...)",&u,0);
3154 + if(count == 0) duel_set_symb_val(v,"#/(empty)",0,0);
3155 + v->val_kind=VK_RVALUE ;
3156 + v->ctype=ctype_int ;
3157 + v->u.rval_int=count ;
3158 + n->eval.level=2 ;
3159 + ok=TRUE ;
3160 + }
3161 + }
3162 + else
3163 + if(n->op==OP_AND) {
3164 + if(n->eval.level==1) { int result=1 ;
3165 + while(duel_eval(n->kids[0],v)) {
3166 + if(!duel_mk_logical(v,"&&/x")) {
3167 + stop_eval(n->kids[0]);
3168 + result=0 ;
3169 + break ;
3170 + }
3171 + }
3172 + v->val_kind=VK_RVALUE ;
3173 + v->ctype=ctype_int ;
3174 + v->u.rval_int=result ;
3175 + sprintf(v->symb_val,"%d",result);
3176 + n->eval.level=2 ;
3177 + ok=TRUE ;
3178 + }
3179 + }
3180 + else
3181 + if(n->op==OP_OR) {
3182 + if(n->eval.level==1) { int result=0 ;
3183 + while(duel_eval(n->kids[0],v)) {
3184 + if(duel_mk_logical(v,"||/x")) {
3185 + stop_eval(n->kids[0]);
3186 + result=1 ;
3187 + break ;
3188 + }
3189 + }
3190 + v->val_kind=VK_RVALUE ;
3191 + v->ctype=ctype_int ;
3192 + v->u.rval_int=result ;
3193 + sprintf(v->symb_val,"%d",result);
3194 + n->eval.level=2 ;
3195 + ok=TRUE ;
3196 + }
3197 + }
3198 + else
3199 + if(n->op==OP_SIZ) {
3200 + if(n->eval.level==1) {
3201 + char *tname=n->kids[0]->ctype->name ;
3202 + duel_assert(n->kids[0]->node_kind==NK_CTYPE);
3203 + v->val_kind=VK_RVALUE ;
3204 + v->ctype=ctype_size_t ;
3205 + v->u.rval_size_t=n->kids[0]->ctype->size ;
3206 + n->eval.level=2 ;
3207 + if(tname==NULL || *tname=='\0') tname="T" ; /* cheating */
3208 + sprintf(v->symb_val,"sizeof(%s)",tname);
3209 + ok=TRUE ;
3210 + }
3211 + }
3212 + else duel_assert(0);
3213 + break ;
3214 + case OPK_UNARY:
3215 + if(!duel_eval(n->kids[0],v)) break ;
3216 + duel_apply_unary_op(n->op,v);
3217 + ok=TRUE ;
3218 + break ;
3219 + case OPK_POST_UNARY:
3220 + if(!duel_eval(n->kids[0],v)) break ;
3221 + duel_apply_post_unary_op(n->op,v);
3222 + ok=TRUE ;
3223 + break ;
3224 + case OPK_BIN: /* a+b, compute and hold a, iterate on b, redo a */
3225 + while(n->eval.level==2 || duel_eval(n->kids[0],&n->eval.v1)) {
3226 + n->eval.level=2 ; /* left side active op in vals[0] */
3227 + while(duel_eval(n->kids[1],&u)) {
3228 + tmp= n->eval.v1 ; /* copy left val, it is destoryed*/
3229 + ok=duel_apply_bin_op(n->op,&tmp,&u,v);
3230 + if(ok) goto done;
3231 + }
3232 + n->eval.level=1 ; /*left side val no longer valid, re-eval*/
3233 + }
3234 + break ;
3235 + case OPK_SBIN: /* a,b etc, special ops */
3236 + ok=duel_eval_sbin(n,v) ;
3237 + break ;
3238 + case OPK_TRI:
3239 + ok=duel_eval_tri(n,v) ;
3240 + break ;
3241 + case OPK_QUAD:
3242 + ok=duel_eval_quad(n,v) ;
3243 + break ;
3244 + case OPK_CAST:
3245 + duel_assert(n->kids[0]->node_kind==NK_CTYPE);
3246 + if(!duel_eval(n->kids[1],v)) break ;
3247 + duel_do_cast(n->kids[0]->ctype,v);
3248 + ok=TRUE ;
3249 + break ;
3250 + case OPK_ASSIGN:
3251 + duel_gen_error("modified assignment is not supported yet",0);
3252 + case OPK_FUNC:
3253 + ok=eval_func_call(n,v) ;
3254 + break ;
3255 + default: duel_assert(0);
3256 + }
3257 + break ;
3258 + default: duel_assert(0);
3259 + }
3260 +done:
3261 + if(!ok) n->eval.level=0 ; /* no other val available */
3262 + duel_set_eval_loc(prev_loc);
3263 + return ok ;
3264 +}
3265 +
3266 +
3267 --- gdb/duel/evalops.c
3268 +++ gdb/duel/evalops.c
3269 @@ -0,0 +1,1273 @@
3270 +/* DUEL - A Very High Level Debugging Langauge. */
3271 +/* Public domain code */
3272 +/* Written by Michael Golan mg@××××××××××××.edu */
3273 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
3274 +
3275 +/* this module contains evalauation code for many standard operators, eg '+'
3276 + */
3277 +
3278 +/*
3279 + * $Log: 10_all_gdb-6.6-duel.patch,v $
3280 + * Revision 1.1 2007/12/29 21:06:06 vapier
3281 + * add DUEL support #199987 by Sergei Golubchik
3282 + *
3283 + * Revision 1.14 93/03/19 15:40:17 mg
3284 + * fixed bug long symbolics handling
3285 + *
3286 + * Revision 1.13 93/03/12 05:50:01 mg
3287 + * uses tuint instead of uint, etc.
3288 + *
3289 + * Revision 1.12 93/02/26 05:00:13 mg
3290 + * fixed void pointers compare. ctype_voidptr is not unique!
3291 + *
3292 + * Revision 1.11 93/02/04 02:09:55 mg
3293 + * typo
3294 + *
3295 + * Revision 1.10 93/02/04 01:24:51 mg
3296 + * better error reports for "="
3297 + *
3298 + * Revision 1.9 93/02/03 21:47:43 mg
3299 + * support "signed char"
3300 + *
3301 + * Revision 1.8 93/01/12 21:51:29 mg
3302 + * cleanup and set for release
3303 + *
3304 + * Revision 1.7 93/01/07 00:10:51 mg
3305 + * auto convert func to &func
3306 + * find a frame for a func
3307 + *
3308 + *
3309 + * Revision 1.6 93/01/03 07:30:02 mg
3310 + * function calls, error reporting, printing.
3311 + *
3312 + * Revision 1.5 92/12/24 23:34:47 mg
3313 + * frames support
3314 + *
3315 + * Revision 1.4 92/10/19 15:07:46 mg
3316 + * fvalue added (not ready yet), svalues dropped
3317 + *
3318 + * Revision 1.3 92/10/14 02:05:10 mg
3319 + * add print/{x} support
3320 + *
3321 + * Revision 1.2 92/09/15 05:48:57 mg
3322 + * support '..' new formats
3323 + *
3324 + */
3325 +
3326 +#include "duel.h"
3327 +
3328 +/*
3329 + * This file is made up of three parts:
3330 + * (1) low-level functions that interact with the debugger/type system directly
3331 + * (2) mid-level functions that compute the result of simple operators like '+'
3332 + * (3) high-level functions that compute any binary/unary op.
3333 + * Only some of the functions in (1) are global, and all of the (3) are.
3334 + * this collection is in one file to allow a minimal of global symbols
3335 + * (for minimum collision with the debugger)
3336 + */
3337 +
3338 +
3339 +
3340 +/****************************************************************************
3341 + A low-level set of functions follows. They interact with the type system
3342 + and the debugger/target's space directly:
3343 + get_storage_type_kind - retrieve ctype_kind, with special conversion for enums
3344 + get_rvalue - retrieve the rvalue of a variable/lvalue.
3345 + set_symb_val - set the symbolic value of a tvalue.
3346 + upgrade_small_int_types - figure out the type to upgrade to from char etc.
3347 + find_numeric_result_type - figure type of x+y where + is generic C op
3348 + convert_scalar_type - convert one scalar type to another
3349 + get_numeric_val - retrieve rvalue, making sure it is numeric
3350 + get_scalar_val - retrieve rvalue, making sure it is numeric or pointer
3351 + get_integral_val- retrieve rvalue, making sure it is an integer
3352 + get_int_val - retrieve rvalue, make sure it's an integer, return int val
3353 + get_pointer_val - retrieve rvalue, make sure it's a pointer.
3354 + ****************************************************************************/
3355 +
3356 +/* give the storage-type kind of a given type.
3357 + * this is the same type-kind as the type itslef, except in the case of enums
3358 + * where the type-kind of the storage will be CTK_INT etc (integral type)
3359 + * the storage type kind is set when the enum is created.
3360 + */
3361 +
3362 +LFUNC tctype_kind get_storage_type_kind(tctype *t)
3363 +{
3364 + if(t->type_kind!=CTK_ENUM) return t->type_kind ;
3365 + return t->u.e.real_type_kind ;
3366 +}
3367 +
3368 +/* try_get_rvalue -- make an rvalue of v. if v is already an rvalue,
3369 + * nothing is done. Else v is an b/lvalue, so its rvalue is fetched.
3370 + * special care:
3371 + * (1) Enums are fetched as int of same size. type stay enum!
3372 + * (2) Arrays and functions are made into pointers
3373 + * (3) Bitfields are converted to ints (debugger dependent)
3374 + * there are no rvalues of 'bitfield' type!
3375 + * return succ/fail for bad mem ref. the "real" function everyone calls is
3376 + * get_rvalue (this function is used only by printing functions to avoid
3377 + * chicken&egg problem of error reporting.)
3378 + */
3379 +
3380 +FUNC duel_try_get_rvalue(tvalue *v,char *op)
3381 +{
3382 + void *p ;
3383 + int n ;
3384 + bool ok;
3385 + if(v->val_kind == VK_RVALUE) return TRUE;
3386 + if(v->val_kind == VK_FVALUE)
3387 + duel_op_error("illegal type 'frame' for operand x of '%s'",op,v,0);
3388 + switch(get_storage_type_kind(v->ctype)) {
3389 + case CTK_CHAR: p= &v->u.rval_char ; n=sizeof(char) ;break ;
3390 + case CTK_SCHAR: p= &v->u.rval_schar ; n=sizeof(tschar) ;break ;
3391 + case CTK_UCHAR: p= &v->u.rval_uchar ; n=sizeof(tuchar) ;break ;
3392 + case CTK_USHORT: p= &v->u.rval_ushort ; n=sizeof(tushort) ;break ;
3393 + case CTK_SHORT: p= &v->u.rval_short ; n=sizeof(short) ;break ;
3394 + case CTK_INT: p= &v->u.rval_int ; n=sizeof(int) ;break ;
3395 + case CTK_UINT: p= &v->u.rval_uint ; n=sizeof(tuint) ;break ;
3396 + case CTK_LONG: p= &v->u.rval_long ; n=sizeof(long) ;break ;
3397 + case CTK_ULONG: p= &v->u.rval_ulong ; n=sizeof(tulong) ;break ;
3398 + case CTK_LONGLONG:p= &v->u.rval_longlong ; n=sizeof(long long) ;break ;
3399 + case CTK_ULONGLONG:p= &v->u.rval_ulonglong;n=sizeof(tulonglong) ;break ;
3400 + case CTK_FLOAT: p= &v->u.rval_float ; n=sizeof(float) ;break ;
3401 + case CTK_DOUBLE: p= &v->u.rval_double ; n=sizeof(double) ;break ;
3402 + case CTK_PTR: p= &v->u.rval_ptr ; n=sizeof(ttarget_ptr) ;break ;
3403 + case CTK_ARRAY: /* the lvalue becomes an rvalue, a real pointer! */
3404 + duel_assert(v->val_kind==VK_LVALUE); /* duel exp rules */
3405 + v->val_kind=VK_RVALUE ;
3406 + v->ctype=duel_mkctype_ptr(v->ctype->u.kid) ;
3407 + v->u.rval_ptr=v->u.lvalue ;
3408 + return TRUE;
3409 + case CTK_FUNC: /* makes it a pointer to a func*/
3410 + duel_assert(v->val_kind==VK_LVALUE); /* duel exp rules */
3411 + v->val_kind=VK_RVALUE ;
3412 + v->ctype=duel_mkctype_ptr(v->ctype) ;
3413 + v->u.rval_ptr=v->u.lvalue ;
3414 + return TRUE;
3415 +
3416 + case CTK_STRUCT: /* can't have an rval from struct? */
3417 + case CTK_UNION:
3418 + /* enums were eliminated above */
3419 + default: duel_assert(0);
3420 + }
3421 + if(v->val_kind == VK_BVALUE) { /* bitfield: lvalue+bitpos/len */
3422 + tbvalue_info bv;
3423 + bv=v->u.bvalue ;
3424 + ok=duel_get_target_bitfield(bv.lvalue, bv.bitpos, bv.bitlen, p,
3425 + v->ctype->type_kind);
3426 + if(!ok) { v->u.bvalue=bv ; return FALSE ; }
3427 + }
3428 + else {
3429 + ttarget_ptr lv=v->u.lvalue ;
3430 + ok=duel_get_target_bytes(lv,p,n); /*fetch n debuggee bytes*/
3431 + if(!ok) { v->u.lvalue=lv ; return FALSE ; }
3432 + }
3433 +
3434 + v->val_kind=VK_RVALUE ;
3435 + /* in remote debugging, one might need to swap byte order at this
3436 + * point. [remote debugging is not supported by duel v1.0]
3437 + */
3438 + return TRUE ;
3439 +}
3440 +
3441 +
3442 +/*
3443 + * safe get_rvalue - produce error messages on memory access failer.
3444 + */
3445 +
3446 +LPROC get_rvalue(tvalue *v,char *op)
3447 +{
3448 + bool ok=duel_try_get_rvalue(v,op);
3449 + if(!ok) duel_op_error("illegal address for operand x of '%s'",op,v,0);
3450 +}
3451 +
3452 +/* put_rvalue: put the rvalue of v2 into the location in v1.
3453 + * types are assumed to be the same.
3454 + */
3455 +
3456 +LPROC put_rvalue(tvalue *v1,tvalue *v2,char *op)
3457 +{
3458 + void *p ;
3459 + int n ;
3460 + duel_assert(v1->val_kind!=VK_RVALUE);
3461 + duel_assert(v1->val_kind!=VK_FVALUE);
3462 + duel_assert(v2->val_kind==VK_RVALUE);
3463 + duel_assert(v1->ctype->size == v2->ctype->size);
3464 + switch(get_storage_type_kind(v2->ctype)) {
3465 + case CTK_CHAR: p= &v2->u.rval_char ; n=sizeof(char) ;break ;
3466 + case CTK_SCHAR: p= &v2->u.rval_schar ; n=sizeof(tschar) ;break ;
3467 + case CTK_UCHAR: p= &v2->u.rval_uchar ; n=sizeof(tuchar) ;break ;
3468 + case CTK_USHORT: p= &v2->u.rval_ushort ; n=sizeof(tushort) ;break ;
3469 + case CTK_SHORT: p= &v2->u.rval_short ; n=sizeof(short) ;break ;
3470 + case CTK_INT: p= &v2->u.rval_int ; n=sizeof(int) ;break ;
3471 + case CTK_UINT: p= &v2->u.rval_uint ; n=sizeof(tuint) ;break ;
3472 + case CTK_LONG: p= &v2->u.rval_long ; n=sizeof(long) ;break ;
3473 + case CTK_ULONG: p= &v2->u.rval_ulong ; n=sizeof(tulong) ;break ;
3474 + case CTK_LONGLONG: p= &v2->u.rval_longlong ; n=sizeof(long long);break ;
3475 + case CTK_ULONGLONG: p= &v2->u.rval_ulonglong ; n=sizeof(tulonglong);break ;
3476 + case CTK_FLOAT: p= &v2->u.rval_float ; n=sizeof(float) ;break ;
3477 + case CTK_DOUBLE: p= &v2->u.rval_double ; n=sizeof(double) ;break ;
3478 + case CTK_PTR: p= &v2->u.rval_ptr ; n=sizeof(ttarget_ptr) ;break ;
3479 + default: duel_assert(0); /* other types not supported as rvalues */
3480 + }
3481 + if(v1->val_kind == VK_BVALUE)
3482 + duel_gen_error("assignment to bitfields is not yet supported",0);
3483 + else
3484 + if(!duel_put_target_bytes(v1->u.lvalue,p,n)) /*store n debuggee bytes*/
3485 + duel_op_error("cant write memory for operand x of '%s'",op,v1,0);
3486 +}
3487 +
3488 +/* set the symbolic val for tvalue. input format is a sprintf,
3489 + * with v1,v2 being other values that show as '%s' in the format.
3490 + * v1,v2 can be zero if they are unused by the format.
3491 + */
3492 +PROC duel_set_symb_val(tvalue *r,char *format,tvalue *v1,tvalue *v2)
3493 +{
3494 + char s[3*VALUE_MAX_SYMBOLIC_SIZE];
3495 + sprintf(s,format,v1->symb_val,v2->symb_val);
3496 + s[VALUE_MAX_SYMBOLIC_SIZE-1]=0 ; /* chop as needed */
3497 + strcpy(r->symb_val,s);
3498 +}
3499 +
3500 +/* given a small int type (short,char,enum) return the upgraded (int or
3501 + * uint) type. Else return the original type
3502 + */
3503 +LFUNC tctype* upgrade_small_int_types(tctype *t)
3504 +{
3505 + switch(t->type_kind) {
3506 + case CTK_ENUM:
3507 + case CTK_CHAR:
3508 + case CTK_SCHAR:
3509 + case CTK_UCHAR:
3510 + case CTK_SHORT:
3511 + return ctype_int ;
3512 + case CTK_USHORT:
3513 + if(sizeof(tushort)==sizeof(int)) return ctype_uint ;
3514 + else return ctype_int ;
3515 + default:
3516 + return t ;
3517 + }
3518 +}
3519 +
3520 +/* find the type of the result of a generic numeric operation on
3521 + * v1,v2. This applies the standard C type upgrade rules.
3522 + * The type of the result is returned.
3523 + * r is setup so it can receive the result: an RVALUE of the specified
3524 + * type. Its symbolic value is also setup based on the symbolic value
3525 + * of v1 v2 and the operation op.
3526 + * Note: op is not used to figure out the numeric result, only
3527 + * the types of v1 and v2. As a side effect, the answer for x|y where
3528 + * y is a double will be given as double. it is up to the caller to
3529 + * verify that v1,v2 have meaningful types of this operation
3530 + *
3531 + */
3532 +
3533 +LFUNC tctype* find_numeric_result_type(tvalue *v1,tvalue *v2,
3534 + tvalue *r,char *op)
3535 +{
3536 + tctype *t1=upgrade_small_int_types(v1->ctype); /* upgrade to int etc */
3537 + tctype *t2=upgrade_small_int_types(v2->ctype);
3538 + char s[80] ;
3539 + r->val_kind=VK_RVALUE ;
3540 + sprintf(s,"%%s%s%%s",op) ; /* eg, if op=">>" then s becomes "%s>>%s" */
3541 + duel_set_symb_val(r,s,v1,v2);
3542 +
3543 + if(t1==ctype_double || t2==ctype_double) return r->ctype=ctype_double ;
3544 + if(t1==ctype_float || t2==ctype_float) return r->ctype=ctype_float ;
3545 + if(t1==ctype_ulonglong || t2==ctype_ulonglong) return r->ctype=ctype_ulonglong ;
3546 + if(t1==ctype_longlong || t2==ctype_longlong) return r->ctype=ctype_longlong ;
3547 + if(t1==ctype_ulong || t2==ctype_ulong) return r->ctype=ctype_ulong ;
3548 + if(sizeof(unsigned)==sizeof(long) &&
3549 + (t1==ctype_long && t2==ctype_uint ||
3550 + t1==ctype_uint && t2==ctype_long)) return r->ctype=ctype_ulong ;
3551 + if(t1==ctype_long || t2==ctype_long) return r->ctype=ctype_long ;
3552 + if(t1==ctype_uint || t2==ctype_uint) return r->ctype=ctype_uint ;
3553 + return r->ctype=ctype_int ;
3554 +}
3555 +
3556 +/* convert_to_fix assisting-macro: takes the val stored in v and put it
3557 + * into w. w is an lvalue with a 'fixed' type (t).
3558 + */
3559 +
3560 +#define convert_to_fix(v,w) \
3561 + switch(get_storage_type_kind(v->ctype)) { \
3562 + case CTK_CHAR: w (v->u.rval_char) ; break ; \
3563 + case CTK_SCHAR: w (v->u.rval_schar) ; break ; \
3564 + case CTK_UCHAR: w (v->u.rval_uchar) ; break ; \
3565 + case CTK_USHORT: w (v->u.rval_ushort) ; break ; \
3566 + case CTK_SHORT: w (v->u.rval_short) ; break ; \
3567 + case CTK_INT: w (v->u.rval_int) ; break ; \
3568 + case CTK_UINT: w (v->u.rval_uint) ; break ; \
3569 + case CTK_LONG: w (v->u.rval_long) ; break ; \
3570 + case CTK_ULONG: w (v->u.rval_ulong) ; break ; \
3571 + case CTK_LONGLONG: w (v->u.rval_longlong) ; break ; \
3572 + case CTK_ULONGLONG: w (v->u.rval_ulonglong) ; break ; \
3573 + case CTK_FLOAT: w (v->u.rval_float) ; break ; \
3574 + case CTK_DOUBLE: w (v->u.rval_double) ; break ; \
3575 + case CTK_PTR: w (tptrsize_int) (v->u.rval_ptr) ; break ; \
3576 + default: duel_assert(0); \
3577 + }
3578 +
3579 +
3580 +/* convert_scalar_type -- convert rvalue v to type t.
3581 + * uses convert_to_fix macro. In effect, this is a huge switch for
3582 + * all possible combinations of basic C types.
3583 + */
3584 +
3585 +LPROC convert_scalar_type(tvalue *v,tctype *t,char *op)
3586 +{
3587 + get_rvalue(v,op);
3588 + switch(get_storage_type_kind(t)) {
3589 + case CTK_CHAR: convert_to_fix(v,v->u.rval_char=(char)) ; break ;
3590 + case CTK_SCHAR: convert_to_fix(v,v->u.rval_schar=(tschar)) ; break ;
3591 + case CTK_UCHAR: convert_to_fix(v,v->u.rval_uchar=(tuchar)) ; break ;
3592 + case CTK_SHORT: convert_to_fix(v,v->u.rval_short=(short)) ; break ;
3593 + case CTK_USHORT: convert_to_fix(v,v->u.rval_ushort=(tushort)) ; break ;
3594 + case CTK_INT: convert_to_fix(v,v->u.rval_int=(int)) ; break ;
3595 + case CTK_UINT: convert_to_fix(v,v->u.rval_uint=(tuint)) ; break ;
3596 + case CTK_LONG: convert_to_fix(v,v->u.rval_long=(long)) ; break ;
3597 + case CTK_ULONG: convert_to_fix(v,v->u.rval_ulong=(tulong)) ; break ;
3598 + case CTK_LONGLONG: convert_to_fix(v,v->u.rval_longlong=(long long)) ; break ;
3599 + case CTK_ULONGLONG: convert_to_fix(v,v->u.rval_ulonglong=(tulonglong)) ; break ;
3600 + case CTK_FLOAT: convert_to_fix(v,v->u.rval_float=(float)) ; break ;
3601 + case CTK_DOUBLE: convert_to_fix(v,v->u.rval_double=(double)) ; break ;
3602 + case CTK_PTR: convert_to_fix(v,
3603 + v->u.rval_ptr=(ttarget_ptr)(tptrsize_int)) ; break ;
3604 + default: duel_assert(0);
3605 + }
3606 + v->ctype=t ;
3607 +}
3608 +
3609 +
3610 +/* verify v is numeric, get its rvalue converted to type tout or at least int*/
3611 +LPROC get_numeric_val(tvalue *v,char *op,tctype *tout)
3612 +{
3613 + if(!ctype_kind_numeric(v->ctype))
3614 + duel_op_error("operand x of '%s' is not numeric",op,v,0);
3615 + if(!tout) tout=upgrade_small_int_types(v->ctype); /* upgrade to int etc */
3616 + convert_scalar_type(v,tout,op);
3617 +}
3618 +
3619 +/*verify v is integral, get its rvalue converted to type tout or at least int*/
3620 +LPROC get_integral_val(tvalue *v,char *op,tctype *tout)
3621 +{
3622 + if(!ctype_kind_integral(v->ctype))
3623 + duel_op_error("operand x of '%s' is not integral",op,v,0);
3624 + if(!tout) tout=upgrade_small_int_types(v->ctype); /* upgrade to int etc */
3625 + convert_scalar_type(v,tout,op);
3626 +}
3627 +
3628 +/* verify v is integral, return its actual value as 'int' */
3629 +FUNC int duel_get_int_val(tvalue *v,char *op)
3630 +{
3631 + get_integral_val(v,op,ctype_int);
3632 + return v->u.rval_int ;
3633 +}
3634 +
3635 +/* verify v is numeric or pointer/array, upgrade type to at least int or ptr
3636 + and get the rvalue */
3637 +LPROC get_scalar_val(tvalue *v,char *op)
3638 +{
3639 + if(ctype_kind_ptr_like(v->ctype)) get_rvalue(v,op);
3640 + else {
3641 + tctype *t=upgrade_small_int_types(v->ctype); /* upgrade to int */
3642 + if(!ctype_kind_numeric(v->ctype))
3643 + duel_op_error("operand x of '%s' is not a scalar",op,v,0);
3644 + convert_scalar_type(v,t,op);
3645 + }
3646 +}
3647 +
3648 +LPROC get_pointer_val(tvalue *v,char *op,bool zero_ok)
3649 +{
3650 + if(ctype_kind_ptr_like(v->ctype)) get_rvalue(v,op);
3651 + else
3652 + if(zero_ok && v->ctype->type_kind==CTK_INT &&
3653 + v->val_kind==VK_RVALUE && v->u.rval_int==0) {
3654 + v->ctype=ctype_voidptr ;
3655 + v->u.rval_ptr=0 ;
3656 + }
3657 + else duel_op_error("operand x of '%s' is not a pointer",op,v,0);
3658 +}
3659 +
3660 +/* copy one lvalue over the other. This copy is used for assignment,
3661 + * including the assignment of structures and unions.
3662 + * supports unlimited size and error reports when memory access fails.
3663 + */
3664 +
3665 +LPROC copy_lvalues(tvalue *v1,tvalue *v2,char *op)
3666 +{
3667 + size_t size ;
3668 + ttarget_ptr to=v1->u.lvalue,from=v2->u.lvalue ;
3669 + char buf[BUFSIZ] ;
3670 + duel_assert(v1->val_kind==VK_LVALUE && v2->val_kind==VK_LVALUE);
3671 + size=v1->ctype->size ;
3672 + duel_assert(v2->ctype->size==size);
3673 + while(size!=0) {
3674 + size_t chunk_size=((size>BUFSIZ)? BUFSIZ:size) ;
3675 + if(!duel_get_target_bytes(from,buf,chunk_size))
3676 + duel_op_error("error reading memory (copy) in '%s'",op,v1,v2);
3677 + if(!duel_put_target_bytes(to,buf,chunk_size))
3678 + duel_op_error("error writing memory (copy) in '%s'",op,v1,v2);
3679 + size-=chunk_size ;
3680 + to+=chunk_size ;
3681 + from+=chunk_size ;
3682 + }
3683 +}
3684 +
3685 +/*
3686 + * check that two values have "compatible" types.
3687 + * since structs compiled in different modules are each unique,
3688 + * we settle for comparing the number of references (array/ptr)
3689 + * and then make sure the same type-kind is used, with the same
3690 + * physical size.
3691 + * this allows, e.g. struct {short x,y } and struct {int x}
3692 + * to be considered equal. Possibly one could compare struct/union
3693 + * for member sizes (but not names?!). this however requires to keep
3694 + * track of self references and is not implemented here.
3695 + */
3696 +
3697 +LPROC duel_check_type_eq(tvalue *v1,tvalue *v2,char *op)
3698 +{
3699 + tctype *t1=v1->ctype, *t2=v2->ctype ;
3700 + if(ctype_kind_ptr_like(t1) && ctype_kind_ptr_like(t2) && /*(void*) match*/
3701 + (t1->u.kid==ctype_void || t2->u.kid==ctype_void)) return;
3702 +
3703 + while(ctype_kind_ptr_like(t1) && ctype_kind_ptr_like(t2))
3704 + t1=t1->u.kid, t2=t2->u.kid ;
3705 + if(t1==t2) return ; /* exact same type */
3706 + if(t1->type_kind != t2->type_kind || t1->size != t2->size)
3707 + duel_op_error("incompatible types for op %s",op,v1,v2);
3708 +}
3709 +
3710 +
3711 +/**************************************************************************
3712 + a set of mid-level functions follow. These actually apply duel/C
3713 + operators to values
3714 + **************************************************************************/
3715 +
3716 +/* these do pointer+int addition/subtraction of v1,v2 and store result in r.
3717 + * NOTE: r's symbolic value is not set.
3718 + */
3719 +
3720 +LPROC add_offset_to_ptr(tvalue *v1,tvalue *v2,tvalue *r)
3721 +{
3722 + size_t len ;
3723 + get_pointer_val(v1,"x+y (ptr add)",FALSE);
3724 + get_integral_val(v2,"y+x (ptr add)",NULL);
3725 + r->val_kind=VK_RVALUE ;
3726 + r->ctype=v1->ctype ;
3727 + len=v1->ctype->u.kid->size ;
3728 + if(len==0) duel_op_error("unknown pointer object size for '+' op",0,v1,0);
3729 + switch(v2->ctype->type_kind) {
3730 + case CTK_INT: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_int ;break ;
3731 + case CTK_UINT: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_uint ;break ;
3732 + case CTK_LONG: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_long ;break ;
3733 + case CTK_ULONG: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_ulong;break ;
3734 + case CTK_LONGLONG: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_longlong ;break ;
3735 + case CTK_ULONGLONG: r->u.rval_ptr =v1->u.rval_ptr +len*v2->u.rval_ulonglong;break ;
3736 + default: duel_assert(0);
3737 + }
3738 +}
3739 +
3740 +LPROC sub_offset_from_ptr(tvalue *v1,tvalue *v2,tvalue *r)
3741 +{
3742 + size_t len ;
3743 + get_pointer_val(v1,"x-y (ptr sub)",FALSE);
3744 + get_integral_val(v2,"y-x (ptr sub)",NULL);
3745 + r->val_kind=VK_RVALUE ;
3746 + r->ctype=v1->ctype ;
3747 + len=v1->ctype->u.kid->size ;
3748 + if(len==0) duel_op_error("unknown pointer object size for '-' op",0,v1,0);
3749 + switch(v2->ctype->type_kind) {
3750 + case CTK_INT: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_int ;break ;
3751 + case CTK_UINT: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_uint ;break ;
3752 + case CTK_LONG: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_long ;break ;
3753 + case CTK_ULONG: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_ulong;break ;
3754 + case CTK_LONGLONG: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_longlong ;break ;
3755 + case CTK_ULONGLONG: r->u.rval_ptr =v1->u.rval_ptr -len*v2->u.rval_ulonglong;break ;
3756 + default: duel_assert(0);
3757 + }
3758 +}
3759 +
3760 +
3761 +/* do addition of v1,v2 and store result in r.
3762 + * NOTE: v1, v2 are destroyed!
3763 + */
3764 +LPROC do_op_add(tvalue *v1,tvalue *v2,tvalue *r)
3765 +{
3766 + tctype *t=find_numeric_result_type(v1,v2,r,"+");
3767 + if(ctype_kind_ptr_like(v1->ctype)) {
3768 + get_integral_val(v2,"pointer+x",NULL);
3769 + add_offset_to_ptr(v1,v2,r);
3770 + return ;
3771 + }
3772 + if(ctype_kind_ptr_like(v2->ctype)) {
3773 + get_integral_val(v1,"x+pointer",NULL);
3774 + add_offset_to_ptr(v2,v1,r);
3775 + return ;
3776 + }
3777 + get_numeric_val(v1,"x+y",t);
3778 + get_numeric_val(v2,"y+x",t);
3779 + r->val_kind=VK_RVALUE ;
3780 + r->ctype=t ;
3781 + duel_set_symb_val(r,"%s+%s",v1,v2);
3782 + switch(t->type_kind) {
3783 + case CTK_INT: r->u.rval_int =v1->u.rval_int +v2->u.rval_int ;break ;
3784 + case CTK_UINT: r->u.rval_uint =v1->u.rval_uint +v2->u.rval_uint ;break ;
3785 + case CTK_LONG: r->u.rval_long =v1->u.rval_long +v2->u.rval_long ;break ;
3786 + case CTK_ULONG: r->u.rval_ulong=v1->u.rval_ulong +v2->u.rval_ulong ;break ;
3787 + case CTK_LONGLONG: r->u.rval_longlong =v1->u.rval_longlong +v2->u.rval_longlong ;break ;
3788 + case CTK_ULONGLONG: r->u.rval_ulonglong=v1->u.rval_ulonglong +v2->u.rval_ulonglong ;break ;
3789 + case CTK_FLOAT: r->u.rval_float=v1->u.rval_float +v2->u.rval_float ;break ;
3790 + case CTK_DOUBLE:r->u.rval_double=v1->u.rval_double+v2->u.rval_double;break;
3791 + default: duel_assert(0);
3792 + }
3793 +}
3794 +
3795 +/* do arithmeric subtraction of v1,v2 and store result in r.
3796 + * v1 and v2 should be of numeric type to begin with.
3797 + * NOTE: v1, v2 are destroyed!
3798 + */
3799 +LPROC do_op_subtract(tvalue *v1,tvalue *v2,tvalue *r)
3800 +{
3801 + tctype *t=find_numeric_result_type(v1,v2,r,"-");
3802 + if(ctype_kind_ptr_like(v1->ctype)) {
3803 + if(ctype_kind_ptr_like(v2->ctype)) {
3804 + long len ; /* length must be signed to allow signed p-q result*/
3805 + get_pointer_val(v1,"x-y",FALSE);
3806 + get_pointer_val(v2,"x-y",FALSE);
3807 + duel_check_type_eq(v1,v2,"- (ptr)");
3808 + /* should compare pointer types */
3809 + len=v1->ctype->u.kid->size ;
3810 + if(len<=0)
3811 + duel_op_error("illegal object size for op %s","- (ptr)",v1,v2);
3812 + r->ctype=ctype_ptrdiff_t ;
3813 + r->u.rval_ptrdiff_t= (v1->u.rval_ptr - v2->u.rval_ptr)/len ;
3814 + return ;
3815 + }
3816 + get_integral_val(v2,"pointer-x",NULL);
3817 + sub_offset_from_ptr(v1,v2,r);
3818 + return ;
3819 + }
3820 + get_numeric_val(v1,"x-y",t);
3821 + get_numeric_val(v2,"y-x",t);
3822 + switch(t->type_kind) {
3823 + case CTK_INT: r->u.rval_int =v1->u.rval_int - v2->u.rval_int ;break;
3824 + case CTK_UINT: r->u.rval_uint =v1->u.rval_uint - v2->u.rval_uint ;break;
3825 + case CTK_LONG: r->u.rval_long =v1->u.rval_long - v2->u.rval_long ;break;
3826 + case CTK_ULONG: r->u.rval_ulong=v1->u.rval_ulong - v2->u.rval_ulong ;break;
3827 + case CTK_LONGLONG: r->u.rval_longlong =v1->u.rval_longlong - v2->u.rval_longlong ;break;
3828 + case CTK_ULONGLONG: r->u.rval_ulonglong=v1->u.rval_ulonglong - v2->u.rval_ulonglong ;break;
3829 + case CTK_FLOAT: r->u.rval_float=v1->u.rval_float - v2->u.rval_float ;break;
3830 + case CTK_DOUBLE:r->u.rval_double=v1->u.rval_double-v2->u.rval_double;break;
3831 + default: duel_assert(0);
3832 + }
3833 +}
3834 +
3835 +/* compare values of v1 and v2, knowing that at least one is a frame-value
3836 + * type. Allows two fvals to be compared, or an fval to be compared
3837 + * to a func (this compares the func at the frame to the given func)
3838 + */
3839 +
3840 +LFUNC bool comp_bin_op_eq_fvals(tvalue *v1,tvalue *v2)
3841 +{
3842 + bool v1f=v1->val_kind == VK_FVALUE ;
3843 + bool v2f=v2->val_kind == VK_FVALUE ;
3844 + int frame_no ;
3845 + ttarget_ptr frame_func,p ;
3846 + if(v1f && v2f) return v1->u.fvalue == v2->u.fvalue ; /*cmp frames */
3847 + if(v1f) {
3848 + frame_no = v1->u.fvalue ;
3849 + get_pointer_val(v2,"frame==x",FALSE) ;
3850 + if(v2->ctype->u.kid->type_kind!=CTK_FUNC)
3851 + duel_op_error("operand x of 'frame=x' not a func pointer",0,v2,0);
3852 + p=v2->u.rval_ptr ;
3853 + }
3854 + else {
3855 + frame_no = v2->u.fvalue ;
3856 + get_pointer_val(v1,"x==frame",FALSE) ;
3857 + if(v1->ctype->u.kid->type_kind!=CTK_FUNC)
3858 + duel_op_error("operand x of 'x==frame' not a func pointer",0,v1,0);
3859 + p=v1->u.rval_ptr ;
3860 + }
3861 + frame_func = duel_get_function_for_frame(frame_no);
3862 + return frame_func == p ;
3863 +}
3864 +
3865 +
3866 +/* compares of v1,v2 and store result in r.
3867 + * v1 and v2 should be of numeric/pointer type to begin with.
3868 + * NOTE: v1, v2 are destroyed!
3869 + */
3870 +
3871 +LPROC do_op_eq(tvalue *v1,tvalue *v2,tvalue *r)
3872 +{
3873 + tctype *t=find_numeric_result_type(v1,v2,r,"==");
3874 + r->ctype=ctype_int ;
3875 + if(v1->val_kind==VK_FVALUE || v2->val_kind==VK_FVALUE) {
3876 + r->u.rval_int = comp_bin_op_eq_fvals(v1,v2);
3877 + return ;
3878 + }
3879 + if(ctype_kind_ptr_like(v1->ctype) || ctype_kind_ptr_like(v2->ctype)) {
3880 + get_pointer_val(v1,"x==y",TRUE);
3881 + get_pointer_val(v2,"y==x",TRUE);
3882 + duel_check_type_eq(v1,v2,"==");
3883 + r->u.rval_int = v1->u.rval_ptr == v2->u.rval_ptr ;
3884 + return ;
3885 + }
3886 + get_numeric_val(v1,"x==y",t);
3887 + get_numeric_val(v2,"y==x",t);
3888 + switch(t->type_kind) {
3889 + case CTK_INT: r->u.rval_int=v1->u.rval_int == v2->u.rval_int ;break;
3890 + case CTK_UINT: r->u.rval_int=v1->u.rval_uint == v2->u.rval_uint ;break;
3891 + case CTK_LONG: r->u.rval_int=v1->u.rval_long == v2->u.rval_long ;break;
3892 + case CTK_ULONG: r->u.rval_int=v1->u.rval_ulong == v2->u.rval_ulong ;break;
3893 + case CTK_LONGLONG: r->u.rval_int=v1->u.rval_longlong == v2->u.rval_longlong ;break;
3894 + case CTK_ULONGLONG: r->u.rval_int=v1->u.rval_ulonglong == v2->u.rval_ulonglong ;break;
3895 + case CTK_FLOAT: r->u.rval_int=v1->u.rval_float == v2->u.rval_float ;break;
3896 + case CTK_DOUBLE:r->u.rval_int=v1->u.rval_double == v2->u.rval_double;break;
3897 + default: duel_assert(0);
3898 + }
3899 +}
3900 +
3901 +
3902 +/* compares of v1,v2 and store result in r.
3903 + * v1 and v2 should be of numeric/pointer type to begin with.
3904 + * NOTE: v1, v2 are destroyed!
3905 + */
3906 +#define mk_func_compare(func,op,sop,xysop,yxsop,nullok) \
3907 +LPROC func(tvalue *v1,tvalue *v2,tvalue *r) \
3908 +{ \
3909 + tctype *t=find_numeric_result_type(v1,v2,r,sop); \
3910 + r->ctype=ctype_int ; \
3911 + \
3912 + if(ctype_kind_ptr_like(v1->ctype) || ctype_kind_ptr_like(v2->ctype)) { \
3913 + get_pointer_val(v1,xysop,nullok); \
3914 + get_pointer_val(v2,yxsop,nullok); \
3915 + duel_check_type_eq(v1,v2,sop); \
3916 + r->u.rval_int = v1->u.rval_ptr op v2->u.rval_ptr ; \
3917 + return ; \
3918 + } \
3919 + get_numeric_val(v1,xysop,t); \
3920 + get_numeric_val(v2,yxsop,t); \
3921 + switch(t->type_kind) { \
3922 + case CTK_INT: r->u.rval_int=v1->u.rval_int op v2->u.rval_int ;break;\
3923 + case CTK_UINT: r->u.rval_int=v1->u.rval_uint op v2->u.rval_uint ;break;\
3924 + case CTK_LONG: r->u.rval_int=v1->u.rval_long op v2->u.rval_long ;break;\
3925 + case CTK_ULONG: r->u.rval_int=v1->u.rval_ulong op v2->u.rval_ulong ;break;\
3926 + case CTK_LONGLONG: r->u.rval_int=v1->u.rval_longlong op v2->u.rval_longlong ;break;\
3927 + case CTK_ULONGLONG: r->u.rval_int=v1->u.rval_ulonglong op v2->u.rval_ulonglong ;break;\
3928 + case CTK_FLOAT: r->u.rval_int=v1->u.rval_float op v2->u.rval_float ;break;\
3929 + case CTK_DOUBLE:r->u.rval_int=v1->u.rval_double op v2->u.rval_double;break;\
3930 + default: duel_assert(0); \
3931 + } \
3932 +}
3933 +
3934 +mk_func_compare(do_op_ne,!=,"!=","x!=y","y!=x",TRUE)
3935 +mk_func_compare(do_op_ge,>=,">=","x>=y","y>=x",FALSE)
3936 +mk_func_compare(do_op_le,<=,"<=","x<=y","y<=x",FALSE)
3937 +mk_func_compare(do_op_ls,<, "<", "x<y", "y<x",FALSE)
3938 +mk_func_compare(do_op_gt,>, ">", "x>y", "y>x",FALSE)
3939 +#undef mk_func_compare
3940 +
3941 +
3942 +/* do_compare_questionmark -- handle the <? >? etc ops */
3943 +
3944 +LFUNC bool do_compare_questionmark(topcode op,tvalue *v1,tvalue *v2,tvalue *r)
3945 +{
3946 + tvalue tmp ;
3947 + tmp= *v1 ;
3948 + switch(op) {
3949 + case OP_EQQ: do_op_eq(v1,v2,r); break ;
3950 + case OP_NEQ: do_op_ne(v1,v2,r); break ;
3951 + case OP_GEQ: do_op_ge(v1,v2,r); break ;
3952 + case OP_LEQ: do_op_le(v1,v2,r); break ;
3953 + case OP_LSQ: do_op_ls(v1,v2,r); break ;
3954 + case OP_GTQ: do_op_gt(v1,v2,r); break ;
3955 + }
3956 + if(r->u.rval_int==0) return FALSE ;
3957 + *r=tmp ;
3958 + return TRUE ;
3959 +}
3960 +
3961 +
3962 +
3963 +/* apply indirection of a pointer.
3964 + * this is easy, you just force the value to be an rvalue pointer, then
3965 + * make it into an lvalue with the pointed-to type.
3966 + * useful for (*x x[y] x->y etc)
3967 + * does not setup a symbolic value!
3968 + */
3969 +
3970 +
3971 +LPROC follow_pointer(tvalue *v,char *op,bool nonull)
3972 +{
3973 + get_pointer_val(v,op,FALSE);
3974 + if(nonull && v->u.rval_ptr == NULL)
3975 + duel_op_error("dereference NULL pointer x in '%s'",op,v,0);
3976 + v->val_kind=VK_LVALUE ;
3977 + v->u.lvalue=v->u.rval_ptr ;
3978 + v->ctype=v->ctype->u.kid ;
3979 +}
3980 +
3981 +PROC duel_get_struct_val(tvalue *v,char *op)
3982 +{
3983 + if(!ctype_kind_struct_like(v->ctype))
3984 + duel_op_error("operand x of '%s' not a sturct/union",op,v,0);
3985 + duel_assert(v->val_kind==VK_LVALUE);
3986 +}
3987 +
3988 +PROC duel_get_struct_ptr_val(tvalue *v,char *op)
3989 +{
3990 + follow_pointer(v,op,FALSE);
3991 + if(!ctype_kind_struct_like(v->ctype))
3992 + duel_op_error("operand x of '%s' not a pointer to sturct/union",op,v,0);
3993 +}
3994 +
3995 +FUNC int duel_get_posint_val(tvalue *v,char *op)
3996 +{
3997 + int x ;
3998 + x=duel_get_int_val(v,op);
3999 + if(x<0) duel_op_error("operand x of '%s' can not be negative",op,v,0);
4000 + return x ;
4001 +}
4002 +
4003 +/* indirection operator (*x) */
4004 +
4005 +LPROC do_op_indirection(tvalue *v)
4006 +{
4007 + follow_pointer(v,"*x",TRUE);
4008 + duel_set_symb_val(v,"*%s",v,0);
4009 +}
4010 +
4011 +/* address operator (&x)
4012 + * x must be an lvalue. it is converted into a pointer to the given type,
4013 + * an rvalue.
4014 + */
4015 +
4016 +LPROC do_op_address(tvalue *v)
4017 +{
4018 + if(v->val_kind != VK_LVALUE)
4019 + duel_op_error("operand x of '&x' is not a lvalue",0,v,0);
4020 + v->val_kind=VK_RVALUE ;
4021 + v->u.rval_ptr=v->u.lvalue ;
4022 + v->ctype=duel_mkctype_ptr(v->ctype);
4023 + duel_set_symb_val(v,"&%s",v,0);
4024 +}
4025 +
4026 +LPROC do_op_index(tvalue *v1,tvalue *v2,tvalue *r)
4027 +{
4028 + get_pointer_val(v1,"x[y]",FALSE);
4029 + get_integral_val(v2,"y[x]",NULL);
4030 + add_offset_to_ptr(v1,v2,r);
4031 + follow_pointer(r,"[]",TRUE);
4032 + duel_set_symb_val(r,"%s[%s]",v1,v2);
4033 +}
4034 +
4035 +
4036 +/* do arithmeric multiply of v1,v2 and store result in r.
4037 + * NOTE: v1, v2 are destroyed!
4038 + */
4039 +LPROC do_op_multiply(tvalue *v1,tvalue *v2,tvalue *r)
4040 +{
4041 + tctype *t=find_numeric_result_type(v1,v2,r,"*");
4042 + get_numeric_val(v1,"x*y",t);
4043 + get_numeric_val(v2,"y*x",t);
4044 + r->val_kind=VK_RVALUE ;
4045 + r->ctype=t ;
4046 + duel_set_symb_val(r,"%s*%s",v1,v2);
4047 + switch(t->type_kind) {
4048 + case CTK_INT: r->u.rval_int =v1->u.rval_int * v2->u.rval_int ;break;
4049 + case CTK_UINT: r->u.rval_uint =v1->u.rval_uint * v2->u.rval_uint ;break;
4050 + case CTK_LONG: r->u.rval_long =v1->u.rval_long * v2->u.rval_long ;break;
4051 + case CTK_ULONG: r->u.rval_ulong =v1->u.rval_ulong * v2->u.rval_ulong;break;
4052 + case CTK_LONGLONG: r->u.rval_longlong =v1->u.rval_longlong * v2->u.rval_longlong ;break;
4053 + case CTK_ULONGLONG: r->u.rval_ulonglong =v1->u.rval_ulonglong * v2->u.rval_ulonglong;break;
4054 + case CTK_FLOAT: r->u.rval_float =v1->u.rval_float * v2->u.rval_float;break;
4055 + case CTK_DOUBLE:r->u.rval_double=v1->u.rval_double*v2->u.rval_double;break;
4056 + default: duel_assert(0);
4057 + }
4058 +}
4059 +
4060 +/* do numeric divide of v1,v2 and store result in r.
4061 + * v1 and v2 should be of numeric type to begin with.
4062 + * NOTE: v1, v2 are destroyed!
4063 + */
4064 +LPROC do_op_divide(tvalue *v1,tvalue *v2,tvalue *r)
4065 +{
4066 + tctype *t=find_numeric_result_type(v1,v2,r,"/");
4067 + get_numeric_val(v1,"x/y",t);
4068 + get_numeric_val(v2,"y/x",t);
4069 + switch(t->type_kind) {
4070 + case CTK_INT: if(v2->u.rval_int==0) goto div_err;
4071 + r->u.rval_int =v1->u.rval_int / v2->u.rval_int ;break;
4072 + case CTK_UINT: if(v2->u.rval_uint==0) goto div_err;
4073 + r->u.rval_uint =v1->u.rval_uint / v2->u.rval_uint ;break;
4074 + case CTK_LONG: if(v2->u.rval_long==0) goto div_err;
4075 + r->u.rval_long =v1->u.rval_long / v2->u.rval_long ;break;
4076 + case CTK_ULONG: if(v2->u.rval_ulong==0) goto div_err;
4077 + r->u.rval_ulong =v1->u.rval_ulong/ v2->u.rval_ulong ;break;
4078 + case CTK_LONGLONG: if(v2->u.rval_longlong==0) goto div_err;
4079 + r->u.rval_longlong =v1->u.rval_longlong / v2->u.rval_longlong ;break;
4080 + case CTK_ULONGLONG: if(v2->u.rval_ulonglong==0) goto div_err;
4081 + r->u.rval_ulonglong =v1->u.rval_ulonglong/ v2->u.rval_ulonglong ;break;
4082 + case CTK_FLOAT: if(v2->u.rval_float==0.0) goto div_err;
4083 + r->u.rval_float =v1->u.rval_float/ v2->u.rval_float ;break;
4084 + case CTK_DOUBLE:if(v2->u.rval_double==0.0) goto div_err;
4085 + r->u.rval_double=v1->u.rval_double/v2->u.rval_double;break;
4086 + default: duel_assert(0);
4087 + }
4088 + return ;
4089 +div_err: duel_op_error("division by zero",0,v1,v2);
4090 +}
4091 +
4092 +
4093 +/* do arithmeric reminder of v1,v2 and store result in r.
4094 + * NOTE: v1, v2 are destroyed!
4095 + */
4096 +LPROC do_op_reminder(tvalue *v1,tvalue *v2,tvalue *r)
4097 +{
4098 + tctype *t=find_numeric_result_type(v1,v2,r,"%");
4099 + get_integral_val(v1,"x%y",t);
4100 + get_integral_val(v2,"y%x",t);
4101 + switch(t->type_kind) {
4102 + case CTK_INT: if(v2->u.rval_int==0) goto div_err;
4103 + r->u.rval_int = v1->u.rval_int % v2->u.rval_int ; break ;
4104 + case CTK_UINT: if(v2->u.rval_uint==0) goto div_err;
4105 + r->u.rval_uint = v1->u.rval_uint % v2->u.rval_uint ; break ;
4106 + case CTK_LONG: if(v2->u.rval_long==0) goto div_err;
4107 + r->u.rval_long = v1->u.rval_long % v2->u.rval_long ; break ;
4108 + case CTK_ULONG: if(v2->u.rval_ulong==0) goto div_err;
4109 + r->u.rval_ulong = v1->u.rval_ulong % v2->u.rval_ulong ; break ;
4110 + case CTK_LONGLONG: if(v2->u.rval_longlong==0) goto div_err;
4111 + r->u.rval_longlong = v1->u.rval_longlong % v2->u.rval_longlong ; break ;
4112 + case CTK_ULONGLONG: if(v2->u.rval_ulonglong==0) goto div_err;
4113 + r->u.rval_ulonglong = v1->u.rval_ulonglong % v2->u.rval_ulonglong ; break ;
4114 + default: duel_assert(0);
4115 + }
4116 + return ;
4117 +div_err: duel_op_error("reminder modulo zero",0,v1,v2);
4118 +}
4119 +
4120 +/* do arithmeric or (bitwise) of v1,v2 and store result in r.
4121 + * NOTE: v1, v2 are destroyed!
4122 + */
4123 +LPROC do_op_or(tvalue *v1,tvalue *v2,tvalue *r)
4124 +{
4125 + tctype *t=find_numeric_result_type(v1,v2,r,"|");
4126 + get_integral_val(v1,"x|y",t);
4127 + get_integral_val(v2,"y|x",t);
4128 + switch(t->type_kind) {
4129 + case CTK_INT: r->u.rval_int = v1->u.rval_int | v2->u.rval_int ; break;
4130 + case CTK_UINT: r->u.rval_uint = v1->u.rval_uint | v2->u.rval_uint ; break;
4131 + case CTK_LONG: r->u.rval_long = v1->u.rval_long | v2->u.rval_long ; break;
4132 + case CTK_ULONG:r->u.rval_ulong= v1->u.rval_ulong | v2->u.rval_ulong; break;
4133 + case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong | v2->u.rval_longlong ; break;
4134 + case CTK_ULONGLONG:r->u.rval_ulonglong= v1->u.rval_ulonglong | v2->u.rval_ulonglong; break;
4135 + default: duel_assert(0);
4136 + }
4137 + return ;
4138 +}
4139 +
4140 +/* do arithmeric and (bitwise) of v1,v2 and store result in r.
4141 + * NOTE: v1, v2 are destroyed!
4142 + */
4143 +LPROC do_op_and(tvalue *v1,tvalue *v2,tvalue *r)
4144 +{
4145 + tctype *t=find_numeric_result_type(v1,v2,r,"&");
4146 + get_integral_val(v1,"x&y",t);
4147 + get_integral_val(v2,"y&x",t);
4148 + switch(t->type_kind) {
4149 + case CTK_INT: r->u.rval_int = v1->u.rval_int & v2->u.rval_int ; break;
4150 + case CTK_UINT: r->u.rval_uint = v1->u.rval_uint & v2->u.rval_uint ; break;
4151 + case CTK_LONG: r->u.rval_long = v1->u.rval_long & v2->u.rval_long ; break;
4152 + case CTK_ULONG:r->u.rval_ulong= v1->u.rval_ulong & v2->u.rval_ulong; break;
4153 + case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong & v2->u.rval_longlong ; break;
4154 + case CTK_ULONGLONG:r->u.rval_ulonglong= v1->u.rval_ulonglong & v2->u.rval_ulonglong; break;
4155 + default: duel_assert(0);
4156 + }
4157 +}
4158 +
4159 +/* do arithmeric xor (bitwise) of v1,v2 and store result in r.
4160 + * NOTE: v1, v2 are destroyed!
4161 + */
4162 +LPROC do_op_xor(tvalue *v1,tvalue *v2,tvalue *r)
4163 +{
4164 +
4165 + tctype *t=find_numeric_result_type(v1,v2,r,"^");
4166 + get_integral_val(v1,"x^y",t);
4167 + get_integral_val(v2,"y^x",t);
4168 + switch(t->type_kind) {
4169 + case CTK_INT: r->u.rval_int = v1->u.rval_int ^ v2->u.rval_int ; break ;
4170 + case CTK_UINT: r->u.rval_uint = v1->u.rval_uint ^ v2->u.rval_uint ; break ;
4171 + case CTK_LONG: r->u.rval_long = v1->u.rval_long ^ v2->u.rval_long ; break ;
4172 + case CTK_ULONG:r->u.rval_ulong= v1->u.rval_ulong^ v2->u.rval_ulong; break ;
4173 + case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong ^ v2->u.rval_longlong ; break ;
4174 + case CTK_ULONGLONG:r->u.rval_ulonglong= v1->u.rval_ulonglong ^ v2->u.rval_ulonglong; break ;
4175 + default: duel_assert(0);
4176 + }
4177 + return ;
4178 +}
4179 +
4180 +/* do arithmeric leftshift of v1,v2 and store result in r.
4181 + * v1 and v2 should be of numeric type to begin with.
4182 + * NOTE: v1, v2 are destroyed!
4183 + */
4184 +LPROC do_op_leftshift(tvalue *v1,tvalue *v2,tvalue *r)
4185 +{
4186 + int by;
4187 + get_integral_val(v1,"x<<y",NULL);
4188 + by=duel_get_int_val(v2,"y<<x");
4189 + r->val_kind=VK_RVALUE ;
4190 + r->ctype=v1->ctype ;
4191 + duel_set_symb_val(r,"%s<<%s",v1,v2);
4192 + switch(v1->ctype->type_kind) {
4193 + case CTK_INT: r->u.rval_int = v1->u.rval_int << by ; break ;
4194 + case CTK_UINT: r->u.rval_uint = v1->u.rval_uint << by ; break ;
4195 + case CTK_LONG: r->u.rval_long = v1->u.rval_long << by ; break ;
4196 + case CTK_ULONG: r->u.rval_ulong = v1->u.rval_ulong << by ; break ;
4197 + case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong << by ; break ;
4198 + case CTK_ULONGLONG: r->u.rval_ulonglong = v1->u.rval_ulonglong << by ; break ;
4199 + default: duel_assert(0);
4200 + }
4201 +}
4202 +
4203 +/* do arithmeric rightshift of v1,v2 and store result in r.
4204 + * v1 and v2 should be of numeric type to begin with.
4205 + * NOTE: v1, v2 are destroyed!
4206 + */
4207 +LPROC do_op_rightshift(tvalue *v1,tvalue *v2,tvalue *r)
4208 +{
4209 + int by ;
4210 + get_integral_val(v1,"x>>y",NULL);
4211 + by=duel_get_int_val(v2,"y>>x");
4212 + r->val_kind=VK_RVALUE ;
4213 + r->ctype=v1->ctype ;
4214 + duel_set_symb_val(r,"%s>>%s",v1,v2);
4215 + switch(v1->ctype->type_kind) {
4216 + case CTK_INT: r->u.rval_int = v1->u.rval_int >> by ; break ;
4217 + case CTK_UINT: r->u.rval_uint = v1->u.rval_uint >> by ; break ;
4218 + case CTK_LONG: r->u.rval_long = v1->u.rval_long >> by ; break ;
4219 + case CTK_ULONG: r->u.rval_ulong = v1->u.rval_ulong >> by ; break ;
4220 + case CTK_LONGLONG: r->u.rval_longlong = v1->u.rval_longlong >> by ; break ;
4221 + case CTK_ULONGLONG: r->u.rval_ulonglong = v1->u.rval_ulonglong >> by ; break ;
4222 + default: duel_assert(0);
4223 + }
4224 +}
4225 +
4226 +/* do arithmeric not of v (!v) */
4227 +LPROC do_op_not(tvalue *v)
4228 +{
4229 + get_scalar_val(v,"!x");
4230 + duel_set_symb_val(v,"!%s",v,0);
4231 + switch(v->ctype->type_kind) {
4232 + case CTK_PTR: v->u.rval_int = ! v->u.rval_ptr ; break ;
4233 + case CTK_INT: v->u.rval_int = ! v->u.rval_int ; break ;
4234 + case CTK_UINT: v->u.rval_int = ! v->u.rval_uint ; break ;
4235 + case CTK_LONG: v->u.rval_int = ! v->u.rval_long ; break ;
4236 + case CTK_ULONG: v->u.rval_int = ! v->u.rval_ulong ; break ;
4237 + case CTK_LONGLONG: v->u.rval_int = ! v->u.rval_longlong ; break ;
4238 + case CTK_ULONGLONG: v->u.rval_int = ! v->u.rval_ulonglong ; break ;
4239 + case CTK_FLOAT: v->u.rval_int = ! v->u.rval_float ; break ;
4240 + case CTK_DOUBLE: v->u.rval_int = ! v->u.rval_double ; break ;
4241 + default: duel_assert(0);
4242 + }
4243 + v->ctype=ctype_int ; /* always returns an int */
4244 +}
4245 +
4246 +/* do bit-complement of v (~v) */
4247 +LPROC do_op_complement(tvalue *v)
4248 +{
4249 + get_integral_val(v,"~x",NULL);
4250 + duel_set_symb_val(v,"~%s",v,0);
4251 + switch(v->ctype->type_kind) {
4252 + case CTK_INT: v->u.rval_int = ~ v->u.rval_int ; break ;
4253 + case CTK_UINT: v->u.rval_uint = ~ v->u.rval_uint ; break ;
4254 + case CTK_LONG: v->u.rval_long = ~ v->u.rval_long ; break ;
4255 + case CTK_ULONG: v->u.rval_ulong = ~ v->u.rval_ulong ; break ;
4256 + case CTK_LONGLONG: v->u.rval_longlong = ~ v->u.rval_longlong ; break ;
4257 + case CTK_ULONGLONG: v->u.rval_ulonglong = ~ v->u.rval_ulonglong ; break ;
4258 + default: duel_assert(0);
4259 + }
4260 +}
4261 +
4262 + /* do arithmeric minus of v (-v) */
4263 +LPROC do_op_minus(tvalue *v)
4264 +{
4265 + get_numeric_val(v,"-x",NULL);
4266 + duel_set_symb_val(v,"-%s",v,0);
4267 + switch(v->ctype->type_kind) {
4268 + case CTK_INT: v->u.rval_int = - v->u.rval_int ; break ;
4269 + case CTK_UINT: v->u.rval_uint = - v->u.rval_uint ; break ;
4270 + case CTK_LONG: v->u.rval_long = - v->u.rval_long ; break ;
4271 + case CTK_ULONG: v->u.rval_ulong = - v->u.rval_ulong ; break ;
4272 + case CTK_LONGLONG: v->u.rval_longlong = - v->u.rval_longlong ; break ;
4273 + case CTK_ULONGLONG: v->u.rval_ulonglong = - v->u.rval_ulonglong ; break ;
4274 + case CTK_FLOAT: v->u.rval_float = - v->u.rval_float ; break ;
4275 + case CTK_DOUBLE: v->u.rval_double= - v->u.rval_double ; break ;
4276 + default: duel_assert(0);
4277 + }
4278 +}
4279 +
4280 +/* do sizeif(exp) - simply return the size of the exp's type */
4281 +LPROC do_op_sizeofexp(tvalue *v)
4282 +{
4283 + v->val_kind=VK_RVALUE ;
4284 + v->u.rval_size_t=v->ctype->size ;
4285 + v->ctype=ctype_size_t ;
4286 + duel_set_symb_val(v,"sizeof(%s)",v,0);
4287 +}
4288 +
4289 +LPROC do_op_assignment(tvalue *v1,tvalue *v2,tvalue *r,char *op)
4290 +{
4291 + char xopy[10],yopx[10] ;
4292 + sprintf(xopy,"x%sy",op);
4293 + sprintf(yopx,"y%sx",op);
4294 + if(v1->val_kind!=VK_LVALUE && v1->val_kind!=VK_BVALUE)
4295 + duel_op_error("operand x is not an lvalue for operator '%s'",xopy,v1,0);
4296 +
4297 + if(ctype_kind_struct_like(v1->ctype)) {
4298 + duel_check_type_eq(v1,v2,xopy);
4299 + copy_lvalues(v1,v2,xopy);
4300 + *r= *v2 ; /* return the result as an lvalue. this means (x1=x2)=x3
4301 + is legal for struct, unlike ansi-c. */
4302 + return ;
4303 + }
4304 + if(ctype_kind_numeric(v1->ctype)) get_numeric_val(v2,yopx,v1->ctype);
4305 + else
4306 + if(v1->ctype->type_kind==CTK_PTR) {
4307 + get_pointer_val(v2,yopx,TRUE);
4308 + duel_check_type_eq(v1,v2,xopy);
4309 + }
4310 + else duel_op_error("bad operand x type for operator '%s'",xopy,v1,0);
4311 + put_rvalue(v1,v2,xopy);
4312 + *r= *v2 ;
4313 +}
4314 +
4315 +LPROC do_op_increment(tvalue *v,char *op,int inc,bool postfix)
4316 +{
4317 + tvalue lvalue_v,oldv ;
4318 + char s[80] ;
4319 + if(v->val_kind!=VK_LVALUE)
4320 + duel_op_error("operand of '%s' must be an lvalue",op,v,0);
4321 + lvalue_v= *v ;
4322 + if(v->ctype->type_kind==CTK_PTR) get_pointer_val(v,op,FALSE);
4323 + else get_integral_val(v,op,0);
4324 + oldv= *v ;
4325 +
4326 + switch(v->ctype->type_kind) {
4327 + case CTK_INT: v->u.rval_int += inc ; break ;
4328 + case CTK_UINT: v->u.rval_uint += inc ; break ;
4329 + case CTK_LONG: v->u.rval_long += inc ; break ;
4330 + case CTK_ULONG: v->u.rval_ulong += inc ; break ;
4331 + case CTK_LONGLONG: v->u.rval_longlong += inc ; break ;
4332 + case CTK_ULONGLONG: v->u.rval_ulonglong += inc ; break ;
4333 + case CTK_PTR: v->u.rval_ptr += inc*v->ctype->u.kid->size ; break;
4334 + default: duel_assert(0);
4335 + }
4336 + convert_scalar_type(v,lvalue_v.ctype,op); /* back to the original type */
4337 + put_rvalue(&lvalue_v,v,op);
4338 + if(postfix) { /* if prefix, keep v and its sym val*/
4339 + *v= oldv ;
4340 + convert_scalar_type(v,lvalue_v.ctype,op); /* back to original type */
4341 + sprintf(s,"%%s%s",op);
4342 + duel_set_symb_val(v,s,v,0);
4343 + }
4344 +}
4345 +
4346 +/* unary op 'frame(n)' converts int n to a "frame type" */
4347 +LPROC do_op_frame(tvalue *v)
4348 +{
4349 + int f=duel_get_int_val(v,"frame(x)");
4350 + if(f<0 || f>=duel_get_frames_number())
4351 + duel_gen_error("Frame number too big",0);
4352 + v->val_kind=VK_FVALUE ;
4353 + v->ctype=ctype_int ;
4354 + v->u.fvalue=f ;
4355 + duel_set_symb_val(v,"frame(%s)",v,0);
4356 +}
4357 +
4358 +/* unary op '(x)'. this only add parenthesis to the symbolic value, if needed*/
4359 +
4360 +LPROC do_op_parenthesis(tvalue *v)
4361 +{
4362 + char *s=v->symb_val ;
4363 + int l=strlen(s);
4364 + if(s[0]=='(' && s[l-1]==')') return ; /* val is (x) dont make it ((x)) */
4365 + while(*s!=0 && (isalnum(*s) || *s=='_')) s++ ; /* find first non alnum*/
4366 + if(*s==0) return ; /* no need for (x) if x is a name or constant number */
4367 + duel_set_symb_val(v,"(%s)",v,0);
4368 +}
4369 +
4370 +/***********************************************************************
4371 + High-level functions, major entries to this module, evaluate a node
4372 + with a standard (single value) result
4373 + ***********************************************************************/
4374 +
4375 +
4376 +/* standardize a paramater to a function call according to the standard rules.
4377 + * we currently don't support union/struct paramater passing
4378 + */
4379 +
4380 +PROC duel_standardize_func_parm(tvalue *p)
4381 +{
4382 + /* convert paramater into "standard" function calling */
4383 + if(ctype_kind_integral(p->ctype)) get_integral_val(p,"f()",NULL);
4384 + else
4385 + if(ctype_kind_numeric(p->ctype)) /* float, double to double */
4386 + convert_scalar_type(p,ctype_double,"f()");
4387 + else
4388 + if(ctype_kind_ptr_like(p->ctype)) get_pointer_val(p,"f()",FALSE);
4389 + else
4390 + duel_op_error("unsupported paramater type",0,p,0);
4391 +}
4392 +
4393 +
4394 +/* given a function (or pointer), find the first (top-most) frame that
4395 + * the function is active in, and return the FVALUE for it
4396 + */
4397 +PROC duel_find_func_frame(tvalue *v,char *op)
4398 +{
4399 + int i, frames_no=duel_get_frames_number();
4400 + get_pointer_val(v,op,FALSE);
4401 +
4402 + for(i=0 ; i<frames_no ; i++) {
4403 + ttarget_ptr frame_func = duel_get_function_for_frame(i);
4404 + if(frame_func==v->u.rval_ptr) {
4405 + v->val_kind=VK_FVALUE ;
4406 + v->ctype=ctype_int ;
4407 + v->u.rval_int=i ;
4408 + return ;
4409 + }
4410 + }
4411 + duel_op_error("func x is not on the call stack for operator '%s'",op,v,0);
4412 +}
4413 +
4414 +
4415 +/* compute the n'th result of v1..v2 operator.
4416 + * result is returned in r, returns false if there isnt an nth result
4417 + * v1,v2 are converted to integer values (but can be used to call this
4418 + * function again. errors are reported if they arenot integral.
4419 + */
4420 +
4421 +FUNC bool duel_do_op_to(tvalue *v1,tvalue *v2,int n,tvalue *r)
4422 +{
4423 + int a,b,inc,x ;
4424 + char *p,*fmt ;
4425 +
4426 + if(!v1) { a=0 ; b=duel_get_int_val(v2,"..x")-1 ; }
4427 + else if(!v2) { a=duel_get_int_val(v1,"x.."); b=INT_MAX ; }
4428 + else { a=duel_get_int_val(v1,"x..y"); b=duel_get_int_val(v2,"x..y"); }
4429 + if(a<=b) inc=1 ;
4430 + else inc= -1 ;
4431 + x=a+n*inc ;
4432 + if(inc>0 && x>b || inc<0 && x<b) return FALSE ;
4433 +
4434 + r->val_kind=VK_RVALUE ;
4435 + r->ctype=ctype_int ;
4436 + r->u.rval_int=x ;
4437 + if(v1) p=v1->symb_val ;
4438 + else p=v2->symb_val ;
4439 + if( *p=='0' && p[1]=='x' || p[1]=='X') fmt="0x%x" ;
4440 + else if(*p=='0' && p[1]>='0' && p[1]<='7') fmt="0%o" ;
4441 + else if(*p=='\'' && isascii(x) && isprint(x)) fmt="'%c'" ;
4442 + else fmt="%d" ;
4443 + sprintf(r->symb_val,fmt,x);
4444 + return TRUE ;
4445 +}
4446 +
4447 +/* convert value to True/False and return it
4448 + * in case of an illegal operand, indicateds the operator is (op)
4449 + * main use: in operators '&&' '||' and 'if'
4450 + */
4451 +
4452 +FUNC bool duel_mk_logical(tvalue *v,char *op)
4453 +{
4454 + get_scalar_val(v,op); /* verify v is scalar */
4455 + do_op_not(v); /* convert and force 0 or 1 */
4456 + v->u.rval_int = !v->u.rval_int ;
4457 + sprintf(v->symb_val,"%d",v->u.rval_int);
4458 + return(v->u.rval_int);
4459 +}
4460 +
4461 +/* cast the value v into type t. */
4462 +
4463 +PROC duel_do_cast(tctype *tout,tvalue *v)
4464 +{
4465 + tctype *t=v->ctype ;
4466 + if(ctype_kind_scalar(t) && ctype_kind_scalar(tout)) {
4467 + if(tout->type_kind==CTK_ARRAY)
4468 + duel_gen_error("casting to an array type is illegal",0);
4469 + else convert_scalar_type(v,tout,"(cast) x");
4470 + }
4471 + else duel_op_error("illegal type conversion in cast op",0,v,0);
4472 +}
4473 +
4474 +
4475 +/* apply unary oprand op to the given value. The original value is
4476 + * destoryed (of course)
4477 + */
4478 +
4479 +PROC duel_apply_unary_op(topcode op,tvalue *v)
4480 +{
4481 + switch(op) {
4482 + case '(': do_op_parenthesis(v); break ;
4483 + case '{': duel_sprint_scalar_value(v->symb_val,v);break ;
4484 + case '-': do_op_minus(v); break ;
4485 + case '!': do_op_not(v); break ;
4486 + case '*': do_op_indirection(v); break ;
4487 + case '~': do_op_complement(v); break ;
4488 + case '&': do_op_address(v); break ;
4489 + case OP_SIZ: do_op_sizeofexp(v); break ;
4490 + case OP_INC: do_op_increment(v,"++",1,FALSE); break ;
4491 + case OP_DEC: do_op_increment(v,"--",-1,FALSE); break ;
4492 + case OP_FRAME: do_op_frame(v); break ;
4493 + default: duel_assert(0);
4494 + }
4495 +}
4496 +
4497 +PROC duel_apply_post_unary_op(topcode op,tvalue *v)
4498 +{
4499 + switch(op) {
4500 + case OP_INC: do_op_increment(v,"++",1,TRUE); break ;
4501 + case OP_DEC: do_op_increment(v,"--",-1,TRUE); break ;
4502 + default: duel_assert(0);
4503 + }
4504 +}
4505 +
4506 +
4507 +/* apply_bin_op -- apply the operator op to the values v1 v2 and return
4508 + * the result in r. the bin op is a 'regular' one, like
4509 + * '+', '*', etc. in the C language.
4510 + * note: v1,v2 are destroyed
4511 + * returns: true if a value has been produced, false otherwise.
4512 + * (ops like '+' always return true. ops like '<=?' also return false)
4513 + */
4514 +
4515 +FUNC bool duel_apply_bin_op(topcode op,tvalue *v1,tvalue *v2,tvalue *r)
4516 +{
4517 + switch(op) {
4518 + case '[': do_op_index(v1,v2,r); break ;
4519 + case '+': do_op_add(v1,v2,r); break ;
4520 + case '-': do_op_subtract(v1,v2,r); break ;
4521 + case '*': do_op_multiply(v1,v2,r); break ;
4522 + case '/': do_op_divide(v1,v2,r); break ;
4523 + case '%': do_op_reminder(v1,v2,r); break ;
4524 + case '|': do_op_or(v1,v2,r); break;
4525 + case '&': do_op_and(v1,v2,r); break ;
4526 + case '^': do_op_xor(v1,v2,r); break ;
4527 + case OP_LSH: do_op_leftshift(v1,v2,r); break ;
4528 + case OP_RSH: do_op_rightshift(v1,v2,r); break ;
4529 + case OP_EQ: do_op_eq(v1,v2,r); break ;
4530 + case OP_NE: do_op_ne(v1,v2,r); break ;
4531 + case OP_GE: do_op_ge(v1,v2,r); break ;
4532 + case OP_LE: do_op_le(v1,v2,r); break ;
4533 + case '<': do_op_ls(v1,v2,r); break ;
4534 + case '>': do_op_gt(v1,v2,r); break ;
4535 + case OP_EQQ:
4536 + case OP_NEQ:
4537 + case OP_GEQ:
4538 + case OP_LEQ:
4539 + case OP_LSQ:
4540 + case OP_GTQ: return do_compare_questionmark(op,v1,v2,r);
4541 + case '=': do_op_assignment(v1,v2,r,"="); break ;
4542 + default: duel_assert(0);
4543 + }
4544 + return TRUE ;
4545 +}
4546 --- gdb/duel/global.h
4547 +++ gdb/duel/global.h
4548 @@ -0,0 +1,450 @@
4549 +/* DUEL - A Very High Level Debugging Langauge. */
4550 +/* Public domain code */
4551 +/* Written by Michael Golan mg@××××××××××××.edu */
4552 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
4553 +
4554 +/* this include file contains global definitions for duel. All global info
4555 + * is shared thru this single file.
4556 + */
4557 +
4558 +/*
4559 + * $Log: 10_all_gdb-6.6-duel.patch,v $
4560 + * Revision 1.1 2007/12/29 21:06:06 vapier
4561 + * add DUEL support #199987 by Sergei Golubchik
4562 + *
4563 + * Revision 1.12 93/03/12 05:50:35 mg
4564 + * uses tuint instead of uint, etc.
4565 + *
4566 + * Revision 1.11 93/02/27 06:03:26 mg
4567 + * added HP9000 support by not defining uint etc
4568 + * clean annoying enum {x,y,} warnings
4569 + *
4570 + * Revision 1.10 93/02/03 21:49:32 mg
4571 + * support "signed char"
4572 + *
4573 + * Revision 1.9 93/01/12 21:52:11 mg
4574 + * cleanup and set for release
4575 + *
4576 + * Revision 1.8 93/01/07 00:10:53 mg
4577 + * macros for func ptr auto-convert
4578 + *
4579 + * Revision 1.7 93/01/03 07:30:23 mg
4580 + * *** empty log message ***
4581 + *
4582 + * Revision 1.6 92/12/24 23:49:25 mg
4583 + * *** empty log message ***
4584 + *
4585 + * Revision 1.5 92/10/19 15:07:58 mg
4586 + * fvalue added (not ready yet), svalues dropped
4587 + *
4588 + * Revision 1.4 92/10/14 02:05:37 mg
4589 + * misc
4590 + *
4591 + * Revision 1.3 92/09/16 11:11:54 mg
4592 + * add builtin ctype_charptr
4593 + *
4594 + * Revision 1.2 92/09/15 05:47:49 mg
4595 + * some ops added
4596 + *
4597 + */
4598 +
4599 +
4600 +/* The following definitions are common programming tricks that I use
4601 + * in every program I write. I hope they are obvious. the FUNC/PROC
4602 + * constants are useful mainly when editing (to find a function def.)
4603 + * or when grep'ing on source files. DEF is set to "extern" by default,
4604 + * allowing declaration and definition of globals in one source. only
4605 + * duel.c should have #define DEF before including duel.h
4606 + */
4607 +
4608 +#define FUNC
4609 +#define PROC void
4610 +#define LPROC static void
4611 +#define LFUNC static
4612 +
4613 +#ifndef DEF
4614 +#define DEF extern /* declare only, 'int x' become 'extern int x'*/
4615 +#endif
4616 +
4617 +/* use simpler names for unsigned types, very common,
4618 + * too common, indeed, so I forced 't' as a prefix.
4619 + */
4620 +
4621 +typedef unsigned int tuint ;
4622 +typedef unsigned char tuchar ;
4623 +typedef unsigned short tushort ;
4624 +typedef unsigned long tulong ;
4625 +typedef unsigned long long tulonglong ;
4626 +
4627 +typedef signed char tschar ; /* explicit signed char */
4628 +typedef int bool ; /* suppose to be just 0,1 */
4629 +#define FALSE 0
4630 +#define TRUE 1
4631 +
4632 + /* these should be inline functions, they replace common lib func which
4633 + * change from system to system.
4634 + * duel_assert can be modified to call duel_fatal, so gdb itself isn't
4635 + * aborted because on an internal duel error.
4636 + */
4637 +
4638 +#define duel_assert(x) assert(x)
4639 +#define duel_bzero(x,y) memset(x,0,y)
4640 +#define duel_bcopy(x,y,s) memcpy(x,y,s)
4641 +
4642 +
4643 +
4644 +/*************
4645 + Parsing: the expression is converted into a tree.
4646 + Each node of this tree is of 'tnode' type.
4647 + Nodes can be:
4648 + An operator (like '+', or ':=' or 'for')
4649 + A constant (numbers. Strings are pointers to space!)
4650 + A symbol.
4651 + A regular expression (really a symbol extention)
4652 +
4653 + The evaluation of any node results in:
4654 + 1. 'Environment': duel variables and their values
4655 + 2. symbolic expression which describe the computation
4656 + meaning: keep the parentethis. in the expression a<<(3+b) (even if not needed!)
4657 + 3. A type & value
4658 +
4659 + Values:
4660 + Values are always a fixed length area of bytes; Any C type is like that.
4661 +**************/
4662 +
4663 +
4664 +/****** TYPES *******
4665 + A type is described in the typical compiler's way, which is also gdb's
4666 + way. That is, a type is made of 'atomic' types, like 'pointer to',
4667 + 'array of', etc. Each atomic type is described by a 'ctype' node. Ctype
4668 + node points to other ctype nodes as required. For example, a ctype node
4669 + of 'array of' will point to the node 'int' for the 'C' type array of int.
4670 + [The name ctype is used to indicate the C language type; 'type' is too
4671 + generic a term]
4672 + Example:
4673 + char *(*f[])() ;
4674 + Here, f is an array of pointers to functions returning a pointer to char.
4675 + The type is described with the top node being of CTK_ARRAY type. It
4676 + points to a 'CTK_PTR' node, which points to a 'CTK_FUNC' node which
4677 + points to a 'CTK_PTR' node which points to a 'CTK_CHAR' node which has,
4678 + as size, 1.
4679 +
4680 + The size of a type is the number of bytes occupied by it. it is zero
4681 + for types like 'function'. An array of 10 integers will have as size
4682 + 10*sizeof(int)
4683 +
4684 + A note on UCHAR vs CHAR vs SCHAR:
4685 + Internally, duel supports all three forums (for aritmetic).
4686 + For output, only "char" types are considered ASCII, and will be displayed
4687 + as 'A' instead of "65", etc. The same is true for char[] and char*.
4688 + GDB doesn't really support "signed char", but some compilers do;
4689 + we convert "signed char" into just a "char" when the default char is signed.
4690 + This is only significant for output.
4691 + Maybe duel shouldn't support "char" at all, and force everything to be
4692 + "schar" or "uchar". I'm not sure. I prefer "char" as a distinct type
4693 + which implies "string" and uchar/schar as "integral".
4694 + ********************/
4695 +
4696 +typedef enum { /* 'C' Type atomic primitive Kinds (CTK_) */
4697 + CTK_VOID, /* void type 'void' */
4698 + CTK_CHAR, /* primitive types */
4699 + CTK_SCHAR, /* signed char (ansi c) */
4700 + CTK_UCHAR, /* note order is used in some macros */
4701 + CTK_SHORT,
4702 + CTK_USHORT,
4703 + CTK_INT,
4704 + CTK_UINT,
4705 + CTK_LONG,
4706 + CTK_ULONG,
4707 + CTK_LONGLONG,
4708 + CTK_ULONGLONG,
4709 + CTK_FLOAT,
4710 + CTK_DOUBLE,
4711 + CTK_PTR, /* pointer '*' */
4712 + CTK_ARRAY, /* array '[]' */
4713 + CTK_FUNC, /* a function '()' */
4714 + CTK_STRUCT, /* a sturcture 'struct{}' */
4715 + CTK_UNION, /* a union 'union{}' */
4716 + CTK_ENUM /* enum type 'enum{}' */
4717 + } tctype_kind ;
4718 +
4719 +typedef struct { /* a field (of struct) info */
4720 + char *name ; /* field name */
4721 + struct sctype *ctype ; /* field type */
4722 + int bitpos, bitlen ; /* for bit fields only */
4723 +} tctype_field ;
4724 +
4725 +typedef struct { /* an enumerator (constant of an enum) info */
4726 + char *name ; /* enumerator name */
4727 + int val ; /* value assigned to the name */
4728 + /* question: ansi-C say cosnt fit in int?*/
4729 +} tctype_enumerator ;
4730 +
4731 +
4732 +typedef struct sctype { /* a 'C' type description */
4733 + tctype_kind type_kind ;
4734 + char *name ; /* named of this type, if any */
4735 + size_t size ; /* size (total bytes) for this type */
4736 + union {
4737 + struct sctype *kid ; /* pointer to next atomic type */
4738 + struct {
4739 + int fields_no ;
4740 + tctype_field *fields ; /* union/struct fields */
4741 + } f ;
4742 + struct {
4743 + tctype_kind real_type_kind ; /* the type used for storage of the enum */
4744 + int enumerators_no ;
4745 + tctype_enumerator *enumerators ; /* enum's type enumerators list */
4746 + } e;
4747 + } u ;
4748 + } tctype ;
4749 +
4750 +
4751 +/**** BASIC C TYPES
4752 + these are initialized at run type to point to the basic C types.
4753 + basic types are never created again, e.g. pointer comparison with
4754 + these is sufficient to check type equality.
4755 + the voidptr is (void*) which is a basic type (what zero is converted
4756 + to when it is a pointer).
4757 + ptrdiff_t and size_t are actually pointing to their actualy types,
4758 + ie. normally point to ctype_int.
4759 + ****/
4760 +
4761 +DEF tctype *ctype_int, *ctype_uint, *ctype_short, *ctype_ushort,
4762 + *ctype_char, *ctype_schar, *ctype_uchar,
4763 + *ctype_long, *ctype_ulong, *ctype_longlong, *ctype_ulonglong,
4764 + *ctype_float, *ctype_double,
4765 + *ctype_void, *ctype_charptr,
4766 + *ctype_voidptr,*ctype_ptrdiff_t,*ctype_size_t ;
4767 +
4768 +/* type checking macros */
4769 +
4770 +/** tell if type is a struct or union */
4771 +#define ctype_kind_struct_like(t) ((t)->type_kind==CTK_STRUCT || \
4772 + (t)->type_kind==CTK_UNION)
4773 +
4774 +/** tell if type is a pointer or can be made one (array, func) */
4775 +#define ctype_kind_ptr_like(t) ((t)->type_kind==CTK_PTR || \
4776 + (t)->type_kind==CTK_ARRAY || (t)->type_kind==CTK_FUNC)
4777 +/* tell if type is numeric */
4778 +#define ctype_kind_numeric(t) (((t)->type_kind>=CTK_CHAR && \
4779 + (t)->type_kind<=CTK_DOUBLE) || (t)->type_kind==CTK_ENUM)
4780 +
4781 +/* tell if type is integral */
4782 +#define ctype_kind_integral(t) ((t)->type_kind>=CTK_CHAR && \
4783 + (t)->type_kind<=CTK_ULONG || (t)->type_kind==CTK_ENUM)
4784 +
4785 +/* tell if type fits into fixed memory size (void not included) */
4786 +#define ctype_kind_scalar(t) (ctype_kind_numeric(t) || ctype_kind_ptr_like(t))
4787 +
4788 +/* tell if type is a "base" ie can't have kids */
4789 +
4790 +#define ctype_kind_base(t) ((t)->type_kind>=CTK_VOID && \
4791 + (t)->type_kind<=CTK_DOUBLE)
4792 +
4793 +/* tell if a type is a function pointer or like a func ptr (ie a func!) */
4794 +#define ctype_kind_func_ptr_like(t) ((t)->type_kind==CTK_FUNC || \
4795 + (t)->type_kind==CTK_PTR && t->u.kid->type_kind==CTK_FUNC)
4796 +
4797 +
4798 +/***** VALUES
4799 + used to keep information when evaluating an expression. A value is
4800 + either:
4801 + 1) a right-value, which is represented in a fixed number of bytes that
4802 + actually contain its value. Example: result of '+' operation.
4803 + 2) a left-value. This is a reference to the actual value, which
4804 + resides in the debuggee's address space.
4805 + 3) a special-value. This contains a long value specifying a special
4806 + target location (e.g. register) from which values can be fetched
4807 + or written to. However, special-values can not be manipulated (i.e
4808 + have an offset added to them, as done to an lvalue struct).
4809 +
4810 + Note that the operation '*x' starts with x as an lvalue - a pointer to
4811 + x is kept. Then, '*x' is executed, fetching the value of x and creating
4812 + another lvalue, which points to where x has pointed to! This allows
4813 + &*x to be executed, as well as *x=1 or &x[1] ...
4814 + When the value of an lvalue is actually needed, it must be fetched
4815 + from the debugge's space.
4816 + *****/
4817 +
4818 +#define VALUE_MAX_CONST_SIZE 8
4819 +#define VALUE_MAX_SYMBOLIC_SIZE 128
4820 +
4821 +typedef long tptrsize_int ; /* type so that
4822 + tptrsize x; char *p ;
4823 + p == (char*) (tptrsize) p
4824 + */
4825 +
4826 + /* type that represent a target address space location. */
4827 +
4828 +typedef char* ttarget_ptr ; /* pointer to target's address */
4829 +
4830 +typedef struct {
4831 + ttarget_ptr lvalue ; /* pointer to target's location of struct*/
4832 + int bitpos,bitlen ; /* as specified in the field info of stuct*/
4833 + } tbvalue_info ;
4834 +
4835 +typedef enum {
4836 + VK_RVALUE, /* this value represent a constant, in the rval_ union */
4837 + VK_LVALUE, /* this value represent a left-value. address in lvalue*/
4838 + VK_BVALUE, /* a bit-field lvalue, given as point and bitpos/bitlen*/
4839 + VK_FVALUE /* a frame, fvalue contains it number */
4840 + } tval_kind ;
4841 +
4842 +typedef struct {
4843 + tval_kind val_kind ;
4844 + tctype *ctype ; /* type of this value */
4845 + union {
4846 + ttarget_ptr lvalue ; /* location in target of the value */
4847 + tbvalue_info bvalue ; /* location in target of a bitfield */
4848 + int fvalue ; /* a frame number (0 = top of stack) */
4849 + char rval_char ;
4850 + tschar rval_schar ;
4851 + tuchar rval_uchar ;
4852 + short rval_short ;
4853 + tushort rval_ushort ;
4854 + int rval_int ;
4855 + tuint rval_uint ;
4856 + long rval_long ;
4857 + tulong rval_ulong ;
4858 + long long rval_longlong ;
4859 + tulonglong rval_ulonglong ;
4860 + float rval_float ;
4861 + double rval_double ;
4862 + ttarget_ptr rval_ptr ;
4863 + ptrdiff_t rval_ptrdiff_t ; /* Synonyms to one of the above fields! */
4864 + size_t rval_size_t ; /* normally these are simply = rval_int */
4865 + } u ;
4866 + char symb_val[VALUE_MAX_SYMBOLIC_SIZE];
4867 + } tvalue ;
4868 +
4869 +
4870 +typedef struct sval_lcell { /* a cell on a linked-list containing a tvalue*/
4871 + tvalue val ;
4872 + struct sval_lcell *next ;
4873 + } tval_lcell ;
4874 +
4875 +typedef struct { /* a linked list of tvalue's */
4876 + tval_lcell *head ;
4877 + tval_lcell *tail ;
4878 +} tval_list ;
4879 +
4880 +/**** OP CODES ****
4881 + Opcodes are divided into groups, or 'kinds'. For example, all the
4882 + C regular unary operators, binary operators, etc.
4883 + An opcode is defined by its 'kind' and actual value. The value is,
4884 + in most cases, a single char. For example, the C plus operator is
4885 + defined as op_kind=OPK_BIN and op='+'. The C operator '+=' is
4886 + defined as op_kind=OPK_ASSIGN and op='+'.
4887 + some operators are uniquely identified by type alone (e.g. func call).
4888 + In the lexer there is a table of actual operators as tokens, and
4889 + the kind & value assigned to each.
4890 + Several opertors use more than one char, and are defined below.
4891 + the OPK_SBIN, etc kinds are special in the sense that A op B isn't
4892 + computed in the normal way of the C language (i.e. compute both sides,
4893 + then apply the operator). Such operators include ',' '&&', etc.
4894 + **********/
4895 +typedef enum {
4896 + /* '+' '-' etc are used directly and have their ascii value */
4897 + OP_LSH = 300, /* '<<' */
4898 + OP_RSH = 301, /* '>>' */
4899 + OP_INC = 302, /* '++' */
4900 + OP_DEC = 303, /* '--' */
4901 + OP_ARR = 304, /* '->' */
4902 + OP_AND = 305, /* '&&' */
4903 + OP_OR = 306, /* '||' */
4904 + OP_EQ = 307, /* '==' */
4905 + OP_GE = 308, /* '>=' */
4906 + OP_LE = 309, /* '<=' */
4907 + OP_NE = 310, /* '!=' */
4908 + OP_SIZ = 311, /* 'sizeof' */
4909 + OP_TO = 312, /* '..' */
4910 + OP_EQQ = 313, /* '==?' */
4911 + OP_NEQ = 314, /* '!=?' */
4912 + OP_GEQ = 315, /* '>=?' */
4913 + OP_LEQ = 316, /* '<=?' */
4914 + OP_GTQ = 317, /* '>?' */
4915 + OP_LSQ = 318, /* '<?' */
4916 + OP_IMP = 319, /* '=>' */
4917 + OP_IF = 320, /* if() */
4918 + OP_DEF = 321, /* ':=' */
4919 + OP_DFS = 322, /* '-->' */
4920 + OP_BFS = 323, /* '->>' */
4921 + OP_POS = 324, /* '>--' */
4922 + OP_IOS = 325, /* '->-' */
4923 + OP_SEL = 326, /*'x[[y]]'*/
4924 + OP_FOR = 327, /*for(;;)'*/
4925 + OP_WHILE= 328, /*while() */
4926 + OP_DECL = 329, /* var decl*/
4927 + OP_FRAME= 330 /* frame(i)*/
4928 + } topcode ;
4929 +
4930 +/**** OPCODE KINDS ****/
4931 +
4932 +typedef enum { /* the kind of the opcode, 'OPK_' = OPcode Kind */
4933 + OPK_UNARY =0, /* regular unary operator */
4934 + OPK_SUNARY =1, /* special unary operator (sizeof) */
4935 + OPK_POST_UNARY =2, /* post unary operator (x++ etc) */
4936 + OPK_BIN =3, /* regular binary operator */
4937 + OPK_SBIN =4, /* special binary operator */
4938 + OPK_TRI =5, /* trinary (eg ?:) operator */
4939 + OPK_QUAD =6, /* quad (e.g.for(;;)) operator */
4940 + OPK_ASSIGN =7, /* assignment ie =, +=, -= etc */
4941 + OPK_FUNC =8, /* function call. 2nd kid made of ',' kids for parms */
4942 + OPK_CAST =9, /* type cast. 2nd kid convert to type in 1st kid */
4943 + OPK_NUM_OF =10 /* number of OPK_* op kinds */
4944 + } top_kind ;
4945 +
4946 +
4947 +/**** NODE KINDS ****/
4948 +
4949 +typedef enum { /* the kind of node */
4950 + NK_OP, /* contain an operator */
4951 + NK_CONST, /* contains a constant */
4952 + NK_NAME, /* contains a name/symbol */
4953 + NK_CTYPE /* contain a 'C' type */
4954 + } tnode_kind ;
4955 +
4956 +#define NODE_MAX_KIDS 4 /* maximum no of kids per node */
4957 +#define NODE_MAX_SYM_LEN 50 /* maximum length for a symbol */
4958 +
4959 +/* the following structure is used to store one node of the expression tree.
4960 + * It contains two parts: (a) information to describe the node and (b)
4961 + * information used during the evaluation of the node.
4962 + *
4963 + * This structure could/should be optimized with ugly unions (e.g., for
4964 + * a node describing a constant(node_kind==NK_CONST) there is no need for
4965 + * the op, kids or any eval stuff!). However, only few nodes (less than 100?)
4966 + * are expected to be in memory at any time (how complex can a user
4967 + * expression be?). Hence, for clarity, no unions where used.
4968 + *
4969 + * All nodes have kids in the typical way. the opcode OPK_FUNC node is tricky:
4970 + * see parsing - the commas are handled as operators and not as part of the
4971 + * syntax. when a func call is evaluated, the top comma nodes are used to
4972 + * separate the arguments (this hack prevents complex parsing and complex tnode
4973 + * with variable num of kids, which would force the kids[] to be malloc etc.)
4974 + */
4975 +
4976 +typedef struct snode { /* a single node on an expression tree */
4977 + tnode_kind node_kind ; /* what kind of note this is */
4978 + /* NK_OP node info: op_kind,op,kids */
4979 + int src_pos ; /* starting source code location (op etc) */
4980 + top_kind op_kind ; /* opcode type (unary,bin etc) */
4981 + topcode op ; /* actual opcode: '-' for both unary&bin '-'*/
4982 + struct snode *kids[NODE_MAX_KIDS] ; /* pointers to node's kids */
4983 + tvalue cnst ; /* NK_CONST info - constant value */
4984 + char *name ; /* NK_NAME info - variable name */
4985 + tctype *ctype ; /* NK_CTYPE info - a type */
4986 +
4987 + struct { /* information used during node evaluation */
4988 + int level ; /* evaluation level (0=none, 1=left in x etc)*/
4989 + tvalue v1,v2 ; /* keep last computed operands, etc */
4990 + tval_list vlist ; /* value list for node (used in --> etc ops) */
4991 + int counter ; /* used for counting */
4992 + } eval ;
4993 + } tnode ;
4994 +
4995 +
4996 +DEF bool duel_debug ; /* debugging duel-itself mode */
4997 +DEF bool duel_output_pipe_style ; /* pipe-style output of values */
4998 +
4999 +/* this things are machine dependent stuff */
5000 +
5001 +#define BITS_PER_BYTE 8 /* no of bits in (char) (right. try '9' :-) */
5002 --- gdb/duel/internals.doc
5003 +++ gdb/duel/internals.doc
5004 @@ -0,0 +1,129 @@
5005 +DUEL 1.0x INTERNALS
5006 +This documents some of the basics internal info, and might help porting
5007 +duel. Incomplete and probably badly written. sorry.
5008 +
5009 +Entry points and modules
5010 +--------------------------
5011 +duel_eval_and_parse is entry point into duel, in duel.c
5012 +duel_parse in parse.y does all parsing
5013 +duel_eval in eval.c makes the evaluation
5014 +evalop.c contains low-level evaluation
5015 +misc.c contains misc stuff
5016 +types.c type create/manage
5017 +output.c all output goes thru duel_printf
5018 +output2.c same as output, but support sending eval output to a pipe,
5019 + like the duel.pipe perl script.
5020 +print.c all output of values is done here
5021 +eval.c high level evaluation code (generators)
5022 +evalops.c low level evaluation code (operators)
5023 +error.c handle erros, display error info "nicely"
5024 +
5025 +start reading the code from duel.c, then global.h, then eval.c.
5026 +eval.c is hairy, especially the state-keeping code. The goto's are
5027 +intentional, they convey control better than other constructs.
5028 +
5029 +Types
5030 +------
5031 +A relatively straight-forward system, if you have read code of real C
5032 +compilers. A type is a "graph" with each node being a base type or
5033 +a composition of other types. see global.h and types.c
5034 +
5035 +Value system
5036 +-------------
5037 +also pretty simple, either an LVALUE, which have u.lvalue point to it,
5038 +or an RVALUE, so u.rval_type contains the actual value. There is also
5039 +a special BVALUE hack to hold lvalued bitfields, which is only useful
5040 +is someone implements modifying a bitfield. and there is an FVALUE, which
5041 +is just stored in u.rval_int but has the special value type (it was either
5042 +this or add a new TYPE, i preferred a new value).
5043 +Note the there is no "register" type support. You must read register variables
5044 +as rvalues (duelgdb.c does that). I don't think it is essential, since
5045 +gdb can be used directly to modify such values (this might be a
5046 +problem in watchpoint/cond.breaks however). Also cc -g don't usually keep
5047 +stuff in registers. We could add "SVALUE" for these.
5048 +Bitfields are a pain, but bvalue is really needed, eg for x[..100].bitfield=0
5049 +
5050 +Memory allocation
5051 +-----------------
5052 +go through duel_malloc/duel_free.
5053 +Memory is allocated only for (a) a new node, while parsing, (b) a value pushed
5054 +on stack for x-->y operator (c) duel aliases.
5055 +It is always safe to call duel_free_nodes which free everything except
5056 +for aliases.
5057 +Memory spill can occur in asynchronous interrupts (^C), but they at most
5058 +reflect items moved from one list to another. This isn't too bad.
5059 +
5060 +Interrupts
5061 +----------
5062 +Duel ignores the issues of interrupts, but is written so it can be
5063 +interrupted at any time. Naturally, some memory could be lost if an
5064 +operation is interrupted, since Duel does not setup critical sections.
5065 +However, interrupts will no result in bad internal structures, so it is
5066 +safe to call duel_free_nodes after an interrupt.
5067 +duelgdb.c implements exactly that - interrupts at all times, and cleanup
5068 +using duel_free_nodes.
5069 +
5070 +Parsing
5071 +--------
5072 +yacc is pretty weak, especially when I tried complex ops like x\y#z
5073 +(as a single, 3 val op!). I have up on such things and the syntax is
5074 +pretty clean. Things to watch for are the semicolon nonsense,
5075 +especially with optional-expressions (as in for(a;b;c);), the T hack
5076 +for user types (only fix is to delay decision on (x)(y) till runtime
5077 +or make clearer rules (consider something; (x)(y), do you parse x as a type
5078 +and ignore the possible x:=printf in "something", etc), and the use of ","
5079 +regular op and nodes for function parameters (the parser knows only about
5080 +a single parameter, an exp!).
5081 +
5082 +Search ops
5083 +-----------
5084 +Straight forward stacking in dfs_... in eval.c
5085 +Note things are put in reversed, so root-->(left,right) does what you
5086 +expect. Also linked-lists could be greatly optimized.
5087 +The functionality for ->> (BFS) is already in, all you need is to
5088 +make the stack into a queue by pushing from the other side (really append)
5089 +
5090 +Multi-expressions
5091 +--------------------
5092 +As far as I know, you could save root (in duel.h) and use it to evaluate
5093 +as often as needed (e.g for breakpoints/watchpoints), the internals
5094 +of the nodes hold all eval info. You must reset the expression
5095 +with eval_stop, if u dont eval it to the last value. Also make sure you
5096 +cleanup the dot stack. Aliases (in misc.c) could become scoped, of course.
5097 +
5098 +Interface to the debugger
5099 +-------------------------
5100 +
5101 +What DUEL needs:
5102 +1. A way to access the symbol table for variable names, types, etc.
5103 +2. A way to access the value of a variable, both for read and writes.
5104 +3. A way to call debuggee functions.
5105 +4. A way to get locals of frame n
5106 +5. misc functions, eg memory alloc, entery/exit code
5107 +
5108 +In practice, you will probably take duelgdb.c and modify it until you
5109 +get the "right thing" for your debugger.
5110 +NOTE: duelgdb.c was written from scratch and has *no* GNU code in it.
5111 +
5112 +The most complex issue is types - you must pass names in a tvalue,
5113 +which include a tctype (the C reminds one of a "C" type, not just 'type'
5114 +which is ambiguous). The code to convert gdb types into duel types is
5115 +typical. Watch out for recursive struct pointers (the hash table handles
5116 +these problems), and for partial types, e.g. pointer to struct which
5117 +contains no fields (size zero!).
5118 +
5119 +You can return a BVALUE an LVALUE (preferred) or an RVALUE for a name
5120 +lookup. use RVALUE for names found in registers, and return the actual
5121 +value.
5122 +
5123 +if a frame number is given for symbol lookup, only local variables
5124 +allocated in that frame should be returned. (else return none. don't
5125 +return a global if it exist with the same name, this will make the dot
5126 +stack compute things wrong).
5127 +
5128 +Node that this doesnt help with scoping problems (for duel)- e.g.
5129 +you can't do myfunc.x if x is a static variable in myfunc. There needs to
5130 +be a more complex & general way in the language to specify this (i.e.
5131 +specify a source location in which the variable is visible, AND a frame
5132 +to use if the value is kept on a frame) frame(n).(scope(file,line).x)?
5133 +
5134 --- gdb/duel/misc.c
5135 +++ gdb/duel/misc.c
5136 @@ -0,0 +1,145 @@
5137 +/* DUEL - A Very High Level Debugging Langauge. */
5138 +/* Public domain code */
5139 +/* Written by Michael Golan mg@××××××××××××.edu */
5140 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
5141 +
5142 +/* misc function/library-like */
5143 +
5144 +/*
5145 + * $Log: 10_all_gdb-6.6-duel.patch,v $
5146 + * Revision 1.1 2007/12/29 21:06:06 vapier
5147 + * add DUEL support #199987 by Sergei Golubchik
5148 + *
5149 + * Revision 1.5 93/03/12 05:51:00 mg
5150 + * support output redirection
5151 + *
5152 + * Revision 1.4 93/01/13 16:22:09 mg
5153 + * allow malloc to return int (is a mini symbol on SUN)
5154 + *
5155 + * Revision 1.3 93/01/12 21:52:43 mg
5156 + * moved aliases mgmt here
5157 + * cleanup and set for release
5158 + *
5159 + */
5160 +
5161 +#include "duel.h"
5162 +
5163 +/* like strncpy, but put a zero at to[len] anyway.
5164 + * are copied (hence taking len+1 bytes
5165 + */
5166 +
5167 +FUNC char* strncpyz(char *to,char *from,size_t len)
5168 +{
5169 + strncpy(to,from,len);
5170 + to[len]=0 ;
5171 + return to ;
5172 +}
5173 +
5174 +/* allocate n bytes in the target's space. Used for storing constant
5175 + * strings when they are parsed, and for variables declaration
5176 + * note: on SUN (and others?) gdb claims malloc to return an integer. we
5177 + * accept this (silly but probably no harm done)
5178 + */
5179 +
5180 +FUNC ttarget_ptr duel_alloc_target_space(size_t n)
5181 +{
5182 + tvalue p,f,r,*parms[1] ;
5183 +
5184 + p.val_kind=VK_RVALUE ; /* mk n into a value, to pass as parm */
5185 + p.ctype=ctype_int ;
5186 + p.u.rval_int=n ;
5187 + parms[0]= &p ;
5188 +
5189 + if(!duel_get_target_variable("malloc",-1,&f) ||
5190 + f.ctype->type_kind!=CTK_FUNC ||
5191 + f.ctype->u.kid->type_kind!=CTK_INT && f.ctype->u.kid->type_kind!=CTK_PTR)
5192 + duel_fatal("malloc() function returning a pointer required in target");
5193 +
5194 + duel_target_func_call(&f,parms,1,&r);
5195 + if(r.u.rval_ptr==NULL) duel_fatal("target's malloc() failed");
5196 + return r.u.rval_ptr ;
5197 +}
5198 +
5199 +PROC duel_free_val_list(tval_list *l) /*free a val list and mark list empty */
5200 +{
5201 + tval_lcell *cell,*next ;
5202 + for(cell=l->head ; cell!=NULL ; cell=next ) {
5203 + next=cell->next ;
5204 + duel_free(cell);
5205 + }
5206 + l->head=l->tail=NULL ;
5207 +}
5208 +
5209 +/* free all the memory allocated in the parse tree from node */
5210 +
5211 +PROC duel_free_nodes(tnode *n)
5212 +{
5213 + int i;
5214 + if(!n) return ;
5215 + for(i=0 ; i<NODE_MAX_KIDS ; i++)
5216 + duel_free_nodes(n->kids[i]);
5217 + duel_free_val_list(&n->eval.vlist);
5218 + duel_free(n);
5219 +}
5220 +
5221 +
5222 +
5223 +/* Aliases management */
5224 +
5225 +typedef struct sduel_var { /* an alias */
5226 + char *name ;
5227 + tvalue val ;
5228 + struct sduel_var *next ;
5229 + } tduel_var ;
5230 +tduel_var *duel_vars_head ;
5231 +
5232 +/* find the value of a duel variable, if exist (else return null */
5233 +
5234 +FUNC tvalue* duel_find_alias(char *name)
5235 +{
5236 + tduel_var *p ;
5237 + for(p=duel_vars_head ; p ; p=p->next) {
5238 + if(strcmp(name,p->name)==0) return(&p->val);
5239 + }
5240 + return NULL ;
5241 +}
5242 +
5243 +/* set a value of a duel alias. Create var as needed */
5244 +
5245 +PROC duel_set_alias(char *name,tvalue *v)
5246 +{
5247 + tduel_var *p ;
5248 + tvalue *found = duel_find_alias(name) ;
5249 + if(found!=NULL) *found= *v ;
5250 + else {
5251 + p=duel_malloc(sizeof(tduel_var)) ;
5252 + p->next=duel_vars_head ;
5253 + p->val= *v ;
5254 + p->name=name ;
5255 + duel_vars_head=p ;
5256 + }
5257 +}
5258 +
5259 +PROC duel_clear_aliases(void) /* clear all defined aliases */
5260 +{
5261 + tduel_var *p=duel_vars_head ;
5262 + while(p) {
5263 + tduel_var *q=p ;
5264 + p=p->next ;
5265 + duel_free(q);
5266 + }
5267 + duel_vars_head=0 ;
5268 +}
5269 +
5270 +PROC duel_show_aliases(void)
5271 +{
5272 + tduel_var *p ;
5273 + if(!duel_vars_head) duel_printf("No aliases defined\n");
5274 + else {
5275 + duel_printf("Aliases table:\n");
5276 + for(p=duel_vars_head ; p ; p=p->next) {
5277 + duel_printf("%s: ",p->name);
5278 + duel_print_value(&p->val);
5279 + }
5280 + }
5281 +}
5282 +
5283 +
5284 +
5285 --- gdb/duel/output.c
5286 +++ gdb/duel/output.c
5287 @@ -0,0 +1,53 @@
5288 +/* DUEL - A Very High Level Debugging Langauge. */
5289 +/* Public domain code */
5290 +/* Written by Michael Golan mg@××××××××××××.edu */
5291 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
5292 +
5293 +/* This module supports i/o for duel. Normally output goes to stdout,
5294 + * but it could be piped out instead.
5295 + * this module support minimal duel output w/o pipes. output2.c which
5296 + * support piped i/o is still an alpha version.
5297 + */
5298 +
5299 +#include <stdarg.h> /* for duel_printf */
5300 +#include "duel.h"
5301 +
5302 +/* output functions:
5303 + * duel_printf all duel output goes thru this - like printf()
5304 + * duel_flush used by duel to flush the output.
5305 + */
5306 +
5307 +PROC duel_printf(char *fmt, ...) /* like printf, but for duel output */
5308 +{
5309 + va_list args;
5310 + va_start(args, fmt);
5311 + vfprintf(stdout,fmt,args);
5312 + va_end(args);
5313 +}
5314 +
5315 +PROC duel_flush(void) /* flush out output from duel */
5316 +{
5317 + fflush(stdout);
5318 +}
5319 +
5320 +/* tells us the output is "directable" now. s is the expression
5321 + * being evaluated for this */
5322 +
5323 +PROC duel_redirectable_output_start(char *s)
5324 +{
5325 + if(s) duel_flush(); /* if(s) is always true. prevents warnings ...*/
5326 +}
5327 +
5328 +PROC duel_redirectable_output_end(void)
5329 +{
5330 + duel_flush();
5331 +}
5332 +
5333 +PROC duel_redirectable_output_abort(void)
5334 +{
5335 + duel_flush();
5336 +}
5337 +
5338 +PROC duel_redirectable_output_init(void)
5339 +{
5340 +}
5341 --- gdb/duel/output2.c
5342 +++ gdb/duel/output2.c
5343 @@ -0,0 +1,141 @@
5344 +/* DUEL - A Very High Level Debugging Langauge. */
5345 +/* Public domain code */
5346 +/* Written by Michael Golan mg@××××××××××××.edu */
5347 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
5348 +
5349 +/* This module supports i/o for duel. Normally output goes to stdout,
5350 + * but it could be piped out instead.
5351 + * Still alpha version.
5352 + * HOW: if file duel.pipe exists, it is opened with stdin/out piped
5353 + * here. results of expressions evaluations are sent to the pipe
5354 + * with $$$START $$$END $$$ABORT and $$$SYM/$$$VAL. The pipe's
5355 + * output is passed back here and is printed to stdout until
5356 + * a $$$DONE is received. The pipe is normally a perl script,
5357 + * that can processes the output at a symbolic level.
5358 + */
5359 +
5360 +#include <stdarg.h> /* for duel_printf */
5361 +#include <sys/types.h> /* for stat() */
5362 +#include <sys/stat.h> /* " */
5363 +#include <fcntl.h> /* for popen impl. */
5364 +#include <signal.h> /* " */
5365 +
5366 +#include "duel.h"
5367 +
5368 +/* output functions:
5369 + * duel_printf all duel output goes thru this - like printf()
5370 + * duel_flush used by duel to flush the output.
5371 + * duel_redirectable_output_start(s) - indicate start of output for exp s that
5372 + * can be redirected to a pipe.
5373 + * duel_redirectable_output_end() - indicate end of that output.
5374 + * duel_redirectable_output_abort() - indicate output was aborted (error,intr)
5375 + *
5376 + * duel_redirectable_output_init() - called to init at first duel use.
5377 + */
5378 +
5379 +static FILE *duel_outf = stdout ; /* current output stream */
5380 +static FILE *poutf,*pinf ; /* pipe i/o streams */
5381 +
5382 +#define PIPE_CMD "./duel.pipe" /* command to pipe into */
5383 +
5384 +bool bidir_popen(void)
5385 +{
5386 + int pout[2],pin[2]; /* pin[0] is my input, pout[1] my output */
5387 + int pid;
5388 + struct stat s ;
5389 +
5390 + if(stat(PIPE_CMD,&s)!=0 || !(s.st_mode & S_IEXEC)) return FALSE;
5391 + if (pipe(pout) < 0 || pipe(pin) < 0) return FALSE ;
5392 +
5393 + if ((pid = fork()) == 0) {
5394 + signal(SIGINT, SIG_IGN);
5395 + signal(SIGQUIT, SIG_IGN);
5396 + dup2(pout[0],0); dup2(pin[1],1);
5397 + close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]);
5398 + execl(PIPE_CMD, PIPE_CMD, NULL);
5399 + _exit(127);
5400 + }
5401 + close(pout[0]); close(pin[1]);
5402 + if (pid == -1) return FALSE;
5403 + pinf =fdopen(pin[0], "r");
5404 + poutf=fdopen(pout[1],"w");
5405 + if(fcntl(pin[0],F_SETFL,O_NDELAY) < 0) return FALSE ;
5406 + return pinf!=NULL && poutf!=NULL ;
5407 +}
5408 +
5409 +
5410 +PROC duel_printf(char *fmt, ...) /* like printf, but for duel output */
5411 +{
5412 + va_list args;
5413 + va_start(args, fmt);
5414 + vfprintf(duel_outf,fmt,args);
5415 + va_end(args);
5416 +}
5417 +
5418 +PROC duel_flush(void) /* flush out output from duel */
5419 +{
5420 + char s[256];
5421 + fflush(duel_outf);
5422 + while(pinf && fgets(s,sizeof(s),pinf)) /* note pinf is non blocking */
5423 + printf("%s",s);
5424 +}
5425 +
5426 +LPROC duel_waitpipe(bool abort) /* wait for pipe to finish working */
5427 +{
5428 + char s[256];
5429 + if(abort) duel_printf("$$$ABORT\n"); /* write termination mesg */
5430 + else duel_printf("$$$DONE\n");
5431 + fflush(duel_outf);
5432 + fcntl(fileno(pinf),F_SETFL,0); /* restore blocking for pipe */
5433 + while(fgets(s,sizeof(s),pinf)!=NULL && strcmp(s,"$$$DONE\n")!=0)
5434 + if(!abort) printf("%s",s);
5435 + fcntl(fileno(pinf),F_SETFL,O_NDELAY);
5436 + if(abort) printf("\n");
5437 +}
5438 +
5439 +/* tells us the output is "directable" now. s is the expression
5440 + * being evaluated for this */
5441 +
5442 +PROC duel_redirectable_output_start(char *s)
5443 +{
5444 + duel_flush();
5445 + if(poutf) {
5446 + duel_flush();
5447 + duel_outf=poutf ;
5448 + duel_output_pipe_style=1 ;
5449 + duel_printf("$$$START: %s\n",s);
5450 + duel_flush();
5451 + }
5452 +}
5453 +
5454 +PROC duel_redirectable_output_end(void)
5455 +{
5456 + duel_flush();
5457 + if(poutf && duel_outf == poutf) {
5458 + duel_waitpipe(FALSE);
5459 + duel_outf=stdout ;
5460 + duel_output_pipe_style=0 ;
5461 + }
5462 +}
5463 +
5464 +PROC duel_redirectable_output_abort(void)
5465 +{
5466 + if(poutf && duel_outf == poutf) {
5467 + duel_waitpipe(TRUE);
5468 + duel_outf=stdout ;
5469 + duel_output_pipe_style=0 ;
5470 + }
5471 + duel_flush();
5472 +}
5473 +
5474 +PROC duel_redirectable_output_init(void)
5475 +{
5476 + /* open the duel pipe, if available. Verify that duel.pipe
5477 + * as an existing executable, because popen() does not, and can
5478 + * later fail with pipe signal!
5479 + */
5480 + if(bidir_popen()) {
5481 + duel_printf("Duel results directed to pipe \"duel.pipe\"\n");
5482 + }
5483 + else poutf=pinf=NULL ;
5484 +}
5485 --- gdb/duel/parse.y
5486 +++ gdb/duel/parse.y
5487 @@ -0,0 +1,940 @@
5488 +%{
5489 +/* DUEL - A Very High Level Debugging Langauge. */
5490 +/* Public domain code */
5491 +/* Written by Michael Golan mg@××××××××××××.edu */
5492 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
5493 +
5494 +/* this module contains the duel parser, in yacc, plus a simple lexer.
5495 + * the lexer is slow, but duel expressions are tiny.
5496 + * the parsing generate an AST with essentially no type checking.
5497 + * names are only looked up when the refer explicitly to types. This forces
5498 + * the use of "T" before user types. You can't parse (x)(y) correctly, if
5499 + * you want the node to contain "cast" or "func", without knowing the x is
5500 + * not a type. (It is interesting to note that (x *)(y) is clearly a cast,
5501 + * but it can not be parsed without a context sensitive grammer!).
5502 + *
5503 + * Version 1.1 now accept (x) as a type cast, so (print)("hi") fails, but
5504 + * (uint)z is ok. Also accepted is (uint*)z. T is still required in sizeof
5505 + * and in variable declarations. A side effect was making "sizeof x" illegal
5506 + * (since then sizeof(x)-1 was parsed sizeof((x)-1) with (x) a cast), so
5507 + * now sizeof(x) must be used. Note that in C, sizoef(x)++ is acceptable,
5508 + * and the '++' operate on x (which is optimized out!) This can be confusing.
5509 + *
5510 + * yacc is also not smart enough to recognize e.g. "if(e) e ; else e" as
5511 + * a special case (redundent ';'). I hacked this in the lexer. It should
5512 + * reduce the trouble with C->duel coding. (It can also be done for {e1}e2,
5513 + * in some speical cases, e.g. if e2 is a keyword, or a name or a unary op,
5514 + * but this can confuse some people, e.g. in {i}[5], so I left it alone.)
5515 + * Finally, the %/ operator is accepted as "#/" and "%%" as "#", to those
5516 + * who wish to keep gdb with # comments.
5517 + * memory: nodes are alloc'ed dynamically. a parsing error loose so-far
5518 + * allocated nodes, which is normally acceptable (yyerror can probably hack
5519 + * into the yacc stack to release them.)
5520 + */
5521 +
5522 +/*
5523 + * $Log: 10_all_gdb-6.6-duel.patch,v $
5524 + * Revision 1.1 2007/12/29 21:06:06 vapier
5525 + * add DUEL support #199987 by Sergei Golubchik
5526 + *
5527 + * Revision 1.14 93/03/17 11:04:12 mg
5528 + * fixed (t*)x bug, was parsed as (t**)x
5529 + *
5530 + * Revision 1.13 93/03/12 06:15:09 mg
5531 + * modified unary's a bit - cosmetics
5532 + * support (x)y as type cast
5533 + * support (x*)y as type cast
5534 + * replace sizeof exp with sizeof(exp) to prevent clash with above
5535 + * more cosmetics, including yyerror abort, tuint for uint.
5536 + * takes anything after |> to be comment (pipe command really)
5537 + *
5538 + *
5539 + * Revision 1.12 93/02/27 06:06:09 mg
5540 + * added signed char parsing.
5541 + *
5542 + * Revision 1.11 93/02/23 19:15:38 mg
5543 + * improved escaped char support
5544 + *
5545 + * Revision 1.10 93/02/03 21:49:34 mg
5546 + * bug fix - yyerror calls now abort parsing (eg called from lex)
5547 + *
5548 + * Revision 1.9 93/01/12 21:53:07 mg
5549 + * cleanup and set for release
5550 + *
5551 + * Revision 1.8 93/01/07 00:14:33 mg
5552 + * add &&/ ||/
5553 + * fixed parsing of trailing ';' was a mess.
5554 + * ignore ';' before 'else' and '}' w/warning.
5555 + *
5556 + * Revision 1.7 93/01/03 07:31:01 mg
5557 + * error reporting
5558 + *
5559 + * Revision 1.6 92/12/24 23:35:50 mg
5560 + * began src pos support
5561 + *
5562 + * Revision 1.5 92/10/19 15:08:02 mg
5563 + * frames() added; bug fixed
5564 + *
5565 + * Revision 1.4 92/10/14 02:06:32 mg
5566 + * misc/change casting parsing/variable def.
5567 + *
5568 + * Revision 1.3 92/09/16 11:09:39 mg
5569 + * add typedef/struct support, const strings
5570 + * cleanup s/r conflict by setting ELSE to a token. explained some stuff in
5571 + * comments.
5572 + *
5573 + * Revision 1.2 92/09/15 06:10:46 mg
5574 + * cosmetics and new ops: x@y, for() while() ..x and x..
5575 + * generic '.' and '_' support. x@y. '..x' and 'x..'. while(), for(), ?:
5576 + *
5577 + */
5578 +
5579 +#include "duel.h"
5580 +
5581 +static char *inputstr ; /* pointer to string being parsed */
5582 +static char *lexptr ; /* current lexer pointer into input str */
5583 +static tnode *root ; /* result of parsing stored here */
5584 +
5585 +/* pick unique names for globals of yacc. gdb has other parsers! */
5586 +#define yyparse duel_yyparse
5587 +#define yylex duel_yylex
5588 +#define yyerror duel_yyerror
5589 +#define yylval duel_yylval
5590 +#define yychar duel_yychar
5591 +#define yydebug duel_yydebug
5592 +#define yypact duel_yypact
5593 +#define yyr1 duel_yyr1
5594 +#define yyr2 duel_yyr2
5595 +#define yydef duel_yydef
5596 +#define yychk duel_yychk
5597 +#define yypgo duel_yypgo
5598 +#define yyact duel_yyact
5599 +#define yyexca duel_yyexca
5600 +#define yyerrflag duel_yyerrflag
5601 +#define yynerrs duel_yynerrs
5602 +#define yyps duel_yyps
5603 +#define yypv duel_yypv
5604 +#define yys duel_yys
5605 +#define yystate duel_yystate
5606 +#define yytmp duel_yytmp
5607 +#define yyv duel_yyv
5608 +#define yyval duel_yyval
5609 +#define yylloc duel_yylloc
5610 +
5611 +typedef struct { /* token info for operators */
5612 + int src_pos ; /* source position */
5613 + topcode opcode ; /* opcode */
5614 + } topinfo ;
5615 +
5616 +typedef struct { /* token info for symbols */
5617 + int src_pos ; /* source position */
5618 + char *name ; /* symbol */
5619 + } tnameinfo ;
5620 +
5621 +/* these are used as operators to mknode_... when source location is unknown*/
5622 +static topinfo seq_op = { -1,';' } ; /* sequencing operator, src pos unkown */
5623 +static topinfo decl_op = { -1,OP_DECL } ; /* declare var op, src pos unkown */
5624 +
5625 +/* local prototypes. */
5626 +LPROC yyerror(char *msg);
5627 +LFUNC int yylex (void);
5628 +
5629 +LPROC push_type(char desc) ;
5630 +LPROC push_type_int(char desc,tnode *n) ;
5631 +LFUNC bool pop_type(char *desc,int *size);
5632 +
5633 +LFUNC tnode* mknode_op(top_kind,topinfo opinfo,tnode*,tnode*,tnode*,tnode*);
5634 +LFUNC tnode* mknode_const(int src_pos,tctype *ctype);
5635 +LFUNC tnode* mknode_ctype(tctype *ctype);
5636 +LFUNC tnode* mknode_name(tnameinfo nameinfo);
5637 +LFUNC tnode* mknode_modified_ctype(tctype *base);
5638 +
5639 +#define mknode_post_unary(op,n) (mknode_op(OPK_POST_UNARY,op,n, 0, 0,0))
5640 +#define mknode_unary(op,n) (mknode_op(OPK_UNARY, op,n, 0, 0,0))
5641 +#define mknode_sunary(op,n) (mknode_op(OPK_SUNARY, op,n, 0, 0,0))
5642 +#define mknode_bin(op,n1,n2) (mknode_op(OPK_BIN, op,n1,n2,0,0))
5643 +#define mknode_sbin(op,n1,n2) (mknode_op(OPK_SBIN, op,n1,n2,0,0))
5644 +#define mknode_tri(op,n1,n2,n3) (mknode_op(OPK_TRI, op,n1,n2,n3,0))
5645 +
5646 +static tctype *decl_tbase ; /* used for variables decl */
5647 +
5648 +/* #define YYDEBUG 1 */
5649 +
5650 +%}
5651 +
5652 +%union
5653 + {
5654 + tnode *node ; /* node pointer for constructed exp tree */
5655 + tctype *ctype; /* type for type nodes */
5656 + tnameinfo nameinfo ; /* a name/symbol + src position */
5657 + topinfo opinfo; /* keyword/operator + source position */
5658 + }
5659 +
5660 +%type <node> start duel_inp duel_exp exp type nameexp sm_exp oexp
5661 +%type <node> all_decls vars_decl var_decl name_decl1 name_decl
5662 +%type <ctype> typebase
5663 +%type <nameinfo> name
5664 +
5665 +%token <node> T_CONST
5666 +%token <nameinfo> T_SYM
5667 +%token <opinfo> T_ASSIGN T_DEFVAR
5668 +
5669 +
5670 +%token <opinfo> T_CHAR T_INT T_SHORT T_LONG T_UNSIGNED T_FLOAT T_DOUBLE T_VOID
5671 +%token <opinfo> T_STRUCT T_UNION T_ENUM T_SIZEOF T_TYPEDEF_INDICATOR T_SIGNED
5672 +
5673 +%token <opinfo> T_IF T_ELSE T_FOR T_WHILE
5674 +%token <opinfo> ';' ',' '=' '?' '|' '^' '&' '<' '>' '+' '-' '*' '/' '%'
5675 +%token <opinfo> '.' '[' ']' '(' ')' '{' '}' '#' '@' '!' '~'
5676 +%token <opinfo> T_OR T_AND T_RSH T_LSH T_INC T_DEC T_COUNT T_FRAME T_TO
5677 +%token <opinfo> T_DFS T_BFS T_ARROW T_OSEL T_CSEL T_IMP T_ANDL T_ORL
5678 +%token <opinfo> T_EQ T_NE T_EQQ T_NEQ T_LE T_GE T_LSQ T_GTQ T_LEQ T_GEQ
5679 +
5680 +%left ';'
5681 +%right STMT T_ELSE
5682 +%right T_IMP
5683 +%right ','
5684 +%right '=' T_ASSIGN T_DEFVAR
5685 +%right '?'
5686 +%left T_OR T_ORL
5687 +%left T_AND T_ANDL
5688 +%left '|'
5689 +%left '^'
5690 +%left '&'
5691 +%left T_EQ T_NE T_EQQ T_NEQ
5692 +%left '<' '>' T_LE T_GE T_LSQ T_GTQ T_LEQ T_GEQ
5693 +%nonassoc T_TO
5694 +%left T_LSH T_RSH
5695 +%left '+' '-'
5696 +%left '*' '/' '%'
5697 +%right UNARY '!' '~' T_INC T_DEC T_COUNT T_FRAME
5698 +%left T_DFS T_BFS T_POS T_ARROW '.' '[' ']' '(' ')' '{' '}' '#' '@' T_OSEL T_CSEL
5699 +%%
5700 +
5701 +start : duel_inp { root=$1 ; }
5702 + ;
5703 +
5704 +duel_inp : all_decls
5705 + | all_decls ';'
5706 + | all_decls ';' duel_exp { $$=mknode_sbin($2,$1,$3);}
5707 + | duel_exp
5708 + ;
5709 +duel_exp : sm_exp
5710 + | sm_exp ';' { $$=mknode_sbin($2,$1,0); }
5711 + ;
5712 +all_decls: vars_decl
5713 + | all_decls ';' vars_decl { $$=mknode_sbin($2,$1,$3); }
5714 + ;
5715 +
5716 +vars_decl: typebase { decl_tbase=$1 ; } var_decl { $$=$3 ; }
5717 + ;
5718 +var_decl : name_decl1
5719 + | var_decl ',' name_decl1 { $$=mknode_sbin(seq_op,$1,$3); }
5720 + ;
5721 +
5722 +name_decl1: name_decl { $$=mknode_sbin(decl_op,$1,
5723 + mknode_modified_ctype(decl_tbase)); }
5724 + ;
5725 +
5726 +name_decl : '(' name_decl ')' { $$=$2 ; }
5727 + | '(' name_decl ')' '(' ')' { $$=$2 ; push_type('('); }
5728 + | '*' name_decl { $$=$2 ; push_type('*'); }
5729 + | name_decl '[' T_CONST ']' { $$=$1 ; push_type_int('[',$3); }
5730 + | nameexp
5731 + ;
5732 +
5733 +/* Statements - not really, these are expressions too!
5734 + Notes: for(;;) oexp - will create lots of shift/reduce conflicts,
5735 + 'for(;;;)' and 'for(;;) exp' are specified
5736 + instead and yacc handle this as a "standard" s/r.
5737 + the only diff is yacc dont complain on these!
5738 + if() - same comments as above, plus, we prevent meaningless
5739 + if's like in C: ' if(x); else;' - a useless statement.
5740 + */
5741 +exp : T_IF '(' exp ')' exp %prec STMT { $$=mknode_tri($1,$3,$5,0); }
5742 + | T_IF '(' exp ')' exp T_ELSE %prec STMT
5743 + { $$=mknode_tri($1,$3,$5,0); }
5744 + | T_IF '(' exp ')' T_ELSE exp %prec STMT
5745 + { $$=mknode_tri($1,$3,0,$6); }
5746 + | T_IF '(' exp ')' exp T_ELSE exp %prec STMT
5747 + { $$=mknode_tri($1,$3,$5,$7); }
5748 +
5749 + | T_FOR '(' oexp ';' exp ';' oexp ')' exp %prec STMT
5750 + { $$=mknode_op(OPK_QUAD,$1,$3,$5,$7,$9); }
5751 + | T_FOR '(' oexp ';' exp ';' oexp ')' %prec STMT
5752 + { $$=mknode_op(OPK_QUAD,$1,$3,$5,$7,0); }
5753 + | T_WHILE '(' exp ')' exp %prec STMT
5754 + { $$=mknode_sbin($1,$3,$5); }
5755 + | T_WHILE '(' exp ')' %prec STMT
5756 + { $$=mknode_sbin($1,$3,0); }
5757 + ;
5758 +
5759 +/* Expressions */
5760 +
5761 +exp : '*' exp %prec UNARY { $$=mknode_unary( $1,$2); }
5762 + | '&' exp %prec UNARY { $$=mknode_unary( $1,$2); }
5763 + | '-' exp %prec UNARY { $$=mknode_unary( $1,$2); }
5764 + | '!' exp { $$=mknode_unary( $1,$2); }
5765 + | '~' exp { $$=mknode_unary( $1,$2); }
5766 + | T_COUNT exp { $$=mknode_sunary($1,$2); }
5767 + | T_ANDL exp { $$=mknode_sunary($1,$2); }
5768 + | T_ORL exp { $$=mknode_sunary($1,$2); }
5769 + | T_INC exp { $$=mknode_unary( $1,$2); }
5770 + | T_DEC exp { $$=mknode_unary( $1,$2); }
5771 + | exp T_INC { $$=mknode_post_unary($2,$1); }
5772 + | exp T_DEC { $$=mknode_post_unary($2,$1); }
5773 + | T_SIZEOF '(' type ')' { $$=mknode_sunary($1,$3); }
5774 + | T_SIZEOF '(' exp ')' { $$=mknode_unary($1,$3); }
5775 + | T_FRAME '(' exp ')' %prec UNARY { $$=mknode_unary( $1,$3); }
5776 + ;
5777 +
5778 +exp : exp T_DFS exp { $$=mknode_sbin($2,$1,$3); }
5779 + | exp T_BFS exp { $$=mknode_sbin($2,$1,$3); }
5780 +
5781 + | exp '#' nameexp { $$=mknode_sbin($2,$1,$3); }
5782 + | exp '@' exp { $$=mknode_sbin($2,$1,$3); }
5783 + | exp T_ARROW exp { $$=mknode_sbin($2,$1,$3); }
5784 + | exp '.' exp { $$=mknode_sbin($2,$1,$3); }
5785 + | exp '[' exp ']' { $$=mknode_bin( $2,$1,$3); }
5786 + | exp T_OSEL exp T_CSEL { $$=mknode_sbin($2,$1,$3); }
5787 + | exp '(' oexp ')' %prec '.' { $$=mknode_op(OPK_FUNC,$2,$1,$3,0,0); }
5788 + | '(' sm_exp ')' { $$=mknode_unary($1,$2); }
5789 + | '{' sm_exp '}' { $$=mknode_unary($1,$2); }
5790 + ;
5791 +
5792 +exp : '(' type ')' exp %prec UNARY
5793 + { $$=mknode_op(OPK_CAST,$1,$2,$4,0,0); }
5794 +/* HACKS to handle the most common cast cases with a typedef, without
5795 + * requiring a 'T'. This code breaks (printf)("hi"), which returns the
5796 + * error "printf not a typedef", but otherwise it works ok.
5797 + * It might be confusing since "(uint *)p" works but "(uint (*)())p" wont,
5798 + * but it seems that (uint*)p, (uint)x are the most common, and users get
5799 + * confused w/o them.
5800 + * The code below works essentially with context-sensitive parsing!
5801 + * see the hacked %prec for nameexp which prevents yacc s/r warning!
5802 + */
5803 + | '(' name ')' exp %prec UNARY {
5804 + tctype *t=duel_get_target_typedef($2.name);
5805 + if(t==NULL) yyerror("not a typedef name");
5806 + $$=mknode_op(OPK_CAST,$1,mknode_ctype(t),$4,0,0); }
5807 + | '(' name '*' type_mod ')' exp %prec UNARY {
5808 + tctype *t=duel_get_target_typedef($2.name);
5809 + if(t==NULL) yyerror("not a typedef name");
5810 + push_type('*');
5811 + $$=mknode_op(OPK_CAST,$1,mknode_modified_ctype(t),$6,0,0); }
5812 + ;
5813 +
5814 + /* Bin ops in decreasing precedence order: */
5815 +
5816 +exp : exp '*' exp { $$=mknode_bin($2,$1,$3); }
5817 + | exp '/' exp { $$=mknode_bin($2,$1,$3); }
5818 + | exp '%' exp { $$=mknode_bin($2,$1,$3); }
5819 + | exp '+' exp { $$=mknode_bin($2,$1,$3); }
5820 + | exp '-' exp { $$=mknode_bin($2,$1,$3); }
5821 + | exp T_LSH exp { $$=mknode_bin($2,$1,$3); }
5822 + | exp T_RSH exp { $$=mknode_bin($2,$1,$3); }
5823 + | exp T_EQ exp { $$=mknode_bin($2,$1,$3); }
5824 + | exp T_NE exp { $$=mknode_bin($2,$1,$3); }
5825 + | exp T_EQQ exp { $$=mknode_bin($2,$1,$3); }
5826 + | exp T_NEQ exp { $$=mknode_bin($2,$1,$3); }
5827 + | exp T_LE exp { $$=mknode_bin($2,$1,$3); }
5828 + | exp T_GE exp { $$=mknode_bin($2,$1,$3); }
5829 + | exp T_LEQ exp { $$=mknode_bin($2,$1,$3); }
5830 + | exp T_GEQ exp { $$=mknode_bin($2,$1,$3); }
5831 + | exp '<' exp { $$=mknode_bin($2,$1,$3); }
5832 + | exp '>' exp { $$=mknode_bin($2,$1,$3); }
5833 + | exp T_LSQ exp { $$=mknode_bin($2,$1,$3); }
5834 + | exp T_GTQ exp { $$=mknode_bin($2,$1,$3); }
5835 + | exp '&' exp { $$=mknode_bin($2,$1,$3); }
5836 + | exp '|' exp { $$=mknode_bin($2,$1,$3); }
5837 + | exp '^' exp { $$=mknode_bin($2,$1,$3); }
5838 + | exp T_AND exp { $$=mknode_sbin($2,$1,$3); }
5839 + | exp T_OR exp { $$=mknode_sbin($2,$1,$3); }
5840 + ;
5841 +
5842 +exp : exp '?' exp ':' exp %prec '?'
5843 + { $$=mknode_tri($2,$1,$3,$5); }
5844 + ;
5845 +
5846 +exp : exp '=' exp { $$=mknode_bin($2,$1,$3); }
5847 + | exp T_ASSIGN exp { $$=mknode_op(OPK_ASSIGN,$2, $1,$3,0,0); }
5848 + |nameexp T_DEFVAR exp { $$=mknode_sbin($2,$1,$3); }
5849 + ;
5850 +
5851 + /* generating expressions */
5852 +
5853 +exp : exp T_TO exp { $$=mknode_sbin($2,$1,$3); }
5854 + | T_TO exp { $$=mknode_sbin($1, 0,$2); }
5855 + | exp T_TO { $$=mknode_sbin($2,$1, 0); }
5856 + | exp ',' exp { $$=mknode_sbin($2,$1,$3); }
5857 + | exp T_IMP exp { $$=mknode_sbin($2,$1,$3); }
5858 + ;
5859 +
5860 +sm_exp : sm_exp ';' exp { $$=mknode_sbin($2,$1,$3); }
5861 + | exp
5862 + ;
5863 +
5864 +oexp : exp /* optional expression, eg in for() */
5865 + | { $$=0 ; }
5866 + ;
5867 +
5868 +exp : T_CONST ;
5869 +exp : nameexp ;
5870 + /* convert a string input (name) into an expression.
5871 + * precedence of '+' is a hack to make the special case
5872 + * of (x*)(y) parsed as a cast, without shift/reduce conflict
5873 + *(this would work the same w/o the '+' but gives warning)
5874 + */
5875 +nameexp : name %prec '+' { $$=mknode_name($1) ; } ;
5876 +
5877 +type : typebase type_mod { $$=mknode_modified_ctype($1); }
5878 + ;
5879 +/* type_mod has no value. bison warning is meaningless. I cant find a way
5880 + * to shut it up
5881 + */
5882 +type_mod: '(' type_mod ')'
5883 + | '(' type_mod ')' '(' ')' { push_type('('); }
5884 + | '*' type_mod { push_type('*'); }
5885 + | type_mod '[' T_CONST ']' { push_type_int('[',$3); }
5886 + |
5887 + ;
5888 +
5889 +
5890 +/* note that names are evaluated at runtime. hence (name)(x) is ambigious
5891 + * as either a function call or a cast.
5892 + * We could identify a typedef 'name' as such and return a special token from
5893 + * the lexr, but this will make 'x.(5+y)' illegal if y is both a field and
5894 + * a typedef (Note that gdb's own code include such things).
5895 + *
5896 + * there is a complex solution, that keeps the the casting as a syntax tree,
5897 + * and compute ctype at runtime, too. However, we want to compute all types at
5898 + * parse time. Out solution forces the reserved word T_TYPEDEF_INDICATOR to
5899 + * appear before any typedef name. (the reserved word is normally just 'T')
5900 + * example: instead of '(list *) x' use in duel: '(T list *) x'
5901 + */
5902 +
5903 +typebase: T_TYPEDEF_INDICATOR name {
5904 + $$=duel_get_target_typedef($2.name);
5905 + if($$==NULL) {
5906 + tvalue v;
5907 + if(duel_get_target_variable($2.name,-1,&v)) $$=v.ctype;
5908 + else yyerror("not a typedef name");
5909 + }
5910 + }
5911 + ;
5912 +
5913 +typebase: T_CHAR { $$ = ctype_char; }
5914 + | T_SIGNED T_CHAR { $$ = ctype_schar; }
5915 + | T_UNSIGNED T_CHAR { $$ = ctype_uchar; }
5916 + | T_INT { $$ = ctype_int; }
5917 + | T_UNSIGNED { $$ = ctype_uint; }
5918 + | T_UNSIGNED T_INT { $$ = ctype_uint; }
5919 + | T_LONG { $$ = ctype_long; }
5920 + | T_LONG T_INT { $$ = ctype_long; }
5921 + | T_UNSIGNED T_LONG { $$ = ctype_ulong; }
5922 + | T_UNSIGNED T_LONG T_INT { $$ = ctype_ulong; }
5923 + | T_LONG T_LONG { $$ = ctype_longlong; }
5924 + | T_LONG T_LONG T_INT { $$ = ctype_longlong; }
5925 + | T_UNSIGNED T_LONG T_LONG { $$ = ctype_ulonglong; }
5926 + | T_UNSIGNED T_LONG T_LONG T_INT { $$ = ctype_ulonglong; }
5927 + | T_SHORT { $$ = ctype_short; }
5928 + | T_SHORT T_INT { $$ = ctype_short; }
5929 + | T_UNSIGNED T_SHORT { $$ = ctype_ushort; }
5930 + | T_UNSIGNED T_SHORT T_INT { $$ = ctype_ushort; }
5931 + | T_FLOAT { $$ = ctype_float ; }
5932 + | T_DOUBLE { $$ = ctype_double; }
5933 + | T_VOID { $$ = ctype_void; }
5934 + | T_STRUCT name
5935 + { $$ = duel_get_target_struct_tag($2.name);
5936 + if($$==NULL) yyerror("not a struct tag"); }
5937 + | T_UNION name
5938 + { $$ = duel_get_target_union_tag($2.name);
5939 + if($$==NULL) yyerror("not a union tag"); }
5940 + | T_ENUM name
5941 + { $$ = duel_get_target_enum_tag($2.name);
5942 + if($$==NULL) yyerror("not an enum tag"); }
5943 + ;
5944 +
5945 +name : T_SYM ;
5946 +%%
5947 +
5948 +static struct stoken { /* all opcodes we recognize */
5949 + char *opstr ; /* op code as a string */
5950 + int token ; /* token to return to yacc */
5951 + int opcode ; /* opcode value associated with the token */
5952 + } tokens[] = { /* the special tokens, longer ones 1st! */
5953 + {">>=",T_ASSIGN, OP_RSH},
5954 + {"<<=",T_ASSIGN, OP_LSH},
5955 + {"-->",T_DFS, OP_DFS},
5956 + {"->>",T_BFS, OP_BFS},
5957 + {"==?", T_EQQ, OP_EQQ},
5958 + {"!=?", T_NEQ, OP_NEQ},
5959 + {"<=?", T_LEQ, OP_LEQ},
5960 + {">=?", T_GEQ, OP_GEQ},
5961 + {"&&/", T_ANDL, OP_AND},
5962 + {"||/", T_ORL, OP_OR},
5963 +
5964 + {"<?", T_LSQ, OP_LSQ},
5965 + {">?", T_GTQ, OP_GTQ},
5966 + {"#/", T_COUNT, '#' },
5967 + {"%/", T_COUNT, '#' }, /* gdb insists to recognize # as start of comma!*/
5968 + {"%%", '#', '#' }, /* same. so %/ for #/ and %% for #. not doc!*/
5969 + {"+=", T_ASSIGN, '+'},
5970 + {"-=", T_ASSIGN, '-'},
5971 + {"*=", T_ASSIGN, '*'},
5972 + {"/=", T_ASSIGN, '/'},
5973 + {"%=", T_ASSIGN, '%'},
5974 + {"|=", T_ASSIGN, '|'},
5975 + {"&=", T_ASSIGN, '&'},
5976 + {"^=", T_ASSIGN, '^'},
5977 + {":=", T_DEFVAR,OP_DEF},
5978 + {"++", T_INC, OP_INC },
5979 + {"--", T_DEC, OP_DEC },
5980 + {"->", T_ARROW, OP_ARR },
5981 + {"&&", T_AND, OP_AND },
5982 + {"||", T_OR, OP_OR },
5983 + {"<<", T_LSH, OP_LSH },
5984 + {">>", T_RSH, OP_RSH },
5985 + {"==", T_EQ, OP_EQ },
5986 + {"!=", T_NE, OP_NE },
5987 + {"<=", T_LE, OP_LE },
5988 + {">=", T_GE, OP_GE },
5989 + {"..", T_TO, OP_TO },
5990 + {"=>", T_IMP, OP_IMP },
5991 + {"[[", T_OSEL, OP_SEL },
5992 + {"]]", T_CSEL, OP_SEL },
5993 + };
5994 +
5995 +static struct skeyword { /* all keywords we recognize */
5996 + char *keyword_str ; /* keyword as a string */
5997 + int token ; /* token to return to yacc */
5998 + topcode opcode ; /* opcode associated w/keyword */
5999 + } keywords[] = {
6000 + {"if", T_IF , OP_IF},
6001 + {"else", T_ELSE },
6002 + {"for", T_FOR , OP_FOR},
6003 + {"while", T_WHILE , OP_WHILE},
6004 + {"sizeof", T_SIZEOF , OP_SIZ},
6005 + {"frame", T_FRAME , OP_FRAME},
6006 +
6007 + {"T", T_TYPEDEF_INDICATOR },
6008 + {"struct", T_STRUCT },
6009 + {"union", T_UNION },
6010 + {"enum", T_ENUM },
6011 +
6012 + {"unsigned",T_UNSIGNED },
6013 + {"signed", T_SIGNED },
6014 + {"short", T_SHORT },
6015 + {"long", T_LONG },
6016 + {"char", T_CHAR },
6017 + {"int", T_INT },
6018 + {"double", T_DOUBLE },
6019 + {"float", T_FLOAT },
6020 + {"void", T_VOID },
6021 + } ;
6022 +
6023 +
6024 +LFUNC tnode* duel_lex_int(void) /* parse next token as integer num */
6025 +{
6026 + tnode *n ;
6027 + tulonglong val=0 ;
6028 + char *p=lexptr ;
6029 + bool is_l=0,is_u=0 ;
6030 + int base=10 ;
6031 + int src_pos=lexptr-inputstr ;
6032 +
6033 + if(*p=='0') { /* figure out the base */
6034 + p++ ;
6035 + if(*p=='x' || *p=='X') base=16,p++ ;
6036 + else
6037 + if(isdigit(*p)) base=8 ; /* avoid having '0' as a base 8 (uint) */
6038 + }
6039 +
6040 + while(isdigit(*p) || base==16 && isxdigit(*p)) { /* get the value */
6041 + val*=base ;
6042 + if(isupper(*p)) val+= *p-'A'+10 ;
6043 + else if(islower(*p)) val+= *p-'a'+10 ;
6044 + else val+= *p-'0' ;
6045 + p++ ;
6046 + }
6047 + for (;*p;p++) { /* yuk. figure 0L etc */
6048 + if (*p == 'l' || *p == 'L') is_l++;
6049 + else if(*p == 'u' || *p == 'U') is_u++;
6050 + else break;
6051 + }
6052 + is_u=is_u || base!=10 ;
6053 +
6054 + if((is_l>1 && is_u) || (long long) val < 0 || ((tulong) val != val && is_u)) {
6055 + n=mknode_const(src_pos,ctype_ulonglong);
6056 + n->cnst.u.rval_ulonglong=val ;
6057 + }
6058 + else
6059 + if(is_l>1 || (tulong) val != val) {
6060 + n=mknode_const(src_pos,ctype_longlong) ;
6061 + n->cnst.u.rval_longlong=(long long) val ;
6062 + }
6063 + else
6064 + if((is_l && is_u) || (long) val < 0 || ((tuint) val != val && is_u)) {
6065 + n=mknode_const(src_pos,ctype_ulong);
6066 + n->cnst.u.rval_ulong=val ;
6067 + }
6068 + else
6069 + if(is_l || (tuint) val != val) {
6070 + n=mknode_const(src_pos,ctype_long) ;
6071 + n->cnst.u.rval_long=(long) val ;
6072 + }
6073 + else
6074 + if(is_u || (int) val < 0) {
6075 + n=mknode_const(src_pos,ctype_uint) ;
6076 + n->cnst.u.rval_uint=(tuint) val ;
6077 + }
6078 + else {
6079 + n=mknode_const(src_pos,ctype_int) ;
6080 + n->cnst.u.rval_int=(int) val ;
6081 + }
6082 + strncpyz(n->cnst.symb_val,lexptr,p-lexptr); /* save the symbolic val*/
6083 + lexptr=p ;
6084 + return n ;
6085 +}
6086 +
6087 +LFUNC tnode* duel_lex_float(void) /* parse next token as float num */
6088 +{
6089 + tnode *n=0 ;
6090 + char *p=lexptr ;
6091 + double val ;
6092 + char c,tmpc ;
6093 + bool ok=TRUE;
6094 + int src_pos = lexptr - inputstr ;
6095 +
6096 + /* this is disgusting.. why isnt there a lib call to recognize floats?! */
6097 + while(isdigit(*p)) p++ ;
6098 + if(*p=='.') p++ ;
6099 + while(isdigit(*p)) p++ ;
6100 + if(*p=='e' || *p=='E') {
6101 + p++ ;
6102 + if(*p=='+' || *p=='-') p++ ;
6103 + if(!isdigit(*p)) ok=FALSE ; /* force digit (scanf allows 1e-.2 ?!) */
6104 + while(isdigit(*p)) p++ ;
6105 + }
6106 + tmpc= *p ; *p=0 ;
6107 + ok=ok && sscanf(lexptr,"%lf%c",&val,&c)==1 ;
6108 + *p=tmpc ;
6109 + if(!ok) yyerror("Invalid float constant.");
6110 +
6111 + n=mknode_const(src_pos,ctype_double);
6112 + n->cnst.u.rval_double=val ;
6113 + strncpyz(n->cnst.symb_val,lexptr,p-lexptr); /* save the symbolic val*/
6114 + lexptr=p ;
6115 + return(n);
6116 +}
6117 +
6118 +/* parse_escaped_char -- parse an escaped char (e.g. '\n').
6119 + * lexptr expected to point to text right after the '\'.
6120 + * return: actual char value (e.g. 012 if 'n' or '012' is found.)
6121 + * lexptr is advanced after the espaced char.
6122 + */
6123 +
6124 +LFUNC char parse_escaped_char(void)
6125 +{
6126 + char retc ;
6127 + switch(lexptr[0]) {
6128 + /*case 'a': retc='\a' ; break ; /* some compilers don't support it. */
6129 + case 'b': retc='\b' ; break ;
6130 + case 'f': retc='\f' ; break ;
6131 + case 'n': retc='\n' ; break ;
6132 + case 'r': retc='\r' ; break ;
6133 + case 't': retc='\t' ; break ;
6134 + case 'v': retc='\v' ; break ;
6135 + case 'x': yyerror("hex char const not yet suppported");
6136 + case '0': case '1': case '2': case '3':
6137 + retc= lexptr[0] - '0' ;
6138 + if(lexptr[1]>='0' && lexptr[1]<='7')
6139 + retc= retc* 010 + *++lexptr - '0' ;
6140 + if(lexptr[1]>='0' && lexptr[1]<='7')
6141 + retc= retc* 010 + *++lexptr - '0' ;
6142 + break ;
6143 + default: retc=lexptr[0] ; /* default also takes care of '\'' '\\' */
6144 + }
6145 + lexptr++ ;
6146 + return retc ;
6147 +}
6148 +
6149 +/* FUNC yylex -- return the next token to yacc.
6150 + * GLOBALS: lexptr point to the string we are parsing next. it is updated.
6151 + */
6152 +
6153 +LFUNC int yylex (void)
6154 +{
6155 + int c,i,src_pos ;
6156 + char *p ;
6157 +
6158 + for(c= *lexptr; c==' ' || c=='\t' || c=='\n' ; c= *++lexptr); /* skip blank*/
6159 +
6160 + src_pos = lexptr - inputstr ; /* current char being parsed */
6161 + yylval.opinfo.src_pos = src_pos ;
6162 +
6163 + if(*lexptr=='\0' || strncmp(lexptr,"|>",2)==0) return 0 ; /* end of expr */
6164 +
6165 + for (i = 0; i < sizeof(tokens)/sizeof(struct stoken) ; i++) {
6166 + int l=strlen(tokens[i].opstr) ; /* check next token vs table */
6167 + if(strncmp(lexptr,tokens[i].opstr,l)==0) {
6168 + lexptr+=l ;
6169 + yylval.opinfo.opcode = tokens[i].opcode;
6170 + return tokens[i].token ;
6171 + }
6172 + }
6173 +
6174 + switch (c = *lexptr) {
6175 + case '\'': /* char constant, but stored as int (ansi-c) */
6176 + p=lexptr++ ;
6177 + c = *lexptr++ ;
6178 + if (c == '\\') c=parse_escaped_char();
6179 + if( *lexptr++ != '\'') yyerror("Invalid character constant.");
6180 + yylval.node=mknode_const(src_pos,ctype_int) ;
6181 + yylval.node->cnst.u.rval_int=c ;
6182 + strncpyz(yylval.node->cnst.symb_val,p,lexptr-p); /*save the symbol. val*/
6183 + return T_CONST ;
6184 +
6185 + case '0': /* chk hex */
6186 + if(lexptr[1]=='x' || lexptr[1]=='X') {
6187 + yylval.node=duel_lex_int();
6188 + return T_CONST ;
6189 + }
6190 + /* fall thru for other numbers */
6191 + case '1': case '2': case '3': /* decimal or floating point number */
6192 + case '4': case '5': case '6': case '7': case '8': case '9':
6193 + for(p=lexptr ; *p>='0' && *p<='9' ; p++ ) ; /*find next non digit*/
6194 + if(*p=='.' && p[1]!='.' || *p=='e' || *p=='E')
6195 + yylval.node=duel_lex_float();
6196 + else yylval.node=duel_lex_int();
6197 + return T_CONST ;
6198 +
6199 + case '(': case ')':
6200 + case '<': case '>':
6201 + case '[': case ']':
6202 + case '{': case '}':
6203 + case '+': case '-': case '*': case '/': case '%':
6204 + case '|': case '&': case '^': case '~': case '!':
6205 + case ',': case '?': case ':': case '=':
6206 + case '.': case '@': case '$': case '#': case '`': case '\\':
6207 + lexptr++;
6208 + yylval.opinfo.opcode=c ;
6209 + return c;
6210 + case ';': { /* hack, ignore ';' before '}' and else. for C compatability*/
6211 + char *save_lexptr= ++lexptr ;
6212 + int tok=yylex() ; /* hack, call myself for next token */
6213 + if(tok=='}' || tok==T_ELSE) {
6214 + duel_printf("warning: useless ';' ignored\n");
6215 + return tok ;
6216 + }
6217 + /* else restore position and return the ';' */
6218 + lexptr=save_lexptr ;
6219 + yylval.opinfo.opcode=';' ;
6220 + yylval.opinfo.src_pos = src_pos ;
6221 + return ';';
6222 + }
6223 + case '"': {
6224 + char s[512] ;
6225 + size_t len=0 ;
6226 + ttarget_ptr dptr ;
6227 + tnode *n ;
6228 +
6229 + p=lexptr++ ;
6230 + while((c= *lexptr++)!='"') {
6231 + if (c == '\\') c=parse_escaped_char();
6232 + s[len++]=c ;
6233 + }
6234 + s[len++]=0 ;
6235 + dptr=duel_alloc_target_space(len);
6236 + duel_put_target_bytes(dptr,s,len);
6237 +
6238 + n=mknode_const(src_pos,ctype_charptr);
6239 + n->cnst.u.rval_ptr=dptr ;
6240 + len=lexptr-p ;
6241 + if(len>60) len=60 ;
6242 + strncpyz(n->cnst.symb_val,p,len); /* save the symbolic val*/
6243 + yylval.node=n ;
6244 + return T_CONST ;
6245 + }
6246 + }
6247 +
6248 + if(c != '_' && !isalpha(c))
6249 + yyerror ("Invalid character in expression.");
6250 +
6251 + p=lexptr ;
6252 + do { c= *++lexptr ; } while(c=='_' || isalnum(c));
6253 +
6254 + for (i = 0; i < sizeof(keywords)/sizeof(struct skeyword) ; i++) {
6255 + int l=strlen(keywords[i].keyword_str) ; /* check next token vs keywords*/
6256 + if(l==lexptr-p && strncmp(p,keywords[i].keyword_str,l)==0) {
6257 + yylval.opinfo.opcode=keywords[i].opcode ;
6258 + return keywords[i].token ;
6259 + }
6260 + }
6261 +
6262 + /* the symbol/name found is not a reserved word, so return it as a T_SYM
6263 + */
6264 +
6265 + i=lexptr-p ; /* length of string found (symbol/name) */
6266 + yylval.nameinfo.src_pos=src_pos ;
6267 + yylval.nameinfo.name=duel_malloc(i+1);
6268 + strncpyz(yylval.nameinfo.name,p,i);
6269 + return T_SYM;
6270 +}
6271 +
6272 +LPROC yyerror(char *msg)
6273 +{
6274 + int i,n=lexptr-inputstr ;
6275 + duel_printf("%s\n",inputstr);
6276 + for(i=0 ; i<n ; i++) duel_printf("-");
6277 + duel_printf("^ %s\n",msg);
6278 + duel_abort(); /* terminate parsing. some callers depend on this*/
6279 +}
6280 +
6281 +/*************************************************************************/
6282 +/* utility functions used to parse the expression and build it as a tree */
6283 +/*************************************************************************/
6284 +
6285 +/* mknode_op -- make a tree node of type op with given opcode and kids
6286 + */
6287 +
6288 +LFUNC tnode* mknode_op(top_kind op_kind,topinfo opinfo,
6289 + tnode *k1,tnode *k2,tnode *k3,tnode *k4)
6290 +{
6291 + tnode *n ;
6292 + duel_assert(opinfo.opcode>' ');
6293 + n=(tnode *) duel_malloc(sizeof(tnode));
6294 + duel_bzero((char*) n,sizeof(tnode));
6295 + n->node_kind=NK_OP ;
6296 + n->op_kind=op_kind ;
6297 + n->op=opinfo.opcode ;
6298 + n->src_pos=opinfo.src_pos ;
6299 + n->kids[0]=k1 ; n->kids[1]=k2 ; n->kids[2]=k3 ; n->kids[3]=k4 ;
6300 + return n ;
6301 +}
6302 +
6303 +
6304 + /* mknode_const -- make a constant node for the given type.
6305 + */
6306 +
6307 +LFUNC tnode* mknode_const(int src_pos,tctype *ctype)
6308 +{
6309 + tnode *n ;
6310 + n=(tnode *) duel_malloc(sizeof(tnode));
6311 + duel_bzero((char*) n,sizeof(tnode));
6312 + n->node_kind=NK_CONST ;
6313 + n->src_pos=src_pos ;
6314 + n->cnst.val_kind=VK_RVALUE ;
6315 + n->cnst.ctype=ctype ;
6316 + return n ;
6317 +}
6318 +
6319 + /* mknode_ctype -- make a node of the given c-type.
6320 + */
6321 +
6322 +LFUNC tnode* mknode_ctype(tctype *ctype)
6323 +{
6324 + tnode *n ;
6325 + n=(tnode *) duel_malloc(sizeof(tnode));
6326 + duel_bzero((char*) n,sizeof(tnode));
6327 + n->node_kind=NK_CTYPE ;
6328 + n->ctype=ctype ;
6329 + return n ;
6330 +}
6331 +
6332 + /* mknode_name -- make a node of the given name/symbol.
6333 + * input is pointer to the saved name (on heap)
6334 + */
6335 +
6336 +LFUNC tnode* mknode_name(tnameinfo nameinfo)
6337 +{
6338 + tnode *n ;
6339 + n=(tnode *) duel_malloc(sizeof(tnode));
6340 + duel_bzero((char*) n,sizeof(tnode));
6341 + n->node_kind=NK_NAME ;
6342 + n->name=nameinfo.name ;
6343 + n->src_pos=nameinfo.src_pos ;
6344 + return n ;
6345 +}
6346 +
6347 +/* In order to parse C types, which are 'reversed' in the parser, a stack
6348 + * is used to push abstract declarators, e.g. in (*)() we first push a func
6349 + * indicator '(' and then push a pointer indicator '*'. for arrays we push
6350 + * a '[' and the array size.
6351 + * This stack is popped and a ctype is constructed at the end of the
6352 + * abstract type parsing. The following functions implement the stack
6353 + */
6354 +
6355 +typedef struct stype_desc { /* stack of type descriptors is made of these */
6356 + char desc ;
6357 + int size ;
6358 + struct stype_desc *next ; /* next on stack */
6359 + } ttype_desc ;
6360 +
6361 +ttype_desc *top = 0 ;
6362 +
6363 +
6364 +LPROC push_type(char desc) /* put desc on the types stack */
6365 +{
6366 + ttype_desc *p = (ttype_desc* ) duel_malloc(sizeof(ttype_desc));
6367 + p->desc=desc ;
6368 + p->size=0 ;
6369 + p->next=top ;
6370 + top=p ;
6371 +}
6372 +
6373 +/* push_type_int -- same as push_type but also set the size parameter, which
6374 + * is given as a constant node (which is expected to be int)
6375 + */
6376 +
6377 +LPROC push_type_int(char desc,tnode *n)
6378 +{
6379 + duel_assert(n->node_kind==NK_CONST);
6380 + if(n->cnst.ctype != ctype_int ||
6381 + n->cnst.u.rval_int <=0 ) duel_gen_error("Illegal array size",0);
6382 + push_type(desc);
6383 + top->size=n->cnst.u.rval_int ;
6384 +}
6385 +
6386 +LFUNC bool pop_type(char *desc,int *size) /* pop item from stack. */
6387 +{
6388 + ttype_desc *p = top ;
6389 + if(p==0) return FALSE ;
6390 + *desc=p->desc ;
6391 + *size=p->size ;
6392 + top=p->next ;
6393 + duel_free(p) ;
6394 + return TRUE ;
6395 +}
6396 +
6397 +
6398 +/* abstract type-modifiers were pushed on a stack. Retrieve
6399 + * them (reversed) creating type nodes as we go
6400 + * input: base type (e.g. 'long').
6401 + * returns: node of the modified type.
6402 + * modification is based on the stack of things pushed while parsing.
6403 + */
6404 +
6405 +LFUNC tnode* mknode_modified_ctype(tctype *base)
6406 +{
6407 + int size;
6408 + char tdesc ; /* descriptor of abs decl eg '*' */
6409 + tctype *t=base ; /* type under construction */
6410 +
6411 + while(pop_type(&tdesc,&size)) /* pop next abs decl */
6412 + switch (tdesc) {
6413 + case '*': t=duel_mkctype_ptr(t); break ;
6414 + case '(': t=duel_mkctype_func(t); break ;
6415 + case '[': t=duel_mkctype_array(t,size); break ;
6416 + }
6417 + return mknode_ctype(t) ;
6418 +}
6419 +
6420 +/* entry point for parsing. the given expression is parsed into the given
6421 + * node as root.
6422 + */
6423 +
6424 +FUNC tnode* duel_parse(char *s)
6425 +{
6426 + lexptr=inputstr=s ;
6427 + top=0 ; /* reset the types stack */
6428 + if(duel_yyparse()) root=NULL ;
6429 + return root ;
6430 +}
6431 --- gdb/duel/patchlevel.h
6432 +++ gdb/duel/patchlevel.h
6433 @@ -0,0 +1,7 @@
6434 +/* DUEL - A Very High Level Debugging Langauge. */
6435 +/* Public domain code */
6436 +/* Written by Michael Golan mg@××××××××××××.edu */
6437 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
6438 +
6439 +#define PATCHLEVEL 4
6440 +#define VERSION "DUEL 1.20"
6441 --- gdb/duel/print.c
6442 +++ gdb/duel/print.c
6443 @@ -0,0 +1,300 @@
6444 +/* DUEL - A Very High Level Debugging Langauge. */
6445 +/* Public domain code */
6446 +/* Written by Michael Golan mg@××××××××××××.edu */
6447 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
6448 +
6449 +/* handle value/type printing */
6450 +
6451 +/*
6452 + * $Log: 10_all_gdb-6.6-duel.patch,v $
6453 + * Revision 1.1 2007/12/29 21:06:06 vapier
6454 + * add DUEL support #199987 by Sergei Golubchik
6455 + *
6456 + * Revision 1.9 93/03/12 06:01:00 mg
6457 + * cosmetics: tuint for uint, etc.
6458 + * display union like structs
6459 + * suport piped output
6460 + * note for all pointers if illegal, better handling of string bad pointers
6461 + *
6462 + * Revision 1.8 93/02/27 06:06:50 mg
6463 + * removed usage of fabs() so -lm is not required in gdb's linking (HP9000)
6464 + *
6465 + * Revision 1.7 93/02/26 05:00:42 mg
6466 + * fixed display of *p for void *p
6467 + *
6468 + * Revision 1.6 93/02/23 20:57:56 mg
6469 + * *** empty log message ***
6470 + *
6471 + * Revision 1.5 93/02/23 19:16:00 mg
6472 + * improved escaped char support
6473 + *
6474 + * Revision 1.4 93/02/03 21:54:49 mg
6475 + * support "signed char"
6476 + *
6477 + * Revision 1.3 93/01/12 21:53:45 mg
6478 + * cleanup and set for release
6479 + *
6480 + * Revision 1.2 93/01/07 00:14:34 mg
6481 + * print union name
6482 + *
6483 + * Revision 1.1 93/01/03 07:31:55 mg
6484 + * Initial revision
6485 + *
6486 + */
6487 +
6488 +#include "duel.h"
6489 +
6490 +/* print type information (no new lines)
6491 + * parm 'expand' controls expansion level for structs & unions. normally 1.
6492 + */
6493 +
6494 +PROC duel_print_type(tctype *t,int expand)
6495 +{
6496 + int i ;
6497 + tctype *kid=t->u.kid ;
6498 +
6499 + switch(t->type_kind) {
6500 + case CTK_VOID: duel_printf("void ") ; break ;
6501 + case CTK_CHAR: duel_printf("char ") ; break ;
6502 + case CTK_SCHAR: duel_printf("schar ") ; break ;
6503 + case CTK_UCHAR: duel_printf("uchar ") ; break ;
6504 + case CTK_USHORT: duel_printf("ushort ") ; break ;
6505 + case CTK_SHORT: duel_printf("short ") ; break ;
6506 + case CTK_INT: duel_printf("int ") ; break ;
6507 + case CTK_UINT: duel_printf("uint ") ; break ;
6508 + case CTK_LONG: duel_printf("long ") ; break ;
6509 + case CTK_ULONG: duel_printf("ulong ") ; break ;
6510 + case CTK_LONGLONG: duel_printf("longong ") ; break ;
6511 + case CTK_ULONGLONG: duel_printf("ulonglong ") ; break ;
6512 + case CTK_FLOAT: duel_printf("float ") ; break ;
6513 + case CTK_DOUBLE: duel_printf("double ") ; break ;
6514 + case CTK_ENUM: duel_printf("enum %s ",t->name); break ;
6515 +
6516 + case CTK_PTR:
6517 + if(ctype_kind_base(kid)) {
6518 + duel_print_type(kid,0);
6519 + duel_printf("* ");
6520 + }
6521 + else {
6522 + duel_printf("ptr to ");
6523 + duel_print_type(kid,expand-1) ;
6524 + }
6525 + break ;
6526 + case CTK_ARRAY: {
6527 + int n=t->size ;
6528 + if(kid->size>0) n/=kid->size ;
6529 +
6530 + if(ctype_kind_base(kid)) {
6531 + duel_print_type(kid,0);
6532 + duel_printf("[%d] ",n);
6533 + }
6534 + else {
6535 + duel_printf("array [%d] of ",n);
6536 + duel_print_type(kid,expand) ;
6537 + }
6538 + }
6539 + break ;
6540 + case CTK_FUNC: duel_printf("func returning ");
6541 + duel_print_type(kid,expand);
6542 + break ;
6543 + case CTK_STRUCT:
6544 + if(expand <= 0) {
6545 + duel_printf("struct %s ",t->name);
6546 + break ;
6547 + }
6548 + duel_printf("struct %s { ",t->name) ;
6549 + for(i=0 ; i<t->u.f.fields_no ; i++) {
6550 + tctype_field *f= &t->u.f.fields[i] ;
6551 + duel_print_type(f->ctype,expand-1);
6552 + duel_printf("%s ",f->name);
6553 + if(f->bitlen != 0) duel_printf(":%d ",f->bitlen);
6554 + duel_printf("; ");
6555 + }
6556 + duel_printf("} ; ");
6557 + break ;
6558 + case CTK_UNION: duel_printf("union %s",t->name) ; break ;
6559 + default: duel_assert(0);
6560 + }
6561 +}
6562 +
6563 +/* display char 'c' in a "neat" way, e.g. c='\n' is displayed as such,
6564 + * etc. Special case for c==quote (normally ' or "), we add '\\'
6565 + * return a pointer to a static string which is overriden each call etc
6566 + */
6567 +char *neat_char(char c,char quote)
6568 +{
6569 + static char s[8] ;
6570 + switch(c) {
6571 + case '\0': strcpy(s,"\\0"); break ;
6572 + case '\n': strcpy(s,"\\n"); break ;
6573 + case '\r': strcpy(s,"\\r"); break ;
6574 + case '\t': strcpy(s,"\\t"); break ;
6575 + case '\\': strcpy(s,"\\\\"); break ;
6576 + default:
6577 + if(!isprint(c) || !isascii(c)) sprintf(s,"\\%3.3o",c & 0377);
6578 + else
6579 + if(c==quote) sprintf(s,"\\%c",c);
6580 + else sprintf(s,"%c",c);
6581 + }
6582 + return s ;
6583 +}
6584 +
6585 +/* print the given scalar value into string s.
6586 + * for none-scalar values, print the lval's address.
6587 + * note: v's value is not modified.
6588 + */
6589 +
6590 +PROC duel_sprint_scalar_value(char *s,tvalue *v)
6591 +{
6592 + bool ok ;
6593 + tvalue rval ; /* copy of v, but as an rval */
6594 + rval = *v ;
6595 + if(v->val_kind==VK_FVALUE) {
6596 + sprintf(s,"frame(%d)",v->u.fvalue);
6597 + return ;
6598 + }
6599 + if(v->val_kind==VK_LVALUE) {
6600 + char tmpstr[256],*m="" ; /* tmpstr= temporary for check, m= message */
6601 + int sz = v->ctype->size ; /* size of object ref. */
6602 + if(sz<1) sz=1 ;
6603 + if(sz>256) sz=256 ;
6604 + /* check for null and bad (try read sz bytes at addr ) references */
6605 + if(v->u.lvalue==NULL ||
6606 + !duel_get_target_bytes(v->u.lvalue,tmpstr,sz)) m=" [ILLEGAL]" ;
6607 +
6608 + switch(v->ctype->type_kind) {
6609 + case CTK_VOID: sprintf(s,"void @%p%s",v->u.lvalue,m); return;
6610 + case CTK_STRUCT: sprintf(s,"struct @%p%s",v->u.lvalue,m); return;
6611 + case CTK_UNION: sprintf(s,"union @%p%s",v->u.lvalue,m); return;
6612 + case CTK_FUNC: sprintf(s,"func @%p%s",v->u.lvalue,m) ; return;
6613 + case CTK_ARRAY:
6614 + if(*m!='\0' || v->ctype->u.kid!=ctype_char) {
6615 + sprintf(s,"array @%p%s",v->u.lvalue,m);
6616 + return;
6617 + }
6618 + }
6619 + /* convert scalar type to rvalue */
6620 + if(!duel_try_get_rvalue(&rval,"")) {
6621 + sprintf(s,"ref @%p [ILLEGAL]",v->u.lvalue,m);
6622 + return ;
6623 + }
6624 + }
6625 + else
6626 + if(v->val_kind==VK_BVALUE) {
6627 + if(!duel_try_get_rvalue(&rval,"")) {
6628 + sprintf(s,"ref @%p [ILLEGAL]",v->u.bvalue.lvalue);
6629 + return ;
6630 + }
6631 + }
6632 +
6633 + switch(rval.ctype->type_kind) { /* handle rvalues */
6634 + case CTK_VOID: sprintf(s,"void") ; break ;
6635 + case CTK_CHAR: sprintf(s,"'%s'",neat_char(rval.u.rval_char,'\''));break;
6636 + case CTK_SHORT: sprintf(s,"%d", rval.u.rval_short) ; break ;
6637 + case CTK_INT: sprintf(s,"%d", rval.u.rval_int) ; break ;
6638 + case CTK_LONG: sprintf(s,"%ldL", rval.u.rval_long) ; break ;
6639 + case CTK_LONGLONG: sprintf(s,"%lldLL", rval.u.rval_longlong) ; break ;
6640 + case CTK_SCHAR: if(rval.u.rval_schar==0) sprintf(s,"'\\0'");
6641 + else sprintf(s,"%d", rval.u.rval_schar) ; break ;
6642 + case CTK_UCHAR: if(rval.u.rval_uchar==0) sprintf(s,"'\\0'");
6643 + else sprintf(s,"'\\x%d'", rval.u.rval_uchar) ; break ;
6644 + case CTK_USHORT: if(rval.u.rval_ushort==0) sprintf(s,"0");
6645 + else sprintf(s,"0x%x", rval.u.rval_ushort) ; break ;
6646 + case CTK_UINT: if(rval.u.rval_uint==0) sprintf(s,"0");
6647 + else sprintf(s,"0x%x", rval.u.rval_uint) ; break ;
6648 + case CTK_ULONG: if(rval.u.rval_ulong==0L) sprintf(s,"0");
6649 + else sprintf(s,"0x%lxUL", rval.u.rval_ulong) ; break ;
6650 + case CTK_ULONGLONG: if(rval.u.rval_ulonglong==0L) sprintf(s,"0");
6651 + else sprintf(s,"0x%llxULL", rval.u.rval_ulonglong) ; break ;
6652 + case CTK_FLOAT: rval.u.rval_double=rval.u.rval_float ;
6653 + case CTK_DOUBLE: { double x=rval.u.rval_double ;
6654 + if(x >= -1e-6 && x <= 1e-6 || x >= 1e8 || x <= -1e8)
6655 + sprintf(s,"%.4le",x); /* standard 'e' fmt */
6656 + else { /* fixed point removing trailing '0'*/
6657 + int l;
6658 + sprintf(s,"%.8lf",x);
6659 + l=strlen(s)-1;
6660 + while(s[l]=='0' && s[l-1]!='.') s[l--]=0 ;
6661 + }
6662 + }
6663 + break ;
6664 + case CTK_PTR:
6665 + if(rval.u.rval_ptr==NULL) sprintf(s,"NULL");
6666 + else {
6667 + char sval[41];
6668 + bool ok=duel_get_target_bytes(rval.u.lvalue,sval,1);
6669 + if(ok && rval.ctype->u.kid==ctype_char) {
6670 + int i ;
6671 + duel_get_target_bytes(rval.u.lvalue,sval,41);
6672 + strcpy(s,"\"");
6673 + for(i=0 ; i<40 && sval[i]!='\0' ; i++)
6674 + strcat(s,neat_char(sval[i],'"'));
6675 + if(sval[i]=='\0') strcat(s,"\"");
6676 + else strcat(s,"...\"");
6677 + }
6678 + else sprintf(s,"@%p%s",rval.u.rval_ptr,ok? "":" [ILLEGAL]");
6679 + }
6680 + break ;
6681 + case CTK_ENUM: {
6682 + int i, n=rval.ctype->u.e.enumerators_no ;
6683 + tctype_enumerator *e=rval.ctype->u.e.enumerators ;
6684 + int val=duel_get_int_val(v,"");
6685 + for(i=0 ; i<n ; i++)
6686 + if(e[i].val == val) { strcpy(s,e[i].name); return ;}
6687 + sprintf(s,"%d",val);
6688 + }
6689 + break ;
6690 + default: duel_assert(0);
6691 + }
6692 +}
6693 +
6694 +/* print the given value, symbolic+val. Handles structures */
6695 +
6696 +PROC duel_print_value(tvalue *v)
6697 +{
6698 + tctype *t=v->ctype ;
6699 + int i ;
6700 + bool topipe=duel_output_pipe_style ;
6701 + char s[160];
6702 +
6703 + duel_printf(topipe? "$$$SYM: %s\n":"%s",v->symb_val);
6704 +
6705 + if(duel_debug && !topipe) {
6706 + duel_printf("`` %s '' ",v->symb_val);
6707 + duel_printf("{ ");
6708 + duel_print_type(v->ctype,2);
6709 + duel_printf("} ");
6710 + if(v->val_kind==VK_LVALUE) {
6711 + duel_printf("lval @%p",v->u.lvalue);
6712 + }
6713 + else
6714 + if(v->val_kind==VK_BVALUE) {
6715 + duel_printf("bval @%p [%d,%d]",v->u.bvalue.lvalue,v->u.bvalue.bitpos,
6716 + v->u.bvalue.bitlen);
6717 + }
6718 + duel_printf("\n");
6719 + }
6720 +
6721 + duel_sprint_scalar_value(s,v);
6722 + if(v->val_kind==VK_LVALUE && strstr(s,"ILLEGAL")==NULL) {
6723 + switch(t->type_kind) {
6724 + case CTK_UNION:
6725 + case CTK_STRUCT:
6726 + duel_printf(topipe? "$$$VAL: { " : " = { ");
6727 + for(i=0 ; i<t->u.f.fields_no ; i++) {
6728 + tvalue u ;
6729 + char *name=t->u.f.fields[i].name ;
6730 + duel_get_dot_name(v,name,&u);
6731 + duel_sprint_scalar_value(s,&u);
6732 + duel_printf("%s = %s",name,s) ;
6733 + if(i < t->u.f.fields_no-1) duel_printf(", ");
6734 + }
6735 + duel_printf(" }\n");
6736 + return ;
6737 + case CTK_ARRAY: ; /* not handled except for char[] as scalar*/
6738 + }
6739 + }
6740 +
6741 + if(topipe) duel_printf("$$$VAL: %s",s);
6742 + else
6743 + if(strcmp(v->symb_val,s)!=0) duel_printf(" = %s",s);
6744 + duel_printf("\n");
6745 +}
6746 +
6747 --- gdb/duel/proto.h
6748 +++ gdb/duel/proto.h
6749 @@ -0,0 +1,101 @@
6750 +/* DUEL - A Very High Level Debugging Langauge. */
6751 +/* Public domain code */
6752 +/* Written by Michael Golan mg@××××××××××××.edu */
6753 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
6754 +
6755 +/* prototypes for all of duel's global functions */
6756 +
6757 +FUNC tctype* duel_mkctype_ptr(tctype *t);
6758 +FUNC tctype* duel_mkctype_func(tctype *t);
6759 +FUNC tctype* duel_mkctype_array(tctype *t,int size);
6760 +FUNC tctype* duel_mkctype_struct(char *name,size_t size,int fields_no,
6761 + bool is_union);
6762 +PROC duel_mkctype_struct_field(tctype *t,int field_no,char *name,
6763 + int bitpos,int bitlen, tctype *fctype);
6764 +FUNC tctype* duel_mkctype_enum(char *name,tctype_kind real_type_kind,
6765 + size_t size,int enumerators_no);
6766 +PROC duel_mkctype_enumerator(tctype *t,int enumerator_no,char *name,int val);
6767 +
6768 +PROC duel_init_basic_ctypes(void);
6769 +
6770 +PROC duel_print_value(tvalue *v);
6771 +PROC duel_print_type(tctype *t,int expand);
6772 +PROC duel_sprint_scalar_value(char *s,tvalue *v);
6773 +
6774 +
6775 +PROC duel_fatal(char *msg);
6776 +PROC duel_abort(void);
6777 +PROC duel_cleanup(void *);
6778 +
6779 +FUNC tnode* duel_parse(char *s);
6780 +
6781 +
6782 +PROC duel_reset_eval(void);
6783 +FUNC bool duel_eval(tnode *n,tvalue *v);
6784 +FUNC bool duel_get_dot_name(tvalue *v,char *name,tvalue *ret);
6785 +
6786 +FUNC tnode* duel_set_eval_loc(tnode *n);
6787 +FUNC char* duel_set_input_string(char *s);
6788 +PROC duel_op_error(char *mesg,char *op,tvalue *v1,tvalue *v2);
6789 +PROC duel_gen_error(char *mesg,char *arg1);
6790 +
6791 +PROC duel_parse_and_eval(char *s);
6792 +
6793 +FUNC bool duel_try_get_rvalue(tvalue *v,char *op);
6794 +PROC duel_standardize_func_parm(tvalue *p);
6795 +FUNC bool duel_do_op_to(tvalue *v1,tvalue *v2,int n,tvalue *r);
6796 +PROC duel_do_cast(tctype *tout,tvalue *v);
6797 +FUNC bool duel_mk_logical(tvalue *v,char *op);
6798 +PROC duel_set_symb_val(tvalue *r,char *format,tvalue *v1,tvalue *v2);
6799 +PROC duel_get_struct_val(tvalue *v,char *op);
6800 +PROC duel_get_struct_ptr_val(tvalue *v,char *op);
6801 +FUNC int duel_get_int_val(tvalue *v,char *op);
6802 +FUNC int duel_get_posint_val(tvalue *v,char *op);
6803 +PROC duel_apply_unary_op(topcode op,tvalue *v);
6804 +PROC duel_apply_post_unary_op(topcode op,tvalue *v);
6805 +FUNC bool duel_apply_bin_op(topcode op,tvalue *v1,tvalue *v2,tvalue *r);
6806 +PROC duel_find_func_frame(tvalue *v,char *op);
6807 +
6808 +/* output management */
6809 +
6810 +PROC duel_printf(char *fmt, ...);
6811 +PROC duel_flush(void);
6812 +PROC duel_redirectable_output_start(char *);
6813 +PROC duel_redirectable_output_end(void);
6814 +PROC duel_redirectable_output_abort(void);
6815 +PROC duel_redirectable_output_init(void);
6816 +
6817 +/* debugger dependent functions */
6818 +
6819 +FUNC void* duel_malloc(size_t size);
6820 +PROC duel_free(void *);
6821 +
6822 +FUNC bool duel_get_target_bytes(ttarget_ptr from,void *to,size_t n);
6823 +FUNC bool duel_put_target_bytes(ttarget_ptr to,void *from,size_t n);
6824 +
6825 +FUNC bool duel_get_target_bitfield(ttarget_ptr struct_at,int bitpos,
6826 + int bitlen,void *to,tctype_kind tkind);
6827 +FUNC bool duel_get_target_variable(char *name, int frame_no, tvalue *v);
6828 +FUNC tctype* duel_get_target_typedef(char *name);
6829 +FUNC tctype* duel_get_target_struct_tag(char *name);
6830 +FUNC tctype* duel_get_target_union_tag(char *name);
6831 +FUNC tctype* duel_get_target_enum_tag(char *name);
6832 +FUNC ttarget_ptr duel_alloc_target_space(size_t n);
6833 +
6834 +FUNC int duel_get_frames_number(void);
6835 +FUNC ttarget_ptr duel_get_function_for_frame(int frame_no);
6836 +PROC duel_target_func_call(tvalue *func, tvalue *parms[],
6837 + int parms_no,tvalue *ret);
6838 +
6839 +/* prototypes for misc functions */
6840 +
6841 +FUNC char* strncpyz(char *to,char *from,size_t len);
6842 +
6843 +PROC duel_free_val_list(tval_list *l);
6844 +PROC duel_free_nodes(tnode *);
6845 +
6846 +FUNC tvalue* duel_find_alias(char *name);
6847 +PROC duel_set_alias(char *name,tvalue *v);
6848 +PROC duel_clear_aliases(void);
6849 +PROC duel_show_aliases(void);
6850 +
6851 --- gdb/duel/tsuite.c
6852 +++ gdb/duel/tsuite.c
6853 @@ -0,0 +1,64 @@
6854 +/* DUEL - A Very High Level Debugging Langauge. */
6855 +/* Public domain code */
6856 +/* Written by Michael Golan mg@××××××××××××.edu */
6857 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
6858 +
6859 +/* this is a test program to be used with tsuite.gdb */
6860 +
6861 +#include <stdlib.h>
6862 +#include <stdio.h>
6863 +#include <string.h>
6864 +
6865 +int gint ;
6866 +typedef unsigned int uint ;
6867 +
6868 +struct { int a,b ; char *name ; } emp[100] ;
6869 +enum { MIKI, DAVE, ELA } us ;
6870 +struct snode { int code ; struct snode *left,*right ; } ;
6871 +typedef struct snode tnode ;
6872 +
6873 +/* amazing, but DEC compiled strcmp such that gdb thinks it returns void */
6874 +int mystrcmp(s,t) char *s; char *t; { return strcmp(s,t); }
6875 +
6876 +void main()
6877 +{
6878 + char *s="main string" ;
6879 + FILE *out=stdout ; /* stdout is not a variable on some machines */
6880 + /* will use fflush(out) from debugger */
6881 + int i ;
6882 + tnode *root,*p,**q ;
6883 +
6884 + for(i=0 ; i<100 ; i++) {
6885 + emp[i].a=i ; emp[i].b=i*i ;
6886 + emp[i].name=(char*) malloc(10);
6887 + sprintf(emp[i].name,"emp%3.3d",i);
6888 + }
6889 + emp[53].a=76 ; /* bug */
6890 + emp[36].b-- ; /* bug */
6891 + emp[74].name[3]='5' ; /* another bug */
6892 +
6893 + root=(tnode*) malloc(sizeof(tnode));
6894 + root->left=root->right=0 ;
6895 + root->code=5000 ;
6896 + for(i=1 ; i<10000 ; i++) { /* insert elements into tree */
6897 + int code=((i*997*1013)>>10)%11000 ; /* "fixed" "random" generaor */
6898 + if(code<0) code= -code ;
6899 + p=root ;
6900 + while(p) {
6901 + if(p->code==code) break ;
6902 + if(p->code<code) q= &p->right, p=p->right ;
6903 + else q= &p->left, p=p->left ;
6904 + }
6905 + if(p==0) {
6906 + p=(tnode*) malloc(sizeof(tnode));
6907 + p->code=code ;
6908 + if(i>8680) p->code+=(i<9210)? 1:-1 ; /* bug */
6909 + p->left=p->right=0 ;
6910 + *q=p ;
6911 + }
6912 + }
6913 +
6914 + printf("trivial tsuite program\n");
6915 + printf("trivial tsuite program\n");
6916 +}
6917 +
6918 --- gdb/duel/tsuite.gdb
6919 +++ gdb/duel/tsuite.gdb
6920 @@ -0,0 +1,126 @@
6921 +set prompt
6922 +## DUEL - A Very High Level Debugging Langauge.
6923 +## Public domain code
6924 +## Written by Michael Golan mg@××××××××××××.edu
6925 +##$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $
6926 +##
6927 +## test suite for duel, can be used with duelself or gdb
6928 +##
6929 +file tsuite
6930 +b 60
6931 +b 61
6932 +r
6933 +## check constants
6934 +dl (1..5)*(2,(double) 2/3)
6935 +## declare array x, set it, search it
6936 +dl int x[100] ;
6937 +dl x[0..99]= -1 ;
6938 +dl x[i:=20..40]=2+i*i ;
6939 +dl x[20..23,38..40]
6940 +dl x[..100] >=? 33*33 <=? 35*35
6941 +dl x[..100]=> ((_>=33*33) & (_<= 35*35)) ==? 1
6942 +dl (*(x+(7..9)))++
6943 +dl y:= &x[7] ;
6944 +dl y[0..2]
6945 +dl x+7 == y
6946 +dl (x[..99]>?0)@(_>100)
6947 +dl printf("%d\n",1..10);
6948 +dl printf("x is: "); printf("%d, ",x[0..99]>? 0); printf("\n");fflush(out);
6949 +dl int j ; for(j=0 ; j<100 ; j++) if(x[j]>37*37) printf("x[%d]=%d\n",j,x[j]);fflush(out);
6950 +dl printf("%d\n",1..5);
6951 +## check void type
6952 +dl void *p
6953 +dl p = &p
6954 +dl p,*p
6955 +## errors
6956 +dl 1e+++3
6957 +dl i=4 ;
6958 +dl x=6 ;
6959 +dl x++ ;
6960 +dl --i ;
6961 +## cleanup
6962 +dl alias
6963 +dl clear
6964 +## access some variables
6965 +dl s
6966 +dl s[4..8]
6967 +dl s[6..]@0
6968 +dl l:=#/s[0..]@0
6969 +dl s[l-2..l]
6970 +dl gint
6971 +dl gint++
6972 +dl gint++
6973 +dl --gint
6974 +dl gint
6975 +dl main.s
6976 +dl ++main.s
6977 +dl main ==? main
6978 +dl main == main
6979 +dl frames_no
6980 +dl frame(0).s
6981 +dl frame(0).(gint+0)
6982 +dl sizeof(gint)
6983 +dl sizeof(T uint)
6984 +dl sizeof(T uint*)
6985 +dl sizeof(T emp)
6986 +dl sizeof(emp)
6987 +dl sizeof(emp[0])
6988 +dl (uint)-1
6989 +dl (uint*)(gint=gint-9)
6990 +dl *(uint*)&gint
6991 +dl T uint myuint ; myuint = -1
6992 +## some errors
6993 +dl frame(0).gint
6994 +dl frame(0).(gint)
6995 +dl frame(0).ha
6996 +dl sizeof(uint)
6997 +dl sizeof gint
6998 +dl main == printf
6999 +dl main+1
7000 +dl main > printf
7001 +dl printf+3
7002 +dl T int x
7003 +dl uint y
7004 +dl T uint z = 5
7005 +## finally, do some serious checks using the bugs in the programs
7006 +dl emp[4]
7007 +dl emp[k:=..100].a !=? k
7008 +dl (emp[k:=..100].a !=? k)[[0]] ; emp[{k}]
7009 +dl emp[k:=..100].if(a!=k) _
7010 +dl emp[k:=..100].b !=? k*k
7011 +dl emp[k:=..100].if(b!=k*k) _,{k}*{k}
7012 +dl emp[k:=..100]=>if(_.b!=k*k) _,{k}*{k}
7013 +dl char s[80];
7014 +dl ..100 => (sprintf(s,"emp%3.3d",_) ; emp[_].name[0..]@0#j !=? s[j])
7015 +dl ..100 => (sprintf(s,"emp%3.3d",_) ; mystrcmp(emp[_].name,s)!=?0)
7016 +dl ..100 => (sprintf(s,"emp%3.3d",_) ; emp[_].name=>if(mystrcmp(_,s))_)
7017 +## now, lets try some pointers and --> stuff!
7018 +dl root-->left[[..8]]->code
7019 +dl root-->(left,right)[[..30]]->code
7020 +dl #/root-->(left,right)
7021 +dl root->(left,right) => #/_-->(left,right)
7022 +dl root->(left->left,left->right,right->left,right->right)=> #/_-->(left,right)
7023 +## this cause very long symbolic vals, core dump/bad results before duel 1.10.3
7024 +dl #/(root+0000000000000000000000000000000000000000000000000000)-->(left,right)
7025 +## compute min, max, check for dups, no-show
7026 +dl root-->left[[#/root-->left-1]]->code
7027 +dl root-->right[[#/root-->right-1]]->code
7028 +dl int codes[11000] ; codes[..11000]=0 ; codes[root-->(left,right)->code]++ ;
7029 +dl codes[..11000] >? 1
7030 +dl (codes[..11000] ==? 0 )[[..10]]
7031 +dl (..11000 => if(!codes[_]) _)[[..10]]
7032 +## check consistency
7033 +dl root-->(left,right)->((left!=?0)->code >=? code, (right!=?0)->code <=? code)
7034 +dl root-->(left,right)->((left!=?0)->code>=code, (right!=?0)->code<=code)==?1
7035 +dl (1000..=>if(&&/( 2,3.._-1 =>__%_)) _)[[..10]]
7036 +## enums
7037 +dl ELA
7038 +dl (T us) 1
7039 +dl us=1 ; us
7040 +dl MIKI..ELA
7041 +## more errors
7042 +dl emp[0]=us
7043 +dl emp=us
7044 +dl us=emp
7045 +## the end
7046 +
7047 --- gdb/duel/tsuite.gdb.out
7048 +++ gdb/duel/tsuite.gdb.out
7049 @@ -0,0 +1,293 @@
7050 +GDB is free software and you are welcome to distribute copies of it
7051 + under certain conditions; type "show copying" to see the conditions.
7052 +There is absolutely no warranty for GDB; type "show warranty" for details.
7053 +GDB 4.8, Copyright 1993 Free Software Foundation, Inc.
7054 +(gdb) Reading symbols from tsuite...done.
7055 + Breakpoint 1 at 0x400518: file tsuite.c, line 60.
7056 + Note: breakpoint 1 also set at pc 0x400518.
7057 +Breakpoint 2 at 0x400518: file tsuite.c, line 61.
7058 + Starting program: /tmp_mnt/n/fs/grad2/mg/duel/tsuite/tsuite
7059 +
7060 +Breakpoint 1, main () at tsuite.c:61
7061 +61 printf("trivial tsuite program\n");
7062 + DUEL 1.10.4, public domain debugging language. "dl" for help
7063 +1*2 = 2
7064 +1*(2/3) = 0.66666667
7065 +2*2 = 4
7066 +2*(2/3) = 1.33333333
7067 +3*2 = 6
7068 +3*(2/3) = 2.0
7069 +4*2 = 8
7070 +4*(2/3) = 2.66666667
7071 +5*2 = 10
7072 +5*(2/3) = 3.33333333
7073 + x[20] = 402
7074 +x[21] = 443
7075 +x[22] = 486
7076 +x[23] = 531
7077 +x[38] = 1446
7078 +x[39] = 1523
7079 +x[40] = 1602
7080 + x[33] = 1091
7081 +x[34] = 1158
7082 + (x[33]>=33*33)&(x[33]<=35*35) = 1
7083 +(x[34]>=33*33)&(x[34]<=35*35) = 1
7084 + (*(x+7))++ = -1
7085 +(*(x+8))++ = -1
7086 +(*(x+9))++ = -1
7087 + y[0] = 0
7088 +y[1] = 0
7089 +y[2] = 0
7090 + x+7==y = 1
7091 + 1
7092 +2
7093 +3
7094 +4
7095 +5
7096 +6
7097 +7
7098 +8
7099 +9
7100 +10
7101 +x is: 402, 443, 486, 531, 578, 627, 678, 731, 786, 843, 902, 963, 1026, 1091, 1158, 1227, 1298, 1371, 1446, 1523, 1602,
7102 + x[37]=1371
7103 +x[38]=1446
7104 +x[39]=1523
7105 +x[40]=1602
7106 + &p = @10020020
7107 + p = @10020020
7108 +*p = void @10020020
7109 + 1e+++3
7110 +^ Invalid float constant.
7111 + Error: i=4 ;
7112 + -^-- operand x is not an lvalue for operator 'x=y'
7113 +operand ``i'' -- type: int
7114 + -- value: 40
7115 + Error: x=6 ;
7116 + -^-- bad operand x type for operator 'x=y'
7117 +operand ``x'' -- type: int [100]
7118 + -- value: array @1001f000
7119 + Error: x++ ;
7120 + -^-- operand x of '++' is not integral
7121 +operand ``x'' -- type: int [100]
7122 + -- value: array @1001f000
7123 + Error: --i ;
7124 + ^-- operand of '--' must be an lvalue
7125 +operand ``i'' -- type: int
7126 + -- value: 40
7127 + Aliases table:
7128 +p: p = @10020020
7129 +j: j = 100
7130 +y: &x[7] = @1001f01c
7131 +i: 40
7132 +x: x = array @1001f000
7133 + Aliases table cleared
7134 + s = "main string"
7135 + s[4] = ' '
7136 +s[5] = 's'
7137 +s[6] = 't'
7138 +s[7] = 'r'
7139 +s[8] = 'i'
7140 + s[6] = 't'
7141 +s[7] = 'r'
7142 +s[8] = 'i'
7143 +s[9] = 'n'
7144 +s[10] = 'g'
7145 + #/(s[0] ...) = 11
7146 + s[9] = 'n'
7147 +s[10] = 'g'
7148 +s[11] = '\0'
7149 + gint = 0
7150 + gint++ = 0
7151 + gint++ = 1
7152 + gint = 1
7153 + gint = 1
7154 + main.s = "main string"
7155 + main.s = "ain string"
7156 + main = func @004001f0
7157 + main==main = 1
7158 + frames_no = 1
7159 + frame(0).s = "ain string"
7160 + frame(0).(gint+0) = 1
7161 + sizeof(gint) = 0x4
7162 + sizeof(unsigned int) = 0x4
7163 + sizeof(T) = 0x4
7164 + sizeof(T) = 0x4b0
7165 + sizeof(emp) = 0x4b0
7166 + sizeof(emp[0]) = 0xc
7167 + -1 = 0xffffffff
7168 + (gint-9) = @fffffff8 [ILLEGAL]
7169 + *&gint = 0xfffffff8
7170 + -1 = 0xffffffff
7171 + Error: frame(0).gint
7172 + --------^-- field not found in operator '.'
7173 +operand ``frame(0)'' -- type: int
7174 + -- value: frame(0)
7175 + frame(0).(gint)
7176 +---------------^ syntax error
7177 + Error: frame(0).ha
7178 + --------^-- field not found in operator '.'
7179 +operand ``frame(0)'' -- type: int
7180 + -- value: frame(0)
7181 + Error: sizeof(uint)
7182 + -------^-- variable 'uint' not found
7183 + sizeof gint
7184 +-----------^ syntax error
7185 + Error: main == printf
7186 + -----^-- incompatible types for op ==
7187 +operand1 ``main'' -- type: ptr to func returning void
7188 + -- value: @004001f0
7189 +operand2 ``printf'' -- type: ptr to func returning int
7190 + -- value: @00400ca0
7191 + Error: main+1
7192 + ----^-- unknown pointer object size for '+' op
7193 +operand ``main'' -- type: ptr to func returning void
7194 + -- value: @004001f0
7195 + Error: main > printf
7196 + -----^-- incompatible types for op >
7197 +operand1 ``main'' -- type: ptr to func returning void
7198 + -- value: @004001f0
7199 +operand2 ``printf'' -- type: ptr to func returning int
7200 + -- value: @00400ca0
7201 + Error: printf+3
7202 + ------^-- unknown pointer object size for '+' op
7203 +operand ``printf'' -- type: ptr to func returning int
7204 + -- value: @00400ca0
7205 + T int x
7206 +-----^ syntax error
7207 + uint y
7208 +------^ syntax error
7209 + T uint z = 5
7210 +----------^ syntax error
7211 + emp[4] = { a = 4, b = 16, name = "emp004" }
7212 + emp[53].a = 76
7213 + emp[53] = { a = 76, b = 2809, name = "emp053" }
7214 + emp[53] = { a = 76, b = 2809, name = "emp053" }
7215 + emp[36].b = 1295
7216 + emp[36] = { a = 36, b = 1295, name = "emp036" }
7217 +emp[36].36*36 = 1296
7218 + emp[36] = { a = 36, b = 1295, name = "emp036" }
7219 +36*36 = 1296
7220 + (emp[74].name[3]) = '5'
7221 + (mystrcmp(emp[74].name,s)) = 5
7222 + (emp[74].name) = "emp574"
7223 + root->code = 5000
7224 +root->left->code = 986
7225 +root-->left[[2]]->code = 835
7226 +root-->left[[3]]->code = 684
7227 +root-->left[[4]]->code = 533
7228 +root-->left[[5]]->code = 383
7229 +root-->left[[6]]->code = 232
7230 +root-->left[[7]]->code = 81
7231 + root->code = 5000
7232 +root->left->code = 986
7233 +root-->left[[2]]->code = 835
7234 +root-->left[[3]]->code = 684
7235 +root-->left[[4]]->code = 533
7236 +root-->left[[5]]->code = 383
7237 +root-->left[[6]]->code = 232
7238 +root-->left[[7]]->code = 81
7239 +root-->left[[8]]->code = 12
7240 +root-->left[[9]]->code = 2
7241 +root-->left[[9]]->right->code = 5
7242 +root-->left[[9]]->right->left->code = 4
7243 +root-->left[[9]]-->right[[2]]->code = 11
7244 +root-->left[[9]]-->right[[2]]->left->code = 8
7245 +root-->left[[9]]-->right[[2]]-->left[[2]]->code = 7
7246 +root-->left[[9]]-->right[[2]]->left->right->code = 10
7247 +root-->left[[8]]->right->code = 24
7248 +root-->left[[8]]->right->left->code = 15
7249 +root-->left[[8]]->right-->left[[2]]->code = 14
7250 +root-->left[[8]]->right->left->right->code = 17
7251 +root-->left[[8]]->right->left->right->left->code = 16
7252 +root-->left[[8]]->right->left-->right[[2]]->code = 23
7253 +root-->left[[8]]->right->left-->right[[2]]->left->code = 20
7254 +root-->left[[8]]->right->left-->right[[2]]-->left[[2]]->code = 19
7255 +root-->left[[8]]->right->left-->right[[2]]->left->right->code = 22
7256 +root-->left[[8]]->right->left-->right[[2]]->left->right->left->code = 21
7257 +root-->left[[8]]-->right[[2]]->code = 36
7258 +root-->left[[8]]-->right[[2]]->left->code = 27
7259 +root-->left[[8]]-->right[[2]]->left->right->code = 35
7260 +root-->left[[8]]-->right[[2]]->left->right->left->code = 32
7261 + #/(root ...) = 7144
7262 + #/(root->left ...) = 3249
7263 +#/(root->right ...) = 3894
7264 + #/(root->(left->left) ...) = 641
7265 +#/(root->(left->right) ...) = 2607
7266 +#/(root->(right->left) ...) = 595
7267 +#/(root->(right->right) ...) = 3298
7268 + #/((root+0000000000000000000000000000000000000000000000000000) ...) = 7144
7269 + root-->left[[9]]->code = 2
7270 + root-->right[[14]]->code = 10999
7271 + codes[2122] = 2
7272 +codes[2308] = 2
7273 +codes[5081] = 2
7274 +codes[5267] = 2
7275 +codes[8040] = 2
7276 +codes[9026] = 2
7277 +codes[9363] = 2
7278 + (codes[0]) = 0
7279 +(codes[1]) = 0
7280 +(codes[3]) = 0
7281 +(codes[6]) = 0
7282 +(codes[9]) = 0
7283 +(codes[13]) = 0
7284 +(codes[18]) = 0
7285 +(codes[25]) = 0
7286 +(codes[26]) = 0
7287 +(codes[29]) = 0
7288 + 0
7289 +1
7290 +3
7291 +6
7292 +9
7293 +13
7294 +18
7295 +25
7296 +26
7297 +29
7298 + root->left-->right[[2]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code) = 2122
7299 +root->left-->right[[2]]-->left[[5]]-->right[[3]]->left->right->left->right->(left->code) = 2308
7300 +root->right-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code) = 5081
7301 +root->right-->left[[5]]-->right[[3]]->left->right->left->right->(left->code) = 5267
7302 +root-->right[[4]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code) = 8040
7303 +root-->right[[5]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code) = 9026
7304 +root-->right[[5]]-->left[[4]]-->right[[3]]->left->right->left->right->(left->code) = 9363
7305 + root->left-->right[[2]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code<=code) = 1
7306 +root->left-->right[[2]]-->left[[5]]-->right[[3]]->left->right->left->right->(left->code>=code) = 1
7307 +root->right-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code<=code) = 1
7308 +root->right-->left[[5]]-->right[[3]]->left->right->left->right->(left->code>=code) = 1
7309 +root-->right[[4]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code<=code) = 1
7310 +root-->right[[5]]-->left[[6]]->right->left-->right[[5]]->left->right->left->(right->code<=code) = 1
7311 +root-->right[[5]]-->left[[4]]-->right[[3]]->left->right->left->right->(left->code>=code) = 1
7312 + 1009
7313 +1013
7314 +1019
7315 +1021
7316 +1031
7317 +1033
7318 +1039
7319 +1049
7320 +1051
7321 +1061
7322 + ELA
7323 + 1 = DAVE
7324 + us = DAVE
7325 + 0
7326 +1
7327 +2
7328 + Error: emp[0]=us
7329 + ------^-- incompatible types for op x=y
7330 +operand1 ``emp[0]'' -- type: struct .F13 { int a ; int b ; char * name ; } ;
7331 + -- value: struct @10001510
7332 +operand2 ``us'' -- type: enum .F14
7333 + -- value: DAVE
7334 + Error: emp=us
7335 + ---^-- bad operand x type for operator 'x=y'
7336 +operand ``emp'' -- type: array [100] of struct .F13 { int a ; int b ; char * name ; } ;
7337 + -- value: array @10001510
7338 + Error: us=emp
7339 + --^-- operand x of 'y=x' is not numeric
7340 +operand ``emp'' -- type: array [100] of struct .F13 { int a ; int b ; char * name ; } ;
7341 + -- value: array @10001510
7342 +
7343 --- gdb/duel/tsuite.self
7344 +++ gdb/duel/tsuite.self
7345 @@ -0,0 +1,111 @@
7346 +## DUEL - A Very High Level Debugging Langauge.
7347 +## Public domain code
7348 +## Written by Michael Golan mg@××××××××××××.edu
7349 +## $Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $
7350 +
7351 +##
7352 +## test suite for duel, can be used with duelself or gdb
7353 +##
7354 +
7355 +## check constants
7356 +(1..5)*(2,(double) 2/3)
7357 +
7358 +## declare array x, set it, search it
7359 +
7360 +int x[100] ;
7361 +x[0..99]= -1 ;
7362 +x[i:=20..40]=2+i*i ;
7363 +x[20..23,38..40]
7364 +x[..100] >=? 33*33 <=? 35*35
7365 +x[..100]=> ((_>=33*33) & (_<= 35*35)) ==? 1
7366 +x
7367 +x+5
7368 +*(x+7..9)++
7369 +*(x+(7..9))++
7370 +(*(x+(7..9)))++
7371 +y:= &x[7] ;
7372 +y[0..2]
7373 +x+7 == y
7374 +(x[..99]>?0)@(_>500)
7375 +
7376 +printf("x is: "); printf("%d, ",x[0..99]>? 0); printf("\n");
7377 +int j ; for(j=0 ; j<100 ; j++) if(x[j]>37*37) printf("x[%d]=%d\n",j,x[j]);
7378 +
7379 +printf("%d, ",1..5); printf("\n");
7380 +
7381 +## check void type
7382 +void *p
7383 +p = &p
7384 +p,*p
7385 +
7386 +## errors
7387 +
7388 +1e++4
7389 +& &x
7390 +i=4 ;
7391 +x=6 ;
7392 +x++ ;
7393 +--i ;
7394 +
7395 +## cleanup
7396 +
7397 +alias
7398 +clear
7399 +
7400 +## access some variables
7401 +s
7402 +s[3..7]
7403 +s[5..]@0
7404 +l:=#/s[0..]@0
7405 +s[l-2..l]
7406 +
7407 +gint
7408 +gint++
7409 +gint++
7410 +--gint
7411 +gint
7412 +main.s
7413 +main.s++
7414 +main.s++
7415 +
7416 +main
7417 +printf
7418 +main ==? main
7419 +main == main
7420 +
7421 +frames_no
7422 +frame(0).s
7423 +
7424 +## gint is a global, not local fro main in frame 0
7425 +frame(0).gint
7426 +## but when we eval (expr) under frame 0 scope, we find it ok.
7427 +frame(0).(gint)
7428 +
7429 +T uint myuint ; myuint = -1
7430 +
7431 +sizeof(int)
7432 +sizeof(long)
7433 +sizeof(int *)
7434 +sizeof(signed char*)
7435 +sizeof()
7436 +sizeof(gint)
7437 +sizeof gint
7438 +sizeof gint+1
7439 +## some errors
7440 +
7441 +main == main
7442 +main == printf
7443 +
7444 +main+1
7445 +malloc[4]
7446 +printf+3
7447 +
7448 +T int x
7449 +int x
7450 +uint y
7451 +T uint y = 5
7452 +T uint y
7453 +
7454 +## the end
7455 +
7456 +
7457 --- gdb/duel/tsuite.self.out
7458 +++ gdb/duel/tsuite.self.out
7459 @@ -0,0 +1,263 @@
7460 +dl> ## DUEL - A Very High Level Debugging Langauge.
7461 +dl> ## Public domain code
7462 +dl> ## Written by Michael Golan mg@××××××××××××.edu
7463 +dl>
7464 +dl> ##
7465 +dl> ## test suite for duel, can be used with duelself or gdb
7466 +dl> ##
7467 +dl>
7468 +dl> ## check constants
7469 +dl> (1..5)*(2,(double) 2/3)
7470 +DUEL 1.10.4, public domain debugging language. "dl" for help
7471 +1*2 = 2
7472 +1*(2/3) = 0.66666667
7473 +2*2 = 4
7474 +2*(2/3) = 1.33333333
7475 +3*2 = 6
7476 +3*(2/3) = 2.0
7477 +4*2 = 8
7478 +4*(2/3) = 2.66666667
7479 +5*2 = 10
7480 +5*(2/3) = 3.33333333
7481 +dl>
7482 +dl> ## declare array x, set it, search it
7483 +dl>
7484 +dl> int x[100] ;
7485 +dl> x[0..99]= -1 ;
7486 +dl> x[i:=20..40]=2+i*i ;
7487 +dl> x[20..23,38..40]
7488 +x[20] = 402
7489 +x[21] = 443
7490 +x[22] = 486
7491 +x[23] = 531
7492 +x[38] = 1446
7493 +x[39] = 1523
7494 +x[40] = 1602
7495 +dl> x[..100] >=? 33*33 <=? 35*35
7496 +x[33] = 1091
7497 +x[34] = 1158
7498 +dl> x[..100]=> ((_>=33*33) & (_<= 35*35)) ==? 1
7499 +(x[33]>=33*33)&(x[33]<=35*35) = 1
7500 +(x[34]>=33*33)&(x[34]<=35*35) = 1
7501 +dl> x
7502 +x = array @10014000
7503 +dl> x+5
7504 +x+5 = @10014014
7505 +dl> *(x+7..9)++
7506 +Error: *(x+7..9)++
7507 + -----^-- operand x of 'x..y' is not integral
7508 +operand ``x+7'' -- type: int *
7509 + -- value: @1001401c
7510 +dl> *(x+(7..9))++
7511 +Error: *(x+(7..9))++
7512 + -----------^-- operand of '++' must be an lvalue
7513 +operand ``(x+7)'' -- type: int *
7514 + -- value: @1001401c
7515 +dl> (*(x+(7..9)))++
7516 +(*(x+7))++ = -1
7517 +(*(x+8))++ = -1
7518 +(*(x+9))++ = -1
7519 +dl> y:= &x[7] ;
7520 +dl> y[0..2]
7521 +y[0] = 0
7522 +y[1] = 0
7523 +y[2] = 0
7524 +dl> x+7 == y
7525 +x+7==y = 1
7526 +dl> (x[..99]>?0)@(_>500)
7527 +(x[20]) = 402
7528 +(x[21]) = 443
7529 +(x[22]) = 486
7530 +dl>
7531 +dl> printf("x is: "); printf("%d, ",x[0..99]>? 0); printf("\n");
7532 +x is: 402, 443, 486, 531, 578, 627, 678, 731, 786, 843, 902, 963, 1026, 1091, 1158, 1227, 1298, 1371, 1446, 1523, 1602,
7533 +dl> int j ; for(j=0 ; j<100 ; j++) if(x[j]>37*37) printf("x[%d]=%d\n",j,x[j]);
7534 +x[37]=1371
7535 +x[38]=1446
7536 +x[39]=1523
7537 +x[40]=1602
7538 +dl>
7539 +dl> printf("%d, ",1..5); printf("\n");
7540 +1, 2, 3, 4, 5,
7541 +dl>
7542 +dl> ## check void type
7543 +dl> void *p
7544 +dl> p = &p
7545 +&p = @10012138
7546 +dl> p,*p
7547 +p = @10012138
7548 +*p = void @10012138
7549 +dl>
7550 +dl> ## errors
7551 +dl>
7552 +dl> 1e++4
7553 +1e++4
7554 +^ Invalid float constant.
7555 +dl> & &x
7556 +Error: & &x
7557 + ^-- operand x of '&x' is not a lvalue
7558 +operand ``&x'' -- type: ptr to int [100]
7559 + -- value: @10014000
7560 +dl> i=4 ;
7561 +Error: i=4 ;
7562 + -^-- operand x is not an lvalue for operator 'x=y'
7563 +operand ``i'' -- type: int
7564 + -- value: 40
7565 +dl> x=6 ;
7566 +Error: x=6 ;
7567 + -^-- bad operand x type for operator 'x=y'
7568 +operand ``x'' -- type: int [100]
7569 + -- value: array @10014000
7570 +dl> x++ ;
7571 +Error: x++ ;
7572 + -^-- operand x of '++' is not integral
7573 +operand ``x'' -- type: int [100]
7574 + -- value: array @10014000
7575 +dl> --i ;
7576 +Error: --i ;
7577 + ^-- operand of '--' must be an lvalue
7578 +operand ``i'' -- type: int
7579 + -- value: 40
7580 +dl>
7581 +dl> ## cleanup
7582 +dl>
7583 +dl> alias
7584 +Aliases table:
7585 +p: p = @10012138
7586 +j: j = 100
7587 +y: &x[7] = @1001401c
7588 +i: 40
7589 +x: x = array @10014000
7590 +dl> clear
7591 +Aliases table cleared
7592 +dl>
7593 +dl> ## access some variables
7594 +dl> s
7595 +s = "main string"
7596 +dl> s[3..7]
7597 +s[3] = 'n'
7598 +s[4] = ' '
7599 +s[5] = 's'
7600 +s[6] = 't'
7601 +s[7] = 'r'
7602 +dl> s[5..]@0
7603 +s[5] = 's'
7604 +s[6] = 't'
7605 +s[7] = 'r'
7606 +s[8] = 'i'
7607 +s[9] = 'n'
7608 +s[10] = 'g'
7609 +dl> l:=#/s[0..]@0
7610 +#/(s[0] ...) = 11
7611 +dl> s[l-2..l]
7612 +s[9] = 'n'
7613 +s[10] = 'g'
7614 +s[11] = '\0'
7615 +dl>
7616 +dl> gint
7617 +gint = 0
7618 +dl> gint++
7619 +gint++ = 0
7620 +dl> gint++
7621 +gint++ = 1
7622 +dl> --gint
7623 +gint = 1
7624 +dl> gint
7625 +gint = 1
7626 +dl> main.s
7627 +main.s = "main string"
7628 +dl> main.s++
7629 +main.s++ = "main string"
7630 +dl> main.s++
7631 +main.s++ = "ain string"
7632 +dl>
7633 +dl> main
7634 +main = func @00400918
7635 +dl> printf
7636 +printf = func @004112b0
7637 +dl> main ==? main
7638 +main = func @00400918
7639 +dl> main == main
7640 +main==main = 1
7641 +dl>
7642 +dl> frames_no
7643 +frames_no = 1
7644 +dl> frame(0).s
7645 +frame(0).s = "in string"
7646 +dl>
7647 +dl> ## gint is a global, not local fro main in frame 0
7648 +dl> frame(0).gint
7649 +Error: frame(0).gint
7650 + --------^-- field not found in operator '.'
7651 +operand ``frame(0)'' -- type: int
7652 + -- value: frame(0)
7653 +dl> ## but when we eval (expr) under frame 0 scope, we find it ok.
7654 +dl> frame(0).(gint)
7655 +frame(0).(gint)
7656 +---------------^ syntax error
7657 +dl>
7658 +dl> T uint myuint ; myuint = -1
7659 +-1 = 0xffffffff
7660 +dl>
7661 +dl> sizeof(int)
7662 +sizeof(int) = 0x4
7663 +dl> sizeof(long)
7664 +sizeof(long) = 0x4
7665 +dl> sizeof(int *)
7666 +sizeof(T) = 0x4
7667 +dl> sizeof(signed char*)
7668 +sizeof(T) = 0x4
7669 +dl> sizeof()
7670 +sizeof()
7671 +--------^ syntax error
7672 +dl> sizeof(gint)
7673 +sizeof(gint) = 0x4
7674 +dl> sizeof gint
7675 +sizeof gint
7676 +-----------^ syntax error
7677 +dl> sizeof gint+1
7678 +sizeof gint+1
7679 +-----------^ syntax error
7680 +dl> ## some errors
7681 +dl>
7682 +dl> main == main
7683 +main==main = 1
7684 +dl> main == printf
7685 +Error: main == printf
7686 + -----^-- incompatible types for op ==
7687 +operand1 ``main'' -- type: ptr to func returning void
7688 + -- value: @00400918
7689 +operand2 ``printf'' -- type: ptr to func returning int
7690 + -- value: @004112b0
7691 +dl>
7692 +dl> main+1
7693 +Error: main+1
7694 + ----^-- unknown pointer object size for '+' op
7695 +operand ``main'' -- type: ptr to func returning void
7696 + -- value: @00400918
7697 +dl> malloc[4]
7698 +Error: malloc[4]
7699 + ------^-- unknown pointer object size for '+' op
7700 +operand ``malloc'' -- type: ptr to func returning void *
7701 + -- value: @00411310
7702 +dl> printf+3
7703 +Error: printf+3
7704 + ------^-- unknown pointer object size for '+' op
7705 +operand ``printf'' -- type: ptr to func returning int
7706 + -- value: @004112b0
7707 +dl>
7708 +dl> T int x
7709 +T int x
7710 +-----^ syntax error
7711 +dl> int x
7712 +dl> uint y
7713 +uint y
7714 +------^ syntax error
7715 +dl> T uint y = 5
7716 +T uint y = 5
7717 +----------^ syntax error
7718 +dl> T uint y
7719 +dl>
7720 +dl> ## the end
7721 +dl>
7722 +dl>
7723 --- gdb/duel/types.c
7724 +++ gdb/duel/types.c
7725 @@ -0,0 +1,202 @@
7726 +/* DUEL - A Very High Level Debugging Langauge. */
7727 +/* Public domain code */
7728 +/* Written by Michael Golan mg@××××××××××××.edu */
7729 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
7730 +
7731 +/* this module contains the duel type system management
7732 + */
7733 +
7734 +/*
7735 + * $Log: 10_all_gdb-6.6-duel.patch,v $
7736 + * Revision 1.1 2007/12/29 21:06:06 vapier
7737 + * add DUEL support #199987 by Sergei Golubchik
7738 + *
7739 + * Revision 1.8 93/03/12 06:01:50 mg
7740 + * use tuint for uint etc
7741 + *
7742 + * Revision 1.7 93/02/03 21:55:26 mg
7743 + * support "signed char"
7744 + *
7745 + * Revision 1.6 93/01/12 21:54:25 mg
7746 + * cleanup and set for release
7747 + *
7748 + * Revision 1.5 93/01/03 07:31:24 mg
7749 + * *** empty log message ***
7750 + *
7751 + * Revision 1.4 92/10/19 15:09:28 mg
7752 + * support zero fields/enumerators because gdb have them sometimes.
7753 + *
7754 + * Revision 1.3 92/10/14 02:07:00 mg
7755 + * misc
7756 + *
7757 + * Revision 1.2 92/09/16 11:11:43 mg
7758 + * added builtin charptr type
7759 + *
7760 + */
7761 +
7762 +#include "duel.h"
7763 +
7764 +FUNC tctype* duel_mkctype_ptr(tctype *t)
7765 +{
7766 + tctype *n ;
7767 + n=(tctype *) duel_malloc(sizeof(tctype));
7768 + duel_bzero((char*) n,sizeof(tctype));
7769 + n->type_kind=CTK_PTR ;
7770 + n->size=sizeof(void*);
7771 + n->u.kid=t ;
7772 + return n ;
7773 +}
7774 +
7775 +FUNC tctype* duel_mkctype_func(tctype *t)
7776 +{
7777 + tctype *n ;
7778 + n=(tctype *) duel_malloc(sizeof(tctype));
7779 + duel_bzero((char*) n,sizeof(tctype));
7780 + n->size=0 ;
7781 + n->type_kind=CTK_FUNC ;
7782 + n->u.kid=t ;
7783 + return n ;
7784 +}
7785 +
7786 +/* create a struct or union type. The fields are not set here, but
7787 + * filled individually with the next function
7788 + * note the having zero fields is supported. This shouldnt be legal in C
7789 + * but compilers allow pointer to sturct w/o every specifying the struct.
7790 + * this is especially true for gdb itself!
7791 + */
7792 +
7793 +FUNC tctype* duel_mkctype_struct(char *name,size_t size,int fields_no,
7794 + bool is_union)
7795 +{
7796 + tctype *n ;
7797 + n=(tctype *) duel_malloc(sizeof(tctype));
7798 + duel_bzero((char*) n,sizeof(tctype));
7799 + n->name=name ;
7800 + n->size=size ;
7801 + if(is_union) n->type_kind=CTK_UNION ;
7802 + else n->type_kind=CTK_STRUCT ;
7803 + n->u.f.fields_no=fields_no ;
7804 + if(fields_no==0) n->u.f.fields=NULL ;
7805 + else {
7806 + n->u.f.fields=(tctype_field *) duel_malloc(fields_no*sizeof(tctype_field));
7807 + duel_bzero((char*) n->u.f.fields,fields_no*sizeof(tctype_field));
7808 + }
7809 + return n ;
7810 +}
7811 +
7812 +/* insert field (field_no) into sturct/union (t), with type fctype
7813 + */
7814 +PROC duel_mkctype_struct_field(tctype *t,int field_no,char *name,
7815 + int bitpos,int bitlen, tctype *fctype)
7816 +{
7817 + tctype_field *f ;
7818 + duel_assert(t->type_kind==CTK_STRUCT || t->type_kind==CTK_UNION);
7819 + duel_assert(field_no>=0 && field_no <= t->u.f.fields_no);
7820 + f= &t->u.f.fields[field_no] ;
7821 + f->name=name ;
7822 + f->bitpos=bitpos ;
7823 + f->bitlen=bitlen ;
7824 + f->ctype=fctype ;
7825 +}
7826 +
7827 +/* create an enum type. The enumerators are not set here, but
7828 + * filled individually with the next function
7829 + * again like sturct, we support zero enums. I am not sure its needed,
7830 + * but better safe than sorry.
7831 + */
7832 +
7833 +FUNC tctype* duel_mkctype_enum(char *name,tctype_kind real_type_kind,
7834 + size_t size,int enumerators_no)
7835 +{
7836 + tctype *n ;
7837 + n=(tctype *) duel_malloc(sizeof(tctype));
7838 + duel_bzero((char*) n,sizeof(tctype));
7839 + n->name=name ;
7840 + n->size=size ;
7841 + n->type_kind=CTK_ENUM ;
7842 + n->u.e.real_type_kind=real_type_kind ;
7843 + n->u.e.enumerators_no=enumerators_no ;
7844 + if(enumerators_no==0) n->u.e.enumerators=NULL ;
7845 + else {
7846 + n->u.e.enumerators= (tctype_enumerator *)
7847 + duel_malloc(enumerators_no*sizeof(tctype_enumerator));
7848 + duel_bzero((char*) n->u.e.enumerators,
7849 + enumerators_no*sizeof(tctype_enumerator));
7850 + }
7851 + return n ;
7852 +}
7853 +
7854 +
7855 +/* insert enumerator (enumerator_no_ into an enum type (t), with given name/val
7856 + */
7857 +PROC duel_mkctype_enumerator(tctype *t,int enumerator_no,char *name,int val)
7858 +{
7859 + tctype_enumerator *e ;
7860 + duel_assert(t->type_kind==CTK_ENUM);
7861 + duel_assert(enumerator_no>=0 && enumerator_no <= t->u.e.enumerators_no);
7862 + e= &t->u.e.enumerators[enumerator_no] ;
7863 + e->name=name ;
7864 + e->val=val ;
7865 +}
7866 +
7867 +FUNC tctype* duel_mkctype_array(tctype *t,int size)
7868 +{
7869 + tctype *n ;
7870 + if(t->size==0) duel_gen_error("array of a type of zero size is illegal",0);
7871 + if(size<=0) duel_gen_error("array of size zero or negative is illegal",0);
7872 + n=(tctype *) duel_malloc(sizeof(tctype));
7873 + duel_bzero((char*) n,sizeof(tctype));
7874 + n->type_kind=CTK_ARRAY ;
7875 + n->size=size*t->size ;
7876 + n->u.kid=t ;
7877 + return n ;
7878 +}
7879 +
7880 +
7881 +LFUNC tctype* init_basic_ctype(tctype_kind tk,char *name,size_t size)
7882 +{
7883 + tctype *p = duel_malloc(sizeof(tctype));
7884 + p->type_kind=tk ;
7885 + p->name=name ;
7886 + p->size=size ;
7887 + return p ;
7888 +}
7889 +
7890 +PROC duel_init_basic_ctypes(void)
7891 +{
7892 + ctype_void= init_basic_ctype(CTK_VOID, "void", 0);
7893 +
7894 + ctype_char =init_basic_ctype(CTK_CHAR, "char", sizeof(char));
7895 + ctype_short =init_basic_ctype(CTK_SHORT, "short",sizeof(short));
7896 + ctype_int =init_basic_ctype(CTK_INT, "int", sizeof(int));
7897 + ctype_long =init_basic_ctype(CTK_LONG, "long", sizeof(long));
7898 + ctype_longlong=init_basic_ctype(CTK_LONGLONG,"long long", sizeof(long long));
7899 +
7900 + ctype_schar =init_basic_ctype(CTK_SCHAR, "signed char", sizeof(tschar));
7901 + ctype_uchar =init_basic_ctype(CTK_UCHAR, "unsigned char", sizeof(tuchar));
7902 + ctype_ushort =init_basic_ctype(CTK_USHORT, "unsigned short",sizeof(tushort));
7903 + ctype_uint =init_basic_ctype(CTK_UINT, "unsigned int", sizeof(tuint));
7904 + ctype_ulong =init_basic_ctype(CTK_ULONG, "unsigned long", sizeof(tulong));
7905 + ctype_ulonglong=init_basic_ctype(CTK_ULONG, "unsigned long long", sizeof(tulonglong));
7906 +
7907 + ctype_double=init_basic_ctype(CTK_DOUBLE, "double", sizeof(double));
7908 + ctype_float =init_basic_ctype(CTK_FLOAT, "float", sizeof(float));
7909 +
7910 + ctype_voidptr=duel_mkctype_ptr(ctype_void);
7911 + ctype_charptr=duel_mkctype_ptr(ctype_char);
7912 + /* find and set the special types.
7913 + * support only a signed ptrdiff; size_t/ptrdiff must both be int or long
7914 + */
7915 + { ptrdiff_t p ; size_t s ;
7916 + p= -1 ; s= -1 ;
7917 + if(p>0) duel_gen_error("bad ptrdiff_t - unsigned",0);
7918 +
7919 + if(sizeof(p)==sizeof(int)) ctype_ptrdiff_t=ctype_int ;
7920 + else if(sizeof(p)==sizeof(long)) ctype_ptrdiff_t=ctype_long ;
7921 + else duel_gen_error("bad ptrdiff_t size",0);
7922 +
7923 + if(sizeof(s)==sizeof(int)) ctype_size_t= (s<0)? ctype_int:ctype_uint ;
7924 + else
7925 + if(sizeof(s)==sizeof(long)) ctype_size_t= (s<0)? ctype_long:ctype_ulong ;
7926 + else duel_gen_error("bad size_t size",0);
7927 + }
7928 +}
7929 +
7930 +
7931 --- gdb/duel/wishlist.doc
7932 +++ gdb/duel/wishlist.doc
7933 @@ -0,0 +1,160 @@
7934 +
7935 + += -= etc operators
7936 + initialize variables e.g. int x=0 , maybe even scopes
7937 + set declared var to zero.
7938 + allow x++ for aliases as a special case.
7939 + x->?y or x?->y to be like (x!=?0)->y OR x?? or ??x as (x!=?0)
7940 +
7941 + +/ */ &/ |/ ^/ ==/ !=/ </ >/ <=/ >=/
7942 + src(location) as scope
7943 + istype(type,x) to check type of x
7944 + ?x to check for x in current scope
7945 + conditional break points, watchpoints
7946 + better type checking of structs.
7947 + bitfield assignment
7948 + better builtin commands, help
7949 + output formatting, duel/xodus, more general out(v)
7950 + duel macros/functions
7951 + \x and \\x
7952 + check array bounds
7953 + x->>y x->-y x>--y
7954 + check cycles in --> expansion
7955 + ..:+ ..:-
7956 + print types, do so better
7957 +
7958 +DUEL.PIPE - make it general purpose
7959 +------------------------------------
7960 +see duel.pipe for some details.
7961 +should be made general purpose, so it is easy to modify/add functions.
7962 +many basic functions can be writted - sort, uniq, matrix, vector,
7963 +compress, etc.
7964 +
7965 +Checking for cycles in --> expansion
7966 +------------------------------------
7967 +One can easily add code to handle head-->(next!=?head), as well as
7968 +head-->(next!=?_). If you don't know what these do, you should RTFM again :-)
7969 +
7970 +You can also keep all pointers that have been expanded already,
7971 +hence detecting any kind of cycle. However, what to do in
7972 +such cases is debatable. Some users would like to see
7973 +cycles terminate expansion quietly, while others will want a fatal error
7974 +to be produced. This could be handled by an operator like x-->?y which
7975 +would indicate that cycles are ok and expansion should terminate quietly,
7976 +while x-->y produce an error on cycles.
7977 +
7978 +Another idea is to have _cyc defined inside -->, to allow the user to
7979 +do something about cycles, e.g. head-->(if(!_cyc) next). There are
7980 +several ways to manage _cyc: a boolean, or equal to head; true if
7981 +this is already a cycle, or a function cyc(next), which return true if
7982 +next would cycle, or return next unles it would cycle, etc.
7983 +This last one seems to handle most cases:
7984 +head-->(cyc(left),cyc(right)) - return tree, igoring cycles
7985 +head-->(cyc(0),left,right) - like head->(left,right), but mention of cyc
7986 + which by itself does nothing, cause general
7987 + cycle detection as errors
7988 +as above, but left!=?_ - detect general cycles, pointer to self ok
7989 +
7990 +While we adding cyc(), we can also add _depth to indicate current depth,
7991 +e.g. head-->(if(_depth<6) (left,right)) -- expand only to depth 6
7992 +and also acceess to the current path with _path(i), _path(0)=_ and
7993 +_path(_depth-1)=head
7994 +head-->(cyc(0), if(! ||/_path(.._deapth)==left) left, ...)
7995 + which avoids cycles "in the path"
7996 +
7997 +If you an strong opinion on this subject, or a better idea, lemme know!
7998 +
7999 +Other expansions: x->>y x->-y x>--y
8000 +------------------------------------
8001 +x-->y applies DFS (Depth First Search). Another useful expansion would be
8002 +BFS (Breath First Search). It is simple to implement - y's values should
8003 +be put on a queue instead of a stack, and the code in place has been written
8004 +with this in mind (eval.c).
8005 +Others will probably want a post-order or in-order search instead of preorder
8006 +search as done by x-->y. I am not sure this is important enough to merit
8007 +new operators, but ->- for inorder and >-- for post order are reserved.
8008 +These, too, should be easy to implement, but it is very unclear that the
8009 +added complexity to the language is worth it. If you really need such
8010 +operators, lemme know.
8011 +
8012 +Increment count for x..y (x..y:+z and x..y:-z)
8013 +------------------------------------------------
8014 +The x..y operator could be extended to support an increment or decrement
8015 +value. This would allow 1..n to be written as 1..n:+1 so when n==0 it
8016 +will not produce the surprising 1,0 results.
8017 +However, 0..10:+2 could also be written as (0..5)*2, so it is unclear
8018 +that such operators are really needed (maybe just x..+y, x..-y to force
8019 +the direction).
8020 +
8021 +
8022 +Duel functions / print procedures
8023 +-------------------------------------
8024 +the command: dl define x expr
8025 +will define x to be duel procedure for expression expr.
8026 +x can then be used like an alias (indeed, it will probably be kept in
8027 +the alias table with a special value). x evaluation returns multiple
8028 +values.
8029 +There is no need parameters, since emp.x would call "x" using the implicit
8030 +parameter "_" set as emp. the expression for x is essentially put into
8031 +the code for the execution. Having no parameters (except implicit ones)
8032 +make it easier to document, use etc.
8033 +
8034 +Such functions (macros?) are most useful for output. e.g.
8035 +dl define empout val_type,a, u.if(val_type==0) code*6,name else code,z
8036 +dl emp.empout
8037 +will produce output for
8038 + struct {
8039 + int val_type,code ;
8040 + char a;
8041 + union { char *name ; double z ; } u
8042 + } emp ;
8043 +
8044 +the empout procedure can be defined just once, and used to output such
8045 +unions as needed.
8046 +
8047 +The next step is to call such functions automatically for output and
8048 +for expansion. We add syntax like dl define out(type) expr
8049 +
8050 +then whenever an expression of the given type is to be printed, this
8051 +code is evaluated instead, e.g.:
8052 +dl define out(struct emp) ...
8053 +dl emp ## this calls the above out code for the output.
8054 +
8055 +We can also expand expressions by calling the right function, e.g.
8056 +The operator "\" calls a function to expand a specific type:
8057 +dl define \(struct list *) (_-->next)
8058 +dl if(\head#i == \head#j && i<j) \head[[i,j]]
8059 +
8060 +instead of writing this code (find non unique elements of linked list):
8061 + if(head-->next#i == head-->next#j && i<j) head-->next[[i,j]]
8062 +
8063 +Both printing and expansion occurs automatically based on TYPE.
8064 +It is unclear if the an array is allowed to be expanded by a pointer
8065 +type expansion or not (i.e. is \(int *) to expand "int x[40]").
8066 +this might require an extension to types allowing \(int [n]) which matches
8067 +any int array and set n for the specific bound. Types could be extended
8068 +in a similar way, e.g. \(type **) _[0..]@0
8069 +which expands any array of pointers (e.g. argv).
8070 +This can quickly require scope-nesting for local aliases/variables.
8071 +
8072 +As before, it is unclear what of these is useful. Unless people depends on
8073 +duel heavily, and write such "output/expansion" functions for the project,
8074 +the features are useless (who is going to use this interactively?)
8075 +
8076 +Regular expressions for names. $xxx and `xxx`
8077 +----------------------------------------------
8078 +this allows things like emp.`value_*` to return all the value_something
8079 +fields. it is really useful with structs, especially if a grep-style hat (^)
8080 +is supported. Obviously extends to func.rexp, to show all locals, etc,
8081 +which will make it possible to write a stack-trace display in duel.
8082 +
8083 +exact semantics (e.g. what is matched and how) unclear.
8084 +
8085 +
8086 +Nicer #/
8087 +---------
8088 +
8089 +hash[..1024] => #/_-->next >? 2
8090 +
8091 +it is probably best if #/(exp) constructed (exp) as symbolic before it
8092 +gets the values. or maybe, yes, best is #/(e) symbolic is #/(e1..en)
8093 +where e1 is the first return symbolc, en the last.
8094 --- gdb/duelgdb.c
8095 +++ gdb/duelgdb.c
8096 @@ -0,0 +1,694 @@
8097 +/* DUEL - A Very High Level Debugging Langauge. */
8098 +/* Public domain code */
8099 +/* Written by Michael Golan mg@××××××××××××.edu */
8100 +/*$Header: /var/cvsroot/gentoo/src/patchsets/gdb/6.7.1/10_all_gdb-6.6-duel.patch,v 1.1 2007/12/29 21:06:06 vapier Exp $*/
8101 +
8102 +/* debugger dependent module, it contains all of duel's access to
8103 + * the outside world (debuggee, symbol table, etc)
8104 + */
8105 +
8106 +/*
8107 + * $Log: 10_all_gdb-6.6-duel.patch,v $
8108 + * Revision 1.1 2007/12/29 21:06:06 vapier
8109 + * add DUEL support #199987 by Sergei Golubchik
8110 + *
8111 + * Revision 1.30 08/11/14 23:14:00 serg
8112 + * ported to gdb 6.6.2, glibc 2.5
8113 + *
8114 + * Revision 1.20 93/03/20 10:35:48 mg
8115 + * fixed system("date")... didnt work on OS/2
8116 + *
8117 + * Revision 1.19 93/03/13 03:28:49 mg
8118 + * bug fixed frame(0).unknown_name caused a crash
8119 + * bug fixed duel didnt support enum of length zero but turns out gdb tables
8120 + * have such things (specifically, for some gdb internals!)
8121 + *
8122 + * Revision 1.18 93/03/12 05:43:22 mg
8123 + * Version 1.10 - tuint instead of uint etc, fixed gdb48 recognis. problem
8124 + *
8125 + * Revision 1.17 93/02/27 06:01:01 mg
8126 + * improved unsigned char default machines support,
8127 + * convert explicit uchar into "char" if they are the same.
8128 + *
8129 + * Revision 1.16 93/02/23 19:11:10 mg
8130 + * beauty changes + gdb4.8 support
8131 + *
8132 + * Revision 1.15 93/02/04 02:09:18 mg
8133 + * fixed enum enum names
8134 + *
8135 + * Revision 1.14 93/02/04 00:54:26 mg
8136 + * arr. fixed.
8137 + *
8138 + * Revision 1.13 93/02/03 21:54:14 mg
8139 + * create duel.out unless compiling with NO_DUEL_OUT
8140 + *
8141 + * Revision 1.12 93/02/03 21:46:33 mg
8142 + * fixed problems with null gdb type names.
8143 + * support "signed char"
8144 + *
8145 + * Revision 1.11 93/01/21 21:22:15 mg
8146 + * *** empty log message ***
8147 + *
8148 + * Revision 1.10 93/01/13 16:19:33 mg
8149 + * support mini symbol table lookup (malloc, printf on SUN didnt work)
8150 + *
8151 + * Revision 1.9 93/01/12 21:30:04 mg
8152 + * cleanup and set for release
8153 + *
8154 + * Revision 1.8 93/01/06 23:59:21 mg
8155 + * new memory alloc/release. moved target's malloc into duel code
8156 + * allow ^c to work, fixed help, fixed variable lookup for specific frame.
8157 + *
8158 + * Revision 1.7 93/01/03 07:27:11 mg
8159 + * support function calls!
8160 + *
8161 + * Revision 1.6 92/12/24 23:33:13 mg
8162 + * frames support
8163 + *
8164 + * Revision 1.5 92/10/19 15:06:29 mg
8165 + * made lcc happy
8166 + * no svalues
8167 + * new registers support and way of getting vars.
8168 + * these are temporary changes, new frames supports soon
8169 + *
8170 + * Revision 1.4 92/10/14 02:03:53 mg
8171 + * misc/gdb4.6/duel vars using malloc
8172 + *
8173 + * Revision 1.3 92/09/16 11:06:22 mg
8174 + * a lot more functions: get typedef/tags, alloc debuggee mem. +cosmetics
8175 + *
8176 + * Revision 1.2 92/09/15 05:37:28 mg
8177 + * fix enum size bug. added headers
8178 + *
8179 + */
8180 +
8181 +
8182 +#include <stddef.h> /* used for ptrdiff_t and size_t */
8183 +#include <stdio.h>
8184 +#include <string.h>
8185 +#include <time.h> /* for time/ctime stamping of duel.out */
8186 +#include <assert.h>
8187 +
8188 +#include "defs.h"
8189 +#include "symtab.h"
8190 +#include "gdbtypes.h"
8191 +#include "gdbcore.h"
8192 +#include "frame.h"
8193 +#include "target.h"
8194 +#include "value.h"
8195 +#include "symfile.h"
8196 +#include "objfiles.h"
8197 +#include "gdbcmd.h"
8198 +#include "call-cmds.h"
8199 +#include "infcall.h"
8200 +
8201 +#include "duel/global.h"
8202 +#include "duel/proto.h"
8203 +
8204 +/* all output goes thru here */
8205 +
8206 +#include <stdarg.h>
8207 +
8208 +PROC duel_printf(char *fmt, ...) /* like printf, but for duel output */
8209 +{
8210 + va_list args;
8211 + va_start(args, fmt);
8212 + vprintf_filtered(fmt,args);
8213 + va_end(args);
8214 +}
8215 +
8216 +PROC duel_flush(void)
8217 +{ /* not yet. only really needed for redirections */
8218 +}
8219 +
8220 +PROC duel_redirectable_output_start(char *s)
8221 +{
8222 +}
8223 +
8224 +PROC duel_redirectable_output_end(void)
8225 +{
8226 +}
8227 +
8228 +PROC duel_redirectable_output_abort(void)
8229 +{
8230 +}
8231 +
8232 +PROC duel_redirectable_output_init(void)
8233 +{
8234 +}
8235 +
8236 +/* all duel memory allocations go thru here */
8237 +
8238 +FUNC void* duel_malloc(size_t size)
8239 +{
8240 + void *p ;
8241 + immediate_quit-- ; /* disable ^C while xmalloc */
8242 + p=xmalloc(size); /* gdb's malloc, incl zero return chk */
8243 + immediate_quit++ ;
8244 + QUIT ; /* check if ^C while xmalloc called */
8245 + return p ;
8246 +}
8247 +
8248 +PROC duel_free(void *p)
8249 +{
8250 + immediate_quit-- ;
8251 + free(p);
8252 + immediate_quit++ ;
8253 + QUIT ;
8254 +}
8255 +
8256 +/* fetch n bytes from the target at the given memory address.
8257 + * the address to fetch from is given by (from).
8258 + * the value is stored at the 'to' location, which points to space for
8259 + * n bytes in the debugger.
8260 + * if the address can not be accessed, false is returned (if all ok, ret true)
8261 + */
8262 +
8263 +FUNC bool duel_get_target_bytes(ttarget_ptr from,void *to,size_t n)
8264 +{
8265 + return target_read_memory((CORE_ADDR)from,to,n)==0;
8266 +}
8267 +
8268 +/* store n bytes to the debuggee. reverse parms from above */
8269 +FUNC bool duel_put_target_bytes(ttarget_ptr to,void *from,size_t n)
8270 +{
8271 + return target_write_memory((CORE_ADDR)to,from,n)==0;
8272 +}
8273 +
8274 +/* fetch the value of a bitfield of a given structure.
8275 + * struct_at - a pointer to the structure
8276 + * bitpos - the position of the field, in bits (as given in the type)
8277 + * bitlen - the length of the field in bits
8278 + * to - pointer to tuint where value will be stored.
8279 + * tkind - the type kind of the field (used to do sign extention if needed)
8280 + * note: I'm unaware of any compiler with bitfields that are not int/tuint.
8281 + */
8282 +
8283 +FUNC bool duel_get_target_bitfield(ttarget_ptr struct_at,int bitpos,
8284 + int bitlen,void *to,tctype_kind tkind)
8285 +{
8286 + tuint bits ;
8287 + duel_assert(tkind==CTK_INT || tkind==CTK_UINT);
8288 + if(!duel_get_target_bytes(struct_at+bitpos/8,&bits,sizeof(bits)))
8289 + return FALSE;
8290 +
8291 + /* now, move the field to the 'bottom' of bits, by shifting right */
8292 + bitpos%=8 ; /* fix it to a bit offset inside the 'bits' */
8293 + if (BITS_BIG_ENDIAN) /* defined by gdb's src code */
8294 + bits >>= (sizeof(bits)*8-bitpos-bitlen) ;
8295 + else
8296 + bits >>= bitpos ;
8297 +
8298 + /* finally chop down 'bits' to only bitlen significant bits,
8299 + * or sign-extend it if output field is 'int' and the sign is 1.
8300 + * ~0 is all ones, shift it to have bitlen zeros. Complement to get
8301 + * a bitlen string of 1's in the low-order bits. Common ugly hacks.
8302 + * Note: this code assume 2's complement
8303 + */
8304 +
8305 + if(tkind==CTK_INT && (bits & 1<<(bitlen-1))) /* int field, negative sign */
8306 + bits|= ~0<<bitlen ; /*sign extend */
8307 + else bits&= ~(~0<<bitlen) ; /* clear all bits above the sign bit */
8308 + *(tuint*) to= bits ;
8309 +
8310 + return TRUE ;
8311 +}
8312 +
8313 +LFUNC struct type* duel_convert_type_to_gdb(tctype *ct);
8314 +LFUNC tctype* duel_convert_type_from_gdb(struct type *gv);
8315 +
8316 +/* convert gdb value into duel's. Used to fetch const, registers, func ret val
8317 + * and convert a symbol into a reference.
8318 + * otherwise, duel access target's memory directly.
8319 + */
8320 +
8321 +LPROC duel_convert_value_from_gdb(struct value *gv, tvalue *dv)
8322 +{
8323 + dv->ctype=duel_convert_type_from_gdb(value_type(gv));
8324 + if(VALUE_LVAL(gv) == lval_memory) {
8325 + dv->val_kind=VK_LVALUE ;
8326 + dv->u.lvalue= (ttarget_ptr) VALUE_ADDRESS(gv) ; /*address of variable*/
8327 + }
8328 + else
8329 + if(ctype_kind_scalar(dv->ctype) && (VALUE_LVAL(gv) == not_lval ||
8330 + VALUE_LVAL(gv) == lval_register)) {
8331 + dv->val_kind=VK_RVALUE ;
8332 + duel_bcopy(&dv->u,value_contents_raw(gv),dv->ctype->size);
8333 + }
8334 + else
8335 + duel_fatal("unsupported value type returned by gdb");
8336 +}
8337 +
8338 +
8339 +/* helper function converts duel values to gdb's values. used only to make
8340 + * function calls to the target, so current support is weak.
8341 + * gdb thinks long=int=pointers, so we go along with that.
8342 + * To support arbitrary types like struct/union, we can probably fake it
8343 + * by making a gdb lvalue. but i am not sure how/what
8344 + */
8345 +
8346 +LFUNC struct value *convert_duel_val_to_gdb_val(tvalue *v)
8347 +{
8348 + struct value *gv ;
8349 + if(v->val_kind!=VK_RVALUE) return 0 ; /* cant handle lvals */
8350 + switch(v->ctype->type_kind) {
8351 +/* duel standardize func parms, so this code is not required. if this
8352 + * function is used for more than func parms, as its name implies, we will
8353 + * need to do better than this.
8354 + * there is no gdb "builtin_type_signed_char", so we assume char
8355 + case CTK_CHAR:
8356 + gv=value_from_longest(builtin_type_char,v->u.rval_char); break;
8357 + case CTK_SCHAR:
8358 + gv=value_from_longest(builtin_type_char,v->u.rval_schar); break;
8359 + case CTK_UCHAR:
8360 + gv=value_from_longest(builtin_type_unsigned_char,v->u.rval_char); break;
8361 + case CTK_USHORT:
8362 + gv=value_from_longest(builtin_type_unsigned_short,v->u.rval_ushort);break;
8363 + case CTK_SHORT:
8364 + gv=value_from_longest(builtin_type_unsigned_short,v->u.rval_short);break;
8365 +*/
8366 + case CTK_INT:
8367 + gv=value_from_longest(builtin_type_int, v->u.rval_int); break;
8368 + case CTK_UINT:
8369 + gv=value_from_longest(builtin_type_unsigned_int, v->u.rval_uint) ; break ;
8370 + case CTK_LONG:
8371 + gv=value_from_longest(builtin_type_long, v->u.rval_long) ; break ;
8372 + case CTK_ULONG:
8373 + gv=value_from_longest(builtin_type_unsigned_long,v->u.rval_ulong); break ;
8374 + case CTK_LONGLONG:
8375 + gv=value_from_longest(builtin_type_long_long, v->u.rval_longlong) ; break ;
8376 + case CTK_ULONGLONG:
8377 + gv=value_from_longest(builtin_type_unsigned_long_long,v->u.rval_ulonglong); break ;
8378 + case CTK_FLOAT:
8379 + gv=value_from_double(builtin_type_float, v->u.rval_float) ; break ;
8380 + case CTK_DOUBLE:
8381 + gv=value_from_double(builtin_type_double, v->u.rval_double) ; break ;
8382 + case CTK_PTR:
8383 + gv=value_from_longest(lookup_pointer_type(builtin_type_void),
8384 + (long) v->u.rval_ptr) ;break ;
8385 + default: duel_assert(0);
8386 + }
8387 + return gv ;
8388 +}
8389 +
8390 +/* make a function call to the target.
8391 + * this is the only case where we convert duel tvalue into gdb's values.
8392 + * gdb thinks long=int=pointers, so we go along with that.
8393 + */
8394 +
8395 +PROC duel_target_func_call(tvalue *func, tvalue *parms[],
8396 + int parms_no,tvalue *rval)
8397 +{
8398 + struct value *gfunc, *grval, *gparms[20] ;
8399 + int i ;
8400 + struct type *gftype ;
8401 +
8402 + duel_assert(func->val_kind==VK_LVALUE);
8403 + for(i=0 ; i<parms_no ; i++) {
8404 + gparms[i]=convert_duel_val_to_gdb_val(parms[i]) ;
8405 + if(gparms[i]==NULL)
8406 + duel_op_error("unsupported func call parm type",0,parms[i],0);
8407 + }
8408 + gftype =duel_convert_type_to_gdb(func->ctype);
8409 + if(!gftype) duel_op_error("unsupported func return parm type",0,func,0);
8410 + gftype = lookup_pointer_type(gftype);
8411 + if(!gftype)
8412 + duel_op_error("unsupproted func return type",0,func,0);
8413 +
8414 + gfunc = value_from_longest(gftype,(LONGEST) func->u.lvalue);
8415 +
8416 + grval=call_function_by_hand(gfunc,parms_no,gparms);
8417 + if(func->ctype->u.kid->type_kind==CTK_VOID) return ; /* no return val*/
8418 + duel_convert_value_from_gdb(grval,rval);
8419 +}
8420 +
8421 +
8422 +
8423 +#define TYPE_HASH_SIZE (1024*128)
8424 +#define type_hash_func(t) ( (((long)t&0xffff) + (((long)t>>16)&0xffff)) \
8425 + % TYPE_HASH_SIZE )
8426 +struct {
8427 + struct type *t ; /* gdb type ptr */
8428 + tctype *ct ; /* duel type ptr */
8429 +} duel_thash[TYPE_HASH_SIZE] ;
8430 +
8431 +LPROC duel_add_hash(struct type *t, tctype *ct)
8432 +{
8433 + int start,i=type_hash_func(t);
8434 + start=i ;
8435 + do {
8436 + if(duel_thash[i].t==0) {
8437 + duel_thash[i].t=t ;
8438 + duel_thash[i].ct=ct ;
8439 + return ;
8440 + }
8441 + if(duel_thash[i].t==t) {
8442 + if(duel_thash[i].ct==ct) return ;
8443 + duel_fatal("type hash table inconsistency ");
8444 + }
8445 + i= (i+1)%TYPE_HASH_SIZE ;
8446 + } while(i!=start);
8447 + duel_fatal("type hash table is full");
8448 +}
8449 +
8450 +LFUNC tctype* duel_find_hash(struct type *t)
8451 +{
8452 + int start,i=type_hash_func(t);
8453 + start=i ;
8454 + do {
8455 + if(duel_thash[i].t==0) break ;
8456 + if(duel_thash[i].t==t) return duel_thash[i].ct ;
8457 + i= (i+1)%TYPE_HASH_SIZE ;
8458 + } while(i!=start);
8459 + return NULL ;
8460 +}
8461 +
8462 +/* a simple conversion back to gdb types, used only for target func calls */
8463 +/* this is a hack and based on the assumption that the type was first
8464 + * converted FROM gdb to duel. (turn out to be false for int func from
8465 + * minimal symbols, so we do this as a special case.)
8466 + */
8467 +LFUNC struct type* duel_convert_type_to_gdb(tctype *ct)
8468 +{
8469 + int i ;
8470 + for(i=0 ; i<TYPE_HASH_SIZE ; i++)
8471 + if(duel_thash[i].ct==ct) return duel_thash[i].t ;
8472 +
8473 + if(ct->type_kind==CTK_FUNC && ct->u.kid->type_kind==CTK_INT)
8474 + return lookup_function_type (builtin_type_int);
8475 + return NULL ;
8476 +}
8477 +
8478 +#define INTTYPE_CHAR 1
8479 +#define INTTYPE_SHORT 2
8480 +#define INTTYPE_INT 0
8481 +#define INTTYPE_LONG 4
8482 +#define INTTYPE_SIGNED 0
8483 +#define INTTYPE_UNSIGNED 16
8484 +
8485 +struct { char *name; int len; int codetype; } name_to_codetype[]=
8486 +{ {"char", 4, INTTYPE_CHAR },
8487 + {"short", 5, INTTYPE_SHORT },
8488 + {"int", 3, INTTYPE_INT },
8489 + {"long", 4, INTTYPE_LONG },
8490 + {"signed", 6, INTTYPE_SIGNED },
8491 + {"unsigned", 8, INTTYPE_UNSIGNED },
8492 + {0,0,0}
8493 +};
8494 +
8495 + /* given a gdb type t, return an equivalent duel type */
8496 +
8497 +LFUNC tctype* duel_convert_type_from_gdb(struct type *t)
8498 +{
8499 + tctype *ct=duel_find_hash(t);
8500 + if(ct) return ct ;
8501 +
8502 + if (duel_debug)
8503 + duel_printf("gdb type: {%d, %s}\n", TYPE_CODE(t), TYPE_NAME(t));
8504 +
8505 + switch (TYPE_CODE (t)) {
8506 + case TYPE_CODE_BOOL:
8507 + if(strcmp(TYPE_NAME(t),"bool")==0) ct=ctype_uchar ; /* XXX HACK */
8508 + break;
8509 + case TYPE_CODE_INT: {
8510 + int i, type=0;
8511 + char *s=TYPE_NAME(t);
8512 + while (*s)
8513 + for (i=0; name_to_codetype[i].name; i++) {
8514 + if (strncmp(s,name_to_codetype[i].name,name_to_codetype[i].len) == 0) {
8515 + s+=name_to_codetype[i].len;
8516 + if (*s == ' ') s++;
8517 + type+= name_to_codetype[i].codetype;
8518 + break;
8519 + }
8520 + }
8521 + if(type == INTTYPE_CHAR) ct=ctype_char ;
8522 + else if(type == INTTYPE_CHAR + INTTYPE_UNSIGNED) ct=ctype_uchar ;
8523 + else if(type == INTTYPE_SHORT) ct=ctype_short ;
8524 + else if(type == INTTYPE_SHORT + INTTYPE_UNSIGNED) ct=ctype_ushort ;
8525 + else if(type == INTTYPE_INT) ct=ctype_int ;
8526 + else if(type == INTTYPE_UNSIGNED) ct=ctype_uint ;
8527 + else if(type == INTTYPE_LONG) ct=ctype_long ;
8528 + else if(type == INTTYPE_UNSIGNED + INTTYPE_LONG) ct=ctype_ulong ;
8529 + else if(type == INTTYPE_LONG + INTTYPE_LONG) ct=ctype_longlong ;
8530 + else if(type == INTTYPE_UNSIGNED + INTTYPE_LONG + INTTYPE_LONG) ct=ctype_ulonglong ;
8531 + break;
8532 + }
8533 + case TYPE_CODE_FLT:
8534 + if(strcmp(TYPE_NAME(t),"float")==0) ct=ctype_float ;
8535 + else
8536 + if(strcmp(TYPE_NAME(t),"double")==0) ct=ctype_double ;
8537 + break;
8538 + case TYPE_CODE_VOID:
8539 + if(strcmp(TYPE_NAME(t),"void")==0) ct=ctype_void ;
8540 + break;
8541 + case TYPE_CODE_PTR:
8542 + case TYPE_CODE_REF:
8543 + {
8544 + /* the pointer might get defined when converting the target, so
8545 + * check the hashing again (reason: self-referencing structs)
8546 + */
8547 + tctype *target=duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t));
8548 + if((ct=duel_find_hash(t))==NULL) ct=duel_mkctype_ptr(target);
8549 + }
8550 + break ;
8551 + case TYPE_CODE_FUNC:
8552 + ct=duel_mkctype_func(duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t)));
8553 + break ;
8554 + case TYPE_CODE_ARRAY:
8555 + { int n=TYPE_LENGTH(TYPE_TARGET_TYPE(t));
8556 + if(n!=0) n=TYPE_LENGTH(t)/n;
8557 + ct=duel_mkctype_array(
8558 + duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t)),n);
8559 + }
8560 + break;
8561 + case TYPE_CODE_STRUCT:
8562 + case TYPE_CODE_UNION:
8563 + { int i,n=TYPE_NFIELDS(t);
8564 + char *name=TYPE_NAME(t);
8565 + if(name == NULL) name="" ; /* duel can't handle null ptr! */
8566 + if(strncmp(name,"struct ",7)==0) name+=7 ;
8567 + if(strncmp(name,"union ",6)==0) name+=6 ;
8568 + ct=duel_mkctype_struct(name,TYPE_LENGTH(t),n,
8569 + TYPE_CODE(t)==TYPE_CODE_UNION);
8570 + duel_add_hash(t,ct); /* so a pointer to myself is recognized */
8571 + for(i=0 ; i<n ; i++)
8572 + duel_mkctype_struct_field(ct,i,TYPE_FIELD_NAME(t,i),
8573 + TYPE_FIELD_BITPOS(t,i), TYPE_FIELD_BITSIZE(t,i),
8574 + duel_convert_type_from_gdb(TYPE_FIELD_TYPE(t,i)));
8575 + }
8576 + break ;
8577 + case TYPE_CODE_ENUM:
8578 + /* TYPE_LENGTH(t) tell how big it is. I assume signed integral types.
8579 + * it is unclear if gdb supports unsigned enums and how
8580 + * (e.g. enum { x=0,y=250 } stored in uchar
8581 + * FIELDS contain the tags, BITPOS is the assigned value.
8582 + */
8583 + { int i,n=TYPE_NFIELDS(t),len=TYPE_LENGTH(t);
8584 + char *name=TYPE_NAME(t);
8585 + tctype_kind k ;
8586 + if(name==NULL) name="" ; /* duel can't handle null ptr */
8587 + if(strncmp(name,"enum ",5)==0) name+=5 ;
8588 + /* select 'real' stored type. note order important if short==int.
8589 + * long is not allowed as far as I know ANSI C (enums are conv. to int)
8590 + * Amazingly, some internal gdb struct (sym) can have an enum of
8591 + * size zero (enum language, gdb4.8). We allow this as int but warn.
8592 + * gdb> p sizeof(sym->ginfo.lang_specific.language) gives zero
8593 + */
8594 + if(len==0) {
8595 + duel_printf("Warning: enum %s is size zero. assumed int\n",name);
8596 + len=sizeof(int);
8597 + }
8598 + if(len==sizeof(int)) k=CTK_INT ;
8599 + else if(len==sizeof(short)) k=CTK_SHORT ;
8600 + else if(len==sizeof(char)) k=CTK_CHAR ;
8601 + else duel_assert(0);
8602 +
8603 + ct=duel_mkctype_enum(name,k,len,n);
8604 + for(i=0 ; i<n ; i++)
8605 + duel_mkctype_enumerator(ct,i,TYPE_FIELD_NAME(t,i),
8606 + TYPE_FIELD_BITPOS(t,i));
8607 + }
8608 + break ;
8609 + case TYPE_CODE_TYPEDEF:
8610 + ct=duel_convert_type_from_gdb(check_typedef(t));
8611 + break ;
8612 + case TYPE_CODE_UNDEF:
8613 + break;
8614 + }
8615 + if(ct==0) duel_fatal("unsupported C type returned by gdb");
8616 + duel_add_hash(t,ct);
8617 + return ct ;
8618 +}
8619 +
8620 +/* optimize frame access so frame(100..0) doesnt start the search from 0
8621 + * everytime. similar to selected_frame etc, but we dont want to mess up
8622 + * gdb's own frame setup (for up/down/print etc)
8623 + * this optimization should have been part of gdb, not here.
8624 + * ie. duel_select_frame should be a simple fast gdb call.
8625 + * we dont optimze going to frame 7 from frame 5 etc, this isn't typical.
8626 + * set last/tot frames to -2 to assure recomputeations (-1 is not good enuf)
8627 + */
8628 +
8629 +static struct frame_info * last_frame ; /* last frame pointer we used */
8630 +static int last_frame_no ; /* last frame number we used */
8631 +static int tot_frames_no ; /* tot number of frames */
8632 +
8633 +LFUNC struct frame_info * duel_select_frame(int frame_no)
8634 +{
8635 + struct frame_info * frame ;
8636 + if(last_frame_no==frame_no) frame=last_frame ;
8637 + else
8638 + if(last_frame_no==frame_no-1) frame=get_prev_frame(last_frame);
8639 + else
8640 + if(last_frame_no==frame_no+1) frame=get_next_frame(last_frame);
8641 + else {
8642 + int count=frame_no ;
8643 + frame=get_current_frame();
8644 + while (frame && --count >= 0)
8645 + frame = get_prev_frame (frame);
8646 + }
8647 + duel_assert(frame); /* callee should have checked frames no*/
8648 + last_frame = frame ;
8649 + last_frame_no = frame_no ;
8650 + return frame ;
8651 +}
8652 +
8653 +FUNC bool duel_get_target_variable(char *name, int frame_no, tvalue *v)
8654 +{
8655 + struct symbol *sym;
8656 + struct frame_info * frame ;
8657 + struct block *blk ;
8658 + int len ;
8659 + struct value *gv ; /* gdb value */
8660 +
8661 + if(frame_no== -1) { /* use the user selected frame and block */
8662 + frame = get_selected_frame("Error!") ;
8663 + blk = get_selected_block(0) ;
8664 + }
8665 + else {
8666 + frame=duel_select_frame(frame_no) ;
8667 + blk = get_frame_block(frame, 0);
8668 + }
8669 + sym = lookup_symbol (name, blk, VAR_DOMAIN,0,0);
8670 + if(!sym) { /* look up the symbol that has no debug info*/
8671 + struct minimal_symbol *m ;
8672 + if(frame_no != -1) return FALSE ; /* only locals looked up- not found*/
8673 + m=lookup_minimal_symbol (name,NULL, 0); /* find printf, malloc etc */
8674 + if(m == NULL) return FALSE ;
8675 + v->val_kind=VK_LVALUE ;
8676 +#ifdef SYMBOL_LANGUAGE
8677 + /* in gdb4.8 the mini table changed. I use the existance of the above
8678 + * #define symbol as hack to indicate gdb.4.8 */
8679 + v->u.lvalue=(ttarget_ptr) SYMBOL_VALUE_ADDRESS(m);
8680 +#else
8681 + v->u.lvalue=(ttarget_ptr) m->address ;
8682 +#endif
8683 + /* guess it is an int if it is a data type, an int func if text */
8684 + if(m->type == mst_data || m->type == mst_bss) v->ctype=ctype_int ;
8685 + else
8686 + if(m->type == mst_text) v->ctype=duel_mkctype_func(ctype_int);
8687 + else return FALSE ;
8688 + return TRUE ;
8689 + }
8690 + if(SYMBOL_CLASS(sym)==LOC_TYPEDEF) return FALSE ;
8691 + /* if frame specificed, allow only local variables to be found */
8692 + if(frame_no!= -1 && (SYMBOL_CLASS(sym)==LOC_STATIC ||
8693 + SYMBOL_CLASS(sym)==LOC_BLOCK || SYMBOL_CLASS(sym)==LOC_CONST)) return FALSE;
8694 + gv=read_var_value(sym,frame);
8695 + if(gv==0) return FALSE ; /* frame not found or illegal */
8696 + duel_convert_value_from_gdb(gv,v);
8697 + return TRUE ;
8698 +}
8699 +
8700 +
8701 +/* return the total number of frames on the stack */
8702 +
8703 +FUNC int duel_get_frames_number(void)
8704 +{
8705 + int n ;
8706 + struct frame_info * frame ;
8707 + if(tot_frames_no!= -2) return tot_frames_no ;
8708 + frame=get_current_frame();
8709 + for(n=0 ; frame ; n++)
8710 + frame = get_prev_frame (frame);
8711 + return tot_frames_no=n ;
8712 +}
8713 +
8714 +FUNC ttarget_ptr duel_get_function_for_frame(int frame_no)
8715 +{
8716 + struct frame_info * frame=duel_select_frame(frame_no);
8717 + struct symbol *sym = get_frame_function(frame);
8718 + struct value *val = read_var_value(sym,frame);
8719 + duel_assert(val!=0 && VALUE_LVAL(val) == lval_memory);
8720 +
8721 + return (ttarget_ptr) VALUE_ADDRESS(val) ;
8722 +}
8723 +
8724 +FUNC tctype* duel_get_target_typedef(char *name)
8725 +{
8726 + struct symbol *sym;
8727 + sym = lookup_symbol (name, get_selected_block(0), VAR_DOMAIN,0,0);
8728 + if(!sym || SYMBOL_CLASS(sym)!=LOC_TYPEDEF) {
8729 + sym = lookup_symbol (name, 0, VAR_DOMAIN, 0,0);
8730 + if(!sym || SYMBOL_CLASS(sym)!=LOC_TYPEDEF) return NULL ;
8731 + }
8732 + return duel_convert_type_from_gdb(SYMBOL_TYPE(sym));
8733 +}
8734 +
8735 +FUNC tctype* duel_get_target_struct_tag(char *name)
8736 +{
8737 + struct symbol *sym;
8738 + sym = lookup_symbol (name, get_selected_block(0), STRUCT_DOMAIN,0,0);
8739 + if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_STRUCT) {
8740 + sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0,0);
8741 + if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_STRUCT) return NULL ;
8742 + }
8743 + return duel_convert_type_from_gdb(SYMBOL_TYPE(sym));
8744 +}
8745 +
8746 +FUNC tctype* duel_get_target_union_tag(char *name)
8747 +{
8748 + struct symbol *sym;
8749 + sym = lookup_symbol (name, get_selected_block(0), STRUCT_DOMAIN,0,0);
8750 + if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_UNION) {
8751 + sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0,0);
8752 + if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_UNION) return NULL ;
8753 + }
8754 + return duel_convert_type_from_gdb(SYMBOL_TYPE(sym));
8755 +}
8756 +
8757 +FUNC tctype* duel_get_target_enum_tag(char *name)
8758 +{
8759 + struct symbol *sym;
8760 + sym = lookup_symbol (name, get_selected_block(0), STRUCT_DOMAIN,0,0);
8761 + if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_ENUM) {
8762 + sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0,0);
8763 + if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_ENUM) return NULL ;
8764 + }
8765 + return duel_convert_type_from_gdb(SYMBOL_TYPE(sym));
8766 +}
8767 +
8768 +/*
8769 + * entry point from gdb.
8770 + * produce help in gdb's format, or call duel enter point.
8771 + * we allow ^c to quit immidiatly, and setup memory release cleanup.
8772 + */
8773 +
8774 +void duel_command(char *exp,int from_tty)
8775 +{
8776 + last_frame_no = -2 ; /* recompute frame location on each dl command */
8777 + tot_frames_no = -2 ;
8778 +
8779 + make_cleanup(duel_cleanup, 0); /* clear all allocated mem */
8780 + immediate_quit++ ;
8781 + duel_parse_and_eval(exp);
8782 + immediate_quit-- ;
8783 +}
8784 +
8785 +void
8786 +_initialize_duel()
8787 +{
8788 + add_com ("duel", class_vars, duel_command,
8789 +"Evaluate Duel expressions. Duel is a very high level debugging language.\n\
8790 +\"dl help\" for help.\n");
8791 + add_com_alias ("dl", "duel", class_vars, 1);
8792 +
8793 +}
8794
8795
8796
8797 1.1 src/patchsets/gdb/6.7.1/11_all_gdb-6.6-duel-integrate.patch
8798
8799 file : http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/gdb/6.7.1/11_all_gdb-6.6-duel-integrate.patch?rev=1.1&view=markup
8800 plain: http://sources.gentoo.org/viewcvs.py/gentoo/src/patchsets/gdb/6.7.1/11_all_gdb-6.6-duel-integrate.patch?rev=1.1&content-type=text/plain
8801
8802 Index: 11_all_gdb-6.6-duel-integrate.patch
8803 ===================================================================
8804 --- gdb/Makefile.in
8805 +++ gdb/Makefile.in
8806 @@ -116,6 +116,9 @@
8807 # Where is the "-liberty" library? Typically in ../libiberty.
8808 LIBIBERTY = ../libiberty/libiberty.a
8809
8810 +# Where is the DUEL library ? Always in duel/src
8811 +DUEL=duel/duel.a
8812 +
8813 # Where is the BFD library? Typically in ../bfd.
8814 BFD_DIR = ../bfd
8815 BFD = $(BFD_DIR)/libbfd.a
8816 @@ -383,9 +386,9 @@
8817 CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) \
8818 $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
8819 $(LIBICONV) $(LIBEXPAT) \
8820 - $(LIBIBERTY) $(WIN32LIBS)
8821 + $(LIBIBERTY) $(WIN32LIBS) $(DUEL)
8822 CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \
8823 - $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS)
8824 + $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(DUEL)
8825
8826 ADD_FILES = $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
8827 ADD_DEPS = $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
8828 @@ -561,7 +564,7 @@
8829 ui-out.c utils.c ui-file.h ui-file.c \
8830 user-regs.c \
8831 valarith.c valops.c valprint.c value.c varobj.c vec.c \
8832 - wrapper.c \
8833 + wrapper.c duelgdb.c \
8834 xml-tdesc.c xml-support.c
8835
8836 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
8837 @@ -948,7 +951,7 @@
8838 dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
8839 ada-lang.o c-lang.o f-lang.o objc-lang.o \
8840 ui-out.o cli-out.o \
8841 - varobj.o vec.o wrapper.o \
8842 + varobj.o vec.o wrapper.o duelgdb.o \
8843 jv-lang.o jv-valprint.o jv-typeprint.o \
8844 m2-lang.o p-lang.o p-typeprint.o p-valprint.o \
8845 scm-exp.o scm-lang.o scm-valprint.o \
8846 @@ -971,7 +974,7 @@
8847
8848 TSOBS = inflow.o
8849
8850 -SUBDIRS = @subdirs@
8851 +SUBDIRS = @subdirs@ duel
8852
8853 # For now, shortcut the "configure GDB for fewer languages" stuff.
8854 YYFILES = c-exp.c \
8855 @@ -3238,4 +3241,7 @@
8856 $(gdb_curses_h) $(gdb_assert_h)
8857 $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
8858
8859 +$(DUEL):
8860 + $(MAKE) -C duel
8861 +
8862 ### end of the gdb Makefile.in.
8863
8864
8865
8866 --
8867 gentoo-commits@g.o mailing list