home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1294 < prev    next >
Internet Message Format  |  1990-12-28  |  32KB

  1. From: new@udel.EDU (Darren New)
  2. Newsgroups: alt.sources
  3. Subject: #define DEBUG (Real source in this posting! oohhh!)
  4. Message-ID: <18965@estelle.udel.EDU>
  5. Date: 9 May 90 18:19:54 GMT
  6.  
  7. Since I don't have any way of making a shar file, I'm just going to
  8. put these all together.  Split apart at the lines containing
  9.  +=+=+=+=+ filename
  10.  
  11. Note that these sources are CBM-Amiga specific to the extent that
  12. they do I/O to a separate window. However, changing this is not much
  13. of a problem. They also include their own version of "printf" which may
  14. need to be hacked for your system.  I've found this to be incredibly
  15. useful but no substitute for a real symbolic debugger. Have fun. -- Darren
  16.  
  17. +=+=+=+=+ DBugLib.doc
  18.  
  19. These files Created 7/86 by Darren New.
  20. Released to the PUBLIC DOMAIN.    No rights reserved.
  21. Do anything you want with it.
  22.  
  23. Simple request: if you make a significant profit from this, or if you have
  24. improvements or suggestions, please contact me at
  25.  
  26.     new@udel.edu
  27.  
  28. (the request about profit just for my curiosity)
  29.  
  30. DISCLAIMER: As I am not making money from this, I am not going to be
  31. oblicated to support it, either.  Thus, THIS IS SUPPLIED "AS IS".  No
  32. warranty of any kind is made or implied.  Lattice is a registered trademark
  33. of Lattice, Inc.  Thus endeth the A__-covering.
  34.  
  35.  
  36. --------------------------------------------------------------------------
  37.  
  38.  
  39. This set of functions is for debugging programs.
  40. The function DEBUG_OPEN() opens a new console at the bottom of the screen.
  41. This console is read and written by DEBUGF().  DEBUG_CLOSE() will close
  42. this console, freeing it's memory.  Eventually, I hope to write these
  43. things as resources or devices, or something where everyone doing debug
  44. output will write to the same console so that multi-tasking functions
  45. can be debuged more easily.  (Probably shortly after I start coding
  46. multi-process programs myself...)
  47.  
  48. The main advantages of these functions over most of the debugging macros
  49. already out there are these:
  50. They write to a separate window, so even things with no windows or that do
  51. ANSI stuff and so on can be debugged.  Another advantage is that they are
  52. interactive -- pure macros must be recompiled and relinked to be disposed;
  53. these functions can be turned on and off at run time.  Of course, a simple
  54. compiler switch can remove all trace of these from the object files, just
  55. like most of the debugging packages.  The debugging info can be sent to a
  56. file or to the printer for really sticky problems.  Also, user's functions
  57. can be called from the keyboard from within the debug functions.  Although
  58. this does take a little setup, it can be worthwhile for stepping through a
  59. program until you start getting strange errors, and then popping back to
  60. your program someplace else in order to examine variables, dump files, or
  61. whatever; I imagine it could also be used to clean up and exit from the
  62. debugger.  Finally, it uses AmigaDOS calls only; no Lattice library calls or
  63. STDIO calls or anything like that.  If you have a "tiny" program, this may
  64. be helpful.
  65.  
  66. All traces of these function will be removed from the program if the
  67. preprocessor symbol USE_DBUGLIB is zero.  They will be compiled in if the
  68. preprocessor symbol USE_DBUGLIB is one.  Note that this takes effect only
  69. when the header <DBugLib.h> is included; i.e., you can't turn them on and
  70. off in the same file.  If USE_DBUGLIB is undefined when the header file is
  71. included, it's value will be one if DEBUG is defined, and zero if DEBUG
  72. is not defined.  Note also that under Lattice, the -d switch (pass 1) will
  73. #define DEBUG for you.
  74.  
  75. Note that in order for the macros to remove the function calls with variable
  76. arguments (under Lattice, at least), any arguments after the formatting
  77. string must be separated from the preceeding argument not by a comma, but by
  78. the pre-processor symbol "COMMA".  This turns all of the variable args into
  79. one argument if "COMMA" is not defined.  Credit for this technique is hereby
  80. given to "Dr. Bob", the author of "DEBUGC", found elsewhere.
  81.  
  82.  
  83. DEBUG_OPEN(S) ---> void
  84.     Opens the console.  All other debug functions will be ignored
  85. while the console is closed.  If S is NULL, the default console string
  86. is used as the file name for the Open call.  If S is not NULL, that string
  87. will be used as the filename.  If the console can not be opened,
  88. DisplayBeep() in a pattern indicative of the error.  Calling this is not an
  89. error the debugging console is already open.  This automatically gets
  90. called whenever DEBUG_ENTER() gets called and the nesting stack is empty;
  91. usually, this means main() is calling it for the first time.
  92.  
  93. DEBUG_CLOSE() ---> void
  94.     Closes the console.  It is not an error to call this when the console
  95. is already closed.  The console is automatically closed when DEBUG_RETURN is
  96. called from the (seemingly) outermost proceedure.
  97.  
  98. DEBUGF(I, SF COMMA A1 COMMA A2 COMMA ...) ---> char *
  99.     Other arguments just like PRINTF.  The output is formatted and sent
  100. to the debug console.  One key is accepted from the keyboard, and interpreted
  101. as follows:
  102. P    the debug line is sent to the PRT: device, which is opened until
  103.     the next DEBUG_CLOSE() if not already open.
  104. Q    DEBUG_CLOSE() will be called, causing deugging output to be disabled
  105.     until DEBUG_OPEN is called again.
  106. F    debugging output will be appended to :T/DEBUGOUT, which will be
  107.     opened if not already opened.  If 'f' is typed, the file will
  108.     remain open until DEBUG_CLOSE() is called.  If 'F' is typed, the
  109.     file will be closed immediately.
  110. B    the debugging window will be closed and reopened full size. (big)
  111.     If 'b' is entered, the window will be 200 scan lines high.
  112.     If 'B' is entered, the window will be 400 scan lines high.
  113. T    DEBUG_TRACEBACK() will be called.
  114. C    the previous action (other than T) will be repeated without pause
  115.     until DEBUG_OPEN or DEBUG_CLOSE is called again.  Good for
  116.     CONTINUOUS output to a file or printer.  Type a space to the debug
  117.     window to regain control.
  118. N    Nest: prompts for a digit 0 through 9.    Any DEBUG_ENTER
  119.     which causes the nesting level to exceed this will still be
  120.     remembered, but will not generate any output on the debug console.
  121.     Zero turns off all the reports except "main".  A space typed in
  122.     response to the prompt allows all nestings to display.
  123. D    Detail: prompts for a digit 0 through 9.  Any DEBUGF specifying an I
  124.     larger than this number will not generate any output.  A space typed
  125.     in response to the prompt allows all details to display.  Note that
  126.     detail level of zero will always display.
  127. S    Skip: debugging output will be discarded until a DEBUG_RETURN is
  128.     called which restores the nesting level to the current level or
  129.     lower.    Essentially, debugging is turned off until the current
  130.     function calls DEBUG_RETURN().
  131. 0 thru 9
  132.     DEBUG_FUNC[0] thru DEBUG_FUNC[9] will be called if not NULL.  Note
  133.     that this could be ugly if the user does not fill in this global
  134.     array with pointers to functions.
  135. RETURN    just return
  136. SPACE    Same as return
  137.  
  138. The routine will keep scanning the keyboard until a C or a newline (return)
  139. or S is detected, at which point it return.  Thus, several actions can be
  140. taken on a single debug statement.
  141.  
  142. DEBUG_CONSOLE() ---> long
  143.     Returns 0 if the debugging console is not open, otherwise returns
  144. a pointer to the open console, suitable for Read() and Write().  Don't
  145. Close() this yourself, or future calls to DEBUG may crash.
  146.  
  147. DEBUG_ENTER(S, SF COMMA A1 COMMA A2 COMMA ...) ---> void
  148.     Pass in the name of the function being entered.  This will be
  149. remembered, even if the console is closed.  If SF is not NULL, then the args
  150. after it (if any) are formatted as in PRINTF and displayed.  If this is
  151. first called when the console is closed, it is assumed to be being called
  152. from main(), and calls DEBUG_OPEN(NULL) for you.
  153.  
  154. DEBUG_RETURN(SF COMMA A1 COMMA A2 COMMA ...) ---> void
  155.     Indicates that the most recent function to call DEBUG_ENTER is
  156. now returning.    Automatically closes the colsole and otherwise makes sure
  157. that all resources have been freed if the nesting stack goes empty;
  158. it is assumed that you are about to exit from main().  This will
  159. eventually be implemented as a macro that actually returns the value of A1,
  160. if I can figure out how to cast the type properly; the problem is one of
  161. side-effects, mainly.
  162.  
  163. DEBUG_EXIT() ---> void
  164.     Frees all resources used by any of the DEBUG functions.  Must be
  165. called before a call to Exit(), exit(), _exit(), or whatever; otherwise, you
  166. will be left with a console sitting around that you can't close.
  167.  
  168. There will probably be much more over time, maybe including a program to
  169. automatically insert debugging calls into the program for you.
  170.  
  171. In the future, I plan to add floating point support.  If I hear requests, I
  172. may do it before I need it myself.  If anyone is interrested in adding it
  173. themselves, I have the fuctions to format the numbers; they just have not
  174. been incorporated into the DO_PRNT function.
  175.  
  176. +=+=+=+=+ DBugLib.h
  177. /*
  178.    This is the header file for the DBugLib package.
  179.    Include it while debugging.
  180. */
  181.  
  182. #ifndef USE_DBUGLIB
  183. #ifdef DEBUG
  184. #define USE_DBUGLIB 1
  185. #else
  186. #define USE_DBUGLIB 0
  187. #endif
  188. #endif
  189.  
  190. #if USE_DBUGLIB==1
  191. #define COMMA ,   /* thanks, Dr. Bob! */
  192. #define C ,
  193. extern void (*DEBUG_FUNC[10])();       /* List of debugging functions */
  194. extern void DEBUG_OPEN(char *);
  195. extern void DEBUG_CLOSE(void);
  196. extern void DEBUGF(int, char *, );
  197. extern void DEBUG_ENTER(char *, char *, );
  198. extern long DEBUG_CONSOLE(void);
  199. extern void DEBUG_RETURN(char *, );
  200. extern void DEBUG_EXIT(void);
  201. extern void DEBUG_TRACEBACK(void);
  202. extern void DEBUG_SETDEFS(char *, char *);
  203. #else
  204. #define DEBUG_OPEN(name) /* nothing */
  205. #define DEBUG_CLOSE() /* nothing */
  206. #define DEBUGF(lev, args) /* nothing */
  207. #define DEBUG_ENTER(name, args) /* nothing */
  208. #define DEBUG_CONSOLE() /* nothing -- shouldn't be referenced */
  209. #define DEBUG_RETURN(args) /* nothing */
  210. #define DEBUG_EXIT() /* nothing */
  211. #define DEBUG_TRACEBACK() /* nothing */
  212. #define DEBUG_SETDEFS(con, file) /* nothing */
  213. #endif
  214.  
  215. +=+=+=+=+ DBugLib.c
  216. /*
  217.  
  218. THIS IS "DBUGLIB.C"
  219.  
  220. Written 7/86 Darren New.
  221. PUBLIC DOMAIN -- May be freely distributed.
  222. See DBugLib.Doc for instructions and details.
  223. To avoid loading STDIO under lattice, compile with -v
  224.  
  225. */
  226.  
  227. #include    "exec/types.h"
  228. #include    "exec/memory.h"
  229. #include    "libraries/dos.h"
  230.  
  231. #include    "proto/exec.h"
  232. #include    "proto/dos.h"
  233.  
  234. #include    "string.h"
  235.  
  236. void (*DEBUG_FUNC[10])();       /* List of debugging functions */
  237.  
  238. /* default default console */
  239. char * def_deb_console = "RAW:0/130/640/70/Debug Console ";
  240.  
  241. /* default default debug output file */
  242. char * def_deb_file    = ":t/DebugOut";
  243.  
  244. static long console;   /* Actually, this should be a file handle */
  245. #define MUL 65000      /* Multiplyer for delays between flashes */
  246.  
  247. static char last_answer;       /* last char typed -- used by 'C' */
  248. static char last_was_c;        /* true if 'C'ing, false otherwise */
  249. static char last_was_skip;       /* true if 'S'kiping, false otherwise */
  250. static char * nest_list;       /* by TRACEBACK */
  251. static int  nest_level;        /* by TRACEBACK */
  252. static int  skip_level;        /* for SKIP */
  253. static long skip_con_hold;       /* for SKIP */
  254. static int  max_nest_level = 9999; /* by ENTER, RETURN */
  255. static int  max_detail = 9999;       /* by DEBUGF */
  256. static long db_file_handle;       /* handle to debug file */
  257. static long db_prt_handle;       /* handle to printer */
  258. static char * laststr;           /* pointer to last string typed */
  259. static long laststralloc;       /* space allocated for laststr */
  260. static char nosave;           /* CONWRITE will not append to laststr */
  261. static char cleol;           /* just to pass stuff around */
  262.  
  263. static void addon(s)
  264. register char * s;
  265. {
  266.    register char * newstr;
  267.    /* add S to the end of laststr */
  268.    if (nosave) return;
  269.   again:
  270.    if (strlen(laststr) + strlen(s) + 1 >= laststralloc) {
  271.       newstr = (char *) AllocMem(laststralloc + strlen(s) + 125,
  272.      MEMF_CLEAR);
  273.       if (newstr == 0) {
  274.      if (laststralloc == 0) {
  275.         /* out of memory */
  276.         return;
  277.         }
  278.      FreeMem(laststr, laststralloc);
  279.      laststralloc = 0; laststr = "";
  280.      goto again;
  281.      }
  282.       strcpy(newstr, laststr);
  283.       FreeMem(laststr, laststralloc);
  284.       laststralloc += strlen(s) + 125;
  285.       laststr = newstr;
  286.       }
  287.    strcat(laststr, s);
  288.    }
  289.  
  290.  
  291. static void conwrite(s)
  292. char * s;
  293. {
  294.    if (console != 0) {
  295.       Write(console, s, strlen(s));
  296.       addon(s);
  297.       }
  298.    }
  299.  
  300.  
  301. static void conwriteint(i)
  302. register int i;
  303. {
  304.    char s[10];
  305.    if (i > 32760) i = 32760;
  306.    s[0] = '0' + i / 10000     ;
  307.    s[1] = '0' + i /  1000 % 10;
  308.    s[2] = '0' + i /   100 % 10;
  309.    s[3] = '0' + i /    10 % 10;
  310.    s[4] = '0' + i         % 10;
  311.    s[5] = '\0';
  312.    conwrite(s);
  313.    }
  314.  
  315.  
  316. static void conwritechar(c)
  317. char c;
  318. {
  319.    char buf[2];
  320.    buf[0] = c; buf[1] = '\0';
  321.    conwrite(buf);
  322.    }
  323.  
  324.  
  325. static void sendto(a)
  326. long a;
  327. {
  328.    register int i;
  329.    if (console == 0) return;
  330.    if (strlen(laststr) != Write(a, laststr, strlen(laststr))) {
  331.       nosave = 1;
  332.       last_was_c = 0;
  333.       i = IoErr();
  334.       conwrite("\033[1mError during output: ");
  335.       conwriteint(i);
  336.       conwrite("\nTry again...\033[0m\n");
  337.       nosave = 0;
  338.       }
  339.    }
  340.  
  341.  
  342. static void isyt()
  343. {
  344.    if (!last_was_c) {
  345.       nosave = 1;
  346.       cleol = 1;
  347.       conwrite("\033[1m  It's still your turn...\033[0m\r");
  348.       nosave = 0;
  349.       }
  350.    }
  351.  
  352.  
  353.  
  354. static void getresp()
  355. {
  356.    char buf;
  357.    register int i;
  358.    register int oncet;
  359.    extern void DEBUG_TRACEBACK();
  360.    if (console == 0) return;
  361.    oncet = 0;
  362.   again:
  363.    /* This gives him 1/10 seconds for each debug in continuous mode */
  364.    if (! last_was_c || WaitForChar(console, 100000)) {
  365.       last_was_c = 0;
  366.       Read(console, &buf, 1);
  367.       }
  368.    else if (oncet) {
  369.       buf = ' ';
  370.       }
  371.    else {
  372.       oncet = 1;
  373.       buf = last_answer;
  374.       }
  375.    if (cleol) {
  376.       nosave = 1; conwrite("\033[0m\033[K"); nosave = 0;
  377.       cleol = 0;
  378.       }
  379.    /* Process buffer here */
  380.    switch (buf) {
  381.       case 'N':
  382.       case 'n':
  383.      nosave = 1;
  384.      conwrite("\033[1mEnter maximum nest level or ' ' for all:\033[0m ");
  385.      Read(console, &buf, 1);
  386.      if (buf <= '9' && buf >= '0') {
  387.         conwritechar(buf);
  388.         max_nest_level = buf - '0';
  389.         }
  390.      else if (buf == ' ')
  391.         max_nest_level = 99999;
  392.      else
  393.         conwritechar('\007', NULL);
  394.      isyt();
  395.      goto again;
  396.       case 'D':
  397.       case 'd':
  398.      nosave = 1;
  399.      conwrite("\033[1mEnter maximum detail level or ' ' for all:\033[0m ");
  400.      Read(console, &buf, 1);
  401.      if (buf <= '9' && buf >= '0') {
  402.         conwritechar(buf, NULL);
  403.         max_detail = buf - '0';
  404.         }
  405.      else if (buf == ' ')
  406.         max_detail = 9999;
  407.      else
  408.         conwritechar('\007', NULL);
  409.      isyt();
  410.      goto again;
  411.       case 'S':
  412.       case 's':
  413.      skip_con_hold = console;
  414.      last_was_skip = 1;
  415.      skip_level = nest_level;
  416.      console = 0; /* temp suspend debugging till return reached */
  417.      goto outness; /* Do NOT try to attempt any more output */
  418.       case 'P':
  419.       case 'p':
  420.      last_answer = buf;
  421.      if (db_prt_handle == 0)
  422.         db_prt_handle = Open("PRT:", MODE_OLDFILE);
  423.      if (db_prt_handle == 0) {
  424.         i = IoErr();
  425.         nosave = 1;
  426.         last_was_c = 0;
  427.         conwrite("\033[1mError opening printer: ");
  428.         conwriteint(i);
  429.         conwrite("\n\033[0m\007");
  430.         nosave = 0;
  431.         isyt();
  432.         goto again;
  433.         }
  434.      sendto(db_prt_handle);
  435.      isyt();
  436.      goto again;
  437.       case 'F':
  438.       case 'f':
  439.      last_answer = buf;
  440.      if (db_file_handle == 0)
  441.         db_file_handle = Open(def_deb_file, MODE_OLDFILE);
  442.      if (db_file_handle != 0)
  443.         Seek(db_file_handle, 0, OFFSET_END);
  444.      if (db_file_handle == 0) {
  445.         i = IoErr();
  446.         if (i == ERROR_OBJECT_NOT_FOUND)
  447.            db_file_handle = Open(def_deb_file, MODE_NEWFILE);
  448.         }
  449.      if (db_file_handle == 0) {
  450.         last_was_c = 0;
  451.         i = IoErr();
  452.         nosave = 1;
  453.         conwrite("\033[1mError opening file: ");
  454.         conwriteint(i);
  455.         conwrite("\n\033[0m\007");
  456.         nosave = 0;
  457.         isyt();
  458.         goto again;
  459.         }
  460.      sendto(db_file_handle);
  461.      if (buf == 'F') {
  462.         if (db_file_handle != 0)
  463.         Close(db_file_handle);
  464.         db_file_handle = 0;
  465.         }
  466.      isyt();
  467.      goto again;
  468.       case 'C':
  469.       case 'c':
  470.      last_was_c = 1;
  471.      break;
  472.       case 'Q':
  473.       case 'q':
  474.      Close(console);
  475.      console = 0; last_answer = 0; last_was_c = 0;
  476.      break;
  477.       case 'B':
  478.       case 'b':
  479.      Close(console);
  480.      if (buf == 'B')
  481.          console = Open("RAW:0/0/640/400/Debug Console ", MODE_NEWFILE);
  482.      else
  483.          console = Open("RAW:0/0/640/200/Debug Console ", MODE_NEWFILE);
  484.      if (console == 0) {     /* could not open */
  485.         long ioerr, tl1, tl2;
  486.         ioerr = IoErr();
  487.         /* Flash hundreds */
  488.         for (tl1 = 0; tl1 < ioerr / 100; tl1++) {
  489.         Write(Output(), "\007", 1);
  490.         for (tl2 = 0; tl2 < MUL; tl2++) ;
  491.         }
  492.         for (tl2 = 0; tl2 < 2 * MUL; tl2++) ;
  493.         /* Flash tens */
  494.         for (tl1 = 0; tl1 < ioerr / 10 % 10; tl1++) {
  495.         Write(Output(), "\007", 1);
  496.         for (tl2 = 0; tl2 < MUL; tl2++) ;
  497.         }
  498.         for (tl2 = 0; tl2 < 2 * MUL; tl2++) ;
  499.         /* Flash ones */
  500.         for (tl1 = 0; tl1 < ioerr % 10; tl1++) {
  501.         Write(Output(), "\007", 1);
  502.         for (tl2 = 0; tl2 < MUL; tl2++) ;
  503.         }
  504.         }
  505.      sendto(console);
  506.      isyt();
  507.      goto again;
  508.       case 'T':
  509.       case 't':
  510.      DEBUG_TRACEBACK((long) 0xBADD1E);
  511.      isyt();
  512.      goto again;
  513.       case '0':  case '5':
  514.       case '1':  case '6':
  515.       case '2':  case '7':
  516.       case '3':  case '8':
  517.       case '4':  case '9':
  518.      if (DEBUG_FUNC[(int) buf - '0'])
  519.          (*DEBUG_FUNC[(int) buf - '0'])();
  520.      isyt();
  521.      break;
  522.       case '\0':  /* continuous */
  523.       case '\r':
  524.       case '\n':
  525.       case ' ':
  526.      if (!last_was_c) last_answer = buf;
  527.      break;
  528.       default:
  529.      nosave = 1;
  530.      conwrite("\033[1mI don't understand ");
  531.      conwriteint(buf);
  532.      conwrite("\033[0m\n\007");
  533.      nosave = 0;
  534.      isyt();
  535.      goto again;
  536.       }
  537.   outness:
  538.    /* if (laststralloc > 0) {
  539.       FreeMem(laststr, laststralloc);
  540.       laststr = "";
  541.       laststralloc = 0;
  542.       } */
  543.    if (laststralloc > 0) {
  544.       laststr[0] = '\0';
  545.       }
  546.    }
  547.  
  548.  
  549. /******* CODE FROM AUSTIN CODE WORKS, MODIFIED BY DHN *******/
  550.  
  551. #define EOS        ('\0')
  552. #define BITS_PER_CHAR    8
  553.  
  554. /*
  555.  * WORKSIZE is the dimension of work[] which must hold enough characters
  556.  * to store a long integer (expanded using the %b format) + '-' and EOS
  557.  */
  558. #define WORKSIZE    (((sizeof (long)) * BITS_PER_CHAR) + 2)
  559.  
  560. struct    fmtbuf {
  561.     char    f_type;     /* Format type ('d', etc.)              */
  562.     char    f_width;    /* Argument width (INT or LONG)         */
  563.     char    f_radix;    /* Argument radix (8, 10, etc.)         */
  564.     };
  565.  
  566. #define INT    0
  567. #define LONG    1
  568. #define NEG    2        /* Signal for output of '-'             */
  569.  
  570. /*
  571.  * formatinfo[] stores information about the "value" formats
  572.  */
  573. static struct fmtbuf formatinfo[] = {
  574.     { 'b',  INT,     2 },
  575.     { 'd',  INT,    10 },
  576.     { 'o',  INT,     8 },
  577.     { 'u',  INT,    10 },
  578.     { 'x',  INT,    16 },
  579.     { 'p',  LONG,   16 },
  580.     { 'B',  LONG,    2 },
  581.     { 'D',  LONG,   10 },
  582.     { 'O',  LONG,    8 },
  583.     { 'U',  LONG,   10 },
  584.     { 'X',  LONG,   16 },
  585.     { 'P',  LONG,   16 },
  586.     { EOS,    0,     0 },
  587.     };
  588.  
  589.  
  590. void c_doprnt(format, argp, func)
  591. char        *format;        /* Format string        */
  592. register int    *argp;            /* Argument vector pointer    */
  593. int        (*func)();              /* Output Function              */
  594. {
  595.     register int         c;
  596.     register struct fmtbuf * pfmt;
  597.     register char *      presult;
  598.     char        ljust;        /* TRUE for left-justification    */
  599.     char        work[WORKSIZE]; /* Number buffer        */
  600.     char        fill;        /* '0' or ' ' for fill          */
  601.     int        prec;        /* Precision            */
  602.     int        slen;        /* Field length         */
  603.     int        width;        /* Argument width        */
  604.     unsigned long    value;
  605.     int        temp;        /* Set if '-' needed.           */
  606.     short        radix;        /* Conversion radix        */
  607.  
  608.     while ((c = *format++) != EOS) {
  609.         /*
  610.          * Check for conversion specifications.
  611.          */
  612.         if (c == '%') {
  613.         /*
  614.          * Check for various options.
  615.          */
  616.         c = *format++;
  617.         ljust = 0;            /* No left adjustment    */
  618.         fill = ' ';                     /* Fill with spaces     */
  619.         if (c == '-') {                 /* %-   left justify    */
  620.             ljust++;
  621.             c = *format++;
  622.             }
  623.         if (c == '0') {                 /* %0d  zero fill arg.  */
  624.             fill = c;
  625.             c = *format++;
  626.             }
  627.         if (c == '?' || c == '*') {     /* %*   width from arg  */
  628.             width = *argp++;
  629.             c = *format++;
  630.             }
  631.         else {                /* %n    field width    */
  632.             width = 0;
  633.             while (isdigit(c)) {
  634.             width *= 10;
  635.             width += (c - '0');
  636.             c = *format++;
  637.             }
  638.             }
  639.         if (c == '.') {                 /* %n.n precision       */
  640.             c = *format++;        /* %n.* (from arg)      */
  641.             if (c == '?' || c == '*') {
  642.             prec = *argp++;
  643.             c = *format++;
  644.             }
  645.             else {
  646.             prec = 0;
  647.             while (isdigit(c)) {
  648.                 prec *= 10;
  649.                 prec += (c - '0');
  650.                 c = *format++;
  651.                 }
  652.             }
  653.             }
  654.         else {
  655.             prec = 32767;        /* No prec. specified    */
  656.             }
  657.         /*
  658.          * Magic code for pointer -- dhn
  659.          */
  660.         if (c == 'p' || c == 'P') {
  661.             fill = '0'; width = 6 + 2 * isupper(c);
  662.             }
  663.         /*
  664.          * Process conversion chars, understanding longs.
  665.          */
  666.         if (c == 'l' || c == 'L') {
  667.             switch (c = *format++) {
  668.             case 'b':
  669.             case 'd':
  670.             case 'o':
  671.             case 'u':
  672.             case 'x':
  673.                 c = toupper(c); /* Make %lb %B          */
  674.             case 'B':
  675.             case 'D':
  676.             case 'O':
  677.             case 'U':
  678.             case 'X':
  679.                 break;
  680.             default:        /* Here on %Lfoo ==> %Ufoo        */
  681.                 c = 'U';
  682.                 format--;
  683.                 break;
  684.             }
  685.             }
  686.         /*
  687.          * Search the numeric format structure for this conversion.
  688.          */
  689.         for (pfmt = formatinfo;
  690.             (pfmt->f_type != c && pfmt->f_type != EOS);
  691.             pfmt++)
  692.             ;
  693.         if (pfmt->f_type != EOS) {
  694.             /*
  695.              * A numeric conversion was found.
  696.              * Get the value and expand it into the work area.
  697.              */
  698.             radix = pfmt->f_radix;
  699.             temp = pfmt->f_width;
  700.             presult = &work[WORKSIZE];
  701.             *--presult = EOS;           /* Terminate result     */
  702.             if (temp == INT) {
  703.             if (c == 'd' && *argp < 0) {
  704.                 value = -*argp++;
  705.                 temp = NEG;     /* Remember signal    */
  706.                 }
  707.             else
  708.                 value = (unsigned) *argp++;
  709.             }
  710.             else {
  711.             value = * (long *) argp;
  712.             argp += (sizeof(long) / sizeof(*argp));
  713.             }
  714.             if (value == 0)
  715.             *--presult = '0';
  716.             else {
  717.             /*
  718.              * Convert an unsigned non-zero number.
  719.              */
  720.             do {
  721.                 c = value % radix;
  722.                 *--presult = c + ((c < 10) ? '0' : ('A' - 10));
  723.                 } while ((value /= radix) != 0);
  724.             if (temp == NEG)
  725.                 *--presult = '-';
  726.             }
  727.             }
  728.         else {
  729.             /*
  730.              * String or something
  731.              */
  732.             switch (c) {
  733.             case 'q':                   /* Funny int value      */
  734.                 /*
  735.                  * Convert a word as a pair of octal bytes.
  736.                  */
  737.                 c = 16384;
  738.                 presult = work;
  739.                 temp = *argp++;
  740.                 while (c > 0) {
  741.                 *presult++ = (temp / c) + '0';
  742.                 temp %= c;
  743.                 if (c == 256) {
  744.                     c = 64;
  745.                     *presult++ = '.';
  746.                     }
  747.                 else
  748.                     c >>= 3;
  749.                 }
  750.                 *presult = EOS;
  751.                 presult = work;
  752.                 break;
  753.  
  754.             case 'r':                   /* Remote format        */
  755.                 argp = (int *) *argp;
  756.                 format = (char *) *argp++;
  757.                 continue;            /* No print here        */
  758.  
  759.             case 's':                   /* String               */
  760.                 if ((presult = (char *) *argp++) == NULL)
  761.                 presult = "{NULL}";        /* Bug hack     */
  762.                 break;
  763.  
  764.             case 'c':                   /* Character            */
  765.                 c = *argp++;
  766.                 /*
  767.                  * Fall through
  768.                  */
  769.             default:            /* %% or whatever        */
  770.                 presult = work;
  771.                 *presult = c;
  772.                 work[1] = EOS;
  773.                 break;
  774.             }
  775.             }
  776.         /*
  777.          * presult -> first byte of string to output.
  778.          * Reuse c as a register temp.
  779.          */
  780.         c = strlen(presult);           /* True result length   */
  781.         slen = (c > prec) ? prec : c;   /* Field length         */
  782.         if (!ljust) {                   /* Right justify?       */
  783.             while (--width >= slen) {
  784.             (*func)(fill);
  785.             }
  786.             }
  787.         /*
  788.          * Output the string (up to "prec" bytes)
  789.          */
  790.         for (c = prec; *presult != EOS && --c >= 0;) {
  791.             (*func)(*presult++);
  792.             }
  793.         if (ljust) {                    /* Left justify?        */
  794.             while (--width >= slen) {
  795.             (*func)(' ');
  796.             }
  797.             }
  798.         }
  799.         else {
  800.         /*
  801.          * Not in a % thing, just output the byte.
  802.          */
  803.         (*func)(c);
  804.         }
  805.         }
  806.     return;
  807.     }
  808.  
  809. /******** END CODE FROM AUSTIN CODE WORKS *********/
  810.  
  811.  
  812. void DEBUG_OPEN(s)
  813. register char * s;
  814. {
  815.    register long tl1;        /* temp loop var 1 */
  816.    register long tl2;        /* temp loop var 2 */
  817.    register int ioerr;
  818.  
  819.    /* Open debugging console, if not already open.  Init stuff */
  820.    if (skip_con_hold) {
  821.       /* open stops skipping */
  822.       console = skip_con_hold;
  823.       skip_con_hold = 0; last_was_skip = 0;
  824.       skip_level = 0;
  825.       }
  826.    if (s == NULL) {
  827.       s = def_deb_console;
  828.       }
  829.    last_answer = '\0'; last_was_c = 0;
  830.    if (laststralloc > 0) {
  831.       FreeMem(laststr, laststralloc);
  832.       laststr = "";
  833.       laststralloc = 0;
  834.       }
  835.    laststr = "";
  836.    nosave = 0;
  837.    if (console != 0) return;
  838.  
  839.    console = Open(s, MODE_NEWFILE);
  840.    if (console == 0) {     /* could not open */
  841.       ioerr = IoErr();
  842.       /* Flash hundreds */
  843.       for (tl1 = 0; tl1 < ioerr / 100; tl1++) {
  844.      Write(Output(), "\007", 1);
  845.      for (tl2 = 0; tl2 < MUL; tl2++) ;
  846.      }
  847.       for (tl2 = 0; tl2 < 2 * MUL; tl2++) ;
  848.       /* Flash tens */
  849.       for (tl1 = 0; tl1 < ioerr / 10 % 10; tl1++) {
  850.      Write(Output(), "\007", 1);
  851.      for (tl2 = 0; tl2 < MUL; tl2++) ;
  852.      }
  853.       for (tl2 = 0; tl2 < 2 * MUL; tl2++) ;
  854.       /* Flash ones */
  855.       for (tl1 = 0; tl1 < ioerr % 10; tl1++) {
  856.      Write(Output(), "\007", 1);
  857.      for (tl2 = 0; tl2 < MUL; tl2++) ;
  858.      }
  859.       }
  860.    else {
  861.       conwrite("\033[1mConsole is open.\033[0m\n");
  862.       }
  863.    }
  864.  
  865.  
  866. void DEBUG_TRACEBACK(i)
  867. long i;
  868. {
  869.    char * holdit;
  870.    if (nest_level < 1) {
  871.       conwrite("DEBUG_TRACEBACK(): Too many returns!\n");
  872.       if (i != 0xBADD1E) getresp();
  873.       return;
  874.       }
  875.    if (nest_level <= max_nest_level || i == 0xBADD1E) {
  876.       /* Display nesting only if enters and returns showing, or if
  877.      called directly from keyboard */
  878.       conwrite("Stack traceback: current nest level is ");
  879.       conwriteint(nest_level);
  880.       holdit = nest_list;
  881.       while(holdit != NULL) {
  882.      conwrite("\n    ");
  883.      conwrite(holdit + sizeof(char *));
  884.      holdit = * (char * *) holdit;
  885.      }
  886.       conwrite("\nEnd of stack traceback.\n");
  887.       if (i != 0xBADD1E) getresp();
  888.       }
  889.    }
  890.  
  891.  
  892. void DEBUGF(sevlev, fmtstr, args)
  893. int sevlev;
  894. char * fmtstr;
  895. int args;
  896. {
  897.    if (console == 0 || sevlev > max_detail) return;
  898.    if (fmtstr == NULL) return;
  899.    nosave = 1; conwrite("\033[0 p"); nosave = 0; /* turn off cursor */
  900.    c_doprnt(fmtstr, &args, conwritechar);
  901.    if (fmtstr[strlen(fmtstr)-1] != '\n')
  902.       conwrite("\n");
  903.    nosave = 1; conwrite("\033[ p"); nosave = 0; /* turn on cursor */
  904.    getresp();
  905.    }
  906.  
  907.  
  908.  
  909. void DEBUG_ENTER(s, sf, args)
  910. register char * s;
  911. char * sf;
  912. int args;
  913. {
  914.    register char * newmem;
  915.    register int i;
  916.    if (s == NULL) return;
  917.    if (nest_level == 0) DEBUG_OPEN(NULL);
  918.    if (nest_level <= max_nest_level) {
  919.       conwriteint(nest_level);
  920.       for (i = 0; i < nest_level; i++)
  921.      conwrite("=");
  922.       conwrite(">");
  923.       conwrite(s);
  924.       conwrite("\n");
  925.       if (sf != NULL) {
  926.      conwrite("     |--> ");
  927.      c_doprnt(sf, &args, conwritechar);
  928.      conwrite("\n");
  929.      }
  930.       }
  931.    newmem = (char *) AllocMem(sizeof(char *) + strlen(s) + 2, 0);
  932.    if (newmem == NULL) return;
  933.    (* (char * *) newmem) = nest_list;
  934.    strcpy(newmem + sizeof(char *), s);
  935.    nest_list = newmem;
  936.    nest_level += 1;
  937.    if (nest_level - 1 <= max_nest_level) getresp();
  938.    }
  939.  
  940.  
  941. void DEBUG_CLOSE()
  942. {
  943.    last_answer = '\0'; last_was_c = 0;
  944.    if (db_file_handle != 0) {
  945.       Close(db_file_handle);
  946.       conwrite("DB File is closed.\n");
  947.       db_file_handle = 0;
  948.       }
  949.    if (db_prt_handle != 0) {
  950.       Close(db_prt_handle);
  951.       conwrite("Printer is closed.\n");
  952.       db_prt_handle = 0;
  953.       }
  954.    if (skip_con_hold) {
  955.       console = skip_con_hold;
  956.       skip_con_hold = last_was_skip = skip_level = 0;
  957.       }
  958.    if (console != 0) {
  959.       conwrite("Console is closed.\n");
  960.       Close(console);
  961.       console = 0;
  962.       }
  963.    if (laststralloc > 0) {
  964.       FreeMem(laststr, laststralloc);
  965.       laststr = "";
  966.       laststralloc = 0;
  967.       }
  968.    }
  969.  
  970.  
  971. void DEBUG_RETURN(sf, args)
  972. char * sf;
  973. int args;
  974. {
  975.    int i;
  976.    char * holdit;
  977.    if (nest_level < 1) {
  978.       conwrite("DEBUG_RETURN(): Too many returns!\n");
  979.       getresp();
  980.       return;
  981.       }
  982.    nest_level -= 1;
  983.    if (last_was_skip && nest_level < skip_level) {
  984.       console = skip_con_hold;
  985.       skip_con_hold = 0; last_was_skip = 0; skip_level = 0;
  986.       }
  987.    if (nest_level <= max_nest_level) {
  988.       conwriteint(nest_level);
  989.       for (i = 0; i < nest_level; i++)
  990.      conwrite("=");
  991.       conwrite("<");
  992.       conwrite(nest_list + sizeof(char *));
  993.       conwrite("\n");
  994.       }
  995.    if (sf != NULL && nest_level <= max_nest_level) {
  996.       conwrite("     <---| ");
  997.       c_doprnt(sf, &args, conwritechar);
  998.       conwrite("\n");
  999.       }
  1000.    if (nest_list != NULL) {
  1001.       holdit = nest_list;
  1002.       nest_list = * (char * *) nest_list;
  1003.       FreeMem(holdit, sizeof(char *) + strlen(holdit +
  1004.      sizeof(char *)) + 2);
  1005.       }
  1006.    if (nest_level <= max_nest_level) getresp();
  1007.    if (nest_level == 0) DEBUG_CLOSE();
  1008.    }
  1009.  
  1010.  
  1011. void DEBUG_EXIT()
  1012. {
  1013.    if (skip_con_hold) console = skip_con_hold;
  1014.    conwrite("About to DEBUG_EXIT()\n");
  1015.    getresp();
  1016.    while (nest_list != NULL) {
  1017.       char * holdit;
  1018.       holdit = nest_list;
  1019.       nest_list = * (char * *) nest_list;
  1020.       FreeMem(holdit, sizeof(char *) + strlen(holdit + sizeof(char *)) + 2);
  1021.       }
  1022.    DEBUG_CLOSE();
  1023.    }
  1024.  
  1025. long DEBUG_CONSOLE()
  1026. {
  1027.     return console;
  1028.     }
  1029.  
  1030. void DEBUG_SETDEFS(con, file)
  1031.     char * con;
  1032.     char * file;
  1033. {
  1034.     if (con != NULL)
  1035.     def_deb_console = con;
  1036.     if (file != NULL)
  1037.     def_deb_file = file;
  1038.     }
  1039.  
  1040. +=+=+=+=+ DBTest.c
  1041. /* This is the test program for the DBugLib package.
  1042.    It exercises all features, assuming you actually attempt to
  1043.    print, file, and so on. (put the include files where you want them)
  1044.  
  1045.    Note that for ANYTHING to happen, #define DEBUG.  This can be done in
  1046.    Lattice by giving "-d" (alone) on the first pass.  This also generates
  1047.    line numbers in the quad file.
  1048.  
  1049.    */
  1050.  
  1051. #include <stdio.h>
  1052. #include "DBugLib.h"
  1053.  
  1054. void main(argc, argv)
  1055. int argc; char * argv[];
  1056. {
  1057.    extern void exit(int);
  1058.    DEBUG_ENTER("Alpha", "Decimal, then Hex: %d, %x" COMMA 123 COMMA 0x456);
  1059.    DEBUG_ENTER("Beta", NULL);
  1060.    DEBUGF(2, "If you type an 'F', this will go to a file");
  1061.    DEBUGF(4, "Making sure long negatives work: %d %X" C -1L C -1L);
  1062.    DEBUG_TRACEBACK();
  1063.    DEBUG_RETURN(NULL);
  1064.    DEBUGF(5, "Here, close the console. then, wait a while...");
  1065.    DEBUGF(5, "This should not display on a closed console");
  1066.    DEBUGF(5, "Neither should this");
  1067.    DEBUG_OPEN(NULL);
  1068.    DEBUGF(0, "This should always display");
  1069.    DEBUGF(0, "About to play with Detail levels:");
  1070.    DEBUGF(1, "ONE");
  1071.    DEBUGF(2, "TWO");
  1072.    DEBUGF(3, "THREE");
  1073.    DEBUGF(4, "FOUR");
  1074.    DEBUGF(5, "FIVE");
  1075.    DEBUGF(6, "SIX");
  1076.    DEBUGF(7, "SEVEN");
  1077.    DEBUGF(8, "EIGHT");
  1078.    DEBUGF(9, "NINE");
  1079.    DEBUGF(10, "TEN");
  1080.    DEBUGF(11, "ELEVEN");
  1081.    DEBUGF(10, "Ten");
  1082.    DEBUGF(9, "Nine");
  1083.    DEBUGF(8, "Eight");
  1084.    DEBUGF(7, "Seven");
  1085.    DEBUGF(6, "Six");
  1086.    DEBUGF(5, "Five");
  1087.    DEBUGF(4, "Four");
  1088.    DEBUGF(3, "Three");
  1089.    DEBUGF(2, "Two");
  1090.    DEBUGF(1, "One");
  1091.    DEBUGF(0, "Zero");
  1092.    DEBUG_TRACEBACK();
  1093.    DEBUGF(0, "About to play with function calls:");
  1094.       /* Level zero is Alpha */
  1095.    DEBUG_ENTER("One", NULL);
  1096.    DEBUG_ENTER("Two", NULL);
  1097.    DEBUG_ENTER("Three", NULL);
  1098.    DEBUG_ENTER("Four", NULL);
  1099.    DEBUG_ENTER("Five", NULL);
  1100.    DEBUG_ENTER("Six", NULL);
  1101.    DEBUG_ENTER("Seven", NULL);
  1102.    DEBUG_ENTER("Eight", NULL);
  1103.    DEBUG_ENTER("Nine", NULL);
  1104.    DEBUG_ENTER("Ten", NULL);
  1105.    DEBUG_ENTER("Eleven", NULL);
  1106.    DEBUGF(0, "This is a debug statement inside %d" COMMA 11);
  1107.    DEBUG_TRACEBACK();
  1108.    DEBUG_RETURN("Eleven");
  1109.    DEBUG_RETURN("Ten");
  1110.    DEBUG_RETURN("Nine");
  1111.    DEBUG_RETURN("Eight");
  1112.    DEBUG_TRACEBACK();
  1113.    DEBUG_ENTER("Eight", NULL);
  1114.    DEBUG_ENTER("Nine", NULL);
  1115.    DEBUG_ENTER("Ten", NULL);
  1116.    DEBUG_ENTER("Eleven", NULL);
  1117.    DEBUG_TRACEBACK();
  1118.    DEBUG_RETURN("Eleven");
  1119.    DEBUG_RETURN("Ten");
  1120.    DEBUG_RETURN("Nine");
  1121.    DEBUG_RETURN("Eight");
  1122.    DEBUG_TRACEBACK();
  1123.    DEBUG_RETURN("Seven");
  1124.    DEBUG_RETURN("Six");
  1125.    DEBUG_RETURN("Five");
  1126.    DEBUG_RETURN("Four");
  1127.    DEBUG_TRACEBACK();
  1128.    DEBUG_RETURN(NULL);
  1129.    DEBUG_RETURN(NULL);
  1130.    DEBUG_RETURN(NULL);
  1131.    DEBUG_RETURN("Returning a string from alpha: |%s|" COMMA "A string!");
  1132.    exit(0);
  1133.    }
  1134.  
  1135.  
  1136. +=+=+=+=+ End of file
  1137.