home *** CD-ROM | disk | FTP | other *** search
- 1 PACKING LIST/INSTALLATION
-
- Presumably, you have received the DEBUGIFY software in some sort of packaged
- form, e.g., as a ZIP or TAR file. The package should include the following
- files:
-
- DEBUGIFY.IC0 The unconfigured ICON source for the DEBUGIFY program
- which installs debug hooks into ucode files. This is
- used to create the configured DEBUGIFY.ICN source.
- DEBUG.ICN The ICON source for an example debug procedure which may
- be used with DEBUGIFY.
- DEBUGIFY.DOC The file you are reading now. This file describes how
- to install and use the above files.
- DEBCFG.ICN The ICON source for the program which configures DEBUGIFY for
- the current version of ICON.
-
- It is assumed that you have previously installed the ICON version 8 translator
- and interpreter and the ICON program library. DEBUGIFY may work with versions 7
- and 7.5, but I have not tested it with them. DEBUGIFY was designed to be as
- system-independent as possible, however, it has only been tested on the MS-DOS
- and UNIX (4.3bsd) ICON versions. It is assumed that you have had some experience
- with ICON, e.g., you know how to link separately compiled modules, you know what
- a ucode file is, etc.
-
- Because of minor differences in ucode files, DEBUGIFY must be configured for the
- version of Icon running on your system. DEBUGIFY MUST BE RECONFIGURED EACH TIME
- A DIFFERENT VERSION OF ICON IS USED!! To configure or reconfigure DEBUGIFY, make
- sure the following files are in the same directory:
-
- DEBUGIFY.IC0
- DEBCFG.ICN
-
- To prepare the configuration process, execute the following in that directory:
-
- icont -c debcfg
- icont debcfg.u
-
- To create DEBUGIFY.ICN, execute the following:
-
- iconx debcfg
-
- To compile DEBUGIFY, execute the following:
-
- icont debugify
-
- after compilation, move the resultant DEBUGIFY or DEBUGIFY.ICX file to a directo-
- ry where you keep executable files.
-
- To compile DEBUG, change to the directory containing DEBUG.ICN and execute the
- following:
-
- icont -c debug
-
- after compilation, move the resultant DEBUG.U1 and DEBUG.U2 files to a directory
- where you keep ICON procedure ucode files.
-
- ONCE AGAIN, ALL OF THE ABOVE STEPS, INCLUDING RECOMPILING DEBCFG.ICN, MUST BE
- PERFORMED EACH TIME A DIFFERENT VERSION OF ICON IS USED!
-
- 2 INTRODUCTION
-
- In using ICON, I have frequently felt the need for a more capable debug facility
- than that offered by the usual ICON tracing. It would be nice to be able to
- trace at a source line level rather than at a procedure entry/exit level. A good
- debugger should also allow interactive display and modification of program
- variables. DEBUGIFY enables the ICON programmer to produce an executable file
- which calls a debug routine prior to executing each ICON statement. The debug
- routine is written in ICON and may be modified or replaced entirely by the
- programmer. This gives the programmer maximum flexibility to define what he
- wants the debug routine to do.
-
- I considered several possible ways of implementing an ICON debugger. The first
- method was to write a program in ICON which would parse an ICON source file and
- insert additional ICON debugging statements in the source file. I actually
- started to write this program. After awhile I realized I would never be able to
- finish this project in the limited spare time I had. The second method consid-
- ered was using the ICON variant translator system to create debugging code along
- with the translation of each source code statement. Unfortunately, the variant
- translator system is not included in all ICON versions, particularly those for
- personal computers. Since I use ICON at work on a UNIX system and at home on my
- MS-DOS system, the variant translator debugging method would not be usable on the
- MS-DOS machine.
-
- In Issue Number 8 (October 1991) of The Icon Analyst, the article "An Imaginary
- Icon Computer" briefly discussed the structure of ucode files. It contained an
- example of an Icon program and its corresponding ucode. I realized that with a
- little study, ucode files are not be hard to understand. Basically, ucode files
- are source code files based on a Postfix-evaluation type of stack language.
- Those of you who have had experience with FORTH would probably be able to read
- ucode files with little difficulty. Anyway, I found that I could modify ucode
- files, compile them into executables, and they would run just as if I had altered
- the original source code instead of the ucode files. DEBUGIFY performs a ucode
- modification automatically.
-
- DEBUGIFY reads a ucode file and inserts additional ucode statements before and
- after each block of ucode statements which correspond to a single source code
- line. To be more precise, the ICON translator converts an ICON source file into
- a stream of ucode stack language commands and inserts ICON source line markers
- wherever appropriate. DEBUGIFY inserts a call to a debugging routine after each
- of the source line markers. DEBUGIFY inserts ucode which is exactly equivalent
- to the following ICON source code:
-
- __vals := []
- every put(_vals, variable(!__names))
- __debug_proc(&file, <proc_name>, &line, __names, __vals)
- every __i := 1 to *__names do
- variable(__names[__i]) := __vals[__i]
-
- The first two lines collect the values of all the currently accessible variables
- and place them on the __vals list. The third line calls a user-written ICON
- procedure called __debug_proc. The last two lines replace the values of all
- variables with new ones which may or may not have been changed by __debug_proc.
-
-
- 3 USING DEBUGIFY
-
- There are basically four steps to follow in producing a DEBUGIFYed program.
-
- 1) Write source code modules
- 2) Compile source code to ucode
- 3) DEBUGIFY selected ucode modules
- 4) Link DEBUGIFYed and regular ucode modules to produce final program
-
- STEP 1: WRITE SOURCE CODE MODULES
-
- Assume you have written an ICON program consisting of three procedures: main,
- proc, and replace contained in the source files MAIN.ICN, PROC.ICN and
- STRINGS.ICN, respectively. Note that STRINGS.ICN is part of the Icon Program
- Library while main and proc are user-written procedures. We will assume that the
- procedure replace has already been thoroughly debugged and therefore you will
- only want to DEBUGIFY main and proc. Optionally, MAIN.ICN and PROC.ICN each may
- contain the statement
-
- link <debugfile>
-
- where <debugfile> is the name of the file containing the __debug_proc procedure.
- This is DEBUG if the supplied __debug_proc is used and DEBUG is contained in a
- directory on the IPATH path.
-
- STEP 2: COMPILE SOURCE CODE TO UCODE
-
- To produce ucode files, enter the following:
-
- icont -c MAIN.ICN
- icont -c PROC.ICN
- icont -c STRINGS.ICN (if not already done)
-
- which will produce the needed .U1 and .U2 files.
-
-
- STEP 3: DEBUGIFY SELECTED UCODE MODULES
-
- This step produces new MAIN.U1 and PROC.U1 files with debugging hooks inserted.
- First rename MAIN.U1 to another file name, say MAIN.TMP and enter either
-
- DEBUGIFY -m MAIN.TMP> MAIN.U1
-
- for UNIX or
-
- iconx DEBUGIFY -m MAIN.TMP> MAIN.U1
-
- for MS-DOS
-
- Repeat the aboe rename and DEBUGIFY steps for PROC.U1.
-
- STEP 4: LINK UCODE MODULES TO PRODUCE FINAL PROGRAM
-
- To create the executable file MAIN (UNIX) or MAIN .ICX (MS-DOS), run the follow-
- ing:
-
- icont MAIN.U PROC.U STRINGS.U DEBUG.U
-
- or if the line "link DEBUG" was inserted in MAIN.ICN, then it is only necessary
- to run
-
- icont MAIN.U PROC.U STRINGS.U
-
- You can now run the executable file and it will enter __debug_proc prior to
- executing each source code line.
-
- LINKING UNDER MS-DOS
-
- Since a debugified ucode file can be 6 times larger than the equivalent untreated
- ucode file, the MS-DOS ICON interpreter may not be able to perform the compila-
- tion of MAIN. If you get an error message which says "icont: out of <something>
- space", then you can try recompiling with the -S option. The <something> might
- be label, constant, code buffer, or any of a number of other space-consuming
- objects. The -S option is of the form -S[cfgilnrstCFL]n where the letter
- following S stands for the one of the type of objects in the table below and n is
- the number of storage units to allocate for objects of that type. For example
-
- icont -SL100 -SC32767 PROG.U
-
- would provide twice the usual amount of label space and the maximum amount of
- code buffer space.
-
- c constant table 100
- f field table 100
- g global symbol table 200
- i identifier table 500
- l local symbol table 100
- n line number table 1000
- r record table 100
- s string space 20000
- t tree space 15000
- C code buffer 15000
- F file names 10
- L labels 500
-
- The numbers given above represent the default storage unit allocations for each
- of the object types. The above table and the information on the -S option is
- based on the technical report "Version 8 of Icon for MS-DOS" by Ralph E.
- Griswold.
-
- If a program cannot be compiled after using the -S option, there are three more
- tricks that can be used. First of all, a considerable amount of memory can be
- saved if DEBUGIFY is run without the -m option. The m option tells DEBUGIFY to
- insert the ucode lines which allow __debug_proc modifications to variable values
- to remain in effect when control passes back to the procedure being debugged.
- Without -m, __debug_proc changes to values are not visible to the procedure being
- debugged. So a __debug_proc with an interactive "set value" command would never
- work unless -m was used. A debugified ucode file created without the -m option
- is about 4 times larger than the undebugified version. Note that it was not
- possible to debugify DEBUGIFY with the -m option on my MS-DOS computer. However,
- when -m was left off, DEBUGIFY could be recompiled with
-
- icont -SL1000 -SC24000 DEBUGIFY.U
-
- The second trick involves restructuring the program to be debugified by breaking
- it into more and smaller procedures. It seems that memory resources used for
- compilation of a procedure are released after the compiler is done with that
- procedure. This means that a program is only as difficult to debugify as is its
- largest (or most complex) procedure. Thus the strategy is to break up large
- procedures into ones that have fewer executable statements and fewer variables.
- The positive side of this restructuring is that it usually improves the read-
- ability and maintainability of a program to reduce the size of very large
- procedures.
-
- The third trick is selectively debugifying only some of the procedures which make
- up the application program. This was already done in the example above involving
- main, proc, and replace. Only main and proc were DEBUGIFYed. However procedures
- can be selectively DEBUGIFYed even when they reside in the same source file. If
- MAIN.ICN contained the procedures main, proc1 and proc2, and proc2 was deemed too
- complex to DEBUGIFY, we could exclude it without breaking it out of MAIN.ICN like
- this
-
- DEBUGIFY -i main -i proc1 MAIN.TMP > MAIN.U1
-
- Use of the -i option includes only the procedures main and proc1 for DEBUIFica-
- tion.
-
- As must be obvious by now, DEBUGIFY is not always simple to use. It is recom-
- mended that the debugification steps presented above be automated via a batch
- (MS-DOS) or shell script (UNIX) file. Such a file would 1) create the initial
- ucode file, 2) rename and debugify it, and 3) perform the final compilation and
- link step.
-
- DEBUGIFY COMMAND LINE SUMMARY
-
- DEBUGIFY [-m] [[-i procedure_name]...] ucode_file
-
- Install debug hooks in all the procedures in ucode_file and writes out the
- resultant ucode file to standard output. When the resultant ucode file is
- compiled and executed the procedure __debug_proc is invoked prior to the execu-
- tion of each source code line. By default, debug hooks are installed in all
- procedures in ucode_file. It is assumed that the source code file for ucode_file
- includes a link statement for the file containing the __debug_proc ucode or will
- be otherwise linked to __debug_proc in a later call to icont.
-
- -m Generate ucode that will allow __debug_proc to alter the value of
- program variables. A debugified ucode file created with -m is about
- 6 times larger than the equivalent untreated ucode file. Without -
- m, this reduces to a factor of about 4.
-
- -i Debugify the procedure whose name follows the -i option. If
- DEBUGIFY encounters any -i options, then only those procedures named
- on the command line with -i will be debugified.
-
- 4 WRITING A NEW DEBUG ROUTINE
-
- One of the great benefits of using DEBUGIFY is that you are not restricted to
- using the debug procedure in the supplied DEBUG.ICN file. A new one may be
- written in Icon or the supplied one may be modified. To get used to using
- DEBUGIFY, it is suggested that initially at least one program be DEBUGIFYed
- using the supplied DEBUG.ICN.
-
- If you intend to modify the supplied debug routine or write one of your own, you
- must be aware of the nature of the debug interface which DEBUGIFY installs. It
- is also suggested that you study the supplied source code in DEBUG.ICN (see the
- next section too).
-
- The debug procedure invocation which DEBUGIFY installs in ucode corresponds
- exactly to the following ICON source code:
-
- __debug_proc(&file, <proc_name>, &line, __names, __vals)
-
- Note that __debug_proc must be the name of the debug procedure you supply. The
- parameters passed to __debug_proc are:
-
- &file The ICON keyword whose value is the name of the current source
- code file.
-
- <proc_name> A string containing the name of the procedure currently
- executing when __debug_proc is called.
-
- &line The ICON keyword whose value is the number of the source code
- line which will be executed after __debug_proc returns.
-
- __names A list of strings, each of which is the name of a
- variable referenced in the currently executing
- procedure. If a variable is global, but not referenced
- anywhere in the procedure, then it will not appear in
- this list.
-
- __vals A list of values, each of which is the value of a
- variable referenced in the currently executing proce-
- dure. The lists, __names and __vals, are ordered in
- such a way that the variable whose name is __names[i]
- has value __vals[i]. The procedure __debug_proc may
- change a value in the procedure from which it was called
- by changing the corresponding element in __vals. For
- example, if __names[3] is "VAR1", then executing
-
- __vals[3] := "panic"
-
- will have the effect of assigning "panic" to the vari-
- able VAR1 when __debug_proc returns to its calling
- routine. This change will only be visible to the call-
- ing procedure if it was debugified with the -m option.
- Note that changing the length of the list __vals may
- have strange and undesirable effects if the -m option is
- set.
-
- 5 USING THE SUPPLIED DEBUG ROUTINE
-
- A simple but useful __debug_proc procedure is supplied in the file DEBUG.ICN.
- It is of the interactive command line variety like the MS-DOS DEBUG program.
- Each time __debug_proc is entered and is producing output (i.e., when not in a
- silent trace and not after an "nd" command), a status line is printed. A typical
- status line might look like:
-
- proc.icn:co-expression_1(1):proc:23
-
- This means __debug_proc has stopped just prior to execution of line 23 in the
- procedure proc during the execution of co-expression co-expression_1(1). The
- file proc.icn is the source file containing the line about to be executed.
-
- Following the appearance of the status line, the user is prompted to enter debug
- commands with the prompt
-
- debug>
-
- This prompt will repeat after each command is executed until one of the following
- occurs:
-
- 1) A blank line is entered
- 2) The "stop" or "nd" command is entered
-
- The debug commands are summarized below:
-
- p var [var]... Print the type and image of each variable speci-
- fied. Currently, thee is no way to print the
- image of structure (record, list, or table) compo-
- nents.
-
- pa Print the type and image of all variables.
-
- sn var number Set the value of the variable to the number
-
- ss var string Set the value of the variable to the string. The
- string may contain blanks however consecutive
- blanks are compressed to a single blank. A blank
- may be represented by "\ " so that consecutive
- blanks may be entered as \ \ \ \ ...
-
- t Turn on trace mode. When in trace mode,
- __debug_proc prints out the current line number
- and other information needed for tracing execution
- and then returns to the caller. No input is
- requested from the user. However if the current
- line number is a breakpoint, then the debug
- interpreter will request input even though in
- trace mode. Note that the trace command does not
- take effect immediately. The debug interpreter
- continues processing input until a blank line is
- entered at which time __debug_proc is exited and
- tracing begins.
-
- ut Turn off trace mode.
-
- ts Make trace run silently. Nothing is printed by
- __debug_proc when in trace mode. Note that "ts"
- does not turn trace mode on or off. It is only
- meaningful when trace mode is activated.
-
- tv Make trace run verbosely (default). The normal
- information is printed by __debug_proc when in
- trace mode. Note that "tv" does not turn trace
- mode on or off. It is only meaningful when trace
- mode is activated.
-
- sbp integer [integer]... Set each of the specified line numbers as trace
- breakpoints. The debug interpreter will not complain if
- you set non-existent lines as breakpoints. It will
- simply have no effect.
-
- ubp integer [integer]... Unset each of the specified trace breakpoints.
-
- pbp Print the line numbers of all current breakpoints.
-
- nd Exit DEBUG immediately and (seemingly) do not
- return to DEBUG later unless __nodebug has been
- set to &null by the program. This essentially
- disables debug processing and allows the program
- to execute normally. Note that __debug_proc is
- still called prior to each line execution. It
- just exits immediately when called.
-
- ?, h, help Print a list of DEBUG interpreter commands.
-
- stop Immediately exit DEBUG and the program.
-
- blank or empty line Return to the program. If trace mode is on then
- DEBUG status information will print prior to the
- execution of each program line until a breakpoint
- is encountered. Otherwise the DEBUG interpreter
- will be invoked prior to the execution of each
- program line.
-
- A number of global variables are provided by __debug_proc which may be changed or
- inspected by the debugified program.
-
- __trace This variable reflects the trace state. It
- contains a non-null value when trace mode is
- active and &null when trace mode is off. The
- program may assign a value to __trace to change
- the trace state.
-
- __nodebug If the program sets __nodebug to a non-null value, then
- debug is disabled. This is the same as entering the
- "nd" command when in the debug interpreter.
-
- __debug_in This is the input file from which __debug_proc requests
- input. The program may change the debug input file via
- a statement like
- __debug_in := open(file_name, "r")
-
- See the discussion of the DEBUG_IN environment
- variable below.
-
- __debug_out This is the output file into which __debug_proc writes
- all its output. The program may change the debug output
- file via a statement like
- __debug_out:= open(file_name, "w")
-
- See the discussion of the DEBUG_OUT environment
- variable below.
-
- __trace_silent Setting this variable to a non-null value has the
- same effect as executing the "ts" command in the
- debug interpreter. Conversely assigning &null to
- it corresponds to "tv".
-
- The following environment variables are recognized by __debug_proc:
-
- TRACEINIT If this environment variable is set, then the program will
- start in trace mode. There will be no human interaction with
- the debug interpreter.
-
- DEBUG_IN This environment variable can be set to specify the name of
- the file from which the debug interpreter will get its input.
- If it is not set, then __debug_proc assumes a system-dependent
- default. For MS-DOS the default is "CON". For UNIX, it is
- "/dev/tty". For other systems, it defaults to the ICON &input
- value.
-
- DEBUG_OUT This environment variable can be set to specify the name of
- the file to which the debug interpreter writes its output. If
- it is not set, then __debug_proc assumes a system-dependent
- default. For MS-DOS the default is "CON". For UNIX, it is
- "/dev/tty". For other systems, it defauls to the ICON &output
- value.
-
-
- If your system does not support environment variables and &input and &output are
- not satisfactory I/O debug devices, it may be tempting to specifiy initial debug
- I/O devices by having your program open up __debug_in and __debug_out. Remember
- that if your main procedure is DEBUGIFYed, then __debug_proc will access its I/O
- devices before the first program statement is executed. You might consider not
- DEBUGIFYing your main procedure, but opening __debug_in and __debug_out prior to
- the first invocation of a DEBUGIFYed procedure.
-
- 6 VERSION HISTORY
-
- Version 1.01 9/6/92. Added DEBCFG.ICN and changed DEBUGIFY to allow
- it to be configured for particular Icon version. Thanks
- to David Kuhlman for uncovering problem.
-
- Version 1.00 11/29/91. Initial release.
-
- 7 ACKNOWLEDGMENT
-
- I wish to thank David Kuhlman for uncovering differences in keyword tokens
- between ucode files for different versions of Icon.
-
- 8 RIGHTS/DISTRIBUTION
-
- DEBUGIFY, DEBUG, and DEBCFG are public domain software with one restriction:
- Source code files and any accompanying documentation must indicate that I am the
- original author. Other than that, you can do whatever you wish with the source
- code. It may be freely distributed and/or modified.
-