home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sd386v50.zip / sd386src.zip / EXPR.C < prev    next >
Text File  |  1996-04-16  |  76KB  |  1,211 lines

  1. /*****************************************************************************/
  2. /* File:                                             IBM INTERNAL USE ONLY   */
  3. /*   expr.c                                                                  */
  4. /*                                                                           */
  5. /* Description:                                                              */
  6. /*   Expression handling routines.                                           */
  7. /*                                                                           */
  8. /*                                                                           */
  9. /* History:                                                                  */
  10. /*                                                                           */
  11. /*   02/08/91 Creation of 32-bit SD86, from 16-bit version.                  */
  12. /*                                                                           */
  13. /*...16->32 port.                                                            */
  14. /*...                                                                        */
  15. /*... 02/08/91  101   Joe       port to 32 bit.                              */
  16. /*... 02/08/91  110   Srinivas  port to 32 bit.                              */
  17. /*... 02/08/91  112   Joe       port to 32 bit.                              */
  18. /*                                                                           */
  19. /*...Release 1.00 (Pre-release 1)                                            */
  20. /*...                                                                        */
  21. /*... 07/09/91  205   srinivas  Hooking up of register variables.            */
  22. /*... 07/18/91  211   Christina need to call findsvar when there is a func   */
  23. /*...                           above main & there is a global variable      */
  24. /*... 07/26/91  219   srinivas  handling near pointers.                      */
  25. /*... 08/05/91  221   srinivas  Hooking up registers and constants in data   */
  26. /*                              window.                                      */
  27. /*... 09/25/91  240   Srinivas  recursive PLX based variables.               */
  28. /*... 09/25/91  243   Srinivas  ISADDREXPR global flag problems.             */
  29. /*...                                                                        */
  30. /*...Release 1.00 (Pre-release 1.05 10/10/91)                                */
  31. /*...                                                                        */
  32. /*... 10/16/91  303   Srinivas  Trap if register constants are entered in    */
  33. /*                              data window when you are in assembly view    */
  34. /*                    --------> Fix Removed taken care by fix No: 533.       */
  35. /*... 11/07/91  312   Srinivas  In data window SS:ESP+a gives wrong results. */
  36. /*...                                                                        */
  37. /*...Release 1.00 (Pre-release 1.08 12/05/91)                                */
  38. /*...                                                                        */
  39. /*... 12/20/91  501   Srinivas  If flat address is specifed in data window   */
  40. /*...                           some times it gives bogus results.           */
  41. /*... 02/10/92  513   Srinivas  Allow array indexs in datawindow to be       */
  42. /*...                           variables.                                   */
  43. /*... 02/12/92  521   Srinivas  Port to C-Set/2.                             */
  44. /*...                                                                        */
  45. /*...Release 1.00 (03/03/92)                                                 */
  46. /*...                                                                        */
  47. /*... 03/20/92  607   Srinivas  CRMA fixes.                                  */
  48. /*...                                                                        */
  49. /*...Release 1.02 (10/22/92)                                                 */
  50. /*...                                                                        */
  51. /*... 01/26/93  809   Selwyn    HLL Level 2 support.                         */
  52. /*... 03/03/93  813   Joe       Revised types handling for HL03.             */
  53. /*... 09/16/93  901   Joe       Add code to handle resource interlock error. */
  54. /*... 10/05/93  904   Joe       Fix for unable to display x[i] in the data   */
  55. /*...                           window.                                      */
  56. /*                                                                           */
  57. /**Includes*******************************************************************/
  58.  
  59. #include "all.h"                        /* SD86 include files                */
  60. static UINT ParseMshExpr=0;
  61.  
  62. /**Defines *******************************************************************/
  63.  
  64. #define NREGS16 16                      /* # of registers in 16 bit world 221*/
  65. #define NREGS32 10                      /* # of registers in 32 bit world 221*/
  66.                                         /* Parse States                      */
  67. #define OP0  0x00                       /* initial -- no operands            */
  68. #define OP0P 0x01                       /* got operand(s) and plus           */
  69. #define OP0M 0x02                       /* got operand(s) and minus          */
  70. #define OP0T 0x04                       /* got operand(s) and times          */
  71.  
  72. #define OP1  0x10                       /* got one operand                   */
  73. #define OP1P 0x11                       /* got one operand and plus          */
  74. #define OP1M 0x12                       /* got one operand and minus         */
  75. #define OP1T 0x14                       /* got one operand and times         */
  76. #define OP1C 0x18                       /* got one operand and colon         */
  77.  
  78. #define OP2  0x20                       /* got two operands                  */
  79. #define OP2P 0x21                       /* got two operands and plus         */
  80. #define OP2M 0x22                       /* got two operands and minus        */
  81. #define OP2T 0x24                       /* got two operands and times        */
  82.  
  83. #define OP3  0x40                       /* got two operands and '.'or '->'   */
  84.  
  85. #define OP4  0x80                       /* mask for OP4L and OP4R            */
  86. #define OP4L 0x81                       /* got two operands and '['          */
  87. #define OP4R 0x82                       /* got two operands and '[number' ???*/
  88.                                         /*                      'number]'    */
  89. #define DONTCARE 0                      /*                                513*/
  90. #define NTYPES   8                      /*                                513*/
  91. /**External declararions******************************************************/
  92.  
  93. extern PtraceBuffer AppPTB;             /* Application Ptrace buffer.        */
  94. extern uint         DataMid;            /* Set by DBData -- Module ID.       */
  95. extern uint         DataTid;            /* Set by DBData -- Type ID.         */
  96. extern SSProc      *Qproc;              /* Set by Qsymbol() to the SSProc 809*/
  97.                                         /*                  and findsvar.    */
  98. extern USHORT       dtab[];             /*                                513*/
  99.  
  100. UCHAR  BadExprMsg[] = "Incorrect expression";
  101. UINT   ExprMid;                         /* Set by ParseExpr.                 */
  102. UINT   ExprTid;                         /* Set by ParseExpr and findlvar     */
  103. UCHAR *ParseError;                      /* Set by ParseExpr if error message */
  104. UINT   ExprAddr;                        /* Set by ParseExpr.                 */
  105. UINT   ExprLno;                         /* Set by ParseExpr.                 */
  106. SCOPE  ExprScope;                       /* Set by ParseExpr and findlvar.    */
  107. long   CmplxBkptVal;                    /*                                   */
  108. UCHAR  IfUscores = TRUE;                /* TRUE if syms may have uscore prefx*/
  109. UCHAR  IsAddrExpr;                      /* Set by ParseExpr if address       */
  110.                                         /* yeilding expression.              */
  111.  
  112.  
  113. /**Static definitions ********************************************************/
  114.  
  115. static  UCHAR ErrMsgBuf[40];            /* local message buffer.             */
  116. static  UCHAR RegNames32[] = "eax ecx edx ebx esp ebp esi edi efl eip ";
  117. static  UCHAR RegNames16[] = "axcxdxbxspbpsidiflipcsdsesfsgsss";
  118.  
  119. /*****************************************************************************/
  120. /* ParseExpr()                                                               */
  121. /*                                                                           */
  122. /* Description:                                                              */
  123. /*                                                                           */
  124. /*  Expression Evaluation Routine                                            */
  125. /*                                                                           */
  126. /*  cp = ParseExpr( expr, context, optmid, optline )                         */
  127. /*                                                                           */
  128. /*     uint Context;                                                         */
  129. /*          Context & 0x0F => 0 = normal, 1 = constant, 2 = no names         */
  130. /*          Context & 0x10 => "optmid" and "optline" parms are specified     */
  131. /*          Context & 0x20 => do not use local names in the expression       */
  132. /*                                                                           */
  133. /*  expr =    &token<op>token<op>token<op>...........                        */
  134. /*         **..                                                              */
  135. /*                                                                           */
  136. /*            token=hex or decimal constant, or a                            */
  137. /*                  register, or a                                           */
  138. /*                  symbol.                                                  */
  139. /*                                                                           */
  140. /*  Evaluation proceeds L->R.                                                */
  141. /*  Expressions using the ":" operator have a default base of hex.           */
  142. /*                                                                           */
  143. /*                                                                           */
  144. /* Parameters:                                                               */
  145. /*                                                                           */
  146. /*   cp       input - pointer to the text expression.                        */
  147. /*   context  input - see above.                                             */
  148. /*   optmid   input - optional module id.                                    */
  149. /*   optline  input - optional line.                                         */
  150. /*   optsfi   input - optional source file index.                            */
  151. /*                                                                           */
  152. /* Return:                                                                   */
  153. /*                                                                           */
  154. /*   sym      Pointer into expression where we encountered a parsing error.  */
  155. /*            If this points to a NULL, then parsing proceeded ok.           */
  156. /*                                                                           */
  157. /* Assumptions:                                                              */
  158. /*                                                                           */
  159. /*   none.                                                                   */
  160. /*                                                                           */
  161. /*****************************************************************************/
  162. uchar * ParseExpr( uchar *cp,
  163.                    uint context,
  164.                    uint optmid,
  165.                    uint optline,
  166.                    int  optsfi  )
  167.                                         /* pointer to text string            */
  168.                                         /* see above                         */
  169.                                         /* only if context & 0x10. module id.*/
  170.                                         /* only if context & 0x10. src line#.*/
  171. {                                       /*                                   */
  172.  uint   mid;                            /* a module id.                      */
  173.  ulong  bigans;                         /* a long representation of a const. */
  174.  uint   ans;                            /* a uint representation of a const. */
  175.  uint   c;                              /* the current character in the expr.*/
  176.  uint   state;                          /* initial state.                    */
  177.  uint   base;                           /* hex or decimal base.              */
  178.  uint   exprbase;                       /* working base for an expression.   */
  179.  uint   progline;                       /* the program source line with var. */
  180.  uint   SymRegIndex;                    /* the register index.               */
  181.  uint   deref;                          /* flag for "*" operator.            */
  182.  uint   addrof;                         /* flag for "&" operator.            */
  183.  uint   fldoff;                         /* offset of variable in structure.  */
  184.  uchar *sym;                            /* -> to token in the expr string.   */
  185.  uint   symlen;                         /* length of token in string.        */
  186.  uint   symloc;                         /* -> to a symbol location.       112*/
  187.  uint   seg;                            /* the selector of symloc.           */
  188.  uint   off;                            /* the offset of symloc.             */
  189.  uchar  buffer[MAXNAMELEN];             /* buffer for a symbol name.      813*/
  190.  uint   NoLocalNames;                   /* flag for using/not using locals.  */
  191.  uint   temp;                           /*                                221*/
  192.  uchar  Regname[4];                     /* temp array to hold reg name    221*/
  193.  uint   IsSymRegName;                   /* flag to know if a sym is a reg 221*/
  194.  uint   TempExprTid;                    /* temp var to hold exprtid       219*/
  195.  DEBFILE     *pdf;                                                      /*901*/
  196.  int          progsfi;
  197.  UCHAR       *cppsym;
  198.  BOOL         ThisProcessing = FALSE;
  199.  
  200. startallover:
  201.  off   = 0;
  202.  state = OP0;
  203. /*****************************************************************************/
  204. /* First, we initialize some global values.                                  */
  205. /*                                                                           */
  206. /*****************************************************************************/
  207.  ExprAddr   = NULL;                     /*                                112*/
  208.  ExprScope  = NULL;                     /*                                   */
  209.  ExprMid    = 0;                        /*                                   */
  210.  ExprTid    = 0;                        /*                                   */
  211.  ExprLno    = 0;                        /*                                   */
  212.  IsAddrExpr = TRUE;                     /*                                243*/
  213.  ParseError = NULL;                     /*                                   */
  214.                                         /*                                   */
  215.  deref = addrof = base = seg = 0;       /*                                   */
  216.  IsSymRegName = 0;                      /*                                221*/
  217.  exprbase = 10;                         /*                                   */
  218.                                         /*                                   */
  219. /*****************************************************************************/
  220. /* If we are parsing from the executing context, then we will get the mid    */
  221. /* and source line from the currently executing afile and ExecLine. Else     */
  222. /* we use the passed values.                                                 */
  223. /*                                                                           */
  224. /*****************************************************************************/
  225. #ifdef MSH
  226.  if(cp[0]=='!' && ParseMshExpr ) {
  227.     int iret;
  228.     ParseMshExpr = 0; /*Control recursion.*/
  229.     iret=mshsd386command(cp+1);
  230.     /*iret = 1: expression evaluates to non-zero; */
  231.     /*       0: expression evaluates to zero;     */
  232.     /*      -1: syntax error.                     */
  233.     /*      -2: semantic error.                   */
  234.     /*      -3: exit                              */
  235.     /*       8: REXX semantic error               */
  236.     /*      10: REXX return code zero             */
  237.     /*      11: REXX return code non-zero         */
  238.     return (uchar *)(10+iret);
  239.  }
  240.  ParseMshExpr = 0; /*Control recursion.*/
  241. #endif
  242.  
  243.  if( context & 0x10 )                   /* use optmid and optline if proper  */
  244.  {                                      /* context.                          */
  245.   mid = optmid;                         /*                                   */
  246.   progline = optline;                   /*                                   */
  247.   progsfi  = optsfi;                    /*                                   */
  248.  }                                      /*                                   */
  249.  else                                   /* else                              */
  250.  {                                      /*                                   */
  251.   AFILE *execfp;
  252.  
  253.   execfp = GetExecfp();
  254.   mid = (execfp ? execfp->mid : 0);     /* get mid from the executing afile. */
  255.   progline = GetExecLno();              /* use executing line                */
  256.  }                                      /*                                   */
  257.                                         /*                                   */
  258.  NoLocalNames = ((context & 0x20) ?     /* set a flag if we are excluding    */
  259.                   TRUE : FALSE);        /* local names.                      */
  260.                                         /*                                   */
  261.  context &= 0x0F;                       /* precipitate normal=0,1=constant,  */
  262.                                         /* or 2=no names context.            */
  263.                                         /*                                   */
  264. /*****************************************************************************/
  265. /* At this point, we are in the OP0 state and will begin to parse off and    */
  266. /* process tokens. We will stay in the token parsing loop until all tokens   */
  267. /* are parsed.                                                               */
  268. /*                                                                           */
  269. /*****************************************************************************/
  270.  
  271.  for( ;; )                              /*  begin token parsing.             */
  272.  {                                      /*  one loop iteration per token.    */
  273. /*****************************************************************************/
  274. /* At this point we want to establish the start of a token or the end of     */
  275. /* parsing. When c==NULL, then parsing is complete. At the completion of the */
  276. /* loop c will be the first token char and cp will point to the character    */
  277. /* following c.                                                              */
  278. /*                                                                           */
  279. /*****************************************************************************/
  280.   for( ;; ++cp )                        /* scan string skipping spaces.      */
  281.   {                                     /*                                   */
  282.    sym = cp;                            /* save the beginning of the token.  */
  283.    if( (c = *cp) > 0x20 )               /* if we hit a non-space then we     */
  284.    {                                    /*                                   */
  285.     ++cp;                               /* are at the start of a token and   */
  286.     break;                              /* can exit the loop.                */
  287.    }                                    /*                                   */
  288.    if( !c )                             /* if we hit end-of-string then      */
  289.     goto fini;                          /* go home.                          */
  290.   }                                     /*                                   */
  291. /*****************************************************************************/
  292. /* At this point, we handle tokens that are constants.  The first thing we   */
  293. /* want to do is establish the base.  If we have the c hex constant          */
  294. /* designation "0x...", then the base is hex.  Otherwise we use decimal.     */
  295. /*                                                                           */
  296. /*****************************************************************************/
  297.  ParseNumber:                           /* handle token is a number.         */
  298.                                         /*                                   */
  299.   if( c >= '0' && c <= '9' )            /* if we have a decimal digit, or    */
  300.   {                                     /*                                   */
  301.    if( c == '0' && ((*cp == 'x') ||     /* if the second digit is x or    501*/
  302.                     (*cp == 'X')))      /* if the second digit is X, then 501*/
  303.    {                                    /*                                   */
  304.     base = 16;                          /* we assume hex base.               */
  305.     ++cp;                               /* bump cp past the "x" part of token*/
  306.    }else                                /*                                   */
  307.     base = exprbase;                    /* use default base = decimal        */
  308.  
  309. /*****************************************************************************/
  310. /* We now execute a loop to evaluate the constant.                           */
  311. /*                                                                           */
  312. /* bigans = bigans*base + c(current digit value).                            */
  313. /*                                                                           */
  314. /* Upper case hex digits are folded to lower case.                           */
  315. /*                                                                           */
  316. /* Loop exits at "break" statement when we encounter a non-digit.            */
  317. /*                                                                           */
  318. /* Also, we might begin evaluating with base=10 for a number that looks like */
  319. /* 19FC. If we do, then we change the base to hex and re-evaluate.           */
  320. /*                                                                           */
  321. /*****************************************************************************/
  322.                                         /*                                   */
  323.  ReparseNumber:                         /*                                   */
  324.                                         /*                                   */
  325.    for( bigans = c - '0' ;; ++cp )      /* begin loop to evaluate constant.  */
  326.    {                                    /*                                   */
  327.     c = *cp - '0';                      /* get value of next digit.          */
  328.     if( c > 9 )                         /* if this is a hex digit a-f, then  */
  329.     {                                   /*                                   */
  330.      c = *cp | 0x20;                    /* convert c to its lower case value.*/
  331.      c = c - 'a' + 10;                  /* calc "real" value of it.          */
  332.      if( c>=10 && c<=15 )               /* if value is in hex a-f range, then*/
  333.      {                                  /*                                   */
  334.       if( base == 10 )                  /* if we are in a decimal base,      */
  335.       {                                 /*                                   */
  336.        base = 16;                       /* change the base to hex ,          */
  337.        c = '0';                         /* force a leading zero and          */
  338.        cp = sym;                        /* backup to start of symbol and     */
  339.        goto ReparseNumber;              /* restart parsing with right base.  */
  340.       }                                 /*                                   */
  341.      }else                              /* c is not a valid decimal or hex   */
  342.       break;                            /* digit, so we have hit the end of  */
  343.                                         /* the token.                        */
  344.     }                                   /*                                   */
  345.     bigans = bigans * base + c;         /* update the value.                 */
  346.    }                                    /* end loop to evaluate constant     */
  347.                                         /*                                   */
  348. /*****************************************************************************/
  349. /* At this point, we can be in many parsing states. If we are in the OP0     */
  350. /* state, then we are working on a simple constant or a seg:off constant.    */
  351. /*                                                                           */
  352. /*****************************************************************************/
  353.    if( state == OP0 )                   /*                                   */
  354.     seg = ( uint )(bigans >> 16);       /* anticipate possible seg:off form. */
  355.    ans = ( uint )bigans;                /* hold 16 bit result.               */
  356.    goto GotOperand;                     /* go to next state and next token.  */
  357.   }                                     /*                                   */
  358.                                         /*                                   */
  359. /*****************************************************************************/
  360. /* If we know by definition, context==1, that this token is a constant, then */
  361. /* getting to this point is a nono.                                          */
  362. /*                                                                           */
  363. /*****************************************************************************/
  364.   if( context == 1 )                    /* if constant by definition, then   */
  365.   {                                     /*                                   */
  366.    ParseError="Constant required";      /* it's bye bye time.                */
  367.    goto bummer;                         /*                                   */
  368.   }                                     /*                                   */
  369. /*****************************************************************************/
  370. /* The following code parses a valid c identifier.                           */
  371. /*                                                                           */
  372. /*****************************************************************************/
  373.   if( IsOKchar( ( uchar )c) )           /* If the leading character is valid,*/
  374.    while( IsOKchar(*cp) )               /* then parse to the end of the      */
  375.    {                                    /* token.                            */
  376.     if(*cp == 0x15 )                    /* maintain italian relations and    */
  377.      *cp = '@';                         /* convert  to @.                   */
  378.     ++cp;                               /*                                   */
  379.    };                                   /*                                   */
  380.                                         /*                                   */
  381.  
  382. /*****************************************************************************/
  383. /* At this point, if we have an operator or a register, we will fall into    */
  384. /* one of these two cases of a switch statement. Otherwise, we will fall     */
  385. /* through.                                                                  */
  386. /*                                                                           */
  387. /* symlen==1 => operator. Valid operators are + - * [ ] -> . & :             */
  388. /* symlen==2 => register.                                                    */
  389. /*                                                                           */
  390. /*****************************************************************************/
  391.   symlen = cp - sym;                    /*                                521*/
  392.   switch( symlen )                      /* begin switch on symlen.           */
  393.   {
  394.     case 1:
  395.       /***********************************************************************/
  396.       /* This is the case of an operator, symlen==1. Single character        */
  397.       /* symbol names will fall through.                                     */
  398.       /***********************************************************************/
  399.  
  400.       switch( c )                       /* begin switch on operator          */
  401.       {                                 /*                                   */
  402.        case '+':                        /*                                   */
  403.          /********************************************************************/
  404.          /* The + operator takes states:                                     */
  405.          /*                                                                  */
  406.          /* OP0->OP0P                                                        */
  407.          /* OP1->OP1P                                                        */
  408.          /* OP2->OP2P                                                        */
  409.          /*                                                                  */
  410.          /* All other entry states are invalid.                              */
  411.          /*                                                                  */
  412.          /********************************************************************/
  413.          if( (state & 0x0F) == 0 )
  414.          {
  415.           state |= OP0P;
  416.           goto NextSymbol;
  417.          }
  418.  
  419.          ParseError="Invalid use of \"+\"";
  420.          goto bummer;
  421.  
  422.        case '-':
  423.          /********************************************************************/
  424.          /* We may have a -> operator at this point. We are working          */
  425.          /* on an expression of the form "ptr->something". The "var"         */
  426.          /* part will have been parsed off and seg:off=&ptr. The             */
  427.          /* following code will resolve the "ptr" part.                      */
  428.          /*                                                                  */
  429.          /* This is only valid from the OP2 state.                           */
  430.          /*                                                                  */
  431.          /********************************************************************/
  432.          if( (state == OP2) &&
  433.              (*cp == '>')
  434.            )
  435.          {
  436.           TempExprTid = ExprTid;                                        /*219*/
  437.           /*******************************************************************/
  438.           /* save the ExprTid in a temp var TempExprTid and pass TempExpr 219*/
  439.           /* Tid to QderefType to dereference the type no. This is being  219*/
  440.           /* done since exprtid is being used in DerefPointer to determine219*/
  441.           /* type of pointer.                                             219*/
  442.           /*******************************************************************/
  443.           if( !QderefType(ExprMid, (USHORT *)&TempExprTid) )            /*219*/
  444.           {
  445.            ParseError = "Invalid type for \"->\"";
  446.            goto bummer;
  447.           }
  448.  
  449.           symloc=DerefPointer( off,ExprMid );                    /*240*//*112*/
  450.           if( symloc == NULL )          /*                                205*/
  451.           {
  452.            if( ThisProcessing == FALSE )
  453.            {
  454.             ParseError = "Invalid pointer for \"->\"";
  455.             goto bummer;
  456.            }
  457.            else
  458.            {
  459.             context = 0x20;
  460.             cp += 1;
  461.             goto startallover;
  462.            }
  463.           }
  464.  
  465.           ExprTid = TempExprTid;        /* refresh exprtid to correct val 219*/
  466.  
  467. /*        seg = SelOf(symloc);     */   /* selector of deref'd pointer.      */
  468.           off = OffOf(symloc);          /* offset of deref'd pointer.        */
  469.           cp += 1;                      /* bump one for ">".                 */
  470.           state = OP3;                  /* move to OP3 state.                */
  471.           goto NextSymbol;              /* now go get the next token.        */
  472.          }                              /*                                   */
  473.  
  474.          /********************************************************************/
  475.          /* The - operator takes states:                                     */
  476.          /*                                                                  */
  477.          /* OP0->OP0M                                                        */
  478.          /* OP1->OP1M                                                        */
  479.          /* OP2->OP2M                                                        */
  480.          /*                                                                  */
  481.          /* All other entry states are invalid.                              */
  482.          /*                                                                  */
  483.          /********************************************************************/
  484.          if( (state & 0x0F) == 0 )
  485.          {
  486.           state |= OP0M;
  487.           goto NextSymbol;
  488.          }
  489.  
  490.          ParseError = "Invalid use of \"-\"";
  491.          goto bummer;
  492.  
  493.        case '*':
  494.          /********************************************************************/
  495.          /* The * treated as "contents of" is valid in the OP0 state.        */
  496.          /*                                                                  */
  497.          /********************************************************************/
  498.          if( state == OP0 &&
  499.              !addrof
  500.            )
  501.           {
  502.            deref += 1;
  503.            goto NextSymbol;
  504.           }
  505.  
  506.          /********************************************************************/
  507.          /* The * operator as times takes states                             */
  508.          /*                                                                  */
  509.          /* OP0->OP0T                                                        */
  510.          /* OP1->OP1T                                                        */
  511.          /* OP2->OP2T                                                        */
  512.          /*                                                                  */
  513.          /* All other entry states are invalid.                              */
  514.          /*                                                                  */
  515.          /********************************************************************/
  516.  
  517.          if( (state & 0x0F) == 0 )
  518.          {
  519.           state |= OP0T;
  520.           goto NextSymbol;
  521.          }
  522.  
  523.          ParseError = "Invalid use of \"*\"";
  524.          goto bummer;
  525.  
  526.  
  527.        case '&':
  528.          /********************************************************************/
  529.          /* The & operator will set the addrof flag in the OP0 state if it   */
  530.          /* has not already been set, or deref has not been set by a previous*/
  531.          /* "*" interpreted as "contents of."                                */
  532.          /*                                                                  */
  533.          /********************************************************************/
  534.          if( state == OP0 &&
  535.              !(addrof|deref)
  536.            )
  537.          {
  538.           addrof = 1;
  539.           goto NextSymbol;
  540.          }
  541.  
  542.          ParseError = "Invalid use of \"&\"";
  543.          goto bummer;
  544.  
  545.        case ':':
  546.          /********************************************************************/
  547.          /* At this point, we are working on an expression of the form       */
  548.          /* selector:offset.  We get here after parsing off a selector value */
  549.          /* in the OP0 state.  By default, expressions of this form are      */
  550.          /* considered hex base.  If the operand before the colon was parsed */
  551.          /* as decimal, then we will convert to hex.                         */
  552.          /*                                                                  */
  553.          /********************************************************************/
  554.          if( state == OP1 )
  555.          {
  556.           state = OP1C;
  557.           ExprTid = 0;                 /* reset the expression type.      243*/
  558.           seg = off;
  559.           exprbase = 16;
  560.  
  561.           if( base == 10 )
  562.           {
  563.            for( c = ans = 0;
  564.                 seg;
  565.                 seg /= 10, c += 4
  566.               )
  567.             ans |= ((seg % 10) << c);
  568.            seg = ans;
  569.           }
  570.           goto NextSymbol;
  571.          }
  572.  
  573.          ParseError = "Invalid use of \":\"";
  574.          goto bummer;
  575.  
  576.        case '.':
  577.          /********************************************************************/
  578.          /* The "." operator takes us to the OP3 state. The OP3 state        */
  579.          /* handles expressions of the form:                                 */
  580.          /*                                                                  */
  581.          /*   ptr->var                                                       */
  582.          /*   struct.member                                                  */
  583.          /*                                                                  */
  584.          /********************************************************************/
  585.          if( state == OP2
  586.            )
  587.          {
  588.           state = OP3;
  589.           goto NextSymbol;
  590.          }
  591.  
  592.          ParseError = "Invalid use of \".\"";
  593.          goto bummer;
  594.  
  595.        case '[':
  596.          /********************************************************************/
  597.          /* The "[" operator takes us to the OP4L state.  The OP4L state     */
  598.          /* tells us that we are parsing the index of an array.              */
  599.          /*                                                                  */
  600.          /********************************************************************/
  601.          if( state == OP2 )
  602.          {
  603.           state = OP4L;
  604.           goto NextSymbol;
  605.          }
  606.  
  607.          ParseError = "Invalid use of \"[\"";
  608.          goto bummer;
  609.  
  610.        case ']':
  611.          /********************************************************************/
  612.          /* The "]" operator takes us to the OP2 state.  You can get to the  */
  613.          /* OP4R state only from the OP4L state.                             */
  614.          /*                                                                  */
  615.          /********************************************************************/
  616.          if( state == OP4R )
  617.          {
  618.           state = OP2;
  619.           goto NextSymbol;
  620.          }
  621.  
  622.          ParseError = "Invalid use of \"]\"";
  623.          goto bummer;
  624.       }
  625.       break;                            /* end of switch on operator.        */
  626.  
  627.     case 2:
  628.  
  629.       /***********************************************************************/
  630.       /* The identifier that we parsed off may be a variable or a reg     221*/
  631.       /* name. There are NREGS16 registers with indices in the range      221*/
  632.       /* 0-NREGS16-1. We first aassume SymRegIndex out of range.          221*/
  633.       /***********************************************************************/
  634.       SymRegIndex = NREGS16;
  635.  
  636.       /***********************************************************************/
  637.       /* This is the case of a possible register. 2 character symbol         */
  638.       /* names will not have a valid register index and will fall thru.      */
  639.       /***********************************************************************/
  640.       SymRegIndex = windex(RegNames16, NREGS16, *(twoc *)sym);
  641.       IsSymRegName = (SymRegIndex < NREGS16) ? TRUE : FALSE;
  642.                                         /* set flag to know the sym is reg221*/
  643.       break;
  644.  
  645.     case 3:
  646.  
  647.       /***********************************************************************/
  648.       /* The identifier that we parsed off may be a variable or a reg     221*/
  649.       /* name. There are NREGS32 registers with indices in the range      221*/
  650.       /* 0-NREGS32-1. We first aassume SymRegIndex out of range.          221*/
  651.       /*                                                                     */
  652.       /* Copy the register name from sym into a temp array with a blank   221*/
  653.       /* character added as a pading.                                     221*/
  654.       /***********************************************************************/
  655.       SymRegIndex = NREGS32;                                            /*221*/
  656.       memcpy(Regname,sym,3);                                            /*221*/
  657.       Regname[3]  = ' ';                                                /*221*/
  658.  
  659.       /***********************************************************************/
  660.       /* This is the case of a possible register. 2 character symbol         */
  661.       /* names will not have a valid register index and will fall thru.      */
  662.       /***********************************************************************/
  663.       SymRegIndex = lindex(RegNames32, NREGS32, *(fourc *)Regname);
  664.       IsSymRegName = (SymRegIndex < NREGS32) ? TRUE : FALSE;
  665.                                         /* set flag to know the sym is reg221*/
  666.       break;
  667.   }                                     /* end of switch on symlen           */
  668.  
  669. /*****************************************************************************/
  670. /* At this point, we may have an expression of the form ABxx:offset. The     */
  671. /* "ABxx" would have been parsed as a symbol name. It may also be a register */
  672. /* name. In this case, we will treat the symbol "ABxx" as a hex number, back */
  673. /* up and reparse i.e., we will start all over.                              */
  674. /*                                                                           */
  675. /*****************************************************************************/
  676.   if( (state == OP1C || *cp == ':') &&  /*                                   */
  677.        !IsSymRegName                    /*                                   */
  678.     )                                   /*                                   */
  679.   {                                     /*                                   */
  680.    c = '0';                             /* force a leading zero              */
  681.    cp = sym;                            /* backup to start of symbol         */
  682.    goto ParseNumber;                    /*                                   */
  683.   }                                     /* parse as a number                 */
  684.                                         /*                                   */
  685. /*****************************************************************************/
  686. /* At this time if we are in OP4* state it indicates we have a expression 513*/
  687. /* of type ....[xxx]. We then call ParseArrayIndex with the pointer to    513*/
  688. /* the variable name which is index. This function returns the value of   513*/
  689. /* the index. If it is not successful report error and return.            513*/
  690. /*****************************************************************************/
  691.   if (state & OP4)                                                      /*513*/
  692.   {                                                                     /*513*/
  693.     uint  IndexValue;                                                   /*513*/
  694.  
  695.     buffer[ symlen+2 ] = 0;               /* changed 1 to a 2.           813*/
  696.     *(USHORT*)buffer = symlen;            /*                             813*/
  697.     memcpy( buffer+2 ,sym, symlen);       /*                             813*/
  698.     if (ParseArrayIndex(buffer+2, mid, progline, progsfi, &IndexValue))
  699.     {                                                                   /*513*/
  700.       ans = IndexValue;                                                 /*513*/
  701.       goto GotOperand;                                                  /*513*/
  702.     }                                                                   /*513*/
  703.     else                                                                /*513*/
  704.     {                                                                   /*513*/
  705.       ParseError = BadExprMsg;                                          /*513*/
  706.       goto bummer;                                                      /*513*/
  707.     }                                                                   /*513*/
  708.   }                                                                     /*513*/
  709.  
  710.   if(context == 2)
  711.   {
  712.    ParseError = BadExprMsg;
  713.    goto bummer;
  714.   }
  715.  
  716. /*****************************************************************************/
  717. /* At this time, we have a token that is a potential symbol variable.        */
  718. /*                                                                           */
  719. /*****************************************************************************/
  720.   buffer[ symlen+2 ] = 0;               /* changed 1 to a 2.              813*/
  721.   *(USHORT*)buffer = symlen;            /*                                813*/
  722.   memcpy( buffer+2 ,sym, symlen);       /*                                813*/
  723.  
  724. /*****************************************************************************/
  725. /* We now look for the symbol in the symbolic info. First, as a local        */
  726. /* variable, and then as a static variable. We move to the OP2 state from    */
  727. /* this state.                                                               */
  728. /*                                                                           */
  729. /*****************************************************************************/
  730.   if( (state == OP0) && ( mid != 0 ) )  /* add mid != 0 check.               */
  731.   {                                     /*                                   */
  732.    if( !NoLocalNames )                  /* if local names are ok, then       */
  733.    {                                    /*                                   */
  734.     BOOL this;
  735.  
  736.     this   = FALSE;
  737.     symloc = findlvar(mid, buffer, progline, progsfi, &this);
  738.     if( this == TRUE )
  739.     {
  740.      ThisProcessing = TRUE;
  741.      cppsym         = Talloc( strlen(buffer+2) + 3 );
  742.      cppsym[0]      = '-' ;
  743.      cppsym[1]      = '>' ;
  744.  
  745.      strcpy( cppsym + 2, buffer + 2 );
  746.  
  747.      cp      = cppsym;
  748.      off     = symloc;
  749.      ExprLno = progline;
  750.      ExprMid = mid;
  751.      state   = OP2;
  752.      goto NextSymbol;
  753.     }
  754.  
  755.     if( symloc != NULL  )               /*  if we found a local symbol, then */
  756.      ExprLno = progline;                /*  establish the source line context*/
  757.  /* these lines ARE needed! see caseg.c  211 */
  758.     else                                /*                                   */
  759.      symloc = findsvar(mid, buffer);    /*  else look for a static symbol.   */
  760.                                         /*                                   */
  761.     if( symloc != NULL )                /*  if we found a symbol, then    110*/
  762.     {                                   /*                                   */
  763. /*   seg = SelOf(symloc);   */          /*  establish its selector and    112*/
  764.      off = symloc;                      /*  offset location.              112*/
  765.      ExprMid = mid;                     /*  establish its mid.               */
  766.      state = OP2;                       /*  move to OP2 state.               */
  767.      ExprLno = progline;                /*  establish the srcline context 513*/
  768.      goto NextSymbol;                   /*  go get the next token.           */
  769.     }                                   /*                                   */
  770.    }                                    /*                                   */
  771.                                         /*                                   */
  772. /*****************************************************************************/
  773. /* We were not successful in our search for the symbol in local or static    */
  774. /* data. So, we will look in the public area.                                */
  775. /*                                                                           */
  776. /*****************************************************************************/
  777.    pdf=FindExeOrDllWithAddr(GetExecAddr());                             /*901*/
  778.  
  779.    symloc= DBPub(buffer+2,pdf);                                         /*901*/
  780.    if( (symloc == NULL)  && IfUscores )
  781.    {
  782.     buffer[1] = '_';
  783.     symloc = DBPub(buffer+1,pdf);                                       /*901*/
  784.    }                                    /*                                   */
  785.                                         /*                                   */
  786.    if( symloc != NULL )                 /* if we finally found the symbol,110*/
  787.    {                                    /* then establish                    */
  788. /*  seg = SelOf(symloc);    */          /* the selector of its location,     */
  789.     off = symloc;                       /* the offset of its location,       */
  790.     ExprMid = DataMid;                  /* the expression module id, and     */
  791.     ExprTid = DataTid;                  /* the expression type id.           */
  792.     state = OP2;                        /* go to the 2 operand state.        */
  793.     ExprLno = progline;                 /*  establish the srcline context 513*/
  794.     goto NextSymbol;                    /* go get the next token.            */
  795.    }                                    /*                                   */
  796.   }                                     /* end of find the symbol.           */
  797.  
  798. /*****************************************************************************/
  799. /* At this point, we have a pointer to the symbol location, symloc. We also  */
  800. /* have an ExprMid and an ExprTid. If we are in the OP3 state, we have       */
  801. /* 2 operands and a "." or a "->". In this case, we need to adjust off for   */
  802. /* the location of the field within the structure. We leave in state OP2.    */
  803. /*                                                                           */
  804. /*****************************************************************************/
  805.   if( state == OP3 )
  806.   {
  807.    if( QstructField(ExprMid, buffer, &fldoff, &ExprTid) )
  808.    {
  809.     off += fldoff;
  810.     state = OP2;
  811.     goto NextSymbol;
  812.    }
  813. /*****************************************************************************/
  814. /* At this point, we may have a typedef record for a PL/X variable.          */
  815. /* A call to findlvar() will establish ExprTid for the PL/X expression of    */
  816. /* the form ptr->sbase, where sbase is a based variable.                     */
  817. /*****************************************************************************/
  818.    {                                    /* open {}.                          */
  819.     uint   typeno;                      /* type number.                      */
  820.     Trec  *tp;                          /* -> base rec for parent dfile no   */
  821.     SSRec *p;                           /*                                809*/
  822.     if((p = Qsymbol(mid, progline, progsfi, buffer)) &&
  823.        (p->RecType == SSUSERDEF )       /*                            809 112*/
  824.       )                                 /*                                   */
  825.      {                                  /*                                   */
  826.       typeno = ((SSUserDef *)p)->TypeIndex;/*define type of based var.809 112*/
  827.       tp = QbasetypeRec(mid, typeno);   /* get -> to the type record.        */
  828.  
  829.       if( tp && (tp->RecType == T_PTR ) )                               /*813*/
  830.        typeno = ((TD_POINTER *)tp)->TypeIndex;                          /*813*/
  831.  
  832.       ExprTid = typeno;                 /* establish the expression type.    */
  833.       ExprMid = mid;                    /* establish mid of typedef.         */
  834.       ExprScope = Qproc;                /* establish the expression scope.   */
  835.       state = OP2;                      /*                                   */
  836.       goto NextSymbol;                  /*                                   */
  837.      }                                  /*                                   */
  838.    }                                    /* close {}                          */
  839.   }                                     /* end of "if state = OP3"           */
  840. /*****************************************************************************/
  841. /* We get to here with a register name so we get a value from the DosDebug   */
  842. /* buffer.                                                                221*/
  843. /* The DosDebug structure looks some thing like this.                     221*/
  844. /*                                                                        221*/
  845. /* {                                                                      221*/
  846. /*  .....                                                                 221*/
  847. /*  ulong  EAX       |                                                    221*/
  848. /*  ulong  ECX       |                                                    221*/
  849. /*  ulong  EDX       |  for these registers the windex and lindex funcs   221*/
  850. /*  ulong  EBX       |  return a SymRegIndex in the range of 0 to 9       221*/
  851. /*  ulong  ESP       |                                                    221*/
  852. /*  ulong  EBP       |  if it falls here the processing is simple         221*/
  853. /*  ulong  ESI       |  take the address of AppPTB.EAX cast it to a uint  221*/
  854. /*  ulong  EDI       |  added the SymRegIndex to it and then take the     221*/
  855. /*  ulong  EFlags    |  contents of the new address.                      221*/
  856. /*  ulong  EIP       |                                                    221*/
  857. /*  ...                                                                   221*/
  858. /*  ushort CS        |                                                    221*/
  859. /*  ulong  Dslim     |  You fall here only to grab the addr of selectors  221*/
  860. /*  ulong  DsBase    |  In this cases the SymRegIndex will be greater     221*/
  861. /*  uchar  DsAcc     |  than 9.                                           221*/
  862. /*  uchar  DsAtr     |  In this cases take the address of AppPTB.CS as    221*/
  863. /*  ushort DS        |  base.                                             221*/
  864. /*  ulong  Eslim     |  Calculate the offset difference between the CS    221*/
  865. /*  ulong  EsBase    |  field and the selector field for which we have    221*/
  866. /*  uchar  EsAcc     |  determine the address of. Here in the below code  221*/
  867. /*  uchar  EsAtr     |  12 is a magic figure which is the size of offset  221*/
  868. /*  ushort ES        |  between each selector fields in DosDebug Buffer.  221*/
  869. /*                                                                        221*/
  870. /*************************************************************************221*/
  871.   if( IsSymRegName )                                                    /*221*/
  872.   {                                                                     /*221*/
  873.    if (state != OP1C)                   /* one operand and a ":"          243*/
  874.      ExprTid = VALUE_CONSTANT;          /* expression type is CONSTANT    243*/
  875.    if ( SymRegIndex < 10 )                                              /*221*/
  876.      ans = *( (uint *)&(AppPTB.EAX) + SymRegIndex );                    /*221*/
  877.    else                                                                 /*221*/
  878.    {                                                                    /*221*/
  879.                                                                         /*221*/
  880.      temp = (uint) &(AppPTB.CS);                                        /*221*/
  881.      temp += ((SymRegIndex - 10) * 12 );                                /*221*/
  882.      ans = *( (ushort *)temp );                                         /*221*/
  883.    }                                                                    /*221*/
  884.    IsSymRegName = 0;                    /* reset the register name flag   312*/
  885.    goto GotOperand;
  886.   }
  887. /*****************************************************************************/
  888. /* We are done.                                                              */
  889. /*****************************************************************************/
  890.  
  891.   goto fini;
  892.  
  893.  GotOperand:
  894.  
  895. /*****************************************************************************/
  896. /* At this point, we are going to go through a state transition.             */
  897. /*                                                                           */
  898. /*****************************************************************************/
  899.   switch( state )                       /*                                   */
  900.   {                                     /*                                   */
  901.    case OP0:                            /* initial state.                    */
  902.        off = ans;                       /*                                   */
  903.        CmplxBkptVal = off;              /*                                   */
  904.        state = OP1;                     /*                                   */
  905.        break;                           /*                                   */
  906.                                         /*                                   */
  907.    case OP0M:                           /* an initial negative number.       */
  908.        off = -(int)ans;                 /*                                521*/
  909.        CmplxBkptVal = (long)((int)off); /*                                   */
  910.        state = OP1;                     /*                                   */
  911.        break;                           /*                                   */
  912.                                         /*                                   */
  913.    case OP1C:                           /* one operand and a ":"             */
  914.        off = ans;                       /*                                   */
  915.        state = OP2;                     /*                                   */
  916.        break;                           /*                                   */
  917.                                         /*                                   */
  918.    case OP1P:                           /* one operand and a "+".            */
  919.    case OP2P:                           /* two operands and a "+".           */
  920.        off += ans;                      /*                                   */
  921.        goto ResetOp;                    /*                                   */
  922.                                         /*                                   */
  923.    case OP1M:                           /* one operand and a "-".            */
  924.    case OP2M:                           /* two operands and a "-".           */
  925.        off -= ans;                      /*                                   */
  926.        goto ResetOp;                    /*                                   */
  927.                                         /*                                   */
  928.    case OP1T:                           /* one operand and a "-".            */
  929.    case OP2T:                           /* two operands and a "-".           */
  930.        off *= ans;                      /*                                   */
  931.                                         /*                                   */
  932.    ResetOp:                             /*                                   */
  933.        /**********************************************************************/
  934.        /* Reset +,-, and * states to OP0,OP1, or OP2 states.                 */
  935.        /*                                                                    */
  936.        /**********************************************************************/
  937.        state &= 0xF0;                   /*                                   */
  938.        break;                           /*                                   */
  939.                                         /*                                   */
  940.    case OP4L:                           /* two operands and a "[".           */
  941.        if( QarrayItem(ExprMid,          /*                                   */
  942.                       ans,              /*                                   */
  943.                       &off,             /*                                   */
  944.                       &ExprTid)         /*                                   */
  945.          )                              /*                                   */
  946.        {                                /*                                   */
  947.            state = OP4R;                /*                                   */
  948.            break;                       /*                                   */
  949.        }                                /*                                   */
  950.                                         /*                                   */
  951.        ParseError = "Invalid type for \"[\"";
  952.        goto bummer;                     /*                                   */
  953.                                         /*                                   */
  954.    default:                             /* invalid states.                   */
  955.        ParseError = BadExprMsg;         /*                                   */
  956.        goto bummer;                     /*                                   */
  957.   }                                     /*                                   */
  958.                                         /*                                   */
  959.                                         /*                                   */
  960.   NextSymbol:;                          /*                                   */
  961.  }                                      /* end of token parsing loop.        */
  962. /*****************************************************************************/
  963. /* All tokens are parsed. We now establish the base symloc for "*" references*/
  964. /*****************************************************************************/
  965.                                         /*                                   */
  966.  fini:                                  /*                                   */
  967.  if( deref )                            /* now resolve "contents of"         */
  968.  {                                      /*                                   */
  969.   if( state != OP2 )                    /* must be in OP2 state.             */
  970.   {                                     /*                                   */
  971.    ParseError="Invalid operand for \"*\"";/*                                 */
  972.    goto bummer;                         /*                                   */
  973.   }                                     /*                                   */
  974.                                         /*                                   */
  975.   while( deref-- )                      /* loop while pointer is not deref'd.*/
  976.   {                                     /*                                   */
  977.    /**************************************************************************/
  978.    /* dereference the pointer and convert to flat if need be.             112*/
  979.    /**************************************************************************/
  980.    symloc = DerefPointer( off,ExprMid );                                /*240*/
  981.    if( symloc != NULL)                  /*                                205*/
  982.    {                                    /*                                   */
  983. /*  seg = SelOf(symloc);   */           /*                                112*/
  984.     off = symloc;                       /*                                112*/
  985.     if( !QderefType(ExprMid, (USHORT*)&ExprTid) )/*                          */
  986.         ExprTid = 0;                    /*                                   */
  987.    }                                    /*                                   */
  988.    else                                 /*                                   */
  989.    {                                    /*                                   */
  990.     ParseError = "Invalid pointer for \"*\"";/*                              */
  991.     goto bummer;                        /*                                   */
  992.    }                                    /*                                   */
  993.   }                                     /*                                   */
  994.  }                                      /*                                   */
  995. /*****************************************************************************/
  996. /* We can return from the OP1 state or the OP2 state.                        */
  997. /*                                                                           */
  998. /*****************************************************************************/
  999.                                         /*                                   */
  1000.  switch( state )                        /*                                   */
  1001.  {                                      /*                                   */
  1002.   case OP2:                             /*                                   */
  1003.     if( addrof )                        /* if "&" flag is set, then          */
  1004.     {                                   /*                                   */
  1005.      ExprTid = ADDRESS_CONSTANT;        /* expression type is CONSTANT    243*/
  1006.      IsAddrExpr = FALSE;                /*                                243*/
  1007.     }                                   /*                                   */
  1008.   NormalReturn:                         /*                                   */
  1009.     if( TestBit(seg,02) )               /* if its a GDT then it must be   221*/
  1010.       ExprAddr = Data_SelOff2Flat((ushort)seg,                              /*827*/
  1011.                  (ushort)off);          /* simple flat address else       607*/
  1012.     else                                /* convert into flat addr.        221*/
  1013.       ExprAddr = off;                   /*                                221*/
  1014.     return( sym );                      /* return -> to vestigial expression.*/
  1015.                                         /*                                   */
  1016.   case OP1:                             /*                                   */
  1017.     if( !addrof )                       /*                                   */
  1018.     {                                   /* its a flat address the segment 501*/
  1019.       seg = 0;                          /* does not make any sense.       501*/
  1020.       goto NormalReturn;                /*                                501*/
  1021.     }                                   /*                                501*/
  1022.  }                                      /*                                   */
  1023.  
  1024.  if(*sym && (ThisProcessing == TRUE) )
  1025.  {
  1026.   /***************************************************************************/
  1027.   /* We will come here if we've tried to find a class variable and           */
  1028.   /* failed. Go back and try again, this time only looking for globals.      */
  1029.   /***************************************************************************/
  1030.   cp             = sym;
  1031.   context        = 0x20;
  1032.   ThisProcessing = FALSE;
  1033.   goto startallover;
  1034.  }
  1035. /*****************************************************************************/
  1036. /* At this point, if there is a vestigial expression, then something has gone*/
  1037. /* awry. If there isn't a vestigial expression, just being here is an error. */
  1038. /*****************************************************************************/
  1039.  if( *sym )                             /* did we finish parsing?            */
  1040.  {                                      /* nope, we need to build a message. */
  1041.   uint n;                               /* was register.                  112*/
  1042.   static uchar emsg[] =                 /* This is the base message. We'll   */
  1043.                "\"%.*s\" is incorrect"; /* add to it.                        */
  1044.                                         /*                                   */
  1045.   n=strlen(sym);                        /* n = length of expression vestige. */
  1046.   if( (n) > (sizeof(ErrMsgBuf) -        /* if n is too big to fit in the     */
  1047.              sizeof(emsg)               /* front of the buffer, then chop it */
  1048.             )                           /* off.                              */
  1049.     )                                   /*                                   */
  1050.   {                                     /*                                   */
  1051.    n=(sizeof(ErrMsgBuf) - sizeof(emsg));/*                                   */
  1052.   }                                     /*                                   */
  1053.                                         /*                                   */
  1054.   ParseError=ErrMsgBuf;                 /*                                   */
  1055.   sprintf(ParseError,emsg,n,sym);       /* format the message.            521*/
  1056.  }                                      /*                                   */
  1057.  else                                   /*                                   */
  1058.   ParseError = BadExprMsg;              /* just a bad expression.            */
  1059.                                         /*                                   */
  1060. bummer:                                 /*                                   */
  1061.  return( NULL );                        /*                                   */
  1062. }
  1063.  
  1064.  uint
  1065. GetAbsAddr(uint addr,uint sfx,uint *absptr)
  1066. {
  1067.  
  1068.     if( TestBit(addr,STACKADDRBIT) )                                    /*205*/
  1069.     {                                                                   /*205*/
  1070.       addr = StackBPRelToAddr( addr , sfx );                            /*205*/
  1071.       if( addr == NULL )                                                /*205*/
  1072.             return( FALSE );                                            /*205*/
  1073.     }else if( (addr >> REGADDCHECKPOS) == REGISTERTYPEADDR ){           /*205*/
  1074.         return( FALSE );
  1075.     }
  1076.     *absptr = addr;
  1077.     return( TRUE );
  1078. }
  1079.  
  1080. /*****************************************************************************/
  1081. /* ParseArrayIndex()                                                      513*/
  1082. /*                                                                           */
  1083. /* Description:                                                              */
  1084. /*                                                                           */
  1085. /*  Gets the value of a index variable passed.                               */
  1086. /*                                                                           */
  1087. /* Parameters:                                                               */
  1088. /*                                                                           */
  1089. /*   cp         input - pointer to the index variable name.                  */
  1090. /*   optmid     input - module id.                                           */
  1091. /*   optline    input - line no.                                             */
  1092. /*   IndexValue input - -> index value.                                      */
  1093. /*                                                                           */
  1094. /* Return:                                                                   */
  1095. /*                                                                           */
  1096. /*   TRUE     able to find the index variable value.                         */
  1097. /*   FALSE    not able to find index variable value.                         */
  1098. /*                                                                           */
  1099. /* Assumptions:                                                              */
  1100. /*                                                                           */
  1101. /*   none.                                                                   */
  1102. /*                                                                           */
  1103. /*****************************************************************************/
  1104. uint ParseArrayIndex(uchar *cp,
  1105.                      uint optmid,
  1106.                      uint optline,
  1107.                      int  optsfi,
  1108.                      uint *IndexValue)
  1109. {
  1110.     uchar  *xp;
  1111.     uint    sfx;
  1112.     uchar  *dp;
  1113.     uint    read;
  1114.     uint    n;
  1115.     uint    Save_ExprAddr;
  1116.     SCOPE   Save_ExprScope;
  1117.     uint    Save_ExprMid;
  1118.     uint    Save_ExprLno;
  1119.     uint    Save_ExprTid;
  1120.     uchar   Save_IsAddrExpr;
  1121.     uchar  *Save_ParseError;
  1122.     uint    Return_Value = FALSE;
  1123.  
  1124.     /*************************************************************************/
  1125.     /* save the global values set by parseexpr since they may be lost by  513*/
  1126.     /* the next call to parseexpr.                                        513*/
  1127.     /*************************************************************************/
  1128.     Save_ExprAddr   = ExprAddr;
  1129.     Save_ExprScope  = ExprScope;
  1130.     Save_ExprMid    = ExprMid;
  1131.     Save_ExprLno    = ExprLno;
  1132.     Save_ExprTid    = ExprTid;
  1133.     Save_IsAddrExpr = IsAddrExpr;
  1134.     Save_ParseError = ParseError;
  1135.  
  1136.     /*************************************************************************/
  1137.     /* call parseexpr to get the expression address and other details     513*/
  1138.     /*************************************************************************/
  1139.     xp = ParseExpr(cp, 0x10, optmid, optline, optsfi);
  1140.     if( !xp || *xp )
  1141.        goto Error;
  1142.  
  1143.     /*************************************************************************/
  1144.     /* get the stack frame index and check if its not active or scope is  513*/
  1145.     /* not correct return failure.                                        513*/
  1146.     /*************************************************************************/
  1147.     sfx=StackFrameIndex(ExprScope);
  1148.     if( ExprScope && !sfx )
  1149.        goto Error;
  1150.  
  1151.     /*************************************************************************/
  1152.     /* find the type no of the index variable. If it is not one of the    513*/
  1153.     /* following return a error. (int,uint,char,uchar,long,ulong)         513*/
  1154.     /*************************************************************************/
  1155.     n = windex(dtab, NTYPES, ExprTid);
  1156.     if (n > (NTYPES-3))
  1157.        goto Error;
  1158.  
  1159.     /*************************************************************************/
  1160.     /* - read the contents of the index variable.                         513*/
  1161.     /* - depending on the type cast the index value to int.               513*/
  1162.     /*************************************************************************/
  1163.     if( !(dp = GetAppData(ExprAddr,QtypeSize(DONTCARE,ExprTid), &read, sfx)) )
  1164.        goto Error;
  1165.  
  1166.     switch( ExprTid )
  1167.     {
  1168.         case TYPE_CHAR:
  1169.           *IndexValue = *(char*)dp;
  1170.           break;
  1171.  
  1172.         case TYPE_UCHAR:
  1173.           *IndexValue = *(uchar*)dp;
  1174.           break;
  1175.  
  1176.         case TYPE_SHORT:
  1177.           *IndexValue = *(short*)dp;
  1178.           break;
  1179.  
  1180.         case TYPE_USHORT:
  1181.           *IndexValue = *(ushort*)dp;
  1182.           break;
  1183.  
  1184.         case TYPE_LONG:
  1185.           *IndexValue = *(long*)dp;
  1186.           break;
  1187.  
  1188.         case TYPE_ULONG:
  1189.           *IndexValue = *(ulong*)dp;
  1190.           break;
  1191.  
  1192.         default:
  1193.           goto Error;
  1194.     }
  1195.  
  1196.     Return_Value = TRUE;
  1197.  
  1198.     /*************************************************************************/
  1199.     /* restore the saved variables and return.                            513*/
  1200.     /*************************************************************************/
  1201.     Error:
  1202.       ExprAddr   = Save_ExprAddr;
  1203.       ExprScope  = Save_ExprScope;
  1204.       ExprMid    = Save_ExprMid;
  1205.       ExprLno    = Save_ExprLno;
  1206.       ExprTid    = Save_ExprTid;
  1207.       IsAddrExpr = Save_IsAddrExpr;
  1208.       ParseError = Save_ParseError;
  1209.       return(Return_Value);
  1210. }
  1211.