G:/ScriptBasic/source/extensions/dbg/interface.c

Go to the documentation of this file.
00001 /*
00002 FILE:   interface.c
00003 HEADER: dbg.h
00004 
00005 --GNU LGPL
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010 
00011 This library is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public
00017 License along with this library; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 This program implements a simple debugger "preprocessor" for ScriptBasic.
00021 
00022 NTLIBS: user32.lib
00023 UXLIBS:
00024 DWLIBS:
00025 MCLIBS:
00026 
00027 */
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <ctype.h>
00032 
00033 #include "../../conftree.h"
00034 #include "../../report.h"
00035 #include "../../reader.h"
00036 #include "../../basext.h"
00037 #include "../../prepext.h"
00038 
00039 #include "dbg.h"
00040 #include "dbg_comm.h"
00041 
00042 /*
00043 TO_HEADER:
00044 // Debug information on user defined functions.
00045 typedef struct _UserFunction_t {
00046   long cLocalVariables;
00047   char *pszFunctionName;
00048   char **ppszLocalVariables;
00049   long NodeId; // node id where the function starts
00050   } UserFunction_t, *pUserFunction_t;
00051 
00052 // Debug information for each byte-code node.
00053 typedef struct _DebugNode_t {
00054   char *pszFileName; // the file name where the source for the node is
00055   long lLineNumber;  // the line number in the file where the node is 
00056   long lNodeId;      // the id of the node 
00057   long lSourceLine;  // the source line number as it is in the memory with included lines counted from 1 
00058                      // this field is zero and is set when the line is first searched to avoid further searches 
00059   } DebugNode_t, *pDebugNode_t;
00060 
00061 // struct for a source line to hold in memory while debugging 
00062 typedef struct _SourceLine_t {
00063   char *line;
00064   long lLineNumber;
00065   char *szFileName;
00066   int BreakPoint;
00067   } SourceLine_t, *pSourceLine_t;
00068 
00069 // to maintain a call stack to make it available for the user to see local variables and PC and so on
00070 typedef struct _DebugCallStack_t {
00071   long Node;//where the execution came here to the function (where the function call is)
00072   pUserFunction_t pUF;
00073   pFixSizeMemoryObject LocalVariables;
00074   struct _DebugCallStack_t *up,*down;
00075   } DebugCallStack_t, *pDebugCallStack_t;
00076 
00077 // this is the thread local variable struct.
00078 
00079 //Note that altough this is a debugger it is possible to have multiple threads to be debugged
00080 //using several debug "windows".
00081 
00082 typedef struct _DebuggerObject {
00083   pPrepext pEXT;
00084   pExecuteObject pEo;
00085   long cGlobalVariables;
00086   char **ppszGlobalVariables;
00087   long cUserFunctions;
00088   pUserFunction_t pUserFunctions;
00089   long cFileNames;
00090   char **ppszFileNames;
00091   long cNodes;
00092   pDebugNode_t Nodes;
00093   long cSourceLines;
00094   pSourceLine_t SourceLines;
00095   pDebugCallStack_t DbgStack;
00096   pDebugCallStack_t StackTop;
00097   pDebugCallStack_t StackListPointer;
00098   long CallStackDepth;
00099   long Run2CallStack;
00100   long Run2Line;
00101   int bLocalStart;
00102   long FunctionNode;
00103   long lPrevPC,lPC;
00104   } DebuggerObject, *pDebuggerObject;
00105 */
00106 
00107 /* Push the item on the debugger stack when entering the function
00108    starting at the node Node
00109 */
00110 static void PushStackItem(pDebuggerObject pDO,
00111                           long Node
00112   ){
00113   pDebugCallStack_t p;
00114   long i;
00115 
00116   p = pDO->pEXT->pST->Alloc(sizeof(DebugCallStack_t),pDO->pEXT->pMemorySegment);
00117   if( p == NULL )return;
00118   if( pDO->StackTop == NULL )pDO->StackTop = p;
00119   p->up = pDO->DbgStack;
00120   p->down = NULL;
00121   p->Node = pDO->lPC;
00122   if( pDO->DbgStack )pDO->DbgStack->down = p;
00123   pDO->DbgStack = p;
00124   p->pUF = NULL;
00125   for( i = 0 ; i < pDO->cUserFunctions ; i++ )
00126     if( pDO->pUserFunctions[i].NodeId == Node ){
00127       p->pUF = pDO->pUserFunctions+i;
00128       break;
00129       }
00130   p->LocalVariables = NULL;
00131   pDO->CallStackDepth++;
00132   return;
00133   }
00134 
00135 /* return from a function and pop off the item from the stack */
00136 static void PopStackItem(pDebuggerObject pDO
00137   ){
00138   pDebugCallStack_t p;
00139 
00140   if( pDO->DbgStack == NULL || pDO->CallStackDepth == 0 )return;
00141   p = pDO->DbgStack;
00142   pDO->DbgStack = pDO->DbgStack->up;
00143   if( pDO->DbgStack )pDO->DbgStack->down = NULL;
00144   pDO->pEXT->pST->Free(p,pDO->pEXT->pMemorySegment);
00145   pDO->CallStackDepth--;
00146   if( pDO->CallStackDepth == 0 )pDO->StackTop = NULL;
00147   return;
00148   }
00149 
00150 static char hexi(unsigned int x ){
00151   if( x < 10 )return x+'0';
00152   return x+'A'-10;
00153   }
00154 
00155 /*POD
00156 =section SPrintVariable
00157 =H Print the value of a variable into a string
00158 
00159 This function should be used to get the textual representation of a
00160 ScriptBasic T<VARIABLE>.
00161 
00162 /*FUNCTION*/
00163 int SPrintVariable(pDebuggerObject pDO,
00164                    VARIABLE v,
00165                    char *pszBuffer,
00166                    unsigned long *cbBuffer
00167   ){
00168 /*noverbatim
00169 
00170 =itemize
00171 =item T<pDO> is the debugger object
00172 =item T<v> is the variable to print
00173 =item T<pszBuffer> is pointer to the buffer that has to have at least
00174 =item T<cbBuffer> number of bytes available
00175 =noitemize
00176 
00177 The function returns zero on success. 
00178 
00179 The function returns 1 if the buffer is not large enough. In this case the
00180 number returned in T<*cbBuffer> will be the size of the buffer needed. It may
00181 happen in case the buffer is extremely short that even the returned size is not
00182 enough. Choosing a buffer length of 80 bytes or so ensures that either the
00183 result fits into the buffer or the returned number is large enough to hold
00184 the result.
00185 
00186 Note that the number can be extremely large in case the variable is a string. In
00187 this case all the characters are copied into the result and non-printable characters
00188 are converted to hex.
00189 
00190 The buffer should be large enough to hold the "->->->->->...->" string representing the
00191 references and the number or string.
00192 CUT*/
00193   long refcount;
00194   unsigned char *s,*r;
00195   char buf[80];
00196   unsigned long slen,i;
00197   unsigned long _cbBuffer = *cbBuffer;
00198 
00199   if( v == NULL || TYPE(v) == VTYPE_UNDEF ){
00200     if( _cbBuffer < 6 )return 1;
00201     strcpy(pszBuffer,"undef");
00202     return 0;
00203     }
00204 
00205 #define APPEND(X) slen = strlen(X);\
00206                   if( _cbBuffer < slen+1 ){\
00207                     *cbBuffer += 40;\
00208                     return 1;\
00209                     }\
00210                   strcpy(s,X);\
00211                   s += slen;\
00212                   _cbBuffer -= slen;
00213 
00214   *pszBuffer = (char)0;
00215   s = pszBuffer;
00216   if( TYPE(v) == VTYPE_REF ){
00217     refcount = 0;
00218     while( TYPE(v) == VTYPE_REF ){
00219       v = *(v->Value.aValue);
00220       if( refcount < 5 ){
00221         APPEND("->")
00222         }
00223       refcount++;
00224       if( refcount == 1000 ){
00225         APPEND("... infinit")
00226         return 0;
00227         }
00228       }
00229     if( refcount > 5 ){
00230       APPEND(" ... ->")
00231       }
00232     }
00233 
00234   if( TYPE(v) == VTYPE_UNDEF ){
00235     APPEND("undef")
00236     return 0;
00237     }
00238 
00239   if( TYPE(v) == VTYPE_LONG ){
00240     sprintf(buf,"%d",v->Value.lValue);
00241     slen = strlen(buf);
00242     if( _cbBuffer < slen+1 ){
00243       *cbBuffer += slen - _cbBuffer;
00244       return 1;
00245       }
00246     strcpy(s,buf);
00247     return 0;
00248     }
00249 
00250   if( TYPE(v) == VTYPE_DOUBLE ){
00251     sprintf(buf,"%lf",v->Value.dValue);
00252     slen = strlen(buf);
00253     if( _cbBuffer < slen+1 ){
00254       *cbBuffer += slen - _cbBuffer;
00255       return 1;
00256       }
00257     strcpy(s,buf);
00258     return 0;
00259     }
00260 
00261   if( TYPE(v) == VTYPE_ARRAY ){
00262     sprintf(buf,"ARRAY@#%08X",LONGVALUE(v));
00263     slen = strlen(buf);
00264     if( _cbBuffer < slen+1 ){
00265       *cbBuffer += slen - _cbBuffer;
00266       return 1;
00267       }
00268     strcpy(s,buf);
00269     return 0;
00270     }
00271 
00272   if( TYPE(v) == VTYPE_STRING ){
00273     /* calculate the printed size */
00274     r = v->Value.pValue;
00275     slen = 2; /* starting and ending " */
00276     i = 0;
00277     while( i < STRLEN(v) ){
00278       if( *r < 0x20 || *r > 0x7F ){
00279         slen += 4 ; /* \xXX */
00280         i++;
00281         r++;
00282         continue;
00283         }
00284       if( *r == '"' ){
00285         slen += 2 ; /* \" */
00286         i++;
00287         r++;
00288         continue;
00289         }
00290       slen ++;
00291       i++;
00292       r++;
00293       continue;
00294       }
00295 
00296     if( _cbBuffer < slen+1 ){
00297       *cbBuffer += slen - _cbBuffer;
00298       return 1;
00299       }
00300 
00301     r = v->Value.pValue;
00302     *s ++ = '"';
00303     i = 0;
00304     while( i < STRLEN(v) ){
00305       if( *r < 0x20 || *r > 0x7F ){
00306         *s ++ = '\\';
00307         *s ++ = 'x';
00308         *s ++ = hexi( (*r) / 16 );
00309         *s ++ = hexi( (*r) & 0xF);
00310         i++;
00311         r++;
00312         continue;
00313         }
00314       if( *r == '"' ){
00315         *s ++ = '\\';
00316         *s ++ = '"';
00317         i++;
00318         r++;
00319         continue;
00320         }
00321       *s ++ = *r;
00322       i++;
00323       r++;
00324       continue;
00325       }
00326     *s ++ = '"';
00327     *s = (char)0;
00328     return 0;
00329     }
00330   return 1;
00331   }
00332 
00333 /*POD
00334 =section SPrintVarByName
00335 =H Print the value of a variable into a string
00336 
00337 This fucntion prints a variable string representation into a buffer.
00338 The name of the variable is given in the variable T<pszName>.
00339 
00340 The fucntion first searches the variable and then calls the function
00341 R<SPrintVariable> to print the value.
00342 
00343 The fucntion first tries to locate the variable as local variable.
00344 For this not the normal debug stack pointer is used, but rather the
00345 T<StackListPointer>. This allows the client to print local
00346 variables levels higher than the bottom of the stack.
00347 
00348 If the function succeeds finding the variable it returns the return value of the
00349 function R<SPrintVariable>. If the variable is not found it returns 2.
00350 
00351 /*FUNCTION*/
00352 int SPrintVarByName(pDebuggerObject pDO,
00353                     pExecuteObject pEo,
00354                     char *pszName,
00355                     char *pszBuffer,
00356                     unsigned long *cbBuffer
00357   ){
00358 /*noverbatim
00359 CUT*/
00360   pUserFunction_t pUF;
00361   long i;
00362   char *s;
00363 
00364   s = pszName;
00365   while( *s ){
00366     if( isupper(*s) )*s = tolower(*s);
00367     s++;
00368     }
00369 
00370   if( pDO->StackListPointer && pDO->StackListPointer->pUF ){
00371     pUF = pDO->StackListPointer->pUF;
00372     for( i=0 ; i < pUF->cLocalVariables ; i++ ){
00373       if( !strcmp(pUF->ppszLocalVariables[i],pszName) )
00374         return SPrintVariable(pDO,ARRAYVALUE(pDO->StackListPointer->LocalVariables,i+1),pszBuffer,cbBuffer);
00375       }
00376     }
00377   for( i=0 ; i < pDO->cGlobalVariables ; i++ ){
00378      if( !strcmp(pDO->ppszGlobalVariables[i],pszName) ){
00379        if( pEo->GlobalVariables )
00380          return SPrintVariable(pDO,ARRAYVALUE(pEo->GlobalVariables,i+1),pszBuffer,cbBuffer);
00381        }
00382      }
00383 
00384   if( pDO->StackListPointer && pDO->StackListPointer->pUF ){
00385     pUF = pDO->StackListPointer->pUF;
00386     for( i=0 ; i < pUF->cLocalVariables ; i++ ){
00387       if( !strncmp(pUF->ppszLocalVariables[i],"main::",6) && !strcmp(pUF->ppszLocalVariables[i]+6,pszName) )
00388         return SPrintVariable(pDO,ARRAYVALUE(pDO->StackListPointer->LocalVariables,i+1),pszBuffer,cbBuffer);
00389       }
00390     }
00391   for( i=0 ; i < pDO->cGlobalVariables ; i++ ){
00392      if( !strncmp(pDO->ppszGlobalVariables[i],"main::",6) && !strcmp(pDO->ppszGlobalVariables[i]+6,pszName) ){
00393        if( pEo->GlobalVariables )
00394          return SPrintVariable(pDO,ARRAYVALUE(pEo->GlobalVariables,i+1),pszBuffer,cbBuffer);
00395        }
00396      }
00397   return 2;
00398   }
00399 
00400 /*POD
00401 =section GetSourceLineNumber
00402 =H Get the source line number for a given node
00403 
00404 /*FUNCTION*/
00405 long GetSourceLineNumber(pDebuggerObject pDO,
00406                          long PC
00407   ){
00408 /*noverbatim
00409 CUT*/
00410   long i,j;
00411   long lLineNumber;
00412   char *pszFileName;
00413 
00414   if( PC < 1 || PC > pDO->cNodes )return 0;
00415 
00416   if( pDO->Nodes[PC-1].lSourceLine )return pDO->Nodes[PC-1].lSourceLine-1;
00417 
00418   /* fill in the whole array */
00419   for( j=0 ; j < pDO->cNodes ; j++ ){
00420     lLineNumber = pDO->Nodes[j].lLineNumber;
00421     pszFileName = pDO->Nodes[j].pszFileName;
00422 
00423     for( i=0 ; i < pDO->cSourceLines ; i ++ )
00424       if( pDO->SourceLines[i].lLineNumber == lLineNumber && 
00425           pDO->SourceLines[i].szFileName                 &&
00426           pszFileName                                    &&
00427           !strcmp(pDO->SourceLines[i].szFileName,pszFileName) )break;
00428     pDO->Nodes[j].lSourceLine = i+1;
00429     }
00430 
00431   return pDO->Nodes[PC-1].lSourceLine-1;
00432   }
00433 
00434 /*FUNCTION*/
00435 long GetCurrentDebugLine(pDebuggerObject pDO
00436   ){
00437 
00438   if( pDO->StackListPointer == NULL && pDO->StackTop )
00439      return GetSourceLineNumber(pDO,pDO->StackTop->Node);
00440 
00441   if( pDO->StackListPointer == NULL || pDO->StackListPointer->down == NULL )
00442     return GetSourceLineNumber(pDO,pDO->pEo->ProgramCounter);
00443 
00444   return GetSourceLineNumber(pDO,pDO->StackListPointer->down->Node);
00445   }
00446 
00447 int MyExecBefore(pExecuteObject pEo){
00448   long i,j,lThisLine;
00449   pPrepext pEXT;
00450   pDebuggerObject pDO;
00451   char lbuf[80];
00452   char cmd;
00453 
00454   pEXT = pEo->pHookers->hook_pointer;
00455   pDO  = pEXT->pPointer;
00456   pDO->pEo = pEo;
00457 
00458   pDO->lPrevPC = pDO->lPC;
00459   pDO->lPC = pEo->ProgramCounter;
00460   if( pDO->DbgStack )pDO->DbgStack->LocalVariables = pEo->LocalVariables;
00461 
00462   lThisLine = GetSourceLineNumber(pDO,pEo->ProgramCounter);
00463 
00464   if( pDO->SourceLines[lThisLine].BreakPoint == 0 ){
00465     /* if we are executing some step over function */
00466     if( pDO->Run2CallStack != -1 && pDO->Run2CallStack < pDO->CallStackDepth )return 0;
00467     if( pDO->Run2Line && pDO->Nodes[pDO->lPC-1].lSourceLine != pDO->Run2Line )return 0;
00468     }
00469 
00470   comm_WeAreAt(pDO,lThisLine);
00471 
00472   pDO->StackListPointer = pDO->DbgStack;
00473   while(1){
00474     cmd = comm_GetCommand(pDO,lbuf,80);
00475 
00476 
00477     switch( cmd ){
00478 
00479       case 'D':/* step the stack list pointer to the bottom */
00480          pDO->StackListPointer = pDO->DbgStack;
00481          comm_Message(pDO,"done");
00482          continue;
00483       case 'u':/* step the stack list pointer up */
00484         if( pDO->StackListPointer ){
00485           pDO->StackListPointer = pDO->StackListPointer->up;
00486           comm_Message(pDO,"done");
00487           }else comm_Message(pDO,"No way up more");
00488         continue;
00489       case 'd':/* step the stack list pointer down */
00490         if( pDO->StackListPointer && pDO->StackListPointer->down )
00491           pDO->StackListPointer = pDO->StackListPointer->down;
00492         else
00493           pDO->StackListPointer = pDO->StackTop;
00494         if( pDO->StackListPointer )
00495           comm_Message(pDO,"done");
00496         else
00497           comm_Message(pDO,"No way down more");
00498         continue;
00499       case 'b': /* set break point at a line */
00500         if( ! *lbuf )/* set it at the current line */
00501           i = GetCurrentDebugLine(pDO)+1;
00502         else
00503           GetRange(lbuf,&i,&j);
00504         if( i < 1 || i > pDO->cSourceLines ){
00505           comm_Message(pDO,"invalid line number");
00506           continue;
00507           }
00508         pDO->SourceLines[i-1].BreakPoint = 1;
00509         comm_Message(pDO,"done");
00510         continue;
00511       case 'B':/* remove breakpoint from line(s) */
00512         if( ! *lbuf )/* remove all */
00513           i = 1, j = pDO->cSourceLines;
00514         else
00515           GetRange(lbuf,&i,&j);
00516         if( i < 1 || i >= pDO->cSourceLines ){
00517           comm_Message(pDO,"invalid line number");
00518           continue;
00519           }
00520         if( j == 0 )j = i;
00521         if( j > pDO->cSourceLines )j = pDO->cSourceLines;
00522         while( i <= j ){
00523           pDO->SourceLines[i-1].BreakPoint = 0;
00524           i++;
00525           }
00526         comm_Message(pDO,"done");
00527         continue;
00528       case 'q':/* quit the program execution */
00529         comm_Message(pDO,"Ok... you have said that... quitting...");
00530         pEo->pszModuleError = "Debugger Operator Forced Exit.";
00531         return COMMAND_ERROR_PREPROCESSOR_ABORT;
00532 
00533       case 's':/*step a single line and step into functions */
00534         pDO->Run2CallStack = pDO->CallStackDepth+1;
00535         pDO->Run2Line = 0;
00536         return 0; /* step one step forward */
00537       case 'o':/* run program until it gets out of the current function */
00538         pDO->Run2CallStack = pDO->CallStackDepth ? pDO->CallStackDepth - 1 : 0 ;
00539         pDO->Run2Line = 0;
00540         return 0; /* step one step forward */
00541       case 'S':
00542         pDO->Run2CallStack = pDO->CallStackDepth;
00543         pDO->Run2Line = 0;
00544         return 0; /* step one step forward but remain on the same level */
00545       case 'r':
00546          pDO->Run2CallStack = -1;/* any level deep */
00547          if( ! *lbuf ){
00548            pDO->Run2Line = -1;/* a nonzero value that can not be a valid line number */
00549            return 0;
00550            }
00551          GetRange(lbuf,&i,&j);
00552          pDO->Run2Line = i;
00553          return 0;
00554       case 'R':
00555          pDO->Run2CallStack = pDO->CallStackDepth; /* on the current level */
00556          if( ! *lbuf ){
00557            pDO->Run2Line = -1;/* a nonzero value that can not be a valid line number */
00558            return 0;
00559            }
00560          GetRange(lbuf,&i,&j);
00561          pDO->Run2Line = i;
00562          return 0;
00563       }
00564     }
00565   return 0;
00566   }
00567 int MyExecAfter(pExecuteObject pEo){
00568   pPrepext pEXT;
00569   pDebuggerObject pDO;
00570 
00571   pEXT = pEo->pHookers->hook_pointer;
00572   pDO  = pEXT->pPointer;
00573   pDO->pEo = pEo;
00574 
00575   return 0;
00576   }
00577 int MyExecCall(pExecuteObject pEo){
00578   pPrepext pEXT;
00579   pDebuggerObject pDO;
00580 
00581   pEXT = pEo->pHookers->hook_pointer;
00582   pDO  = pEXT->pPointer;
00583   pDO->pEo = pEo;
00584 
00585   PushStackItem(pDO,pEo->ProgramCounter);
00586   
00587   return 0;
00588   }
00589 int MyExecReturn(pExecuteObject pEo){
00590   pPrepext pEXT;
00591   pDebuggerObject pDO;
00592 
00593   pEXT = pEo->pHookers->hook_pointer;
00594   pDO  = pEXT->pPointer;
00595   pDO->pEo = pEo;
00596 
00597   PopStackItem(pDO);
00598 
00599   return 0;
00600   }
00601 
00602 static pDebuggerObject new_DebuggerObject(pPrepext pEXT){
00603   pDebuggerObject pDO;
00604 
00605   pDO = pEXT->pST->Alloc(sizeof(DebuggerObject),pEXT->pMemorySegment);
00606   if( pDO == NULL )return NULL;
00607 
00608   pDO->pEXT = pEXT;
00609   pDO->cGlobalVariables = 0;
00610   pDO->ppszGlobalVariables = NULL;
00611 
00612   pDO->cUserFunctions = 0;
00613   pDO->pUserFunctions = NULL;
00614 
00615   pDO->cFileNames = 0;
00616   pDO->ppszFileNames = NULL;
00617 
00618   pDO->cNodes = 0;
00619   pDO->Nodes = NULL;
00620 
00621   pDO->cSourceLines = 0;
00622   pDO->SourceLines = NULL;
00623 
00624   pDO->Run2CallStack = 0;
00625   pDO->Run2Line = 0;
00626   return pDO;
00627   }
00628 
00629 /*
00630 This function allocates space for the file name in the
00631 preprocessor memory segment.
00632 
00633 In case the name was already used then returns the pointer to
00634 the already allocated file name.
00635 */
00636 static char *AllocFileName(pPrepext pEXT,
00637                            char *pszFileName
00638   ){
00639   long i;
00640   pDebuggerObject pDO = pEXT->pPointer;
00641   char **p;
00642 
00643   if( pszFileName == NULL )return NULL;
00644   for( i=0 ;  i < pDO->cFileNames ; i++ )
00645     if( !strcmp(pDO->ppszFileNames[i],pszFileName) )return pDO->ppszFileNames[i];
00646   pDO->cFileNames++;
00647   p = pEXT->pST->Alloc( sizeof(char *)*pDO->cFileNames,pEXT->pMemorySegment);
00648   if( p == NULL )return NULL;
00649   if( pDO->ppszFileNames ){
00650     memcpy(p,pDO->ppszFileNames,sizeof(char *)*pDO->cFileNames);
00651     pEXT->pST->Free(pDO->ppszFileNames,pEXT->pMemorySegment);
00652     }
00653   pDO->ppszFileNames = p;
00654   pDO->ppszFileNames[pDO->cFileNames-1] = pEXT->pST->Alloc( strlen(pszFileName)+1,pEXT->pMemorySegment);
00655   if( pDO->ppszFileNames[pDO->cFileNames-1] == NULL )return NULL;
00656   strcpy(pDO->ppszFileNames[pDO->cFileNames-1],pszFileName);
00657   return pDO->ppszFileNames[pDO->cFileNames-1];
00658   }
00659 
00660 static pUserFunction_t AllocUserFunction(pPrepext pEXT,
00661                                          char *pszUserFunction
00662   ){
00663   pDebuggerObject pDO = pEXT->pPointer;
00664   pUserFunction_t p;
00665 
00666   pDO->cUserFunctions++;
00667   p = pEXT->pST->Alloc( sizeof(UserFunction_t)*pDO->cUserFunctions,pEXT->pMemorySegment);
00668   if( p == NULL )return NULL;
00669   if( pDO->pUserFunctions ){
00670     memcpy(p,pDO->pUserFunctions,sizeof(UserFunction_t)*pDO->cUserFunctions);
00671     pEXT->pST->Free(pDO->pUserFunctions,pEXT->pMemorySegment);
00672     }
00673   pDO->pUserFunctions = p;
00674   pDO->pUserFunctions[pDO->cUserFunctions-1].pszFunctionName = pEXT->pST->Alloc( strlen(pszUserFunction)+1,pEXT->pMemorySegment);
00675   if( pDO->pUserFunctions[pDO->cUserFunctions-1].pszFunctionName == NULL )return NULL;
00676   strcpy(pDO->pUserFunctions[pDO->cUserFunctions-1].pszFunctionName,pszUserFunction);
00677   pDO->pUserFunctions[pDO->cUserFunctions-1].ppszLocalVariables = NULL;
00678   pDO->pUserFunctions[pDO->cUserFunctions-1].cLocalVariables = 0;
00679   return &(pDO->pUserFunctions[pDO->cUserFunctions-1]);
00680   }
00681 
00682 void CBF_ListLocalVars(char *pszName,
00683                        void *pSymbol,
00684                        void **pv){
00685   pSymbolVAR pVAR = pSymbol;
00686   pUserFunction_t pUF= pv[0];
00687   pPrepext pEXT = pv[1];
00688 
00689   pUF->ppszLocalVariables[pVAR->Serial-1] = pEXT->pST->Alloc(strlen(pszName)+1,pEXT->pMemorySegment);
00690   if( pUF->ppszLocalVariables[pVAR->Serial-1] == NULL )return;
00691   strcpy(pUF->ppszLocalVariables[pVAR->Serial-1],pszName);
00692   }
00693 
00694 void CBF_ListGlobalVars(char *pszName,
00695                        void *pSymbol,
00696                        void *pv){
00697   pSymbolVAR pVAR = pSymbol;
00698   pDebuggerObject pDO = pv;
00699 
00700   pDO->ppszGlobalVariables[pVAR->Serial-1] = pDO->pEXT->pST->Alloc(strlen(pszName)+1,pDO->pEXT->pMemorySegment);
00701   if( pDO->ppszGlobalVariables[pVAR->Serial-1] == NULL )return;
00702   strcpy(pDO->ppszGlobalVariables[pVAR->Serial-1],pszName);
00703   }
00704 
00705 int DLL_EXPORT preproc(pPrepext pEXT,
00706                        long *pCmd,
00707                        void *p
00708   ){
00709 
00710   switch( *pCmd ){
00711 
00712     case PreprocessorReadDone3:{
00713       pReadObject pRo = p;
00714       pDebuggerObject pDO = pEXT->pPointer;
00715       pSourceLine Result;
00716       long i;
00717 
00718       Result = pRo->Result;
00719 
00720       i = 0;
00721       while( Result ){
00722         i++;
00723         Result = Result->next;
00724         }
00725       pDO->cSourceLines = i;
00726       pDO->SourceLines = pEXT->pST->Alloc(sizeof(SourceLine_t)*i,pEXT->pMemorySegment);
00727       *pCmd = PreprocessorUnload;
00728       if( pDO->SourceLines == NULL )return 1;
00729       Result = pRo->Result;
00730       i = 0;
00731       while( Result ){
00732         pDO->SourceLines[i].line = pEXT->pST->Alloc(strlen(Result->line)+1,pEXT->pMemorySegment);
00733         if( pDO->SourceLines[i].line == NULL )return 1;
00734         strcpy(pDO->SourceLines[i].line,Result->line);
00735         pDO->SourceLines[i].szFileName = AllocFileName(pEXT,Result->szFileName);
00736         pDO->SourceLines[i].lLineNumber = Result->lLineNumber;
00737         pDO->SourceLines[i].BreakPoint = 0;
00738         i++;
00739         Result = Result->next;
00740         }
00741       *pCmd = PreprocessorContinue;
00742       return 0;
00743       }
00744 
00745     case PreprocessorLoad:{
00746       pDebuggerObject pDO;
00747 
00748       if( pEXT->lVersion != IP_INTERFACE_VERSION ){
00749         *pCmd = PreprocessorUnload;
00750         return 0;
00751         }
00752 
00753       pDO = new_DebuggerObject(pEXT);
00754       *pCmd = PreprocessorUnload;
00755       if( pDO == NULL )return 1;
00756 
00757       pEXT->pPointer = pDO;
00758       *pCmd = PreprocessorContinue;
00759       return 0;
00760       }
00761 
00762   case PreprocessorExFinish:{
00763       peXobject pEx = p;
00764       pDebuggerObject pDO = pEXT->pPointer;
00765       peNODE_l Result = pEx->pCommandList;
00766       long i;
00767 
00768       pDO->cNodes = pEx->NodeCounter;
00769       pDO->Nodes = pEXT->pST->Alloc(sizeof(DebugNode_t)*pDO->cNodes,pEXT->pMemorySegment);
00770       if( pDO->Nodes == NULL ){
00771         *pCmd = PreprocessorUnload;
00772         return 1;
00773         }
00774       for( i=0 ; i < pDO->cNodes ; i++ ){
00775         pDO->Nodes[i].pszFileName = NULL;
00776         pDO->Nodes[i].lLineNumber = 0;
00777         pDO->Nodes[i].lSourceLine = 0;
00778         }
00779       while( Result ){
00780         pDO->Nodes[Result->NodeId-1].pszFileName = AllocFileName(pEXT,Result->szFileName);
00781         pDO->Nodes[Result->NodeId-1].lLineNumber = Result->lLineNumber;
00782         Result = Result->rest;
00783         }
00784       pDO->cGlobalVariables = pEx->cGlobalVariables;
00785       pDO->ppszGlobalVariables = pEXT->pST->Alloc( sizeof(char *)*pDO->cGlobalVariables,pEXT->pMemorySegment);
00786       if( pDO->ppszGlobalVariables == NULL ){
00787         *pCmd = PreprocessorUnload;
00788         return 1;
00789         }
00790       pEXT->pST->TraverseSymbolTable(pEx->GlobalVariables,CBF_ListGlobalVars,pDO);
00791       *pCmd = PreprocessorContinue;
00792       return 0;
00793       }
00794   case PreprocessorExStartLocal:{
00795       peXobject pEx = p;
00796       pDebuggerObject pDO = pEXT->pPointer;
00797 
00798       pDO->bLocalStart = 1;
00799       *pCmd = PreprocessorContinue;
00800       return 0;
00801       }
00802   case PreprocessorExLineNode:{
00803       peXobject pEx = p;
00804       pDebuggerObject pDO = pEXT->pPointer;
00805 
00806       if( pDO->bLocalStart ){
00807         pDO->bLocalStart = 0;
00808         pDO->FunctionNode = pEx->NodeCounter;
00809         }
00810       *pCmd = PreprocessorContinue;
00811       return 0;
00812       }
00813   case PreprocessorExEndLocal:{
00814       peXobject pEx = p;
00815       pUserFunction_t pUF;
00816       pDebuggerObject pDO = pEXT->pPointer;
00817       void *pv[2];
00818 
00819       *pCmd = PreprocessorContinue;
00820       if( pEx->ThisFunction == NULL )return 0;/* may happen if syntax error in the BASIC program */
00821       pUF = AllocUserFunction(pEXT,pEx->ThisFunction->FunctionName);
00822       pUF->cLocalVariables = pEx->cLocalVariables;
00823       if( pUF->cLocalVariables )
00824         pUF->ppszLocalVariables = pEXT->pST->Alloc( sizeof(char *)*pUF->cLocalVariables,pEXT->pMemorySegment);
00825       else
00826         pUF->ppszLocalVariables = NULL;
00827       pUF->NodeId = pDO->FunctionNode;
00828       *pCmd = PreprocessorUnload;
00829       if( pUF->cLocalVariables && pUF->ppszLocalVariables == NULL )return 1;
00830       pv[0] = pUF;
00831       pv[1] = pEXT;
00832       pEXT->pST->TraverseSymbolTable(pEx->LocalVariables,(void *)CBF_ListLocalVars,pv);
00833       *pCmd = PreprocessorContinue;
00834       return 0;
00835       }
00836 
00837   case PreprocessorExeStart:
00838     { pExecuteObject pEo = p;
00839       pDebuggerObject pDO = pEXT->pPointer;
00840       pEo->pHookers->hook_pointer = pEXT;
00841       pDO->CallStackDepth = 0;
00842       pDO->DbgStack = NULL;
00843       pDO->StackTop = NULL;
00844       pEo->pHookers->HOOK_ExecBefore = MyExecBefore;
00845       pEo->pHookers->HOOK_ExecAfter = MyExecAfter;
00846       pEo->pHookers->HOOK_ExecCall = MyExecCall;
00847       pEo->pHookers->HOOK_ExecReturn = MyExecReturn;
00848       GetSourceLineNumber(pDO,1);/* to calculate all the node numbers for each lines (or the other way around?) */
00849       comm_Init(pDO);
00850       *pCmd = PreprocessorContinue;
00851       return 0;
00852       }
00853 
00854     default: /* in any cases that are not handled by the preprocessor just go on */
00855       *pCmd = PreprocessorContinue;
00856       return 0;
00857     }
00858 
00859   }

Generated on Sun Mar 12 23:56:28 2006 for ScriptBasic by  doxygen 1.4.6-NO