Subject: Functions using variable values (shell archive) Date: Sat, 03 May 1997 13:19:53 +0300 From: The RATS #!/bin/sh # This is a shell archive (produced by GNU sharutils 4.2). # To extract the files from this archive, save it to some FILE, remove # everything before the `!/bin/sh' line above, then type `sh FILE'. # # Existing files will *not* be overwritten unless `-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 5776 -rw-rw-r-- call.c # 678 -rw-rw-r-- call.h # 1044 -rw-rw-r-- callChk.4gl # 706 -rw-rw-r-- error.c # 138 -rw-rw-r-- error.h # 2443 -rw-rw-r-- makefile # 34 -rw-rw-r-- makefile.depend # 443 -rw-rw-r-- makefile.prj # 5887 -rw-rw-r-- symtab.c # save_IFS="${IFS}" IFS="${IFS}:" gettext_dir=FAILED locale_dir=FAILED first_param="$1" for dir in $PATH do if test "$gettext_dir" = FAILED && test -f $dir/gettext \ && ($dir/gettext --version >/dev/null 2>&1) then set `$dir/gettext --version 2>&1` if test "$3" = GNU then gettext_dir=$dir fi fi if test "$locale_dir" = FAILED && test -f $dir/shar \ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) then locale_dir=`$dir/shar --print-text-domain-dir` fi done IFS="$save_IFS" if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED then echo=echo else TEXTDOMAINDIR=$locale_dir export TEXTDOMAINDIR TEXTDOMAIN=sharutils export TEXTDOMAIN echo="$gettext_dir/gettext -s" fi touch -am 1231235999 $$.touch >/dev/null 2>&1 if test ! -f 1231235999 && test -f $$.touch; then shar_touch=touch else shar_touch=: echo $echo 'WARNING: not restoring timestamps. Consider getting and' $echo "installing GNU \`touch', distributed in GNU File Utilities..." echo fi rm -f 1231235999 $$.touch # if mkdir _sh03210; then $echo 'x -' 'creating lock directory' else $echo 'failed to create lock directory' exit 1 fi # ============= call.c ============== if test -f 'call.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'call.c' '(file already exists)' else $echo 'x -' extracting 'call.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'call.c' && /* X Dynamic Calling Interface for 4GL programs. X X Written by Emil Sarkissian X Copyright( c ) 1997, Svilosa Co. */ X #include #include #include "error.h" #include "call.h" #include #include X /* default cache */ X long searchDefaultCache(); struct DynamicCache *DefaultCache = 0; X /* default 4gl function type */ X typedef (*TFglFunc)(); X /* X LET IdFunc = GetFuncId( FuncName ) */ X int getfuncid ( arg ) int arg; { X char funcName[ MAXFUNCNAME ]; X char fgeName[ 255 ]; X long funcAdr; X int i; X X popvchar( funcName, MAXFUNCNAME ); X X i=0; X while( funcName[i] ) X { X funcName[i] = tolower( funcName[i] ); X i++; X } X X if( (funcAdr = searchDefaultCache( funcName )) == -1 ) X { X pushint( 0 ); X arg_val(1); X popvchar( fgeName, 254 ); X X if( (funcAdr = getFuncAdr( fgeName, funcName )) == -1 ) X SysError("function name not found", M_CALL ); X } X retlong( funcAdr ); X return 1; } X /* X Search default cache for a certain function. Return -1 if X address not found. */ X long searchDefaultCache( funcName ) char *funcName; { X int i; X long address; X X if( !DefaultCache ) X return -1; X X for( i = 0;inumFuncs;i++ ) X if( (strcmp( funcName, DefaultCache->funcDefs[i].name ) == 0)) X if( DefaultCache->funcDefs[i].value ) X { X return DefaultCache->funcDefs[i].value; X } X else X return -1; X X return -1; } X /* X --------- Cache Functions ----------- X X Caches can be created for a certain file and a number of functions. X One cache can be used as the default cache. When a function address X is required, the default cache is searched first. If it is not found X there, the current executable file will be searched and then, if X the function is not found, an error will be generated. X */ X /* X LET IdCache = NewCache( FileName ) X X Creates a new cache for the current file name. X Returns the cache handle ( address ). */ X int newcache( arg ) int arg; { X int i; X struct DynamicCache *cache; X X cache = (struct DynamicCache*)malloc( sizeof( struct DynamicCache ) ); X X if( !cache ) X SysError("unable to allocate dynamic cache",M_CALL ); X X popvchar( cache->fileName, 254 ); X X cache->numFuncs = 0; X X for( i = 0;ifuncDefs[i].value = 0; X cache->funcDefs[i].name[0] = 0; X } X X pushlong( (long)cache ); X return 1; } X /* X CALL AddCacheFunc( FuncName, CacheId ) */ X #define CF_NAME cache->funcDefs[cache->numFuncs].name X int addcachefunc( arg ) int arg; { X struct DynamicCache *cache; X int i; X X poplong( (long*)&cache ); X popvchar( CF_NAME, MAXFUNCNAME ); X X for( i=0;inumFuncs++; X return 0; } X /* X X CALL LoadCache( CacheId ) X X Loads the entire cache up from its associated executable file. X */ X int loadcache( arg ) int arg; { X struct DynamicCache *cache; X X poplong( (long*)&cache ); X X createCache( cache ); X X return 0; } X /* X CALL DestroyCache( CacheId ) X X Destroys the cache, and removes it from the default position if it X is the default cache as well. */ X int destroycache( arg ) int arg; { X struct DynamicCache *cache; X X poplong( (long*)&cache ); X X if( DefaultCache == cache ) X DefaultCache = 0; X X if( cache ) X free( cache ); X X return 0; } X /* X CALL SetDefaultCache( CacheId ) X X Set the default cache. */ X int setdefaultcache( arg ) int arg; { X poplong( (long*)&DefaultCache ); } X /* X CALL ExecFuncId( ..., Id ) X X The point of having several ExecFuncIds is that the 4GL compiler X checks all function calls within a certain module and makes sure X that the same function is always called with the same number of X params, thus the following will be wrong: X X CALL ExecFuncId( Param1, Param2, FuncId1 ) # OK X X ... X X # later in the same sourse file X X CALL ExecFuncId( Param1, FuncId2 ) # Error - function ExecFuncId called X # with 2 params, instead of 3. X X So, to solve this problem I've provided several ExecFuncIds. So, the X correct way of writing the above will be: X X CALL ExecFuncId( Param1, Param2, FuncId1 ) # OK X X ... X X # later in the same sourse file ( we use ExecFuncId1 ) X X CALL ExecFuncId1( Param1, FuncId2 ) # Error - function ExecFuncId called X # with 2 params, instead of 3. */ X int execfuncid( arg ) int arg; { X int fgl_ret; X X TFglFunc func; X X poplong( &func ); X fgl_ret = func( arg-1 ); X return fgl_ret; } X int execfuncid1( arg ) int arg; { X int fgl_ret; X X TFglFunc func; X X poplong( &func ); X fgl_ret = func( arg-1 ); X return fgl_ret; } X int execfuncid2( arg ) int arg; { X int fgl_ret; X X TFglFunc func; X X poplong( &func ); X fgl_ret = func( arg-1 ); X return fgl_ret; } X int execfuncid3( arg ) int arg; { X int fgl_ret; X X TFglFunc func; X X poplong( &func ); X fgl_ret = func( arg-1 ); X return fgl_ret; } X int execfuncid4( arg ) int arg; { X int fgl_ret; X X TFglFunc func; X X poplong( &func ); X fgl_ret = func( arg-1 ); X return fgl_ret; } X int execfuncid5( arg ) int arg; { X int fgl_ret; X X TFglFunc func; X X poplong( &func ); X fgl_ret = func( arg-1 ); X return fgl_ret; } X int execfuncid6( arg ) int arg; { X int fgl_ret; X X TFglFunc func; X X poplong( &func ); X fgl_ret = func( arg-1 ); X return fgl_ret; } X #ifdef __DEBUG_ME_ X int cdebuginfo( arg ) int arg; { X int i; X struct DynamicCache *cache; X X poplong( &cache ); X X fprintf(stderr,"numFuncs: %d, fileName: >%s<\n", X cache->numFuncs, cache->fileName); X X for( i = 0;inumFuncs; i++ ) X fprintf(stderr,"%s --> %d\n", cache->funcDefs[i].name, X cache->funcDefs[i].value ); X return 0; } X #endif SHAR_EOF $shar_touch -am 0503130997 'call.c' && chmod 0664 'call.c' || $echo 'restore of' 'call.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'call.c:' 'MD5 check failed' 4c08df16224695a7b644260ffca2526c call.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'call.c'`" test 5776 -eq "$shar_count" || $echo 'call.c:' 'original size' '5776,' 'current size' "$shar_count!" fi fi # ============= call.h ============== if test -f 'call.h' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'call.h' '(file already exists)' else $echo 'x -' extracting 'call.h' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'call.h' && X /* X DFCI definitions. X X Written by Emil Sarkissian X Copyright( c ) 1997, Svilosa Co. */ X #ifndef __CALL_H #define __CALL_H X /* define constants cache will be around 2K */ X #define MAXFUNCNAME 30 #define MAXFUNCS 50 X /* Definition of the function description structure */ X struct FuncDesc { X X char name[MAXFUNCNAME]; /* function name */ X long value; /* function address */ X }; X /* Definition of the cache structure */ X struct DynamicCache { X X char fileName[255]; /* filename of program where functions reside */ X int numFuncs; /* number of function descriptions in cache */ X X struct FuncDesc funcDefs[MAXFUNCS]; }; X #endif /* __CALL_H */ SHAR_EOF $shar_touch -am 0503130997 'call.h' && chmod 0664 'call.h' || $echo 'restore of' 'call.h' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'call.h:' 'MD5 check failed' 8d6da63324278712fe5e33ca5e8de3df call.h SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'call.h'`" test 678 -eq "$shar_count" || $echo 'call.h:' 'original size' '678,' 'current size' "$shar_count!" fi fi # ============= callChk.4gl ============== if test -f 'callChk.4gl' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'callChk.4gl' '(file already exists)' else $echo 'x -' extracting 'callChk.4gl' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'callChk.4gl' && # Dynamic Function Calling Interface ( DFCI ) Testing Program X MAIN X DEFINE X IdCache INTEGER, X FirstName VARCHAR(30), X SecondName VARCHAR(30) X X # the cache is optional and speeds up the application X X # cache initialized here ---------------------------- X X LET IdCache = NewCache( ARG_VAL(0) ) X X CALL AddCacheFunc( "testthisfunc", IdCache ) X CALL SetDefaultCache( IdCache ) X CALL LoadCache( IdCache ) X X LET IdCache = GetFuncId("MyHandler") X X # end of cache initialization ----------------------- X X CALL ExecFuncId( '130697', 'Friday', 13, IdCache ) X RETURNING FirstName, SecondName X END MAIN X # this is the dynamic function which is called # via it's address in MAIN X FUNCTION MyHandler( DateVar, CharVar, IntVar) X DEFINE X DateVar DATE, X CharVar VARCHAR(20), X IntVar INTEGER X X DISPLAY "Testing Testing Testing..." X X DISPLAY "DateVar is: ", DateVar X DISPLAY "CharVar is: ", CharVar X DISPLAY "IntVar is: ", IntVar X X DISPLAY "Testing Testing Testing..." X X RETURN 'Emil','Sarkissian' END FUNCTION X SHAR_EOF $shar_touch -am 0503130997 'callChk.4gl' && chmod 0664 'callChk.4gl' || $echo 'restore of' 'callChk.4gl' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'callChk.4gl:' 'MD5 check failed' 24d23208670fc85b519d321d748fd2b7 callChk.4gl SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'callChk.4gl'`" test 1044 -eq "$shar_count" || $echo 'callChk.4gl:' 'original size' '1044,' 'current size' "$shar_count!" fi fi # ============= error.c ============== if test -f 'error.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'error.c' '(file already exists)' else $echo 'x -' extracting 'error.c' '(binary)' sed 's/^X//' << 'SHAR_EOF' | uudecode && begin 600 error.c M+RH*("!%2YH/@HC M:6YC;'5D92`\PH@(").;VYA M;64B+`H@(")$1D-)(@I].PH*+RH*("!R97!O"`I"FEN="!);F1E>#L*>PH@ ?(')E='5R;B!T>7!E17)R37-G6R!);F1E>"!=.PI]"FEN ` end SHAR_EOF $shar_touch -am 0503131097 'error.c' && chmod 0664 'error.c' || $echo 'restore of' 'error.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'error.c:' 'MD5 check failed' c34469cc0a0be43bf8952149311a1702 error.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'error.c'`" test 706 -eq "$shar_count" || $echo 'error.c:' 'original size' '706,' 'current size' "$shar_count!" fi fi # ============= error.h ============== if test -f 'error.h' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'error.h' '(file already exists)' else $echo 'x -' extracting 'error.h' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'error.h' && #ifndef __ERROR_H #define __ERROR_H X /* Module definitions for errors. */ X #define M_CALL 1 X void SysError( /* char *, int */); X #endif SHAR_EOF $shar_touch -am 0503130297 'error.h' && chmod 0664 'error.h' || $echo 'restore of' 'error.h' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'error.h:' 'MD5 check failed' 602464651a447d42c80f86af6f03425e error.h SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'error.h'`" test 138 -eq "$shar_count" || $echo 'error.h:' 'original size' '138,' 'current size' "$shar_count!" fi fi # ============= makefile ============== if test -f 'makefile' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'makefile' '(file already exists)' else $echo 'x -' extracting 'makefile' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile' && #------------------------------------------------------------------------------# X # Informix directory IDIR = /usr/informix X # AT&T compiler ( preferred by Informix ) CC = rcc X # Preprocessor to produce 4gl from 4gp files. PREP = m4 X # 4GL to ESQL/C compiler FGLE = $(IDIR)/lib/fglc X # ESQL/C to C compiler SQLC = $(IDIR)/lib/fglc2 X # Our libraries and standard libraries LIB = # -lintl -lcurses X # Included because of Informix recommendation FLG = -Dunix -Di386 X # Directory for Informix include files INCL = -I$(IDIR)/incl X # Informix FORM compiler. FRMC = form4gl X # Libraries to build Informix executables LIB4 = $(IDIR)/lib/lib4gl.a $(IDIR)/lib/libnforms.a $(IDIR)/lib/libfesql.a X #------------------------------------------------------------------------------# X # FGPSRC, FGLSRC, SQLSRC, CSRC, FRMSRC, LIB1, LIB2, LIB3, CFL, LINKFL, EXENAME # may be defined, if any, in makefile.prj file include makefile.prj X FGPOBJ = $(FGPSRC:.4gp=.o) FGLOBJ = $(FGLSRC:.4gl=.o) SQLOBJ = $(SQLSRC:.ec=.o) COBJ = $(CSRC:.c=.o) FRMOBJ = $(FRMSRC:.per=.frm) X #------------------------------------------------------------------------------# X X.SUFFIXES : .4gp .4gh .4gl .ec .c .h .o .a .per .frm X X.4gp.o : X @echo -n "Producing: $(<:.4gp=.4gl) " X @$(PREP) $< > $(<:.4gp=.4gl) X @echo -n "$(<:.4gp=.ec) " X @$(FGLE) $(<:.4gp=.4gl) X @echo "$(<:.4gp=.c)" X @$(SQLC) -4GL $(<:.4gp=.ec) X @echo -n "Compiling ... " X @$(CC) -c $(INCL) $(<:.4gp=.c) X @echo "Removing unnecessary files ..." X @rm $(<:.4gp=.c) $(<:.4gp=.ec) $(<:.4gp=.4gl) X X.4gl.o : X @echo "Producing $(<:.4gl=.ec) ..." X @$(FGLE) $< X @echo "Producing $(<:.4gl=.c) ..." X @$(SQLC) -4GL $(<:.4gl=.ec) X @echo "Compiling ..." X @$(CC) -c $(INCL) $(<:.4gl=.c) X @echo "Removing unnecessary files ..." X @rm $(<:.4gl=.c) $(<:.4gl=.ec) X X.ec.o : X $(SQLC) -4GL $< X @echo "Compiling ..." X $(CC) -c $(INCL) $(<:.ec=.c) X @echo "Removing unnecessary files ..." X @rm $(<:.ec=.c) X X.c.o : X @echo "Compiling ..." X $(CC) -c $< X X.per.frm : X @echo "Compiling forms ..." X $(FRMC) $< X #------------------------------------------------------------------------------# X $(EXENAME): $(FGPOBJ) $(FGLOBJ) $(SQLOBJ) $(COBJ) $(FRMOBJ) X @echo "Assembling executable file '$(EXENAME)' ..." X @c4gl $(CFL) $(FGPOBJ) $(FGLOBJ) $(SQLOBJ) $(COBJ) -o $(EXENAME) $(LINKFL) \ X $(LIB1) $(LIB4) $(LIB2) $(LIB) $(LIB3) X @echo "Done." X include makefile.depend X #------------------------------------------------------------------------------# SHAR_EOF $shar_touch -am 0503130297 'makefile' && chmod 0664 'makefile' || $echo 'restore of' 'makefile' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'makefile:' 'MD5 check failed' 8c559ab533c60163661b781967d0f845 makefile SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'makefile'`" test 2443 -eq "$shar_count" || $echo 'makefile:' 'original size' '2443,' 'current size' "$shar_count!" fi fi # ============= makefile.depend ============== if test -f 'makefile.depend' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'makefile.depend' '(file already exists)' else $echo 'x -' extracting 'makefile.depend' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile.depend' && error.o: error.h X call.o: call.h SHAR_EOF $shar_touch -am 0503130297 'makefile.depend' && chmod 0664 'makefile.depend' || $echo 'restore of' 'makefile.depend' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'makefile.depend:' 'MD5 check failed' 0cbb794a1362271a06d306acec0d30a3 makefile.depend SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'makefile.depend'`" test 34 -eq "$shar_count" || $echo 'makefile.depend:' 'original size' '34,' 'current size' "$shar_count!" fi fi # ============= makefile.prj ============== if test -f 'makefile.prj' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'makefile.prj' '(file already exists)' else $echo 'x -' extracting 'makefile.prj' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile.prj' && # 4GL source files to be preprocessed (*.pgl) FGPSRC = X # FGL source files (*.4gl) FGLSRC = callChk.4gl X # ESQL/C source files (*.ec) SQLSRC = X # C source files (*.c) CSRC = symtab.c error.c call.c X # 4GL form files (*.per) FRMSRC = X # Declare all search directories VPATH = X # Libraries to include LIB1 = LIB2 = LIB3 = X # C compiler flags (if any) CFL = X # Linker flags (if any) LINKFL = X # Executable file name EXENAME = callChk SHAR_EOF $shar_touch -am 0503130297 'makefile.prj' && chmod 0664 'makefile.prj' || $echo 'restore of' 'makefile.prj' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'makefile.prj:' 'MD5 check failed' 0168c9e8ed07b725574c15befaeb5670 makefile.prj SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'makefile.prj'`" test 443 -eq "$shar_count" || $echo 'makefile.prj:' 'original size' '443,' 'current size' "$shar_count!" fi fi # ============= symtab.c ============== if test -f 'symtab.c' && test "$first_param" != -c; then $echo 'x -' SKIPPING 'symtab.c' '(file already exists)' else $echo 'x -' extracting 'symtab.c' '(text)' sed 's/^X//' << 'SHAR_EOF' > 'symtab.c' && /* X Symbol table reading functions. X X Written by Emil Sarkissian and Milen Metodiev X Copyright( c ) 1997, Svilosa Co. */ X #include #include #include #include #include #include #include "error.h" #include "call.h" X /* #define __DEBUG_ME_ */ X static char *strTable=0; X /* X Load string table from end of file. Offset of string table is X calculated using information from the file header ( filehdr ). X X The formulae is : f_symptr + ( f_nsyms * SYMESZ ) X X The table is loaded in dynamic memory and is not freed until X the end of the program. */ X void loadStringTable( fh, fhdr ) int fh; struct filehdr *fhdr; { X long flen; X long strOffset; X int i; X X strOffset = fhdr->f_symptr + ( fhdr->f_nsyms * SYMESZ ); X X lseek( fh, 0L, SEEK_SET ); X flen = lseek( fh, 0L, SEEK_END ); X X lseek( fh, strOffset, SEEK_SET ); X X if( (strTable = (char*)malloc( flen - strOffset ) ) == NULL ) X SysError("Out of memory: malloc from loadStringtable",M_CALL ); X X read( fh, strTable, flen-strOffset ); X } X #ifdef __DEBUG_ME_ X void printFileHdr( hdr ) struct filehdr *hdr; { X fprintf( stderr, "\nFile header: Magic: %X, Sections: %X, Time: %ld,\ X \nSym. Tab. Ptr: %ld, Sym. Tab.Num: %ld, sizeof( opt hdr ): %d, flags: %d\n", X hdr->f_magic, hdr->f_nscns, hdr->f_timdat, hdr->f_symptr, hdr->f_nsyms, X hdr->f_opthdr, hdr->f_flags ); } X void printSymEntry( entry ) struct syment *entry; { X X entry->n_name[7] = 0; X fprintf( stderr, "\nSym name: %s, Sym offset: %ld, Aux: %d\n", X entry->n_name, entry->n_offset, entry->n_numaux ); } X #endif X /* X Opens the file, reads the file header. Then checks to see if the X string table is loaded, and loads it if it is not. X X The file header contains the offset of the symbol table in X f_symptr, and it contains the number of symbols ( including auxentry X unions ) in f_nsyms. X X This function traverses the symbol table. When it meets a symbol X entry, it skips all the auxiliary entries using lseek. If no X auxentries are available, it moves to the next symbol and so on. X X Symbols are filtered using the ISFCN( x ) macro, thus letting only X function names through. X X Depending on how long the entry is, it could be placed directly in X the symbol entry ( n_name ) or it could be placed in the string X table in the end of the file. This means that if it is longer than X SYMNLEN, then it goes to the string table because of the fixed size X of a symbol entry. X X PS. Symbol entries and auxentry unions are of the same size which X is defined to be SYMESZ bytes. */ X long getFuncAdr( fileName, funcName ) char *fileName, *funcName; { X int fh; X int i,j; X X union auxent auxentry; X struct filehdr fhdr; X struct syment sym; X X /* open binary file */ X X if( ( fh = open(fileName,O_RDONLY) )==-1 ) X SysError( "Can not open executable.",M_CALL ); X X /* read file header at beginning of file */ X X read( fh, &fhdr, sizeof ( struct filehdr ) ); X X /* load string table if not already loaded */ X X if( !strTable ) X loadStringTable( fh, &fhdr ); X X /* set position to start of symbol table */ X X lseek( fh, fhdr.f_symptr, SEEK_SET ); X X /* traverse through all the symbol table entries */ X X while( fhdr.f_nsyms-- ) X { X read( fh, &sym, SYMESZ ); X X /* skip any auxiliary entries for the current symbol table entry */ X while( sym.n_numaux-- ) X { X lseek( fh, SYMESZ, SEEK_CUR ); X fhdr.f_nsyms--; /* f_nsyms includes auxentries. */ X } X X /* check functions only */ X X if( (sym.n_type==0 ) || ISFCN(sym.n_type) ) X if( sym.n_zeroes == 0L) /* in stringTable */ X { X if( (strcmp( funcName, &strTable[ sym.n_offset ] )) == NULL ) X { X close( fh ); X return sym.n_value; X } X } X else /* directly placed in syment structure. watchout for trailing 0! */ X { X /* use strncmp to avoid 8 chars with no 0 at the end of n_name. */ X X if( (strncmp( sym.n_name, funcName, SYMNMLEN /* 8 */ )) == NULL ) X { X close(fh); X return sym.n_value; X } X } X } X X /* search was not successful */ X X close( fh ); X return -1; } X /* X X Does the same job as getFuncAdr, but fills an array of structures X within cache, each of which contains information about one function. X */ X int createCache( cache ) struct DynamicCache *cache; { X int fh; X int i,j,n; X X union auxent auxentry; X struct filehdr fhdr; X struct syment sym; X X /* open binary file */ X X if( ( fh = open(cache->fileName,O_RDONLY) )==-1 ) X SysError( "Can not open executable.",M_CALL ); X X /* read file header at beginning of file */ X X read( fh, &fhdr, sizeof ( struct filehdr ) ); X X /* load string table if not already loaded */ X X if( !strTable ) X loadStringTable( fh, &fhdr ); X X /* set position to start of symbol table */ X X lseek( fh, fhdr.f_symptr, SEEK_SET ); X X /* traverse through all the symbol table entries */ X X while( fhdr.f_nsyms-- ) X { X read( fh, &sym, SYMESZ ); X X /* skip any auxiliary entries for the current symbol table entry */ X while( sym.n_numaux-- ) X { X lseek( fh, SYMESZ, SEEK_CUR ); X fhdr.f_nsyms--; /* f_nsyms includes auxentries. */ X } X X /* check functions only */ X X if( (sym.n_type==0 ) || ISFCN(sym.n_type) ) X if( sym.n_zeroes == 0L) /* in stringTable */ X { X for( n = 0; nnumFuncs; n++ ) X if( (strcmp( cache->funcDefs[n].name, X &strTable[ sym.n_offset ] )) == NULL ) X { X cache->funcDefs[n].value = sym.n_value; X } X } X else /* directly placed in syment structure. watchout for trailing 0! */ X { X /* use strncmp to avoid 8 chars with no 0 at the end of n_name. */ X X for( n = 0; nnumFuncs; n++ ) X if( (strncmp(sym.n_name, cache->funcDefs[n].name, SYMNMLEN)) == NULL ) X { X cache->funcDefs[n].value = sym.n_value; X } X } X } X X close( fh ); X return 0; } X #ifdef __DEBUG_ME_ X void main( argc, argv ) int argc; char *argv[]; { X X printf("Function address: %ld\n" ,getFuncAdr("ss",argv[1] )); } X #endif X SHAR_EOF $shar_touch -am 0503130297 'symtab.c' && chmod 0664 'symtab.c' || $echo 'restore of' 'symtab.c' 'failed' if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then md5sum -c << SHAR_EOF >/dev/null 2>&1 \ || $echo 'symtab.c:' 'MD5 check failed' 7cf70c7b2597a329396392e6fed54d2f symtab.c SHAR_EOF else shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'symtab.c'`" test 5887 -eq "$shar_count" || $echo 'symtab.c:' 'original size' '5887,' 'current size' "$shar_count!" fi fi rm -fr _sh03210 exit 0