home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-23 | 49.3 KB | 1,319 lines |
- Newsgroups: alt.sources
- Path: sparky!uunet!cs.utexas.edu!qt.cs.utexas.edu!yale.edu!newsserver.jvnc.net!princeton!csservices!tyrolia!mg
- From: mg@tyrolia (Michael Golan)
- Subject: Duel - a language for debugging C programs part 2/6
- Message-ID: <1993Jan22.034402.21027@csservices.Princeton.EDU>
- Sender: news@csservices.Princeton.EDU (USENET News System)
- Organization: Department of Computer Science, Princeton University
- Date: Fri, 22 Jan 1993 03:44:02 GMT
- Lines: 1308
-
- Submitted-by: mg@cs.princeton.edu
- Archive-name: duel/part02
-
- #!/bin/sh
- # This is part 02 of duel
- if touch 2>&1 | fgrep 'amc' > /dev/null
- then TOUCH=touch
- else TOUCH=true
- fi
- # ============= gnu-vs-duel.doc ==============
- echo "x - extracting gnu-vs-duel.doc (Text)"
- sed 's/^X//' << 'SHAR_EOF' > gnu-vs-duel.doc &&
- XGNU VS DUEL, or why DUEL is not part of the GNU project.
- X
- XDUEL IS PUBLIC DOMAIN SOFTWARE
- X
- XDUEL is public domain software. There is *no* copyright.
- XTherefor you may copy it, change a few lines, remove my name,
- Xclaim credit for it all and sell it. Feel free to do so! Of course,
- XI'd rather see people who modify the code give me credit and the
- Xcode for free. However, I encourage you, for the sake of society,
- Xto use this code even if you can't give me credit for it (i.e. if
- Xyour company won't allow my name to be kept, but you want to use the
- Xcode to develop a new product, go ahead and delete my name!).
- X
- XDUEL is not under the "GNU Public License" (GPL). I disagree with
- Xmany of the "GNU ideas", even though I like to see public domain
- Xsoftware available. GPL software is not public domain nor "free" for
- Xmany reasons. If you develop code and distribute it freely, I
- Xurge you not to apply the GPL restrictions to it. Keep it free!
- X
- XBy making code "freely available", you loose almost all of your rights,
- Xfor all practical purposes. I am unaware of a case where someone who used
- Xfreely available source code in violation of the copyright notice
- Xhas been sued. (Since such a case has probably never made it to court,
- Xthe legality of notices like "use this for anything but not commercially"
- Xis unclear. Some lawyers believe such notices to be invalid.
- XConsider "Use this freely unless you are a black male" to realize why.)
- XBesides, when you release free code but attach some "rules" to its use,
- Xyou only prevent honest people from using the code.
- X
- X
- XThe rest of this file discuss the GPL. You probably won't agree with many of
- Xthe arguments, but even one of these is a good reason to avoid the GNU license.
- X
- X
- XTHE GNU LICENSE
- X
- XWhat is wrong with the GNU license?
- X
- X1) It seem to be unenforceable.
- X Many lawyers claim it isn't. There isn't really a license (you don't sign
- X anything nor negotiate), and the mention of the code as "free" means a
- X very weak, if any, copyright protection. Since copyright law protects
- X the holder from monetary damages, and since the FSF doesn't want nor
- X intend to make any money, it seems that even a ruling in their favor
- X won't mean much. Propagating the GPL seems like propagating FUD, the
- X kind that the worst and lowest commercial companies sometimes use.
- X
- X2) It seem no one will ever try to enforce it.
- X FSF don't have the money nor the will to try to enforce the GPL.
- X I am unaware of anyone who violates it, but I am certain there are such
- X cases. By not enforcing it, FSF most likely loose their ability to do so
- X in the future, making the license useless. Even if they went to court
- X and won, there is no way the judge would require anyone to surrender his
- X source code. They can only demand money (the amount of which is unclear,
- X since they didn't loose any). For that matter, I wonder if the GNU
- X software was even sent to the copyright office. If it haven't, they can't
- X win any kind of case (ask a lawyer if you don't believe me. And don't
- X bother to claim code you released is copyrighted at all if you didn't
- X file it with the copyright office).
- X
- X3) The license can be easily circumvented with your own smart license.
- X By making your own special license, you could give people only "diff"
- X files and ask them to apply it to original GNU code. The diff files
- X being independent code, they can't give them aways unless you allow it.
- X Under the same license you can also provide "installation" of this code,
- X and provide them with a binary image as a service ... While clearly
- X against the intent of the GPL, it practically sell binaries only:
- X "We here by agree that I sell you:"
- X (a) a file of source changes, which you may use only ONCE
- X to patch source code for GNU product x, and compile into
- X a binary program to be used on a single machine. You must
- X destroy the diff file and the patched gnu code immediately
- X after it has been compiled.
- X (b) a service of applying the diff file you acquired in (a)
- X to a publicly available GNU code of product x. I will give you
- X only the binary result from this service.
- X
- X Lawyers could refine this, I am sure. For example, (a) might cost $100
- X and (b) another $100. A total of $200 for the bin file only. You may
- X choose only (a), but then you must apply it on my premises, pay rent...
- X This makes (a) and (b) independent, like the 'no purchase necessary' rules.
- X
- X4) The license hurts people who can not use this code.
- X Many people won't use GNU products, let alone code, just to prevent
- X legal problems. In some cases companies disallow use of such code.
- X In many cases, all you really want is a few GNU functions which you
- X have learned/used while developing GNU code yourself. Yet, you can't
- X use them! You end up spending time re-implementing something you have
- X on your disk already (example: GNU pattern matching code).
- X DUEL provided me with a good example of this. While developing DUEL,
- X I spend lots of time reading GDB code. Some of this code could be useful
- X in a commercial package I am developing, but I can't use it. Morally,
- X can I look at the code while I re-implement it? What if I use the same
- X actual code, from memory? Did I infringe on the copyright? Do I have to
- X go out of my way to implement it "differently"?
- X
- X5) The GNU project seems to be promoted by a small group of people for
- X their own agenda. The same people use this power, knowledge and position
- X to advance their own interests in a fight against security, private
- X enterprise, patents, etc. By making your code GNUish, you are
- X helping them to advance ALL of their causes. Make sure you understand
- X what these causes are, before adding your implicit support.
- X
- X6) GNU gives lawyers work!
- X Amazingly, many companies spend time and money on lawyers concerning
- X GNU and GNU-like "free" software. Lawyers are suspicious of any
- X rules or contracts that aren't standard, especially if they accompany
- X a "free" package. For example, in AT&T, you can purchase commercial
- X software in 24 hours, but to get permission to use "free" tools like GNU
- X the lawyers must check and verify the contract is "ok". This can
- X take months (I ain't joking!)
- X
- XIt seems the GNU project has outrun itself, and is now slowing down
- Xinnovation. By not allowing anyone to build upon it and still make
- Xany money, the GNU project sets a minimal standard that any software
- Xdeveloper must overcome, before developing improved software. As a
- Xresult, while the GNU project has improved the minimal software standard
- Xoverall, it has also reduced the development of new, better software.
- XHad the GNU code been public domain, it could have been built upon by
- Xsmall companies, to produce better software.
- X
- X
- XIF YOU WRITE "FREE PROGRAMS"
- X
- XI urge you to make your program public domain. Any honest person who
- Xuse you code will give you proper credit anyway. The less honest people
- Xwill use your code against your wishes either way.
- X
- XIf you insist on making your program copyrighted, I suggest that you either:
- X
- X1. Allow people to grab some parts of your source code and use it as public
- X domain. In other words, allow people who hacked your code and got familiar
- X with it to use a few of your functions in a big in-house project without
- X having to rewrite them from scratch (or illegally steal them!).
- X
- X2. Retain only the copyright notice. Demand that your copyright notice
- X be kept in the sources, and/or in manual pages and binary code if it is
- X distributed. This allows people to base commercial products on it,
- X but not without giving you some fame or glory.
- X
- X3. Use the "artistic license" provided with Perl.
- X
- X
- X
- X
- SHAR_EOF
- $TOUCH -am 0121190893 gnu-vs-duel.doc &&
- chmod 0644 gnu-vs-duel.doc ||
- echo "restore of gnu-vs-duel.doc failed"
- set `wc -c gnu-vs-duel.doc`;Wc_c=$1
- if test "$Wc_c" != "7719"; then
- echo original size 7719, current size $Wc_c
- fi
- # ============= duelgdb.c ==============
- echo "x - extracting duelgdb.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > duelgdb.c &&
- X/* DUEL - A Very High Level Debugging Langauge. */
- X/* Public domain code */
- X/* Written by Michael Golan mg@cs.princeton.edu */
- X/*$Header: /tmp_mnt/n/fs/grad2/mg/duel/RCS/duelgdb.c,v 1.11 93/01/21 21:22:15 mg Exp $*/
- X
- X/* debugger dependent module, it contains all of duel's access to
- X * the outside world (debuggee, symbol table, etc)
- X */
- X
- X/*
- X * $Log: duelgdb.c,v $
- X * Revision 1.11 93/01/21 21:22:15 mg
- X * *** empty log message ***
- X *
- X * Revision 1.10 93/01/13 16:19:33 mg
- X * support mini symbol table lookup (malloc, printf on SUN didnt work)
- X *
- X * Revision 1.9 93/01/12 21:30:04 mg
- X * cleanup and set for release
- X *
- X * Revision 1.8 93/01/06 23:59:21 mg
- X * new memory alloc/release. moved target's malloc into duel code
- X * allow ^c to work, fixed help, fixed variable lookup for specific frame.
- X *
- X * Revision 1.7 93/01/03 07:27:11 mg
- X * support function calls!
- X *
- X * Revision 1.6 92/12/24 23:33:13 mg
- X * frames support
- X *
- X * Revision 1.5 92/10/19 15:06:29 mg
- X * made lcc happy
- X * no svalues
- X * new registers support and way of getting vars.
- X * these are temporary changes, new frames supports soon
- X *
- X * Revision 1.4 92/10/14 02:03:53 mg
- X * misc/gdb4.6/duel vars using malloc
- X *
- X * Revision 1.3 92/09/16 11:06:22 mg
- X * a lot more functions: get typedef/tags, alloc debuggee mem. +cosmetics
- X *
- X * Revision 1.2 92/09/15 05:37:28 mg
- X * fix enum size bug. added headers
- X *
- X */
- X
- X
- X#include <stddef.h> /* used for ptrdiff_t and size_t */
- X#include <stdio.h>
- X#include <string.h>
- X#include <assert.h>
- X
- X#include "defs.h"
- X#include "symtab.h"
- X#include "gdbtypes.h"
- X#include "gdbcore.h"
- X#include "frame.h"
- X#include "target.h"
- X#include "value.h"
- X#include "symfile.h"
- X#include "objfiles.h"
- X#include "gdbcmd.h"
- X#include "call-cmds.h"
- X
- X#include "duel/src/global.h"
- X#include "duel/src/proto.h"
- X
- X/* all duel memory allocation go thru here */
- X
- XFUNC void* duel_malloc(size_t size)
- X{
- X void *p ;
- X immediate_quit-- ; /* disable ^C while xmalloc */
- X p=xmalloc(size); /* gdb's malloc, incl zero return chk */
- X immediate_quit++ ;
- X QUIT ; /* check if ^C while xmalloc called */
- X return p ;
- X}
- X
- XPROC duel_free(void *p)
- X{
- X immediate_quit-- ;
- X free(p);
- X immediate_quit++ ;
- X QUIT ;
- X}
- X
- X
- X/* fetch n bytes from the target at the given memory address.
- X * the address to fetch from is given by (from).
- X * the value is stored at the 'to' location, which points to space for
- X * n bytes in the debugger.
- X * if the address can not be accessed, false is returned (if all ok, ret true)
- X */
- X
- XFUNC bool duel_get_target_bytes(ttarget_ptr from,void *to,size_t n)
- X{
- X return target_read_memory((CORE_ADDR)from,to,n)==0;
- X}
- X
- X/* store n bytes to the debuggee. reverse parms from above */
- XFUNC bool duel_put_target_bytes(ttarget_ptr to,void *from,size_t n)
- X{
- X return target_write_memory((CORE_ADDR)to,from,n)==0;
- X}
- X
- X/* fetch the value of a bitfield of a given structure.
- X * struct_at - a pointer to the structure
- X * bitpos - the position of the field, in bits (as given in the type)
- X * bitlen - the length of the field in bits
- X * to - pointer to uint where value will be stored.
- X * tkind - the type kind of the field (used to do sign extention if needed)
- X * note: I'm unaware of any compiler with bitfields that are not int/uint.
- X */
- X
- XFUNC bool duel_get_target_bitfield(ttarget_ptr struct_at,int bitpos,
- X int bitlen,void *to,tctype_kind tkind)
- X{
- X uint bits ;
- X duel_assert(tkind==CTK_INT || tkind==CTK_UINT);
- X if(!duel_get_target_bytes(struct_at+bitpos/8,&bits,sizeof(bits)))
- X return FALSE;
- X
- X /* now, move the field to the 'bottom' of bits, by shifting right */
- X bitpos%=8 ; /* fix it to a bit offset inside the 'bits' */
- X#if BITS_BIG_ENDIAN /* defined by gdb's src code */
- X bits >>= (sizeof(bits)*8-bitpos-bitlen) ;
- X#else
- X bits >>= bitpos ;
- X#endif
- X
- X /* finally chop down 'bits' to only bitlen significant bits,
- X * or sign-extend it if output field is 'int' and the sign is 1.
- X * ~0 is all ones, shift it to have bitlen zeros. Complement to get
- X * a bitlen string of 1's in the low-order bits. Common ugly hacks.
- X * Note: this code assume 2's complement
- X */
- X
- X if(tkind==CTK_INT && (bits & 1<<(bitlen-1))) /* int field, negative sign */
- X bits|= ~0<<bitlen ; /*sign extend */
- X else bits&= ~(~0<<bitlen) ; /* clear all bits above the sign bit */
- X *(uint*) to= bits ;
- X
- X return TRUE ;
- X}
- X
- XLFUNC struct type* duel_convert_type_to_gdb(tctype *ct);
- XLFUNC tctype* duel_convert_type_from_gdb(struct type *gv);
- X
- X/* convert gdb value into duel's. Used to fetch const, registers, func ret val
- X * and convert a symbol into a reference.
- X * otherwise, duel access target's memory directly.
- X */
- X
- XLPROC duel_convert_value_from_gdb(value gv, tvalue *dv)
- X{
- X dv->ctype=duel_convert_type_from_gdb(VALUE_TYPE(gv));
- X if(VALUE_LVAL(gv) == lval_memory) {
- X dv->val_kind=VK_LVALUE ;
- X dv->u.lvalue= (ttarget_ptr) VALUE_ADDRESS(gv) ; /*address of variable*/
- X }
- X else
- X if(ctype_kind_scalar(dv->ctype) && (VALUE_LVAL(gv) == not_lval ||
- X VALUE_LVAL(gv) == lval_register ||
- X VALUE_LVAL(gv) == lval_reg_frame_relative )) {
- X dv->val_kind=VK_RVALUE ;
- X duel_bcopy(&dv->u,VALUE_CONTENTS_RAW(gv),dv->ctype->size);
- X }
- X else
- X duel_fatal("unsupported value type returned by gdb");
- X}
- X
- X
- X/* helper function converts duel values to gdb's values. used only to make
- X * function calls to the target, so current support is weak.
- X * gdb thinks long=int=pointers, so we go along with that.
- X * To support arbitrary types like struct/union, we can probably fake it
- X * by making a gdb lvalue. but i am not sure how/what
- X */
- X
- XLFUNC value convert_duel_val_to_gdb_val(tvalue *v)
- X{
- X value gv ;
- X if(v->val_kind!=VK_RVALUE) return 0 ; /* cant handle lvals */
- X switch(v->ctype->type_kind) {
- X/* duel standardize func parms, so this code is not required. if this
- X * function is used for more than func parms, as its name implies, we will
- X * need to do better than this.
- X case CTK_CHAR:
- X gv=value_from_longest(builtin_type_char,v->u.rval_char); break;
- X case CTK_UCHAR:
- X gv=value_from_longest(builtin_type_unsigned_char,v->u.rval_char); break;
- X case CTK_USHORT:
- X gv=value_from_longest(builtin_type_unsigned_short,v->u.rval_ushort);break;
- X case CTK_SHORT:
- X gv=value_from_longest(builtin_type_unsigned_short,v->u.rval_short);break;
- X*/
- X case CTK_INT:
- X gv=value_from_longest(builtin_type_int, v->u.rval_int); break;
- X case CTK_UINT:
- X gv=value_from_longest(builtin_type_unsigned_int, v->u.rval_uint) ; break ;
- X case CTK_LONG:
- X gv=value_from_longest(builtin_type_long, v->u.rval_long) ; break ;
- X case CTK_ULONG:
- X gv=value_from_longest(builtin_type_unsigned_long,v->u.rval_ulong); break ;
- X case CTK_FLOAT:
- X gv=value_from_double(builtin_type_float, v->u.rval_float) ; break ;
- X case CTK_DOUBLE:
- X gv=value_from_double(builtin_type_double, v->u.rval_double) ; break ;
- X case CTK_PTR:
- X gv=value_from_longest(lookup_pointer_type(builtin_type_void),
- X (long) v->u.rval_ptr) ;break ;
- X default: duel_assert(0);
- X }
- X return gv ;
- X}
- X
- X/* make a function call to the target.
- X * this is the only case where we convert duel tvalue into gdb's values.
- X * gdb thinks long=int=pointers, so we go along with that.
- X */
- X
- XPROC duel_target_func_call(tvalue *func, tvalue *parms[],
- X int parms_no,tvalue *rval)
- X{
- X value gfunc, grval, gparms[20] ;
- X int i ;
- X struct type *gftype ;
- X
- X duel_assert(func->val_kind==VK_LVALUE);
- X for(i=0 ; i<parms_no ; i++) {
- X gparms[i]=convert_duel_val_to_gdb_val(parms[i]) ;
- X if(gparms[i]==NULL)
- X duel_op_error("unsupported func call parm type",0,parms[i],0);
- X }
- X gftype =duel_convert_type_to_gdb(func->ctype);
- X if(!gftype) duel_op_error("unsupported func return parm type",0,func,0);
- X gftype = lookup_pointer_type(gftype);
- X if(!gftype)
- X duel_op_error("unsupproted func return type",0,func,0);
- X
- X gfunc = value_from_longest(gftype,(LONGEST) func->u.lvalue);
- X
- X grval=call_function_by_hand(gfunc,parms_no,gparms);
- X if(func->ctype->u.kid->type_kind==CTK_VOID) return ; /* no return val*/
- X duel_convert_value_from_gdb(grval,rval);
- X}
- X
- X
- X
- X#define TYPE_HASH_SIZE 1024
- X#define type_hash_func(t) ( (((long)t&0xffff) + (((long)t>>16)&0xffff)) \
- X % TYPE_HASH_SIZE )
- Xstruct {
- X struct type *t ; /* gdb type ptr */
- X tctype *ct ; /* duel type ptr */
- X} duel_thash[TYPE_HASH_SIZE] ;
- X
- XLPROC duel_add_hash(struct type *t, tctype *ct)
- X{
- X int start,i=type_hash_func(t);
- X start=i ;
- X do {
- X if(duel_thash[i].t==0) {
- X duel_thash[i].t=t ;
- X duel_thash[i].ct=ct ;
- X return ;
- X }
- X if(duel_thash[i].t==t) {
- X if(duel_thash[i].ct==ct) return ;
- X duel_fatal("type hash table inconsistency ");
- X }
- X i= (i+1)%TYPE_HASH_SIZE ;
- X } while(i!=start);
- X duel_fatal("type hash table is full");
- X}
- X
- XLFUNC tctype* duel_find_hash(struct type *t)
- X{
- X int start,i=type_hash_func(t);
- X start=i ;
- X do {
- X if(duel_thash[i].t==0) break ;
- X if(duel_thash[i].t==t) return duel_thash[i].ct ;
- X i= (i+1)%TYPE_HASH_SIZE ;
- X } while(i!=start);
- X return NULL ;
- X}
- X
- X/* a simple conversion back to gdb types, used only for target func calls */
- X/* this is a hack and based on the assumption that the type was first
- X * converted FROM gdb to duel. (turn out to be false for int func from
- X * minimal symbols, so we do this as a special case.)
- X */
- XLFUNC struct type* duel_convert_type_to_gdb(tctype *ct)
- X{
- X int i ;
- X for(i=0 ; i<TYPE_HASH_SIZE ; i++)
- X if(duel_thash[i].ct==ct) return duel_thash[i].t ;
- X
- X if(ct->type_kind==CTK_FUNC && ct->u.kid->type_kind==CTK_INT)
- X return lookup_function_type (builtin_type_int);
- X return NULL ;
- X}
- X
- X /* given a gdb type t, return an equivalent duel type */
- X
- XLFUNC tctype* duel_convert_type_from_gdb(struct type *t)
- X{
- X tctype *ct=duel_find_hash(t);
- X if(ct) return ct ;
- X
- X switch (TYPE_CODE (t)) {
- X case TYPE_CODE_INT:
- X if( strcmp(TYPE_NAME(t),"char")==0) ct=ctype_char ;
- X else if(strcmp(TYPE_NAME(t),"short")==0) ct=ctype_short ;
- X else if(strcmp(TYPE_NAME(t),"int")==0) ct=ctype_int ;
- X else if(strcmp(TYPE_NAME(t),"long")==0) ct=ctype_long ;
- X else if(strcmp(TYPE_NAME(t),"unsigned char")==0) ct=ctype_uchar ;
- X else if(strcmp(TYPE_NAME(t),"unsigned short")==0) ct=ctype_ushort ;
- X else if(strcmp(TYPE_NAME(t),"unsigned int")==0) ct=ctype_uint ;
- X else if(strcmp(TYPE_NAME(t),"unsigned long")==0) ct=ctype_ulong ;
- X break;
- X case TYPE_CODE_FLT:
- X if(strcmp(TYPE_NAME(t),"float")==0) ct=ctype_float ;
- X else
- X if(strcmp(TYPE_NAME(t),"double")==0) ct=ctype_double ;
- X break;
- X case TYPE_CODE_VOID:
- X if(strcmp(TYPE_NAME(t),"void")==0) ct=ctype_void ;
- X break;
- X case TYPE_CODE_PTR:
- X {
- X /* the pointer might get defined when converting the target, so
- X * check the hashing again (reason: self-referencing structs)
- X */
- X tctype *target=duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t));
- X if((ct=duel_find_hash(t))==NULL) ct=duel_mkctype_ptr(target);
- X }
- X break ;
- X case TYPE_CODE_FUNC:
- X ct=duel_mkctype_func(duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t)));
- X break ;
- X case TYPE_CODE_ARRAY:
- X { int n=TYPE_LENGTH(TYPE_TARGET_TYPE(t));
- X if(n!=0) n=TYPE_LENGTH(t)/n;
- X ct=duel_mkctype_array(
- X duel_convert_type_from_gdb(TYPE_TARGET_TYPE(t)),n);
- X }
- X break;
- X case TYPE_CODE_STRUCT:
- X case TYPE_CODE_UNION:
- X { int i,n=TYPE_NFIELDS(t);
- X char *name=TYPE_NAME(t);
- X if(strncmp(name,"struct ",7)==0) name+=7 ;
- X if(strncmp(name,"union ",6)==0) name+=6 ;
- X ct=duel_mkctype_struct(name,TYPE_LENGTH(t),n,
- X TYPE_CODE(t)==TYPE_CODE_UNION);
- X duel_add_hash(t,ct); /* so a pointer to myself is recognized */
- X for(i=0 ; i<n ; i++)
- X duel_mkctype_struct_field(ct,i,TYPE_FIELD_NAME(t,i),
- X TYPE_FIELD_BITPOS(t,i), TYPE_FIELD_BITSIZE(t,i),
- X duel_convert_type_from_gdb(TYPE_FIELD_TYPE(t,i)));
- X }
- X break ;
- X case TYPE_CODE_ENUM:
- X /* TYPE_LENGTH(t) tell how big it is. I assume signed integral types.
- X * it is unclear if gdb supports unsigned enums and how
- X * (e.g. enum { x=0,y=250 } stored in uchar
- X * FIELDS contain the tags, BITPOS is the assigned value.
- X */
- X { int i,n=TYPE_NFIELDS(t),len=TYPE_LENGTH(t);
- X tctype_kind k ;
- X /* select 'real' stored type. note order important if short==int.
- X * long is not allowed as far as I know ANSI C (enums are conv. to int)
- X */
- X if(len==sizeof(int)) k=CTK_INT ;
- X else if(len==sizeof(short)) k=CTK_SHORT ;
- X else if(len==sizeof(char)) k=CTK_CHAR ;
- X else duel_assert(0);
- X
- X ct=duel_mkctype_enum(TYPE_NAME(t),k,len,n);
- X for(i=0 ; i<n ; i++)
- X duel_mkctype_enumerator(ct,i,TYPE_FIELD_NAME(t,i),
- X TYPE_FIELD_BITPOS(t,i));
- X }
- X break ;
- X case TYPE_CODE_UNDEF:
- X break;
- X }
- X if(ct==0) duel_fatal("unsupported C type returned by gdb");
- X duel_add_hash(t,ct);
- X return ct ;
- X}
- X
- X/* optimize frame access so frame(100..0) doesnt start the search from 0
- X * everytime. similar to selected_frame etc, but we dont want to mess up
- X * gdb's own frame setup (for up/down/print etc)
- X * this optimization should have been part of gdb, not here.
- X * ie. duel_select_frame should be a simple fast gdb call.
- X * we dont optimze going to frame 7 from frame 5 etc, this isn't typical.
- X * set last/tot frames to -2 to assure recomputeations (-1 is not good enuf)
- X */
- X
- Xstatic FRAME last_frame ; /* last frame pointer we used */
- Xstatic int last_frame_no ; /* last frame number we used */
- Xstatic int tot_frames_no ; /* tot number of frames */
- X
- XLFUNC FRAME duel_select_frame(int frame_no)
- X{
- X FRAME frame ;
- X if(last_frame_no==frame_no) frame=last_frame ;
- X else
- X if(last_frame_no==frame_no-1) frame=get_prev_frame(last_frame);
- X else
- X if(last_frame_no==frame_no+1) frame=get_next_frame(last_frame);
- X else {
- X int count=frame_no ;
- X frame=get_current_frame();
- X while (frame && --count >= 0)
- X frame = get_prev_frame (frame);
- X }
- X duel_assert(frame); /* callee should have checked frames no*/
- X last_frame = frame ;
- X last_frame_no = frame_no ;
- X return frame ;
- X}
- X
- XFUNC bool duel_get_target_variable(char *name, int frame_no, tvalue *v)
- X{
- X struct symbol *sym;
- X FRAME frame ;
- X struct block *blk ;
- X int len ;
- X value gv ; /* gdb value */
- X
- X if(frame_no== -1) { /* use the user selected frame and block */
- X frame = selected_frame ;
- X blk = get_selected_block() ;
- X }
- X else {
- X frame=duel_select_frame(frame_no) ;
- X blk = get_frame_block(frame);
- X }
- X sym = lookup_symbol (name, blk, VAR_NAMESPACE,0,0);
- X if(!sym && frame_no== -1) { /* look up the symbol that has no debug info*/
- X struct minimal_symbol *m ;
- X m=lookup_minimal_symbol (name,NULL); /* find printf, malloc etc */
- X if(m == NULL) return FALSE ;
- X v->val_kind=VK_LVALUE ;
- X v->u.lvalue=(ttarget_ptr) m->address ;
- X /* guess it is an int if it is a data type, an int func if text */
- X if(m->type == mst_data || m->type == mst_bss) v->ctype=ctype_int ;
- X else
- X if(m->type == mst_text) v->ctype=duel_mkctype_func(ctype_int);
- X else return FALSE ;
- X return TRUE ;
- X }
- X if(SYMBOL_CLASS(sym)==LOC_TYPEDEF) return FALSE ;
- X /* if frame specificed, allow only local variables to be found */
- X if(frame_no!= -1 && (SYMBOL_CLASS(sym)==LOC_STATIC ||
- X SYMBOL_CLASS(sym)==LOC_BLOCK || SYMBOL_CLASS(sym)==LOC_CONST)) return FALSE;
- X gv=read_var_value(sym,frame);
- X if(gv==0) return FALSE ; /* frame not found or illegal */
- X duel_convert_value_from_gdb(gv,v);
- X return TRUE ;
- X}
- X
- X
- X/* return the total number of frames on the stack */
- X
- XFUNC int duel_get_frames_number(void)
- X{
- X int n ;
- X FRAME frame ;
- X if(tot_frames_no!= -2) return tot_frames_no ;
- X frame=get_current_frame();
- X for(n=0 ; frame ; n++)
- X frame = get_prev_frame (frame);
- X return tot_frames_no=n ;
- X}
- X
- XFUNC ttarget_ptr duel_get_function_for_frame(int frame_no)
- X{
- X FRAME frame=duel_select_frame(frame_no);
- X struct symbol *sym = get_frame_function(frame);
- X value val = read_var_value(sym,frame);
- X duel_assert(val!=0 && VALUE_LVAL(val) == lval_memory);
- X
- X return (ttarget_ptr) VALUE_ADDRESS(val) ;
- X}
- X
- XFUNC tctype* duel_get_target_typedef(char *name)
- X{
- X struct symbol *sym;
- X sym = lookup_symbol (name, get_selected_block(), VAR_NAMESPACE,0,0);
- X if(!sym || SYMBOL_CLASS(sym)!=LOC_TYPEDEF) {
- X sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0,0);
- X if(!sym || SYMBOL_CLASS(sym)!=LOC_TYPEDEF) return NULL ;
- X }
- X return duel_convert_type_from_gdb(SYMBOL_TYPE(sym));
- X}
- X
- XFUNC tctype* duel_get_target_struct_tag(char *name)
- X{
- X struct symbol *sym;
- X sym = lookup_symbol (name, get_selected_block(), STRUCT_NAMESPACE,0,0);
- X if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_STRUCT) {
- X sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0,0);
- X if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_STRUCT) return NULL ;
- X }
- X return duel_convert_type_from_gdb(SYMBOL_TYPE(sym));
- X}
- X
- XFUNC tctype* duel_get_target_union_tag(char *name)
- X{
- X struct symbol *sym;
- X sym = lookup_symbol (name, get_selected_block(), STRUCT_NAMESPACE,0,0);
- X if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_UNION) {
- X sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0,0);
- X if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_UNION) return NULL ;
- X }
- X return duel_convert_type_from_gdb(SYMBOL_TYPE(sym));
- X}
- X
- XFUNC tctype* duel_get_target_enum_tag(char *name)
- X{
- X struct symbol *sym;
- X sym = lookup_symbol (name, get_selected_block(), STRUCT_NAMESPACE,0,0);
- X if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_ENUM) {
- X sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0,0);
- X if(!sym || TYPE_CODE(SYMBOL_TYPE(sym))!=TYPE_CODE_ENUM) return NULL ;
- X }
- X return duel_convert_type_from_gdb(SYMBOL_TYPE(sym));
- X}
- X
- X/* a short command summary for those who can't manage with gdb help command*/
- X
- XLPROC gdb_help(void)
- X{ printf("\
- XNO NONSENSE SUMMARY OF GDB COMMANDS for DUEL users\n\
- X\n\
- XTo COMPILE: cc -g myprog.c -o myprog. \n\
- XTo RUN: gdb myprog <ret> (gdb) b main <ret> (gdb) r arg1 arg2 <ret>\n");
- X printf("\n\
- XBREAKPOINTS LISTING\n\
- Xb 59 # in line 59 l 25 # line 25..<ret> more\n\
- Xb qsort # in function qsort l xsort # func xsort\n\
- Xb eval.c:33 # in file eval.c, line 33 l eval.c:12 # file eval.c line 12\n\
- Xd 3 # delete breakpoint 3. info break # show breakpoints\n");
- X printf("\n\
- XTypical: 'l func' to list func, <ret> to show more, 'b 59' to set break \n\
- Xat line 59. When breakpoint occurs, gdb gives its number. 'd 3' delete\n\
- Xbreakpoint number 3.\n");
- X printf("\n\
- XSTEPPING DISPLAY \n\
- Xs # trace into functions bt # show stack \n\
- Xn # step over functions p exp # evaluate and print exp\n\
- Xc # continue execution pt exp # print exp's type\n\
- Xr # restart program (run) dl exp # Duel\n\
- Xn 5 # repeat n 5 times (s too) up/down # move up/down the frames stack\n");
- X}
- X
- X/*
- X * entry point from gdb.
- X * produce help in gdb's format, or call duel enter point.
- X * we allow ^c to quit immidiatly, and setup memory release cleanup.
- X */
- X
- Xvoid duel_command(char *exp,int from_tty)
- X{
- X last_frame_no = -2 ; /* recompute frame location on each dl command */
- X tot_frames_no = -2 ;
- X
- X if(exp && strcmp(exp,"gdb")==0) gdb_help();
- X else {
- X make_cleanup(duel_cleanup); /* clear all allocated mem */
- X immediate_quit++ ;
- X duel_parse_and_eval(exp);
- X immediate_quit-- ;
- X if(!exp || strcmp(exp,"help")==0 || strcmp(exp,"?")==0)
- X printf("Try \"dl gdb\" for a summary of useful gdb commands\n");
- X }
- X}
- X
- X_initialize_duel()
- X{
- X add_com ("duel", class_vars, duel_command,
- X"Evaluate Duel expressions. Duel is a very high level debugging langauge.\n\
- X\"dl help\" for help. \"dl gdb\" for summary of GDB commands\n");
- X add_com_alias ("dl", "duel", class_vars, 1);
- X
- X}
- SHAR_EOF
- $TOUCH -am 0121212893 duelgdb.c &&
- chmod 0644 duelgdb.c ||
- echo "restore of duelgdb.c failed"
- set `wc -c duelgdb.c`;Wc_c=$1
- if test "$Wc_c" != "20549"; then
- echo original size 20549, current size $Wc_c
- fi
- # ============= src/Makefile ==============
- if test ! -d 'src'; then
- echo "x - creating directory src"
- mkdir 'src'
- fi
- echo "x - extracting src/Makefile (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/Makefile &&
- X#
- X# generic makefile for Duel 1.00.0
- X# nothing fancy is required: yacc/bison of parse.y, compile all other modules,
- X# and put all of the OBJ= modules into duel.a library.
- X# gdb is compiled with its own makefile (you add duel.a and duelgdb.c)
- X# selfduel, for testing, is compiled and linked with duel.a
- X
- X# NOTE:
- X# for SUN (sparc) you must use gcc or another ANSI compiler. cc doesnt
- X# support prototypes!
- X# Also for SUN, yacc inserts a declaration of malloc() at the first line
- X# of y.tab.c, which is WRONG (return char*). just delete it.
- X
- XCFLAGS= -g
- XCC= cc # won't work on SUN. need ANSI C prototypes support.
- X#CC= gcc
- X#CC = gcc -U__GNU__ # if you get __eprintf undefined (assert.h problem)
- XYACC=yacc
- X
- XOBJ= duel.o types.o eval.o misc.o y.tab.o error.o evalops.o print.o
- X
- Xall: duel.a duelself
- X
- Xduelself: duel.a duelself.o
- X $(CC) duelself.o duel.a -o duelself
- X
- Xduel.a: $(OBJ)
- X ar ru duel.a $(OBJ)
- X ranlib duel.a
- X
- Xy.tab.c: parse.y
- X $(YACC) parse.y
- Xclean:
- X rm -f $(OBJ) y.tab.c duelself.o
- X
- SHAR_EOF
- $TOUCH -am 0121204093 src/Makefile &&
- chmod 0644 src/Makefile ||
- echo "restore of src/Makefile failed"
- set `wc -c src/Makefile`;Wc_c=$1
- if test "$Wc_c" != "993"; then
- echo original size 993, current size $Wc_c
- fi
- # ============= src/patchlevel.h ==============
- echo "x - extracting src/patchlevel.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/patchlevel.h &&
- X#define PATCHLEVEL 0
- SHAR_EOF
- $TOUCH -am 0113165193 src/patchlevel.h &&
- chmod 0644 src/patchlevel.h ||
- echo "restore of src/patchlevel.h failed"
- set `wc -c src/patchlevel.h`;Wc_c=$1
- if test "$Wc_c" != "21"; then
- echo original size 21, current size $Wc_c
- fi
- # ============= src/duel.h ==============
- echo "x - extracting src/duel.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/duel.h &&
- X/* DUEL - A Very High Level Debugging Langauge. */
- X/* Public domain code */
- X/* Written by Michael Golan mg@cs.princeton.edu */
- X/*$Header: /tmp_mnt/n/fs/grad2/mg/duel/RCS/duel.h,v 1.4 93/01/12 21:28:47 mg Exp $*/
- X
- X/* duel.h - include file to be used with all duel source code.
- X * it defines important global constants & data types, as well as some
- X * global variables. prototypes should go in the duelprot.h file
- X */
- X
- X
- X/* common duel include files. I dunno why people don't like recursive
- X * includes, as long as it is consistent. Note only one level of recursion.
- X * the debugger module itself dont use this file, instead it includes what
- X * it needs directly.
- X * as for including "everything", unless one redefine some standard lib func,
- X * I feel safer including most standard lib files. It seems to prevent errors
- X * even if it garble the name space a bit.
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <stddef.h>
- X#include <string.h>
- X#include <assert.h>
- X#include <ctype.h>
- X#include <limits.h>
- X#include <math.h>
- X/* global data and types */
- X
- X#include "global.h"
- X
- X/* prototypes for all global functions follows */
- X
- X#include "proto.h"
- SHAR_EOF
- $TOUCH -am 0113165193 src/duel.h &&
- chmod 0644 src/duel.h ||
- echo "restore of src/duel.h failed"
- set `wc -c src/duel.h`;Wc_c=$1
- if test "$Wc_c" != "1162"; then
- echo original size 1162, current size $Wc_c
- fi
- # ============= src/global.h ==============
- echo "x - extracting src/global.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/global.h &&
- X/* DUEL - A Very High Level Debugging Langauge. */
- X/* Public domain code */
- X/* Written by Michael Golan mg@cs.princeton.edu */
- X/*$Header: /tmp_mnt/n/fs/grad2/mg/duel/RCS/global.h,v 1.9 93/01/12 21:52:11 mg Exp $*/
- X
- X/* this include file contains global definitions for duel. All global info
- X * is shared thru this single file.
- X */
- X
- X/*
- X * $Log: global.h,v $
- X * Revision 1.9 93/01/12 21:52:11 mg
- X * cleanup and set for release
- X *
- X * Revision 1.8 93/01/07 00:10:53 mg
- X * macros for func ptr auto-convert
- X *
- X * Revision 1.7 93/01/03 07:30:23 mg
- X * *** empty log message ***
- X *
- X * Revision 1.6 92/12/24 23:49:25 mg
- X * *** empty log message ***
- X *
- X * Revision 1.5 92/10/19 15:07:58 mg
- X * fvalue added (not ready yet), svalues dropped
- X *
- X * Revision 1.4 92/10/14 02:05:37 mg
- X * misc
- X *
- X * Revision 1.3 92/09/16 11:11:54 mg
- X * add builtin ctype_charptr
- X *
- X * Revision 1.2 92/09/15 05:47:49 mg
- X * some ops added
- X *
- X */
- X
- X
- X/* The following definitions are common programming tricks that I use
- X * in every program I write. I hope they are obvious. the FUNC/PROC
- X * constants are useful mainly when editing (to find a function def.)
- X * or when grep'ing on source files. DEF is set to "extern" by default,
- X * allowing declaration and definition of globals in one source. only
- X * duel.c should have #define DEF before including duel.h
- X */
- X
- X#define FUNC
- X#define PROC void
- X#define LPROC static void
- X#define LFUNC static
- X
- X#ifndef DEF
- X#define DEF extern /* declare only, 'int x' become 'extern int x'*/
- X#endif
- X
- X/* use simpler names for unsigned types, very common, I hope */
- X
- Xtypedef unsigned int uint ;
- Xtypedef unsigned char uchar ;
- Xtypedef unsigned short ushort ;
- Xtypedef unsigned long ulong ;
- X
- Xtypedef int bool ; /* suppose to be just 0,1 */
- X#define FALSE 0
- X#define TRUE 1
- X
- X /* these should be inline functions, they replace common lib func which
- X * change from system to system.
- X * duel_assert can be modified to call duel_fatal, so gdb itself isn't
- X * aborted because on an internal duel error.
- X */
- X
- X#define duel_assert(x) assert(x)
- X#define duel_bzero(x,y) memset(x,0,y)
- X#define duel_bcopy(x,y,s) memcpy(x,y,s)
- X
- X
- X
- X/*************
- X Parsing: the expression is converted into a tree.
- X Each node of this tree is of 'tnode' type.
- X Nodes can be:
- X An operator (like '+', or ':=' or 'for')
- X A constant (numbers. Strings are pointers to space!)
- X A symbol.
- X A regular expression (really a symbol extention)
- X
- X The evaluation of any node results in:
- X 1. 'Environment': duel variables and their values
- X 2. symbolic expression which describe the computation
- X meaning: keep the parentethis. in the expression a<<(3+b) (even if not needed!)
- X 3. A type & value
- X
- X Values:
- X Values are always a fixed length area of bytes; Any C type is like that.
- X**************/
- X
- X
- X/****** TYPES *******
- X A type described in the typical compiler's way, and also gdb's original
- X way. That is, a type is made of an 'atomic' types, like 'pointer to',
- X 'array of', etc. Each atomic type is described by a 'ctype' node. Ctype
- X node points to other ctype nodes as required. For example, a ctype node
- X of 'array of' will point to the node 'int' for the 'C' type array of int.
- X [The name ctype is used to indicate the C language type; 'type' is too
- X generic a term]
- X Example:
- X char *(*f[])() ;
- X Here, f is an array of pointers to functions returning a pointer to char.
- X The type is described with the top node being of CTK_ARRAY type. It
- X points to a 'CTK_PTR' node, which points to a 'CTK_FUNC' node which
- X points to a 'CTK_PTR' node which points to a 'CTK_CHAR' node which has,
- X as size, 1.
- X
- X The size of a type is the number of bytes occupied by it. it is zero
- X for types like 'function'. An array of 10 integers will have as size
- X 10*sizeof(int)
- X ********************/
- X
- Xtypedef enum { /* 'C' Type atomic primitive Kinds (CTK_) */
- X CTK_VOID=0, /* void type 'void' */
- X CTK_CHAR=1, /* primitive types */
- X CTK_UCHAR=2, /* note order is used in some macros */
- X CTK_SHORT=3,
- X CTK_USHORT=4,
- X CTK_INT=5,
- X CTK_UINT=6,
- X CTK_LONG=7,
- X CTK_ULONG=8,
- X CTK_FLOAT=9,
- X CTK_DOUBLE=10,
- X CTK_PTR=11, /* pointer '*' */
- X CTK_ARRAY=12, /* array '[]' */
- X CTK_FUNC=13, /* a function '()' */
- X CTK_STRUCT=14, /* a sturcture 'struct{}' */
- X CTK_UNION=15, /* a union 'union{}' */
- X CTK_ENUM=16 /* enum type 'enum{}' */
- X } tctype_kind ;
- X
- Xtypedef struct { /* a field (of struct) info */
- X char *name ; /* field name */
- X struct sctype *ctype ; /* field type */
- X int bitpos, bitlen ; /* for bit fields only */
- X} tctype_field ;
- X
- Xtypedef struct { /* an enumerator (constant of an enum) info */
- X char *name ; /* enumerator name */
- X int val ; /* value assigned to the name */
- X /* question: ansi-C say cosnt fit in int?*/
- X} tctype_enumerator ;
- X
- X
- Xtypedef struct sctype { /* a 'C' type description */
- X tctype_kind type_kind ;
- X char *name ; /* named of this type, if any */
- X size_t size ; /* size (total bytes) for this type */
- X union {
- X struct sctype *kid ; /* pointer to next atomic type */
- X struct {
- X int fields_no ;
- X tctype_field *fields ; /* union/struct fields */
- X } f ;
- X struct {
- X tctype_kind real_type_kind ; /* the type used for storage of the enum */
- X int enumerators_no ;
- X tctype_enumerator *enumerators ; /* enum's type enumerators list */
- X } e;
- X } u ;
- X } tctype ;
- X
- X
- X/**** BASIC C TYPES
- X these are initialized at run type to point to the basic C types.
- X basic types are never created again, e.g. pointer comparison with
- X these is sufficient to check type equality.
- X the voidptr is (void*) which is a basic type (what zero is converted
- X to when it is a pointer).
- X ptrdiff_t and size_t are actually pointing to their actualy types,
- X ie. normally point to ctype_int.
- X ****/
- X
- XDEF tctype *ctype_int, *ctype_uint, *ctype_short, *ctype_ushort,
- X *ctype_char, *ctype_uchar, *ctype_long, *ctype_ulong,
- X *ctype_float, *ctype_double,
- X *ctype_void, *ctype_charptr,
- X *ctype_voidptr,*ctype_ptrdiff_t,*ctype_size_t ;
- X
- X/* type checking macros */
- X
- X/** tell if type is a struct or union */
- X#define ctype_kind_struct_like(t) ((t)->type_kind==CTK_STRUCT || \
- X (t)->type_kind==CTK_UNION)
- X
- X/** tell if type is a pointer or can be made one (array, func) */
- X#define ctype_kind_ptr_like(t) ((t)->type_kind==CTK_PTR || \
- X (t)->type_kind==CTK_ARRAY || (t)->type_kind==CTK_FUNC)
- X/* tell if type is numeric */
- X#define ctype_kind_numeric(t) ((t)->type_kind>=CTK_CHAR && \
- X (t)->type_kind<=CTK_DOUBLE || (t)->type_kind==CTK_ENUM)
- X
- X/* tell if type is integral */
- X#define ctype_kind_integral(t) ((t)->type_kind>=CTK_CHAR && \
- X (t)->type_kind<=CTK_ULONG || (t)->type_kind==CTK_ENUM)
- X
- X/* tell if type fits into fixed memory size (void not included) */
- X#define ctype_kind_scalar(t) (ctype_kind_numeric(t) || ctype_kind_ptr_like(t))
- X
- X/* tell if type is a "base" ie can't have kids */
- X
- X#define ctype_kind_base(t) ((t)->type_kind>=CTK_VOID && \
- X (t)->type_kind<=CTK_DOUBLE)
- X
- X/* tell if a type is a function pointer or like a func ptr (ie a func!) */
- X#define ctype_kind_func_ptr_like(t) ((t)->type_kind==CTK_FUNC || \
- X (t)->type_kind==CTK_PTR && t->u.kid->type_kind==CTK_FUNC)
- X
- X
- X/***** VALUES
- X used to keep information when evaluating an expression. A value is
- X either:
- X 1) a right-value, which is represented in a fixed number of bytes that
- X actually contain its value. Example: result of '+' operation.
- X 2) a left-value. This is a reference to the actual value, which
- X resides in the debuggee's address space.
- X 3) a special-value. This contains a long value specifying a special
- X target location (e.g. register) from which values can be fetched
- X or written to. However, special-values can not be manipulated (i.e
- X have an offset added to them, as done to an lvalue struct).
- X
- X Note that the operation '*x' starts with x as an lvalue - a pointer to
- X x is kept. Then, '*x' is executed, fetching the value of x and creating
- X another lvalue, which points to where x has pointed to! This allows
- X &*x to be executed, as well as *x=1 or &x[1] ...
- X When the value of an lvalue is actually needed, it must be fetched
- X from the debugge's space.
- X *****/
- X
- X#define VALUE_MAX_CONST_SIZE 8
- X#define VALUE_MAX_SYMBOLIC_SIZE 128
- X
- Xtypedef int tptrsize_int ; /* type so that
- X tptrsize x; char *p ;
- X p == (char*) (tptrsize) p
- X */
- X
- X /* type that represent a target address space location. */
- X
- Xtypedef char* ttarget_ptr ; /* pointer to target's address */
- X
- Xtypedef struct {
- X ttarget_ptr lvalue ; /* pointer to target's location of struct*/
- X int bitpos,bitlen ; /* as specified in the field info of stuct*/
- X } tbvalue_info ;
- X
- Xtypedef enum {
- X VK_RVALUE, /* this value represent a constant, in the rval_ union */
- X VK_LVALUE, /* this value represent a left-value. address in lvalue*/
- X VK_BVALUE, /* a bit-field lvalue, given as point and bitpos/bitlen*/
- X VK_FVALUE, /* a frame, fvalue contains it number */
- X } tval_kind ;
- X
- Xtypedef struct {
- X tval_kind val_kind ;
- X tctype *ctype ; /* type of this value */
- X union {
- X ttarget_ptr lvalue ; /* location in target of the value */
- X tbvalue_info bvalue ; /* location in target of a bitfield */
- X int fvalue ; /* a frame number (0 = top of stack) */
- X char rval_char ;
- X uchar rval_uchar ;
- X short rval_short ;
- X ushort rval_ushort ;
- X int rval_int ;
- X uint rval_uint ;
- X long rval_long ;
- X ulong rval_ulong ;
- X float rval_float ;
- X double rval_double ;
- X ttarget_ptr rval_ptr ;
- X ptrdiff_t rval_ptrdiff_t ; /* Synonyms to one of the above fields! */
- X size_t rval_size_t ; /* normally these are simply = rval_int */
- X } u ;
- X char symb_val[VALUE_MAX_SYMBOLIC_SIZE];
- X } tvalue ;
- X
- X
- Xtypedef struct sval_lcell { /* a cell on a linked-list containing a tvalue*/
- X tvalue val ;
- X struct sval_lcell *next ;
- X } tval_lcell ;
- X
- Xtypedef struct { /* a linked list of tvalue's */
- X tval_lcell *head ;
- X tval_lcell *tail ;
- X} tval_list ;
- X
- X/**** OP CODES ****
- X Opcodes are divided into groups, or 'kinds'. For example, all the
- X C regular unary operators, binary operators, etc.
- X An opcode is defined by its 'kind' and actual value. The value is,
- X in most cases, a single char. For example, the C plus operator is
- X defined as op_kind=OPK_BIN and op='+'. The C operator '+=' is
- X defined as op_kind=OPK_ASSIGN and op='+'.
- X some operators are uniquely identified by type alone (e.g. func call).
- X In the lexer there is a table of actual operators as tokens, and
- X the kind & value assigned to each.
- X Several opertors use more than one char, and are defined below.
- X the OPK_SBIN, etc kinds are special in the sense that A op B isn't
- X computed in the normal way of the C language (i.e. compute both sides,
- X then apply the operator). Such operators include ',' '&&', etc.
- X **********/
- Xtypedef enum {
- X /* '+' '-' etc are used directly and have their ascii value */
- X OP_LSH = 300, /* '<<' */
- X OP_RSH = 301, /* '>>' */
- X OP_INC = 302, /* '++' */
- X OP_DEC = 303, /* '--' */
- X OP_ARR = 304, /* '->' */
- X OP_AND = 305, /* '&&' */
- X OP_OR = 306, /* '||' */
- X OP_EQ = 307, /* '==' */
- X OP_GE = 308, /* '>=' */
- X OP_LE = 309, /* '<=' */
- X OP_NE = 310, /* '!=' */
- X OP_SIZ = 311, /* 'sizeof' */
- X OP_TO = 312, /* '..' */
- X OP_EQQ = 313, /* '==?' */
- X OP_NEQ = 314, /* '!=?' */
- X OP_GEQ = 315, /* '>=?' */
- X OP_LEQ = 316, /* '<=?' */
- X OP_GTQ = 317, /* '>?' */
- X OP_LSQ = 318, /* '<?' */
- X OP_IMP = 319, /* '=>' */
- X OP_IF = 320, /* if() */
- X OP_DEF = 321, /* ':=' */
- X OP_DFS = 322, /* '-->' */
- X OP_BFS = 323, /* '->>' */
- X OP_POS = 324, /* '>--' */
- X OP_IOS = 325, /* '->-' */
- X OP_SEL = 326, /*'x[[y]]'*/
- X OP_FOR = 327, /*for(;;)'*/
- X OP_WHILE= 328, /*while() */
- X OP_DECL = 329, /* var decl*/
- X OP_FRAME= 330, /* frame(i)*/
- X } topcode ;
- X
- X/**** OPCODE KINDS ****/
- X
- Xtypedef enum { /* the kind of the opcode, 'OPK_' = OPcode Kind */
- X OPK_UNARY =0, /* regular unary operator */
- X OPK_SUNARY =1, /* special unary operator (sizeof) */
- X OPK_POST_UNARY =2, /* post unary operator (x++ etc) */
- X OPK_BIN =3, /* regular binary operator */
- X OPK_SBIN =4, /* special binary operator */
- X OPK_TRI =5, /* trinary (eg ?:) operator */
- X OPK_QUAD =6, /* quad (e.g.for(;;)) operator */
- X OPK_ASSIGN =7, /* assignment ie =, +=, -= etc */
- X OPK_FUNC =8, /* function call. 2nd kid made of ',' kids for parms */
- X OPK_CAST =9, /* type cast. 2nd kid convert to type in 1st kid */
- X OPK_NUM_OF =10 /* number of OPK_* op kinds */
- X } top_kind ;
- X
- X
- X/**** NODE KINDS ****/
- X
- Xtypedef enum { /* the kind of node */
- X NK_OP, /* contain an operator */
- X NK_CONST, /* contains a constant */
- X NK_NAME, /* contains a name/symbol */
- X NK_CTYPE, /* contain a 'C' type */
- X } tnode_kind ;
- X
- X#define NODE_MAX_KIDS 4 /* maximum no of kids per node */
- X#define NODE_MAX_SYM_LEN 50 /* maximum length for a symbol */
- X
- X/* the following structure is used to store one node of the expression tree.
- X * It contains two parts: (a) information to describe the node and (b)
- X * information used during the evaluation of the node.
- X *
- X * This structure could/should be optimized with ugly unions (e.g., for
- X * a node describing a constant(node_kind==NK_CONST) there is no need for
- X * the op, kids or any eval stuff!). However, only few nodes (less than 100?)
- X * are expected to be in memory at any time (how complex can a user
- X * expression be?). Hence, for clarity, no unions where used.
- X *
- X * All nodes have kids in the typical way. the opcode OPK_FUNC node is tricky:
- X * see parsing - the commas are handled as operators and not as part of the
- X * syntax. when a func call is evaluated, the top comma nodes are used to
- X * separate the arguments (this hack prevents complex parsing and complex tnode
- X * with variable num of kids, which would force the kids[] to be malloc etc.)
- X */
- X
- Xtypedef struct snode { /* a single node on an expression tree */
- X tnode_kind node_kind ; /* what kind of note this is */
- X /* NK_OP node info: op_kind,op,kids */
- X int src_pos ; /* starting source code location (op etc) */
- X top_kind op_kind ; /* opcode type (unary,bin etc) */
- X topcode op ; /* actual opcode: '-' for both unary&bin '-'*/
- X struct snode *kids[NODE_MAX_KIDS] ; /* pointers to node's kids */
- X tvalue cnst ; /* NK_CONST info - constant value */
- X char *name ; /* NK_NAME info - variable name */
- X tctype *ctype ; /* NK_CTYPE info - a type */
- X
- X struct { /* information used during node evaluation */
- X int level ; /* evaluation level (0=none, 1=left in x etc)*/
- X tvalue v1,v2 ; /* keep last computed operands, etc */
- X tval_list vlist ; /* value list for node (used in --> etc ops) */
- X int counter ; /* used for counting */
- X } eval ;
- X } tnode ;
- X
- X
- XDEF bool duel_debug ; /* debugging duel-itself mode */
- X
- X/* this things are machine dependent stuff */
- X
- X#define BITS_PER_BYTE 8 /* no of bits in (char) (right. try '9' :-) */
- SHAR_EOF
- $TOUCH -am 0113165193 src/global.h &&
- chmod 0644 src/global.h ||
- echo "restore of src/global.h failed"
- set `wc -c src/global.h`;Wc_c=$1
- if test "$Wc_c" != "15898"; then
- echo original size 15898, current size $Wc_c
- fi
- echo "End of part 2, continue with part 3"
- exit 0
-