Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* asmpars.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Verwaltung von Symbolen und das ganze Drumherum...                        */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <assert.h>
  15.  
  16. #include "be_le.h"
  17. #include "bpemu.h"
  18. #include "nls.h"
  19. #include "nlmessages.h"
  20. #include "as.rsc"
  21. #include "strutil.h"
  22. #include "strcomp.h"
  23.  
  24. #include "asmdef.h"
  25. #include "asmsub.h"
  26. #include "errmsg.h"
  27. #include "asmfnums.h"
  28. #include "asmrelocs.h"
  29. #include "asmstructs.h"
  30. #include "chunks.h"
  31. #include "trees.h"
  32. #include "operator.h"
  33. #include "function.h"
  34. #include "intformat.h"
  35. #include "ieeefloat.h"
  36. #include "chartrans.h"
  37. #include "dynstr_nls.h"
  38.  
  39. #include "asmpars.h"
  40.  
  41. #define LEAVE  goto func_exit
  42. #define LEAVE2 goto func_exit2
  43.  
  44. /* Mask, Min & Max are computed at initialization */
  45.  
  46. tIntTypeDef IntTypeDefs[IntTypeCnt] =
  47. {
  48.   { 0x0000, 0, 0, 0 }, /* UInt0 */
  49.   { 0x0001, 0, 0, 0 }, /* UInt1 */
  50.   { 0x0002, 0, 0, 0 }, /* UInt2 */
  51.   { 0x0003, 0, 0, 0 }, /* UInt3 */
  52.   { 0x8004, 0, 0, 0 }, /* SInt4 */
  53.   { 0x0004, 0, 0, 0 }, /* UInt4 */
  54.   { 0xc004, 0, 0, 0 }, /* Int4 */
  55.   { 0x8005, 0, 0, 0 }, /* SInt5 */
  56.   { 0x0005, 0, 0, 0 }, /* UInt5 */
  57.   { 0xc005, 0, 0, 0 }, /* Int5 */
  58.   { 0x8006, 0, 0, 0 }, /* SInt6 */
  59.   { 0x0006, 0, 0, 0 }, /* UInt6 */
  60.   { 0x8007, 0, 0, 0 }, /* SInt7 */
  61.   { 0x0007, 0, 0, 0 }, /* UInt7 */
  62.   { 0x8008, 0, 0, 0 }, /* SInt8 */
  63.   { 0x0008, 0, 0, 0 }, /* UInt8 */
  64.   { 0xc008, 0, 0, 0 }, /* Int8 */
  65.   { 0x8009, 0, 0, 0 }, /* SInt9 */
  66.   { 0x0009, 0, 0, 0 }, /* UInt9 */
  67.   { 0x000a, 0, 0, 0 }, /* UInt10 */
  68.   { 0xc00a, 0, 0, 0 }, /* Int10 */
  69.   { 0x000b, 0, 0, 0 }, /* UInt11 */
  70.   { 0x000c, 0, 0, 0 }, /* UInt12 */
  71.   { 0xc00c, 0, 0, 0 }, /* Int12 */
  72.   { 0x000d, 0, 0, 0 }, /* UInt13 */
  73.   { 0x000e, 0, 0, 0 }, /* UInt14 */
  74.   { 0xc00e, 0, 0, 0 }, /* Int14 */
  75.   { 0x800f, 0, 0, 0 }, /* SInt15 */
  76.   { 0x000f, 0, 0, 0 }, /* UInt15 */
  77.   { 0xc00f, 0, 0, 0 }, /* Int15 */
  78.   { 0x8010, 0, 0, 0 }, /* SInt16 */
  79.   { 0x0010, 0, 0, 0 }, /* UInt16 */
  80.   { 0xc010, 0, 0, 0 }, /* Int16 */
  81.   { 0x0011, 0, 0, 0 }, /* UInt17 */
  82.   { 0x0012, 0, 0, 0 }, /* UInt18 */
  83.   { 0x0013, 0, 0, 0 }, /* UInt19 */
  84.   { 0x8014, 0, 0, 0 }, /* SInt20 */
  85.   { 0x0014, 0, 0, 0 }, /* UInt20 */
  86.   { 0xc014, 0, 0, 0 }, /* Int20 */
  87.   { 0x0015, 0, 0, 0 }, /* UInt21 */
  88.   { 0x0016, 0, 0, 0 }, /* UInt22 */
  89.   { 0x0017, 0, 0, 0 }, /* UInt23 */
  90.   { 0x8018, 0, 0, 0 }, /* SInt24 */
  91.   { 0x0018, 0, 0, 0 }, /* UInt24 */
  92.   { 0xc018, 0, 0, 0 }, /* Int24 */
  93.   { 0x801e, 0, 0, 0 }, /* SInt30 */
  94.   { 0x001e, 0, 0, 0 }, /* UInt30 */
  95.   { 0xc01e, 0, 0, 0 }, /* Int30 */
  96.   { 0x8020, 0, 0, 0 }, /* SInt32 */
  97.   { 0x0020, 0, 0, 0 }, /* UInt32 */
  98.   { 0xc020, 0, 0, 0 }, /* Int32 */
  99. #ifdef HAS64
  100.   { 0x8040, 0, 0, 0 }, /* SInt64 */
  101.   { 0x0040, 0, 0, 0 }, /* UInt64 */
  102.   { 0xc040, 0, 0, 0 }, /* Int64 */
  103. #endif
  104. };
  105.  
  106. typedef struct
  107. {
  108.   Boolean Back;
  109.   LongInt Counter;
  110. } TTmpSymLog;
  111.  
  112. LongInt MomLocHandle;          /* Merker, den lokale Symbole erhalten        */
  113. LongInt TmpSymCounter,         /* counters for local symbols                 */
  114.         FwdSymCounter,
  115.         BackSymCounter;
  116. char TmpSymCounterVal[10];     /* representation as string                   */
  117. TTmpSymLog TmpSymLog[LOCSYMSIGHT];
  118. LongInt TmpSymLogDepth;
  119.  
  120. LongInt LocHandleCnt;          /* mom. verwendeter lokaler Handle            */
  121.  
  122. typedef struct sSymbolEntry
  123. {
  124.   TTree Tree;
  125.   Boolean Defined, Used, Changeable, changed;
  126.   TempResult SymWert;
  127.   LargeInt unchanged_value;
  128.   PCrossRef RefList;
  129.   Byte FileNum;
  130.   LongInt LineNum;
  131. } TSymbolEntry, *PSymbolEntry;
  132.  
  133. typedef struct sSymbolStackEntry
  134. {
  135.   struct sSymbolStackEntry *Next;
  136.   TempResult Contents;
  137. } TSymbolStackEntry, *PSymbolStackEntry;
  138.  
  139. typedef struct sSymbolStack
  140. {
  141.   struct sSymbolStack *Next;
  142.   char *Name;
  143.   PSymbolStackEntry Contents;
  144. } TSymbolStack, *PSymbolStack;
  145.  
  146. typedef struct sDefSymbol
  147. {
  148.   struct sDefSymbol *Next;
  149.   char *SymName;
  150.   TempResult Wert;
  151. } TDefSymbol, *PDefSymbol;
  152.  
  153. typedef struct sCToken
  154. {
  155.   struct sCToken *Next;
  156.   char *Name;
  157.   LongInt Parent;
  158.   ChunkList Usage;
  159. } TCToken, *PCToken;
  160.  
  161. typedef struct sLocHeap
  162. {
  163.   struct sLocHeap *Next;
  164.   LongInt Cont;
  165. } TLocHeap, *PLocHandle;
  166.  
  167. typedef struct sRegDefList
  168. {
  169.   struct sRegDefList *Next;
  170.   LongInt Section;
  171.   char *Value;
  172.   Boolean Used;
  173. } TRegDefList, *PRegDefList;
  174.  
  175. typedef struct sRegDef
  176. {
  177.   struct sRegDef *Left, *Right;
  178.   char *Orig;
  179.   PRegDefList Defs, DoneDefs;
  180. } TRegDef, *PRegDef;
  181.  
  182. static PSymbolEntry FirstSymbol, FirstLocSymbol;
  183. static PDefSymbol FirstDefSymbol;
  184. /*static*/ PCToken FirstSection;
  185. static Boolean DoRefs,              /* Querverweise protokollieren */
  186.                RegistersDefined;
  187. static PLocHandle FirstLocHandle;
  188. static PSymbolStack FirstStack;
  189. static PCToken MomSection;
  190. static char *LastGlobSymbol;
  191. static PFunction FirstFunction;         /* Liste definierter Funktionen */
  192.  
  193. void InitPass_AsmPars(void)
  194. {
  195.   RadixBase = 10;
  196.   OutRadixBase = 16;
  197. }
  198.  
  199. void AsmParsInit(void)
  200. {
  201.   FirstSymbol = NULL;
  202.  
  203.   FirstLocSymbol = NULL; MomLocHandle = -1; SetMomSection(-1);
  204.   FirstSection = NULL;
  205.   FirstLocHandle = NULL;
  206.   FirstStack = NULL;
  207.   FirstFunction = NULL;
  208.   DoRefs = True;
  209.   InitPass_AsmPars();
  210.   RegistersDefined = False;
  211.   AddInitPassProc(InitPass_AsmPars);
  212. }
  213.  
  214. /*!------------------------------------------------------------------------
  215.  * \fn     range_not_checkable(IntType type)
  216.  * \brief  can integer type's range not be checked on host system?
  217.  * \param  type integer type
  218.  * \return true if range can NOT be checked
  219.  * ------------------------------------------------------------------------ */
  220.  
  221. static Boolean range_not_checkable(IntType type)
  222. {
  223. #ifndef HAS64
  224.   return (((int)type) >= ((int)SInt32));
  225. #else
  226.   return (((int)type) >= ((int)SInt64));
  227. #endif
  228. }
  229.  
  230. /*!------------------------------------------------------------------------
  231.  * \fn     RangeCheck(LargeInt Wert, IntType Typ)
  232.  * \brief  check whether value is within integer type's ranges
  233.  * \param  Wert value to check
  234.  * \param  Typ integer type giving range
  235.  * \return true if within range
  236.  * ------------------------------------------------------------------------ */
  237.  
  238. Boolean RangeCheck(LargeInt Wert, IntType Typ)
  239. {
  240.   return range_not_checkable(Typ) || ((Wert >= IntTypeDefs[(int)Typ].Min) && (Wert <= IntTypeDefs[(int)Typ].Max));
  241. }
  242.  
  243. /*!------------------------------------------------------------------------
  244.  * \fn     ChkRangeByType(LargeInt value, IntType type, const struct sStrComp *p_comp)
  245.  * \brief  check whether value is within integer type's ranges, and throw error if not
  246.  * \param  value value to check
  247.  * \param  type integer type giving range
  248.  * \param  p_comp corresponding source argument
  249.  * \return true if within range
  250.  * ------------------------------------------------------------------------ */
  251.  
  252. Boolean ChkRangeByType(LargeInt value, IntType type, const struct sStrComp *p_comp)
  253. {
  254.   return range_not_checkable(type) || ChkRangePos(value, IntTypeDefs[(int)type].Min, IntTypeDefs[(int)type].Max, p_comp);
  255. }
  256.  
  257. /*!------------------------------------------------------------------------
  258.  * \fn     ChkRangeWarnByType(LargeInt value, IntType type, const struct sStrComp *p_comp)
  259.  * \brief  check whether value is within integer type's ranges, and throw warning if not
  260.  * \param  value value to check
  261.  * \param  type integer type giving range
  262.  * \param  p_comp corresponding source argument
  263.  * \return true if within range
  264.  * ------------------------------------------------------------------------ */
  265.  
  266. Boolean ChkRangeWarnByType(LargeInt value, IntType type, const struct sStrComp *p_comp)
  267. {
  268.   return range_not_checkable(type) || ChkRangeWarnPos(value, IntTypeDefs[(int)type].Min, IntTypeDefs[(int)type].Max, p_comp);
  269. }
  270.  
  271. Boolean FloatRangeCheck(Double Wert, FloatType Typ)
  272. {
  273.   /* NaN/Infinity is representable in all formats */
  274.  
  275.   int numclass = as_fpclassify(Wert);
  276.   if ((numclass == AS_FP_NAN) || (numclass == AS_FP_INFINITE))
  277.     return True;
  278.  
  279.   switch (Typ)
  280.   {
  281.     case Float16:
  282.       return (fabs(Wert) <= 65504.0);
  283.     case Float32:
  284.       return (fabs(Wert) <= 3.4e38);
  285.     case Float64:
  286.       return (fabs(Wert) <= 1.7e308);
  287. /**     case FloatCo: return fabs(Wert) <= 9.22e18; */
  288.     case Float80:
  289.       return True;
  290.     case FloatDec:
  291.       return True;
  292.     default:
  293.       return False;
  294.   }
  295. /**   if (Typ == FloatDec) && (fabs(Wert) > 1e1000) WrError(ErrNum_BigDecFloat);**/
  296. }
  297.  
  298. Boolean SingleBit(LargeInt Inp, LargeInt *Erg)
  299. {
  300.   *Erg = 0;
  301.   do
  302.   {
  303.     if (!Odd(Inp))
  304.       (*Erg)++;
  305.     if (!Odd(Inp))
  306.       Inp = Inp >> 1;
  307.   }
  308.   while ((*Erg != LARGEBITS) && (!Odd(Inp)));
  309.   return (*Erg != LARGEBITS) && (Inp == 1);
  310. }      
  311.  
  312. IntType GetSmallestUIntType(LargeWord MaxValue)
  313. {
  314.   IntType Result;
  315.  
  316.   Result = (IntType) 0;
  317.   for (Result = (IntType) 0; Result < IntTypeCnt; Result++)
  318.   {
  319.     if (IntTypeDefs[Result].Min < 0)
  320.       continue;
  321.     if (IntTypeDefs[Result].Max >= (LargeInt)MaxValue)
  322.       return Result;
  323.   }
  324.   return UInt32;
  325. }
  326.  
  327. IntType GetUIntTypeByBits(unsigned Bits)
  328. {
  329.   IntType Result;
  330.   for (Result = (IntType) 0; Result < IntTypeCnt; Result++)
  331.   {
  332.     if (IntTypeDefs[Result].SignAndWidth & 0x8000)
  333.       continue;
  334.     if (Lo(IntTypeDefs[Result].SignAndWidth) == Bits)
  335.       return Result;
  336.   }
  337.   return UInt0;
  338. }
  339.  
  340. static Boolean ProcessBk(char **Start, char *Erg)
  341. {
  342.   LongInt System = 0, Acc = 0, Digit = 0;
  343.   char ch;
  344.   int cnt;
  345.   Boolean Finish;
  346.  
  347.   switch (as_toupper(**Start))
  348.   {
  349.     case '\'': case '\\': case '"':
  350.       *Erg = **Start;
  351.       (*Start)++;
  352.       return True;
  353.     case 'H':
  354.       *Erg = '\'';
  355.       (*Start)++;
  356.       return True;
  357.     case 'I':
  358.       *Erg = '"';
  359.       (*Start)++;
  360.     return True;
  361.     case 'B':
  362.       *Erg = Char_BS;
  363.       (*Start)++;
  364.       return True;
  365.     case 'A':
  366.       *Erg = Char_BEL;
  367.       (*Start)++;
  368.       return True;
  369.     case 'E':
  370.       *Erg = Char_ESC;
  371.       (*Start)++;
  372.        return True;
  373.     case 'T':
  374.       *Erg = Char_HT;
  375.       (*Start)++;
  376.        return True;
  377.     case 'N':
  378.       *Erg = Char_LF;
  379.       (*Start)++;
  380.       return True;
  381.     case 'R':
  382.       *Erg = Char_CR;
  383.       (*Start)++;
  384.       return True;
  385.     case 'X':
  386.       System = 16;
  387.       (*Start)++;
  388.       /* fall-through */
  389.     case '0': case '1': case '2': case '3': case '4':
  390.     case '5': case '6': case '7': case '8': case '9':
  391.       if (System == 0)
  392.         System = (**Start == '0') ? 8 : 10;
  393.       cnt = (System == 16) ? 1 : ((System == 10) ? 0 : -1);
  394.       do
  395.       {
  396.         ch = as_toupper(**Start);
  397.         Finish = False;
  398.         if ((ch >= '0') && (ch <= '9'))
  399.           Digit = ch - '0';
  400.         else if ((System == 16) && (ch >= 'A') && (ch <= 'F'))
  401.           Digit = (ch - 'A') + 10;
  402.         else
  403.           Finish = True;
  404.         if (!Finish)
  405.         {
  406.           (*Start)++;
  407.           cnt++;
  408.           if (Digit >= System)
  409.           {
  410.             WrError(ErrNum_OverRange);
  411.             return False;
  412.           }
  413.           Acc = (Acc * System) + Digit;
  414.         }
  415.       }
  416.       while ((!Finish) && (cnt < 3));
  417.       if (!ChkRange(Acc, 0, 255))
  418.         return False;
  419.       *Erg = Acc;
  420.       return True;
  421.     default:
  422.       WrError(ErrNum_InvEscSequence);
  423.       return False;
  424.   }
  425. }
  426.  
  427. /*!------------------------------------------------------------------------
  428.  * \fn     NonZString2Int(const struct as_nonz_dynstr *p_str, LargeInt *p_result)
  429.  * \brief  convert string to its "ASCII representation"
  430.  * \param  p_str string containing characters
  431.  * \param  p_result dest buffer
  432.  * \return 0 or error message
  433.  * ------------------------------------------------------------------------ */
  434.  
  435. tErrorNum NonZString2Int(const struct as_nonz_dynstr *p_str, LargeInt *p_result)
  436. {
  437.   if ((p_str->len > 0) && (p_str->len <= 4))
  438.   {
  439.     unsigned digit, shift;
  440.     const char *p_run = p_str->p_str;
  441.     size_t run_len = p_str->len;
  442.     int ret;
  443.  
  444.     *p_result = shift = 0;
  445.     while (!(ret = as_chartrans_xlate_next(CurrTransTable->p_table, &digit, &p_run, &run_len)))
  446.       if (multi_char_le)
  447.       {
  448.         *p_result |= ((LargeWord)digit) << shift;
  449.         shift += 8;
  450.       }
  451.       else
  452.         *p_result = (*p_result << 8) | (digit & 0xff);
  453.     /* ENOMEM -> regular end of string */
  454.     return (ret == ENOMEM) ? ErrNum_None : ErrNum_UnmappedChar;
  455.   }
  456.   return ErrNum_MultiCharInvLength;
  457. }
  458.  
  459. Boolean Int2NonZString(struct as_nonz_dynstr *p_str, LargeInt src)
  460. {
  461.   char *p_dest;
  462.   int ret;
  463.  
  464.   if (p_str->capacity < 32)
  465.     as_nonz_dynstr_realloc(p_str, 32);
  466.   p_str->len = 0;
  467.   p_dest = &p_str->p_str[multi_char_le ? 0 : p_str->capacity];
  468.   while (src && (p_str->len < p_str->capacity))
  469.   {
  470.     ret = as_chartrans_xlate_rev(CurrTransTable->p_table, src & 0xff);
  471.     if (ret >= 0)
  472.     {
  473.       *(multi_char_le ? p_dest++ : --p_dest) = ret;
  474.       p_str->len++;
  475.     }
  476.     src = (src >> 8) & 0xfffffful;
  477.   }
  478.   if (!multi_char_le)
  479.     memmove(p_str->p_str, p_dest, p_str->len);
  480.   return True;
  481. }
  482.  
  483. /*!------------------------------------------------------------------------
  484.  * \fn     TempResultToInt(TempResult *pResult)
  485.  * \brief  convert TempResult to integer
  486.  * \param  pResult temp result to convert
  487.  * \return 0 or error code
  488.  * ------------------------------------------------------------------------ */
  489.  
  490. int TempResultToInt(TempResult *pResult)
  491. {
  492.   int ret = 0;
  493.  
  494.   switch (pResult->Typ)
  495.   {
  496.     case TempInt:
  497.       break;
  498.     case TempString:
  499.     {
  500.       LargeInt Result;
  501.       tErrorNum error_num = NonZString2Int(&pResult->Contents.str, &Result);
  502.  
  503.       if (error_num == ErrNum_None)
  504.         as_tempres_set_int(pResult, Result);
  505.       else
  506.       {
  507.         WrError(error_num);
  508.         as_tempres_set_none(pResult);
  509.         ret = -1;
  510.       }
  511.       break;
  512.     }
  513.     default:
  514.       as_tempres_set_none(pResult);
  515.       ret = -1;
  516.   }
  517.   return ret;
  518. }
  519.  
  520. /*!------------------------------------------------------------------------
  521.  * \fn     MultiCharToInt(TempResult *pResult, unsigned MaxLen)
  522.  * \brief  optionally convert multi-character constant to integer
  523.  * \param  pResult holding value
  524.  * \param  MaxLen maximum length of multi-character constant
  525.  * \return True if converted
  526.  * ------------------------------------------------------------------------ */
  527.  
  528. Boolean MultiCharToInt(TempResult *pResult, unsigned MaxLen)
  529. {
  530.   if ((pResult->Typ == TempString)
  531.    && (pResult->Contents.str.len <= MaxLen)
  532.    && (pResult->Flags & eSymbolFlag_StringSingleQuoted))
  533.   {
  534.     TempResultToInt(pResult);
  535.     return True;
  536.   }
  537.   return False;
  538. }
  539.  
  540. /*!------------------------------------------------------------------------
  541.  * \fn     ExpandStrSymbol(tStrComp *p_dest, const tStrComp *p_src, Boolean convert_upper)
  542.  * \brief  expand symbol name from string component
  543.  * \param  p_dest dest buffer (initialize to 0 capacity)
  544.  * \param  p_src source component
  545.  * \param  convert_upper convert to upper while copying?
  546.  * \return resulting component or NULL if error
  547.  * ------------------------------------------------------------------------ */
  548.  
  549. tStrComp *ExpandStrSymbol(tStrComp *p_dest, const tStrComp *p_src, Boolean convert_upper)
  550. {
  551.   tStrComp src_comp;
  552.   Boolean first = True;
  553.  
  554.   StrCompRefRight(&src_comp, p_src, 0);
  555.   while (True)
  556.   {
  557.     const char *p_start = QuotPos(src_comp.str.p_str, '{');
  558.     if (first)
  559.     {
  560.       p_dest->Pos = p_src->Pos;
  561.       p_dest->str.p_str[0] = '\0';
  562.     }
  563.     if (p_start)
  564.     {
  565.       unsigned ls = p_start - src_comp.str.p_str;
  566.       String expr, result;
  567.       tStrComp expr_comp;
  568.       tEvalResult eval_result;
  569.       const char *p_stop;
  570.  
  571.       if (convert_upper)
  572.         as_dynstr_append_upr(&p_dest->str, src_comp.str.p_str, ls);
  573.       else
  574.         as_dynstr_append(&p_dest->str, src_comp.str.p_str, ls);
  575.  
  576.       p_stop = QuotPos(p_start + 1, '}');
  577.       if (!p_stop)
  578.       {
  579.         WrStrErrorPos(ErrNum_InvSymName, p_src);
  580.         return NULL;
  581.       }
  582.       StrCompMkTemp(&expr_comp, expr, sizeof(expr));
  583.       StrCompCopySub(&expr_comp, &src_comp, p_start + 1 - src_comp.str.p_str, p_stop - p_start - 1);
  584.       EvalStrStringExpressionWithResult(&expr_comp, &eval_result, result);
  585.       if (!eval_result.OK)
  586.         return NULL;
  587.       if (mFirstPassUnknown(eval_result.Flags))
  588.       {
  589.         WrStrErrorPos(ErrNum_FirstPassCalc, &expr_comp);
  590.         return NULL;
  591.       }
  592.       if (CaseSensitive)
  593.         as_dynstr_append_c_str(&p_dest->str, result);
  594.       else
  595.         as_dynstr_append_c_str_upr(&p_dest->str, result);
  596.       StrCompIncRefLeft(&src_comp, p_stop + 1 - src_comp.str.p_str);
  597.       first = False;
  598.     }
  599.     else
  600.     {
  601.       if (convert_upper)
  602.         as_dynstr_append_c_str_upr(&p_dest->str, src_comp.str.p_str);
  603.       else
  604.         as_dynstr_append_c_str(&p_dest->str, src_comp.str.p_str);
  605.       return p_dest;
  606.     }
  607.   }
  608. }
  609.  
  610. /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  611. /* check whether this is a local symbol and expand local counter if yes.  They
  612.    have to be handled in different places of the parser, therefore two separate
  613.    functions */
  614.  
  615. void InitTmpSymbols(void)
  616. {
  617.   TmpSymCounter = FwdSymCounter = BackSymCounter = 0;
  618.   *TmpSymCounterVal = '\0';
  619.   TmpSymLogDepth = 0;
  620.   *LastGlobSymbol = '\0';
  621. }
  622.  
  623. static void AddTmpSymLog(Boolean Back, LongInt Counter)
  624. {
  625.   /* shift out oldest value */
  626.  
  627.   if (TmpSymLogDepth)
  628.   {
  629.     LongInt ShiftCnt = min(TmpSymLogDepth, LOCSYMSIGHT - 1);
  630.  
  631.     memmove(TmpSymLog + 1, TmpSymLog, sizeof(TTmpSymLog) * (ShiftCnt));
  632.   }
  633.  
  634.   /* insert new one */
  635.  
  636.   TmpSymLog[0].Back = Back;
  637.   TmpSymLog[0].Counter = Counter;
  638.   if (TmpSymLogDepth < LOCSYMSIGHT)
  639.     TmpSymLogDepth++;
  640. }
  641.  
  642. static Boolean ChkTmp1(char *Name, as_symbol_source_t symbol_source)
  643. {
  644.   char *Src, *Dest;
  645.   Boolean Result = FALSE;
  646.  
  647.   /* $$-Symbols: append current $$-counter */
  648.  
  649.   if (!strncmp(Name, "$$", 2))
  650.   {
  651.     /* manually copy since this will implicitly give us the point to append
  652.        the number */
  653.  
  654.     for (Src = Name + 2, Dest = Name; *Src; *(Dest++) = *(Src++));
  655.  
  656.     /* append number. only generate the number once */
  657.  
  658.     if (*TmpSymCounterVal == '\0')
  659.       as_snprintf(TmpSymCounterVal, sizeof(TmpSymCounterVal), "%d", TmpSymCounter);
  660.     strcpy(Dest, TmpSymCounterVal);
  661.     Result = TRUE;
  662.   }
  663.  
  664.   /* no special local symbol: increment $$-counter */
  665.  
  666.   else if (symbol_source != e_symbol_source_none)
  667.   {
  668.     TmpSymCounter++;
  669.     *TmpSymCounterVal = '\0';
  670.   }
  671.  
  672.   return Result;
  673. }
  674.  
  675. static Boolean ChkTmp2(char *pDest, const char *pSrc, as_symbol_source_t symbol_source)
  676. {
  677.   const char *pRun, *pBegin, *pEnd;
  678.   int Cnt;
  679.   Boolean Result = FALSE;
  680.  
  681.   for (pBegin = pSrc; as_isspace(*pBegin); pBegin++);
  682.   for (pEnd = pSrc + strlen(pSrc); (pEnd > pBegin) && as_isspace(*(pEnd - 1)); pEnd--);
  683.  
  684.   /* Note: We have to deal with three symbol definitions:
  685.  
  686.       "-" for backward-only referencing
  687.       "+" for forward-only referencing
  688.       "/" for either way of referencing
  689.  
  690.       "/" and "+" are both expanded to forward symbol names, so the
  691.       forward refencing to both types is unproblematic, however
  692.       only "/" and "-" are stored in the backlog of the three
  693.       most-recent symbols for backward referencing.
  694.   */
  695.  
  696.   /* backward references ? */
  697.  
  698.   if (*pBegin == '-')
  699.   {
  700.     for (pRun = pBegin; *pRun; pRun++)
  701.       if (*pRun != '-')
  702.         break;
  703.     Cnt = pRun - pBegin;
  704.     if (pRun == pEnd)
  705.     {
  706.       if ((symbol_source != e_symbol_source_none) && (Cnt == 1))
  707.       {
  708.         as_snprintf(pDest, STRINGSIZE, "__BACK%d", (int)BackSymCounter);
  709.         AddTmpSymLog(TRUE, BackSymCounter);
  710.         BackSymCounter++;
  711.         Result = TRUE;
  712.       }
  713.  
  714.       /* TmpSymLogDepth cannot become larger than LOCSYMSIGHT, so we only
  715.          have to check against the log's actual depth. */
  716.  
  717.       else if (Cnt <= TmpSymLogDepth)
  718.       {
  719.         Cnt--;
  720.         as_snprintf(pDest, STRINGSIZE, "__%s%d",
  721.                     TmpSymLog[Cnt].Back ? "BACK" : "FORW",
  722.                     (int)TmpSymLog[Cnt].Counter);
  723.         Result = TRUE;
  724.       }
  725.     }
  726.   }
  727.  
  728.   /* forward references ? */
  729.  
  730.   else if (*pBegin == '+')
  731.   {
  732.     for (pRun = pBegin; *pRun; pRun++)
  733.       if (*pRun != '+')
  734.         break;
  735.     Cnt = pRun - pBegin;
  736.     if (pRun == pEnd)
  737.     {
  738.       if ((symbol_source != e_symbol_source_none) && (Cnt == 1))
  739.       {
  740.         as_snprintf(pDest, STRINGSIZE, "__FORW%d", (int)FwdSymCounter++);
  741.         Result = TRUE;
  742.       }
  743.       else if (Cnt <= LOCSYMSIGHT)
  744.       {
  745.         as_snprintf(pDest, STRINGSIZE, "__FORW%d", (int)(FwdSymCounter + (Cnt - 1)));
  746.         Result = TRUE;
  747.       }
  748.     }
  749.   }
  750.  
  751.   /* slash: only allowed for definition, but add to log for backward ref. */
  752.  
  753.   else if ((pEnd - pBegin == 1) && (*pBegin == '/') && (symbol_source != e_symbol_source_none))
  754.   {
  755.     AddTmpSymLog(FALSE, FwdSymCounter);
  756.     as_snprintf(pDest, STRINGSIZE, "__FORW%d", (int)FwdSymCounter);
  757.     FwdSymCounter++;
  758.     Result = TRUE;
  759.   }
  760.  
  761.   return Result;
  762. }
  763.  
  764. static Boolean ChkTmp3(char *Name, as_symbol_source_t symbol_source)
  765. {
  766.   if ('.' == *Name)
  767.   {
  768.     strmaxprep2(Name, LastGlobSymbol, STRINGSIZE);
  769.     return True;
  770.   }
  771.  
  772. #if 0
  773.   if (symbol_source == e_symbol_source_label)
  774. #else
  775.   if (symbol_source != e_symbol_source_none)
  776. #endif
  777.     strmaxcpy(LastGlobSymbol, Name, STRINGSIZE);
  778.   return False;
  779. }
  780.  
  781. static Boolean ChkTmp(char *Name, as_symbol_source_t symbol_source)
  782. {
  783.   Boolean IsTmp1, IsTmp2, IsTmp3;
  784.  
  785.   IsTmp1 = ChkTmp1(Name, symbol_source);
  786.   IsTmp2 = ChkTmp2(Name, Name, symbol_source);
  787.   IsTmp3 = ChkTmp3(Name, IsTmp2 ? e_symbol_source_none : symbol_source);
  788.   return IsTmp1 || IsTmp2 || IsTmp3;
  789. }
  790.  
  791. Boolean IdentifySection(const tStrComp *pName, LongInt *p_ret)
  792. {
  793.   PSaveSection SLauf;
  794.   String exp_name_buf;
  795.   tStrComp exp_name, *p_exp_name;
  796.   sint Depth;
  797.   size_t exp_len;
  798.  
  799.   StrCompMkTemp(&exp_name, exp_name_buf, sizeof(exp_name_buf));
  800.   p_exp_name = ExpandStrSymbol(&exp_name, pName, !CaseSensitive);
  801.   if (!p_exp_name)
  802.     return False;
  803.  
  804.   exp_len = strlen(p_exp_name->str.p_str);
  805.   if (!exp_len)
  806.   {
  807.     *p_ret = -1;
  808.     return True;
  809.   }
  810.   else if (((exp_len == 6) || (exp_len == 7))
  811.        && !as_strncasecmp(p_exp_name->str.p_str, "PARENT", 6)
  812.        && ((exp_len == 6) || as_isdigit(p_exp_name->str.p_str[6])))
  813.   {
  814.     Depth = (exp_len == 6) ? 1 : p_exp_name->str.p_str[6] - AscOfs;
  815.     SLauf = SectionStack;
  816.     *p_ret = MomSectionHandle;
  817.     while ((Depth > 0) && (*p_ret != -2))
  818.     {
  819.       if (!SLauf) *p_ret = -2;
  820.       else
  821.       {
  822.         *p_ret = SLauf->Handle;
  823.         SLauf = SLauf->Next;
  824.       }
  825.       Depth--;
  826.     }
  827.     if (*p_ret == -2)
  828.     {
  829.       WrStrErrorPos(ErrNum_InvSection, pName);
  830.       return False;
  831.     }
  832.     else
  833.       return True;
  834.   }
  835.   else if (!strcmp(p_exp_name->str.p_str, GetSectionName(MomSectionHandle)))
  836.   {
  837.     *p_ret = MomSectionHandle;
  838.     return True;
  839.   }
  840.   else
  841.   {
  842.     SLauf = SectionStack;
  843.     while ((SLauf) && (strcmp(GetSectionName(SLauf->Handle), p_exp_name->str.p_str)))
  844.       SLauf = SLauf->Next;
  845.     if (!SLauf)
  846.     {
  847.       WrStrErrorPos(ErrNum_InvSection, pName);
  848.       return False;
  849.     }
  850.     else
  851.     {
  852.       *p_ret = SLauf->Handle;
  853.       return True;
  854.     }
  855.   }
  856. }
  857.  
  858. static Boolean GetSymSection(tStrComp *p_name, LongInt *p_ret, const tStrComp *pUnexpComp)
  859. {
  860.   tStrComp TmpComp;
  861.   char *q;
  862.   int l = strlen(p_name->str.p_str), pos;
  863.  
  864.   if (!l || (p_name->str.p_str[l - 1] != ']'))
  865.   {
  866.     *p_ret = -2;
  867.     return True;
  868.   }
  869.  
  870.   p_name->str.p_str[l - 1] = '\0';
  871.   q = RQuotPos(p_name->str.p_str, '[');
  872.   if (!q)
  873.   {
  874.     *p_ret = -2;
  875.     return True;
  876.   }
  877.   p_name->str.p_str[l - 1] = ']';
  878.   if (p_name->str.p_str + l - q <= 1)
  879.   {
  880.     WrStrErrorPos(ErrNum_InvSymName, pUnexpComp ? pUnexpComp : p_name);
  881.     return False;
  882.   }
  883.  
  884.   StrCompShorten(p_name, 1); l--;
  885.   pos = q - p_name->str.p_str;
  886.   StrCompRefRight(&TmpComp, p_name, pos + 1);
  887.   StrCompShorten(p_name, l - pos);
  888.  
  889.   return IdentifySection(&TmpComp, p_ret);
  890. }
  891.  
  892. /*****************************************************************************
  893.  * Function:    ConstIntVal
  894.  * Purpose:     evaluate integer constant
  895.  * Result:      integer value
  896.  *****************************************************************************/
  897.  
  898. static LargeInt ConstIntVal(const char *pExpr, IntType Typ, Boolean *pResult)
  899. {
  900.   LargeInt Wert;
  901.   Boolean NegFlag = False;
  902.   int Digit;
  903.   tIntCheckCtx Ctx;
  904.   const tIntFormatList *pIntFormat;
  905.  
  906.   /* empty string is interpreted as 0 */
  907.  
  908.   if (!*pExpr)
  909.   {
  910.     *pResult = True;
  911.     return 0;
  912.   }
  913.  
  914.   *pResult = False;
  915.  
  916.   /* sign: */
  917.  
  918.   switch (*pExpr)
  919.   {
  920.     case '-':
  921.       NegFlag = True;
  922.       /* else fall-through */
  923.     case '+':
  924.       pExpr++;
  925.       break;
  926.   }
  927.   Ctx.pExpr = pExpr;
  928.   Ctx.ExprLen = strlen(pExpr);
  929.   Ctx.Base = -1;
  930.  
  931.   for (pIntFormat = IntFormatList; pIntFormat->Check; pIntFormat++)
  932.     if (pIntFormat->Check(&Ctx, pIntFormat->Ch))
  933.     {
  934.       Ctx.Base = (pIntFormat->Base > 0) ? pIntFormat->Base : RadixBase;
  935.       break;
  936.     }
  937.   if (Ctx.Base <= 0)
  938.     return -1;
  939.  
  940.   /* we may have decremented Ctx.ExprLen, so do not run until string end */
  941.  
  942.   Wert = 0;
  943.   while (Ctx.ExprLen > 0)
  944.   {
  945.     if (256 == Ctx.Base)
  946.     {
  947.       Digit = as_chartrans_xlate(CurrTransTable->p_table, ((unsigned)*Ctx.pExpr) & 0xff);
  948.       if (Digit < 0)
  949.       {
  950.         WrError(ErrNum_UnmappedChar);
  951.         Digit = 0;
  952.       }
  953.     }
  954.     else
  955.       Digit = DigitVal(as_toupper(*Ctx.pExpr), Ctx.Base);
  956.     if (Digit == -1)
  957.       return -1;
  958.     Wert = Wert * Ctx.Base + Digit;
  959.     Ctx.pExpr++; Ctx.ExprLen--;
  960.   }
  961.  
  962.   if (NegFlag)
  963.     Wert = -Wert;
  964.  
  965.   /* post-processing, range check */
  966.  
  967.   *pResult = RangeCheck(Wert, Typ);
  968.   if (*pResult)
  969.     return Wert;
  970.   else if (HardRanges)
  971.   {
  972.     WrError(ErrNum_OverRange);
  973.     return -1;
  974.   }
  975.   else
  976.   {
  977.     *pResult = True;
  978.     WrError(ErrNum_WOverRange);
  979.     return Wert & IntTypeDefs[(int)Typ].Mask;
  980.   }
  981. }
  982.  
  983. /*****************************************************************************
  984.  * Function:    ConstFloatVal
  985.  * Purpose:     evaluate floating point constant
  986.  * Result:      value
  987.  *****************************************************************************/
  988.  
  989. static Double ConstFloatVal(const char *pExpr, FloatType Typ, Boolean *pResult)
  990. {
  991.   Double Erg;
  992.   char *pEnd;
  993.  
  994.   UNUSED(Typ);
  995.  
  996.   if (*pExpr)
  997.   {
  998.     /* Some strtod() implementations interpret hex constants starting with '0x'.  We
  999.        don't want this here.  Either 0x for hex constants is allowed, then it should
  1000.        have been parsed before by ConstIntVal(), or not, then we don't want the constant
  1001.        be stored as float. */
  1002.  
  1003.     if ((strlen(pExpr) >= 2)
  1004.      && (pExpr[0] == '0')
  1005.      && (toupper(pExpr[1]) == 'X'))
  1006.     {
  1007.       Erg = 0;
  1008.       *pResult = False;
  1009.     }
  1010.  
  1011.     else
  1012.     {
  1013.       Erg = strtod(pExpr, &pEnd);
  1014.       *pResult = (*pEnd == '\0');
  1015.     }
  1016.   }
  1017.   else
  1018.   {
  1019.     Erg = 0.0;
  1020.     *pResult = True;
  1021.   }
  1022.   return Erg;
  1023. }
  1024.  
  1025. /*****************************************************************************
  1026.  * Function:    ConstStringVal
  1027.  * Purpose:     evaluate string constant
  1028.  * Result:      value
  1029.  *****************************************************************************/
  1030.  
  1031. static void ConstStringVal(const tStrComp *pExpr, TempResult *pDest, Boolean *pResult)
  1032. {
  1033.   tStrComp Raw, Copy, Remainder;
  1034.   char *pPos, QuoteChar;
  1035.   int l, TLen;
  1036.  
  1037.   *pResult = False;
  1038.  
  1039.   l = strlen(pExpr->str.p_str);
  1040.   if (l < 2)
  1041.     return;
  1042.   switch (*pExpr->str.p_str)
  1043.   {
  1044.     case '"':
  1045.     case '\'':
  1046.       QuoteChar = *pExpr->str.p_str;
  1047.       if (pExpr->str.p_str[l - 1] == QuoteChar)
  1048.       {
  1049.         if ('\'' == QuoteChar)
  1050.           pDest->Flags |= eSymbolFlag_StringSingleQuoted;
  1051.         break;
  1052.       }
  1053.       /* conditional fall-through */
  1054.     default:
  1055.       return;
  1056.   }
  1057.  
  1058.   StrCompAlloc(&Raw, STRINGSIZE);
  1059.   StrCompCopySub(&Raw, pExpr, 1, l - 2);
  1060.   /* use LEAVE from now on instead of return */
  1061.  
  1062.   /* go through source */
  1063.  
  1064.   as_tempres_set_c_str(pDest, "");
  1065.   StrCompRefRight(&Copy, &Raw, 0);
  1066.   while (1)
  1067.   {
  1068.     pPos = strchr(Copy.str.p_str, '\\');
  1069.     if (pPos)
  1070.       StrCompSplitRef(&Copy, &Remainder, &Copy, pPos);
  1071.  
  1072.     /* " before \ -> not a simple string but something like "...." ... " */
  1073.  
  1074.     if (strchr(Copy.str.p_str, QuoteChar))
  1075.     {
  1076.       as_tempres_set_none(pDest);
  1077.       LEAVE;
  1078.     }
  1079.  
  1080.     /* copy part up to next '\' verbatim: */
  1081.  
  1082.     as_nonz_dynstr_append_raw(&pDest->Contents.str, Copy.str.p_str, strlen(Copy.str.p_str));
  1083.  
  1084.     /* are we done? If not, advance pointer to behind '\' */
  1085.  
  1086.     if (!pPos)
  1087.       break;
  1088.     Copy = Remainder;
  1089.  
  1090.     /* treat escaped section: stringification? */
  1091.  
  1092.     if (*Copy.str.p_str == '{')
  1093.     {
  1094.       TempResult t;
  1095.       char *pStr;
  1096.       String Str;
  1097.       Boolean OK = True;
  1098.  
  1099.       as_tempres_ini(&t);
  1100.       StrCompIncRefLeft(&Copy, 1);
  1101.  
  1102.       /* cut out part in {...} */
  1103.  
  1104.       pPos = QuotPos(Copy.str.p_str, '}');
  1105.       if (!pPos)
  1106.       {
  1107.         OK = False;
  1108.         LEAVE2;
  1109.       }
  1110.       StrCompSplitRef(&Copy, &Remainder, &Copy, pPos);
  1111.       KillPrefBlanksStrCompRef(&Copy);
  1112.       KillPostBlanksStrComp(&Copy);
  1113.  
  1114.       /* evaluate expression */
  1115.  
  1116.       EvalStrExpression(&Copy, &t);
  1117.       if (t.Relocs)
  1118.       {
  1119.         WrStrErrorPos(ErrNum_NoRelocs, &Copy);
  1120.         FreeRelocs(&t.Relocs);
  1121.         as_tempres_set_none(&t);
  1122.       }
  1123.  
  1124.       /* append result */
  1125.  
  1126.       switch (t.Typ)
  1127.       {
  1128.         case TempInt:
  1129.           TLen = SysString(Str, sizeof(Str), t.Contents.Int, OutRadixBase, 0, False, HexStartCharacter, SplitByteCharacter);
  1130.           pStr = Str;
  1131.           break;
  1132.         case TempFloat:
  1133.           FloatString(Str, sizeof(Str), t.Contents.Float);
  1134.           pStr = Str;
  1135.           TLen = strlen(pStr);
  1136.           break;
  1137.         case TempString:
  1138.           pStr = t.Contents.str.p_str;
  1139.           TLen = t.Contents.str.len;
  1140.           break;
  1141.         default:
  1142.           *pResult = True;
  1143.           OK = False;
  1144.       }
  1145.       if (OK)
  1146.       {
  1147.         as_nonz_dynstr_append_raw(&pDest->Contents.str, pStr, TLen);
  1148.         pDest->Flags |= t.Flags & eSymbolFlags_Promotable;
  1149.       }
  1150.  
  1151.       /* advance source pointer to behind '}' */
  1152.  
  1153.       Copy = Remainder;
  1154.  
  1155.    func_exit2:
  1156.       as_tempres_free(&t);
  1157.       if (!OK)
  1158.       {
  1159.         as_tempres_set_none(pDest);
  1160.         LEAVE;
  1161.       }
  1162.     }
  1163.  
  1164.     /* simple character escape: */
  1165.  
  1166.     else
  1167.     {
  1168.       char Res, *pNext = Copy.str.p_str;
  1169.  
  1170.       if (!ProcessBk(&pNext, &Res))
  1171.       {
  1172.         as_tempres_set_none(pDest);
  1173.         LEAVE;
  1174.       }
  1175.       as_nonz_dynstr_append_raw(&pDest->Contents.str, &Res, 1);
  1176.       StrCompIncRefLeft(&Copy, pNext - Copy.str.p_str);
  1177.     }
  1178.   }
  1179.  
  1180.   *pResult = True;
  1181. func_exit:
  1182.   StrCompFree(&Raw);
  1183. }
  1184.  
  1185.  
  1186. typedef enum { e_expand_chk_none, e_expand_chk_upto, e_expand_chk_empty_upto } expand_chk_t;
  1187.  
  1188. static PSymbolEntry ExpandAndFindNode(
  1189. #ifdef __PROTOS__
  1190. const struct sStrComp *pComp, TempType SearchType, Boolean SearchLocal, expand_chk_t chk, Boolean *p_error_on_find
  1191. #endif
  1192. );
  1193.  
  1194. /*!------------------------------------------------------------------------
  1195.  * \fn     EvalResultClear(tEvalResult *pResult)
  1196.  * \brief  reset all elements of EvalResult
  1197.  * ------------------------------------------------------------------------ */
  1198.  
  1199. void EvalResultClear(tEvalResult *pResult)
  1200. {
  1201.   pResult->OK = False;
  1202.   pResult->Flags = eSymbolFlag_None;
  1203.   pResult->AddrSpaceMask = 0;
  1204.   pResult->DataSize = eSymbolSizeUnknown;
  1205. }
  1206.  
  1207. /*****************************************************************************
  1208.  * Function:    EvalStrExpression
  1209.  * Purpose:     evaluate expression
  1210.  * Result:      implicitly in pErg
  1211.  *****************************************************************************/
  1212.  
  1213. #define LEAVE goto func_exit
  1214.  
  1215. static tErrorNum DeduceExpectTypeErrMsgMask(unsigned Mask, TempType ActType)
  1216. {
  1217.   switch (ActType)
  1218.   {
  1219.     case TempInt:
  1220.       switch (Mask)
  1221.       {
  1222.         case TempString:
  1223.           return ErrNum_StringButInt;
  1224.         /* int is convertible to float, so combinations are impossible: */
  1225.         case TempFloat:
  1226.         case TempFloat | TempString:
  1227.         default:
  1228.           return ErrNum_InternalError;
  1229.       }
  1230.     case TempFloat:
  1231.       switch (Mask)
  1232.       {
  1233.         case TempInt:
  1234.           return ErrNum_IntButFloat;
  1235.         case TempString:
  1236.           return ErrNum_StringButFloat;
  1237.         case TempInt | TempString:
  1238.           return ErrNum_StringOrIntButFloat;
  1239.         default:
  1240.           return ErrNum_InternalError;
  1241.       }
  1242.     case TempString:
  1243.       switch (Mask)
  1244.       {
  1245.         case TempInt:
  1246.           return ErrNum_IntButString;
  1247.         case TempFloat:
  1248.           return ErrNum_FloatButString;
  1249.         case TempInt | TempFloat:
  1250.           return ErrNum_IntOrFloatButString;
  1251.         default:
  1252.           return ErrNum_InternalError;
  1253.       }
  1254.     case TempReg:
  1255.       switch (Mask)
  1256.       {
  1257.         case TempInt:
  1258.           return ErrNum_ExpectInt;
  1259.         case TempString:
  1260.           return ErrNum_ExpectString;
  1261.         case TempInt | TempString:
  1262.           return ErrNum_ExpectIntOrString;
  1263.         case TempInt | TempFloat:
  1264.           return ErrNum_IntOrFloatButReg;
  1265.         case TempInt | TempFloat | TempString:
  1266.           return ErrNum_StringOrIntOrFloatButReg;
  1267.         default:
  1268.           return ErrNum_InternalError;
  1269.       }
  1270.     default:
  1271.       return ErrNum_InternalError;
  1272.   }
  1273. }
  1274.  
  1275. static Byte GetOpTypeMask(Byte TotMask, int OpIndex)
  1276. {
  1277.   return (TotMask >> (OpIndex * 4)) & 15;
  1278. }
  1279.  
  1280. static Byte TryConvert(Byte TypeMask, TempType ActType, int OpIndex)
  1281. {
  1282.   if (TypeMask & ActType)
  1283.     return 0 << (4 * OpIndex);
  1284.   if ((TypeMask & TempFloat) && (ActType == TempInt))
  1285.     return 1 << (4 * OpIndex);
  1286.   if ((TypeMask & TempInt) && (ActType == TempString))
  1287.     return 2 << (4 * OpIndex);
  1288.   if ((TypeMask & TempFloat) && (ActType == TempString))
  1289.     return (1|2) << (4 * OpIndex);
  1290.   return 255;
  1291. }
  1292.  
  1293. void EvalStrExpression(const tStrComp *pExpr, TempResult *pErg)
  1294. {
  1295.   const Operator *pOp;
  1296.   const Operator *FOps[OPERATOR_MAXCNT];
  1297.   LongInt FOpCnt = 0;
  1298.  
  1299.   Boolean OK;
  1300.   tStrComp InArgs[3];
  1301.   TempResult InVals[3];
  1302.   int z1, cnt;
  1303.   char Save = '\0';
  1304.   sint LKlamm, RKlamm, WKlamm, zop;
  1305.   sint OpMax, OpPos = -1;
  1306.   Boolean InSgl, InDbl, NextEscaped, ThisEscaped;
  1307.   PFunction ValFunc;
  1308.   tStrComp CopyComp, STempComp;
  1309.   char *KlPos, *zp, *pOpPos;
  1310.   const tFunction *pFunction;
  1311.   PRelocEntry TReloc;
  1312.   tSymbolFlags PromotedFlags;
  1313.   unsigned PromotedAddrSpaceMask;
  1314.   tSymbolSize PromotedDataSize;
  1315.  
  1316.   ChkStack();
  1317.  
  1318.   for (z1 = 0; z1 < 3; z1++)
  1319.     as_tempres_ini(&InVals[z1]);
  1320.   StrCompAlloc(&CopyComp, STRINGSIZE);
  1321.   StrCompAlloc(&STempComp, STRINGSIZE);
  1322.  
  1323.   if (MakeDebug)
  1324.     fprintf(Debug, "Parse '%s'\n", pExpr->str.p_str);
  1325.  
  1326.   /* Annahme Fehler */
  1327.  
  1328.   as_tempres_set_none(pErg);
  1329.   pErg->Relocs = NULL;
  1330.   pErg->Flags = eSymbolFlag_None;
  1331.   pErg->AddrSpaceMask = 0;
  1332.   pErg->DataSize = eSymbolSizeUnknown;
  1333.  
  1334.   StrCompCopy(&CopyComp, pExpr);
  1335.   KillPrefBlanksStrComp(&CopyComp);
  1336.   KillPostBlanksStrComp(&CopyComp);
  1337.  
  1338.   /* sort out local symbols like - and +++.  Do it now to get them out of the
  1339.      formula parser's way. */
  1340.  
  1341.   ChkTmp2(CopyComp.str.p_str, CopyComp.str.p_str, e_symbol_source_none);
  1342.   StrCompCopy(&STempComp, &CopyComp);
  1343.  
  1344.   /* Programmzaehler ? */
  1345.  
  1346.   if (PCSymbol && (!as_strcasecmp(CopyComp.str.p_str, PCSymbol)))
  1347.   {
  1348.     as_tempres_set_int(pErg, EProgCounter());
  1349.     pErg->Relocs = NULL;
  1350.     pErg->AddrSpaceMask |= 1 << ActPC;
  1351.     LEAVE;
  1352.   }
  1353.  
  1354.   /* Konstanten ? */
  1355.  
  1356.   pErg->Contents.Int = ConstIntVal(CopyComp.str.p_str, (IntType) (IntTypeCnt - 1), &OK);
  1357.   if (OK)
  1358.   {
  1359.     pErg->Typ = TempInt;
  1360.     pErg->Relocs = NULL;
  1361.     LEAVE;
  1362.   }
  1363.  
  1364.   pErg->Contents.Float = ConstFloatVal(CopyComp.str.p_str, Float80, &OK);
  1365.   if (OK)
  1366.   {
  1367.     pErg->Typ = TempFloat;
  1368.     pErg->Relocs = NULL;
  1369.     LEAVE;
  1370.   }
  1371.  
  1372.   ConstStringVal(&CopyComp, pErg, &OK);
  1373.   if (OK)
  1374.   {
  1375.     pErg->Relocs = NULL;
  1376.     LEAVE;
  1377.   }
  1378.  
  1379.   /* durch Codegenerator gegebene Konstanten ? */
  1380.  
  1381.   pErg->Relocs = NULL;
  1382.   InternSymbol(CopyComp.str.p_str, pErg);
  1383.   if (pErg->Typ != TempNone)
  1384.   {
  1385.     LEAVE;
  1386.   }
  1387.  
  1388.   /* find out which operators *might* occur in expression */
  1389.  
  1390.   OpMax = 0;
  1391.   LKlamm = 0;
  1392.   RKlamm = 0;
  1393.   WKlamm = 0;
  1394.   InSgl =
  1395.   InDbl =
  1396.   ThisEscaped =
  1397.   NextEscaped = False;
  1398.   for (pOp = Operators + 1; pOp->Id; pOp++)
  1399.   {
  1400.     pOpPos = (pOp->IdLen == 1) ? (strchr(CopyComp.str.p_str, *pOp->Id)) : (strstr(CopyComp.str.p_str, pOp->Id));
  1401.     if (pOpPos)
  1402.       FOps[FOpCnt++] = pOp;
  1403.   }
  1404.  
  1405.   /* nach Operator hoechster Rangstufe ausserhalb Klammern suchen */
  1406.  
  1407.   for (zp = CopyComp.str.p_str; *zp; zp++, ThisEscaped = NextEscaped)
  1408.   {
  1409.     NextEscaped = False;
  1410.     switch (*zp)
  1411.     {
  1412.       case '(':
  1413.         if (!(InSgl || InDbl))
  1414.           LKlamm++;
  1415.         break;
  1416.       case ')':
  1417.         if (!(InSgl || InDbl))
  1418.           RKlamm++;
  1419.         break;
  1420.       case '{':
  1421.         if (!(InSgl || InDbl))
  1422.           WKlamm++;
  1423.         break;
  1424.       case '}':
  1425.         if (!(InSgl || InDbl))
  1426.           WKlamm--;
  1427.         break;
  1428.       case '"':
  1429.         if (!InSgl && !ThisEscaped)
  1430.           InDbl = !InDbl;
  1431.         break;
  1432.       case '\'':
  1433.         if (!InDbl && !ThisEscaped)
  1434.         {
  1435.           if (InSgl || !QualifyQuote || QualifyQuote(CopyComp.str.p_str, zp))
  1436.             InSgl = !InSgl;
  1437.         }
  1438.         break;
  1439.       case '\\':
  1440.         if ((InDbl || InSgl) && !ThisEscaped)
  1441.           NextEscaped = True;
  1442.         break;
  1443.       default:
  1444.         if ((LKlamm == RKlamm) && (WKlamm == 0) && (!InSgl) && (!InDbl))
  1445.         {
  1446.           Boolean OpFnd = False;
  1447.           sint OpLen = 0, LocOpMax = 0;
  1448.  
  1449.           for (zop = 0; zop < FOpCnt; zop++)
  1450.           {
  1451.             pOp = FOps[zop];
  1452.             if ((!strncmp(zp, pOp->Id, pOp->IdLen)) && (pOp->IdLen >= OpLen))
  1453.             {
  1454.               OpFnd = True;
  1455.               OpLen = pOp->IdLen;
  1456.               LocOpMax = pOp - Operators;
  1457.               if (Operators[LocOpMax].Priority >= Operators[OpMax].Priority)
  1458.               {
  1459.                 OpMax = LocOpMax;
  1460.                 OpPos = zp - CopyComp.str.p_str;
  1461.               }
  1462.             }
  1463.           }
  1464.           if (OpFnd)
  1465.             zp += Operators[LocOpMax].IdLen - 1;
  1466.         }
  1467.     }
  1468.   }
  1469.  
  1470.   /* Klammerfehler ? */
  1471.  
  1472.   if (LKlamm != RKlamm)
  1473.   {
  1474.     WrStrErrorPos(ErrNum_BrackErr, &CopyComp);
  1475.     LEAVE;
  1476.   }
  1477.  
  1478.   /* Operator gefunden ? */
  1479.  
  1480.   if (OpMax)
  1481.   {
  1482.     int ThisArgCnt, CompLen, z, z2;
  1483.     Byte ThisOpMatch, BestOpMatch, BestOpMatchIdx, SumCombinations, TypeMask;
  1484.  
  1485.     pOp = Operators + OpMax;
  1486.  
  1487.     /* Minuszeichen sowohl mit einem als auch 2 Operanden */
  1488.  
  1489.     if (!strcmp(pOp->Id, "-"))
  1490.     {
  1491.       if (!OpPos)
  1492.         pOp = &MinusMonadicOperator;
  1493.     }
  1494.  
  1495.     else if (!strcmp(pOp->Id, "^"))
  1496.     {
  1497.       if (!OpPos && pPotMonadicOperator)
  1498.         pOp = pPotMonadicOperator;
  1499.     }
  1500.  
  1501.     /* Operandenzahl pruefen */
  1502.  
  1503.     CompLen = strlen(CopyComp.str.p_str);
  1504.     if (CompLen <= 1)
  1505.       ThisArgCnt = 0;
  1506.     else if (!OpPos || (OpPos == (int)strlen(CopyComp.str.p_str) - 1))
  1507.       ThisArgCnt = 1;
  1508.     else
  1509.       ThisArgCnt = 2;
  1510.     if (!ChkArgCntExtPos(ThisArgCnt, pOp->Dyadic ? 2 : 1, pOp->Dyadic ? 2 : 1, &CopyComp.Pos))
  1511.       LEAVE;
  1512.  
  1513.     /* Teilausdruecke rekursiv auswerten */
  1514.  
  1515.     Save = StrCompSplitRef(&InArgs[0], &InArgs[1], &CopyComp, CopyComp.str.p_str + OpPos);
  1516.     StrCompIncRefLeft(&InArgs[1], strlen(pOp->Id) - 1);
  1517.     EvalStrExpression(&InArgs[1], &InVals[1]);
  1518.     if (pOp->Dyadic)
  1519.       EvalStrExpression(&InArgs[0], &InVals[0]);
  1520.     else if (InVals[1].Typ == TempFloat)
  1521.       as_tempres_set_float(&InVals[0], 0.0);
  1522.     else
  1523.     {
  1524.       as_tempres_set_int(&InVals[0], 0);
  1525.       InVals[0].Relocs = NULL;
  1526.     }
  1527.     CopyComp.str.p_str[OpPos] = Save;
  1528.  
  1529.     /* Abbruch, falls dabei Fehler */
  1530.  
  1531.     if ((InVals[0].Typ == TempNone) || (InVals[1].Typ == TempNone))
  1532.       LEAVE;
  1533.  
  1534.     /* relokatible Symbole nur fuer + und - erlaubt */
  1535.  
  1536.     if ((OpMax != 12) && (OpMax != 13) && (InVals[0].Relocs || InVals[1].Relocs))
  1537.     {
  1538.       WrStrErrorPos(ErrNum_NoRelocs, &CopyComp);
  1539.       LEAVE;
  1540.     }
  1541.  
  1542.     /* see whether data types match operator's restrictions: */
  1543.  
  1544.     BestOpMatch = 255; BestOpMatchIdx = OPERATOR_MAXCOMB;
  1545.     SumCombinations = 0;
  1546.     for (z = 0; z < OPERATOR_MAXCOMB; z++)
  1547.     {
  1548.       if (!pOp->TypeCombinations[z])
  1549.         break;
  1550.       SumCombinations |= pOp->TypeCombinations[z];
  1551.  
  1552.       ThisOpMatch = 0;
  1553.       for (z2 = pOp->Dyadic ? 0 : 1; z2 < 2; z2++)
  1554.         ThisOpMatch |= TryConvert(GetOpTypeMask(pOp->TypeCombinations[z], z2), InVals[z2].Typ, z2);
  1555.       if (ThisOpMatch < BestOpMatch)
  1556.       {
  1557.         BestOpMatch = ThisOpMatch;
  1558.         BestOpMatchIdx = z;
  1559.       }
  1560.       if (!BestOpMatch)
  1561.         break;
  1562.     }
  1563.  
  1564.     /* did not find a way to satisfy restrictions, even by conversions? */
  1565.  
  1566.     if (BestOpMatch >= 255)
  1567.     {
  1568.       for (z2 = pOp->Dyadic ? 0 : 1; z2 < 2; z2++)
  1569.       {
  1570.         TypeMask = GetOpTypeMask(SumCombinations, z2);
  1571.         if (!(TypeMask & InVals[z2].Typ))
  1572.           WrStrErrorPos(DeduceExpectTypeErrMsgMask(TypeMask, InVals[z2].Typ), &InArgs[z2]);
  1573.       }
  1574.       LEAVE;
  1575.     }
  1576.  
  1577.     /* necessary conversions: */
  1578.  
  1579.     for (z2 = pOp->Dyadic ? 0 : 1; z2 < 2; z2++)
  1580.     {
  1581.       TypeMask = (BestOpMatch >> (z2 * 4)) & 15;
  1582.       if (TypeMask & 2)  /* String -> Int */
  1583.         TempResultToInt(&InVals[z2]);
  1584.       if (TypeMask & 1) /* Int -> Float */
  1585.         TempResultToFloat(&InVals[z2]);
  1586.     }
  1587.  
  1588.     /* actual operation */
  1589.  
  1590.     (void)BestOpMatchIdx;
  1591.     pOp->pFunc(pErg, &InVals[0], &InVals[1]);
  1592.     LEAVE;
  1593.   } /* if (OpMax) */
  1594.  
  1595.   /* kein Operator gefunden: Klammerausdruck ? */
  1596.  
  1597.   if (LKlamm != 0)
  1598.   {
  1599.     tStrComp FName, FArg, Remainder;
  1600.  
  1601.     /* erste Klammer suchen, Funktionsnamen abtrennen */
  1602.  
  1603.     KlPos = strchr(CopyComp.str.p_str, '(');
  1604.  
  1605.     /* Funktionsnamen abschneiden */
  1606.  
  1607.     StrCompSplitRef(&FName, &FArg, &CopyComp, KlPos);
  1608.     StrCompShorten(&FArg, 1);
  1609.     KillPostBlanksStrComp(&FName);
  1610.  
  1611.     /* Nullfunktion: nur Argument */
  1612.  
  1613.     if (*FName.str.p_str == '\0')
  1614.     {
  1615.       EvalStrExpression(&FArg, pErg);
  1616.       LEAVE;
  1617.     }
  1618.  
  1619.     /* selbstdefinierte Funktion ? */
  1620.  
  1621.     ValFunc = FindFunction(FName.str.p_str);
  1622.     if (ValFunc)
  1623.     {
  1624.       as_dynstr_t CompArgStr;
  1625.       tStrComp CompArg;
  1626.       as_dynstr_t stemp;
  1627.  
  1628.       PromotedFlags = eSymbolFlag_None;
  1629.       PromotedAddrSpaceMask = 0;
  1630.       PromotedDataSize = eSymbolSizeUnknown;
  1631.       as_dynstr_ini_c_str(&CompArgStr, ValFunc->Definition);
  1632.       as_dynstr_ini(&stemp, STRINGSIZE);
  1633.       for (z1 = 1; z1 <= ValFunc->ArguCnt; z1++)
  1634.       {
  1635.         if (!*FArg.str.p_str)
  1636.         {
  1637.           WrError(ErrNum_InvFuncArgCnt);
  1638.           LEAVE2;
  1639.         }
  1640.  
  1641.         KlPos = QuotPos(FArg.str.p_str, ',');
  1642.         if (KlPos)
  1643.           StrCompSplitRef(&FArg, &Remainder, &FArg, KlPos);
  1644.  
  1645.         EvalStrExpression(&FArg, &InVals[0]);
  1646.         if (InVals[0].Relocs)
  1647.         {
  1648.           WrStrErrorPos(ErrNum_NoRelocs, &FArg);
  1649.           FreeRelocs(&InVals[0].Relocs);
  1650.           LEAVE2;
  1651.         }
  1652.         PromotedFlags |= InVals[0].Flags & eSymbolFlags_Promotable;
  1653.         PromotedAddrSpaceMask |= InVals[0].AddrSpaceMask;
  1654.         if (PromotedDataSize == eSymbolSizeUnknown) PromotedDataSize = InVals[0].DataSize;
  1655.  
  1656.         if (KlPos)
  1657.           FArg = Remainder;
  1658.         else
  1659.           StrCompReset(&FArg);
  1660.  
  1661.         as_sdprintf(&stemp, "(");
  1662.         if (as_tempres_append_dynstr(&stemp, &InVals[0]))
  1663.           LEAVE2;
  1664.         as_sdprcatf(&stemp, ")");
  1665.         ExpandLine(stemp.p_str, z1, &CompArgStr);
  1666.       }
  1667.       if (*FArg.str.p_str)
  1668.       {
  1669.         WrError(ErrNum_InvFuncArgCnt);
  1670.         LEAVE2;
  1671.       }
  1672.       StrCompMkTemp(&CompArg, CompArgStr.p_str, CompArgStr.capacity);
  1673.       EvalStrExpression(&CompArg, pErg);
  1674.       pErg->Flags |= PromotedFlags;
  1675.       pErg->AddrSpaceMask |= PromotedAddrSpaceMask;
  1676.       if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = PromotedDataSize;
  1677. func_exit2:
  1678.       as_dynstr_free(&stemp);
  1679.       as_dynstr_free(&CompArgStr);
  1680.       LEAVE;
  1681.     }
  1682.  
  1683.     /* hier einmal umwandeln ist effizienter */
  1684.  
  1685.     NLS_UpString(FName.str.p_str);
  1686.  
  1687.     /* symbolbezogene Funktionen */
  1688.  
  1689.     if (!strcmp(FName.str.p_str, "SYMTYPE"))
  1690.     {
  1691.       as_tempres_set_int(pErg, GetSymbolType(&FArg));
  1692.       LEAVE;
  1693.     }
  1694.  
  1695.     else if (!strcmp(FName.str.p_str, "DEFINED"))
  1696.     {
  1697.       as_tempres_set_int(pErg, !!IsSymbolDefined(&FArg));
  1698.       LEAVE;
  1699.     }
  1700.  
  1701.     else if (!strcmp(FName.str.p_str, "ASSUMEDVAL"))
  1702.     {
  1703.       unsigned IdxAssume;
  1704.  
  1705.       for (IdxAssume = 0; IdxAssume < ASSUMERecCnt; IdxAssume++)
  1706.         if (!as_strcasecmp(FArg.str.p_str, pASSUMERecs[IdxAssume].Name))
  1707.         {
  1708.           as_tempres_set_int(pErg, *(pASSUMERecs[IdxAssume].Dest));
  1709.           LEAVE;
  1710.         }
  1711.       WrStrErrorPos(ErrNum_SymbolUndef, &FArg);
  1712.       LEAVE;
  1713.     }
  1714.  
  1715.     /* Unterausdruck auswerten (interne Funktionen maxmimal mit drei Argumenten) */
  1716.  
  1717.     cnt = 0;
  1718.     PromotedFlags = eSymbolFlag_None;
  1719.     PromotedAddrSpaceMask = 0;
  1720.     PromotedDataSize = eSymbolSizeUnknown;
  1721.     do
  1722.     {
  1723.       zp = QuotPos(FArg.str.p_str, ',');
  1724.       if (zp)
  1725.         StrCompSplitRef(&InArgs[cnt], &Remainder, &FArg, zp);
  1726.       else
  1727.         InArgs[cnt] = FArg;
  1728.       if (cnt < 3)
  1729.       {
  1730.         EvalStrExpression(&InArgs[cnt], &InVals[cnt]);
  1731.         if (InVals[cnt].Typ == TempNone)
  1732.           LEAVE;
  1733.         TReloc = InVals[cnt].Relocs;
  1734.       }
  1735.       else
  1736.       {
  1737.         WrError(ErrNum_InvFuncArgCnt);
  1738.         LEAVE;
  1739.       }
  1740.       if (TReloc)
  1741.       {
  1742.         WrStrErrorPos(ErrNum_NoRelocs, &InArgs[cnt]);
  1743.         FreeRelocs(&TReloc);
  1744.         LEAVE;
  1745.       }
  1746.       if (zp)
  1747.         FArg = Remainder;
  1748.       PromotedFlags |= InVals[cnt].Flags & eSymbolFlags_Promotable;
  1749.       PromotedAddrSpaceMask |= InVals[cnt].AddrSpaceMask;
  1750.       if (PromotedDataSize == eSymbolSizeUnknown) PromotedDataSize = InVals[0].DataSize;
  1751.       cnt++;
  1752.     }
  1753.     while (zp);
  1754.  
  1755.     /* search function */
  1756.  
  1757.     pFunction = function_find(FName.str.p_str);
  1758.     if (!pFunction)
  1759.     {
  1760.       WrStrErrorPos(ErrNum_UnknownFunc, &FName);
  1761.       LEAVE;
  1762.     }
  1763.  
  1764.     /* argument checking */
  1765.  
  1766.     if ((cnt < pFunction->MinNumArgs) || (cnt > pFunction->MaxNumArgs))
  1767.     {
  1768.       WrError(ErrNum_InvFuncArgCnt);
  1769.       LEAVE;
  1770.     }
  1771.     for (z1 = 0; z1 < cnt; z1++)
  1772.     {
  1773.       if ((InVals[z1].Typ == TempInt) && !(pFunction->ArgTypes[z1] & TempInt))
  1774.         TempResultToFloat(&InVals[z1]);
  1775.       if (!(pFunction->ArgTypes[z1] & InVals[z1].Typ))
  1776.       {
  1777.         WrStrErrorPos(DeduceExpectTypeErrMsgMask(pFunction->ArgTypes[z1], InVals[z1].Typ), &InArgs[z1]);
  1778.         LEAVE;
  1779.       }
  1780.     }
  1781.     if (!pFunction->pFunc(pErg, InVals, cnt))
  1782.     {
  1783.       WrStrErrorPos(ErrNum_UnknownFunc, &FName);
  1784.       LEAVE;
  1785.     }
  1786.     pErg->Flags |= PromotedFlags;
  1787.     pErg->AddrSpaceMask |= PromotedAddrSpaceMask;
  1788.     if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = PromotedDataSize;
  1789.  
  1790.     LEAVE;
  1791.   }
  1792.  
  1793.   /* nichts dergleichen, dann einfaches Symbol: urspruenglichen Wert wieder
  1794.      herstellen, dann Pruefung auf $$-temporaere Symbole */
  1795.  
  1796.   StrCompCopy(&CopyComp, &STempComp);
  1797.   KillPrefBlanksStrComp(&CopyComp);
  1798.   KillPostBlanksStrComp(&CopyComp);
  1799.  
  1800.   ChkTmp1(CopyComp.str.p_str, e_symbol_source_none);
  1801.  
  1802.   /* interne Symbole ? */
  1803.  
  1804.   if (!as_strcasecmp(CopyComp.str.p_str, "MOMFILE"))
  1805.   {
  1806.     as_tempres_set_c_str(pErg, CurrFileName);
  1807.     LEAVE;
  1808.   }
  1809.  
  1810.   if (!as_strcasecmp(CopyComp.str.p_str, "MOMLINE"))
  1811.   {
  1812.     as_tempres_set_int(pErg, CurrLine);
  1813.     LEAVE;
  1814.   }
  1815.  
  1816.   if (!as_strcasecmp(CopyComp.str.p_str, "MOMPASS"))
  1817.   {
  1818.     as_tempres_set_int(pErg, PassNo);
  1819.     LEAVE;
  1820.   }
  1821.  
  1822.   if (!as_strcasecmp(CopyComp.str.p_str, "MOMSECTION"))
  1823.   {
  1824.     as_tempres_set_c_str(pErg, GetSectionName(MomSectionHandle));
  1825.     LEAVE;
  1826.   }
  1827.  
  1828.   if (!as_strcasecmp(CopyComp.str.p_str, "MOMSEGMENT"))
  1829.   {
  1830.     as_tempres_set_c_str(pErg, SegNames[ActPC]);
  1831.     LEAVE;
  1832.   }
  1833.  
  1834.   /* plain symbol */
  1835.  
  1836.   LookupSymbol(&CopyComp, pErg, True, TempAll);
  1837.  
  1838. func_exit:
  1839.  
  1840.   StrCompFree(&CopyComp);
  1841.   StrCompFree(&STempComp);
  1842.  
  1843.   for (z1 = 0; z1 < 3; z1++)
  1844.   {
  1845.     if (InVals[z1].Relocs)
  1846.       FreeRelocs(&InVals[z1].Relocs);
  1847.     as_tempres_free(&InVals[z1]);
  1848.   }
  1849. }
  1850.  
  1851. void EvalExpression(const char *pExpr, TempResult *pErg)
  1852. {
  1853.   tStrComp Expr;
  1854.  
  1855.   StrCompMkTemp(&Expr, (char*)pExpr, 0);
  1856.   EvalStrExpression(&Expr, pErg);
  1857. }
  1858.  
  1859. LargeInt EvalStrIntExpressionWithResult(const tStrComp *pComp, IntType Type, tEvalResult *pResult)
  1860. {
  1861.   TempResult t;
  1862.   LargeInt Result = -1;
  1863.  
  1864.   as_tempres_ini(&t);
  1865.   EvalResultClear(pResult);
  1866.  
  1867.   EvalStrExpression(pComp, &t);
  1868.   SetRelocs(t.Relocs);
  1869.  
  1870.   switch (t.Typ)
  1871.   {
  1872.     case TempInt:
  1873.       Result = t.Contents.Int;
  1874.       pResult->Flags = t.Flags;
  1875.       pResult->AddrSpaceMask = t.AddrSpaceMask;
  1876.       pResult->DataSize = t.DataSize;
  1877.       break;
  1878.     case TempString:
  1879.     {
  1880.       int l = t.Contents.str.len;
  1881.  
  1882.       if ((l > 0) && (l <= 4))
  1883.       {
  1884.         int ret = NonZString2Int(&t.Contents.str, &Result);
  1885.  
  1886.         if (ENOENT == ret)
  1887.         {
  1888.           WrStrErrorPos(ErrNum_UnmappedChar, pComp);
  1889.           FreeRelocs(&LastRelocs);
  1890.           LEAVE;
  1891.         }
  1892.         pResult->Flags = t.Flags;
  1893.         pResult->AddrSpaceMask = t.AddrSpaceMask;
  1894.         pResult->DataSize = t.DataSize;
  1895.         break;
  1896.       }
  1897.       else
  1898.       {
  1899.         WrStrErrorPos(ErrNum_IntButString, pComp);
  1900.         FreeRelocs(&LastRelocs);
  1901.         LEAVE;
  1902.       }
  1903.     }
  1904.     /* else fall-through */
  1905.     default:
  1906.       if (t.Typ != TempNone)
  1907.         WrStrErrorPos(DeduceExpectTypeErrMsgMask(TempInt | TempString, t.Typ), pComp);
  1908.       FreeRelocs(&LastRelocs);
  1909.       LEAVE;
  1910.   }
  1911.  
  1912.   if (mFirstPassUnknown(t.Flags))
  1913.     Result &= IntTypeDefs[(int)Type].Mask;
  1914.  
  1915.   pResult->OK = HardRanges ? ChkRangeByType(Result, Type, pComp) : ChkRangeWarnByType(Result, Type, pComp);
  1916.   if (!pResult->OK)
  1917.   {
  1918.     if (HardRanges)
  1919.     {
  1920.       FreeRelocs(&LastRelocs);
  1921.       Result = -1;
  1922.       LEAVE;
  1923.     }
  1924.     else
  1925.     {
  1926.       pResult->OK = True;
  1927.       Result &= IntTypeDefs[(int)Type].Mask;
  1928.     }
  1929.   }
  1930.  
  1931. func_exit:
  1932.   as_tempres_free(&t);
  1933.   return Result;
  1934. }
  1935.  
  1936. LargeInt EvalStrIntExpressionWithFlags(const tStrComp *pComp, IntType Type, Boolean *pResult, tSymbolFlags *pFlags)
  1937. {
  1938.   tEvalResult EvalResult;
  1939.   LargeInt Result = EvalStrIntExpressionWithResult(pComp, Type, &EvalResult);
  1940.  
  1941.   *pResult = EvalResult.OK;
  1942.   if (pFlags)
  1943.     *pFlags = EvalResult.Flags;
  1944.   return Result;
  1945. }
  1946.  
  1947. LargeInt EvalStrIntExpression(const tStrComp *pComp, IntType Type, Boolean *pResult)
  1948. {
  1949.   tEvalResult EvalResult;
  1950.   LargeInt Result = EvalStrIntExpressionWithResult(pComp, Type, &EvalResult);
  1951.  
  1952.   *pResult = EvalResult.OK;
  1953.   return Result;
  1954. }
  1955.  
  1956. LargeInt EvalStrIntExpressionOffsWithResult(const tStrComp *pExpr, int Offset, IntType Type, tEvalResult *pResult)
  1957. {
  1958.   if (Offset)
  1959.   {
  1960.     tStrComp Comp;
  1961.  
  1962.     StrCompRefRight(&Comp, pExpr, Offset);
  1963.     return EvalStrIntExpressionWithResult(&Comp, Type, pResult);
  1964.   }
  1965.   else
  1966.     return EvalStrIntExpressionWithResult(pExpr, Type, pResult);
  1967. }
  1968.  
  1969. LargeInt EvalStrIntExpressionOffsWithFlags(const tStrComp *pComp, int Offset, IntType Type, Boolean *pResult, tSymbolFlags *pFlags)
  1970. {
  1971.   tEvalResult EvalResult;
  1972.   LargeInt Result = EvalStrIntExpressionOffsWithResult(pComp, Offset, Type, &EvalResult);
  1973.  
  1974.   *pResult = EvalResult.OK;
  1975.   if (pFlags)
  1976.     *pFlags = EvalResult.Flags;
  1977.   return Result;
  1978. }
  1979.  
  1980. LargeInt EvalStrIntExpressionOffs(const tStrComp *pComp, int Offset, IntType Type, Boolean *pResult)
  1981. {
  1982.   tEvalResult EvalResult;
  1983.   LargeInt Result = EvalStrIntExpressionOffsWithResult(pComp, Offset, Type, &EvalResult);
  1984.  
  1985.   *pResult = EvalResult.OK;
  1986.   return Result;
  1987. }
  1988.  
  1989. Double EvalStrFloatExpressionWithResult(const tStrComp *pExpr, FloatType Type, tEvalResult *pResult)
  1990. {
  1991.   TempResult t;
  1992.   Double Result = -1;
  1993.  
  1994.   as_tempres_ini(&t);
  1995.   EvalResultClear(pResult);
  1996.  
  1997.   EvalStrExpression(pExpr, &t);
  1998.   switch (t.Typ)
  1999.   {
  2000.     case TempNone:
  2001.       LEAVE;
  2002.     case TempInt:
  2003.       Result = t.Contents.Int;
  2004.       pResult->Flags = t.Flags;
  2005.       pResult->AddrSpaceMask = t.AddrSpaceMask;
  2006.       pResult->DataSize = t.DataSize;
  2007.       break;
  2008.     case TempString:
  2009.     {
  2010.       WrStrErrorPos(ErrNum_FloatButString, pExpr);
  2011.       LEAVE;
  2012.     }
  2013.     default:
  2014.       Result = t.Contents.Float;
  2015.   }
  2016.  
  2017.   if (!FloatRangeCheck(Result, Type))
  2018.   {
  2019.     WrStrErrorPos(ErrNum_OverRange, pExpr);
  2020.     LEAVE;
  2021.   }
  2022.  
  2023.   pResult->OK = True;
  2024. func_exit:
  2025.   as_tempres_free(&t);
  2026.   return Result;
  2027. }
  2028.  
  2029. Double EvalStrFloatExpression(const tStrComp *pExpr, FloatType Type, Boolean *pResult)
  2030. {
  2031.   Double Ret;
  2032.   tEvalResult Result;
  2033.  
  2034.   Ret = EvalStrFloatExpressionWithResult(pExpr, Type, &Result);
  2035.   *pResult = Result.OK;
  2036.   return Ret;
  2037. }
  2038.  
  2039. void EvalStrStringExpressionWithResult(const tStrComp *pExpr, tEvalResult *pResult, char *pEvalResult)
  2040. {
  2041.   TempResult t;
  2042.  
  2043.   as_tempres_ini(&t);
  2044.   EvalResultClear(pResult);
  2045.  
  2046.   EvalStrExpression(pExpr, &t);
  2047.   if (t.Typ != TempString)
  2048.   {
  2049.     *pEvalResult = '\0';
  2050.     if (t.Typ != TempNone)
  2051.     {
  2052.       if (mFirstPassUnknown(t.Flags))
  2053.       {
  2054.         *pEvalResult = '\0';
  2055.         pResult->Flags = t.Flags;
  2056.         pResult->AddrSpaceMask = t.AddrSpaceMask;
  2057.         pResult->DataSize = t.DataSize;
  2058.         pResult->OK = True;
  2059.       }
  2060.       else
  2061.         WrStrErrorPos(DeduceExpectTypeErrMsgMask(TempString, t.Typ), pExpr);
  2062.     }
  2063.   }
  2064.   else
  2065.   {
  2066.     as_nonz_dynstr_to_c_str(pEvalResult, &t.Contents.str, STRINGSIZE);
  2067.     pResult->Flags = t.Flags;
  2068.     pResult->AddrSpaceMask = t.AddrSpaceMask;
  2069.     pResult->DataSize = t.DataSize;
  2070.     pResult->OK = True;
  2071.   }
  2072.   as_tempres_free(&t);
  2073. }
  2074.  
  2075. void EvalStrStringExpression(const tStrComp *pExpr, Boolean *pResult, char *pEvalResult)
  2076. {
  2077.   tEvalResult Result;
  2078.  
  2079.   EvalStrStringExpressionWithResult(pExpr, &Result, pEvalResult);
  2080.   *pResult = Result.OK;
  2081. }
  2082.  
  2083. /*!------------------------------------------------------------------------
  2084.  * \fn     EvalStrRegExpressionWithResult(const struct sStrComp *pExpr, struct sRegDescr *pResult, struct sEvalResult *pEvalResult, Boolean IssueErrors)
  2085.  * \brief  retrieve/evaluate register expression
  2086.  * \param  pExpr source code expression
  2087.  * \param  pResult retrieved register
  2088.  * \param  pEvalResult success flag, symbol size & flags
  2089.  * \param  IssueErrors print errors at all?
  2090.  * \param  p_error_on_find True if error on symbol resolution and not just not found
  2091.  * \return occured error
  2092.  * ------------------------------------------------------------------------ */
  2093.  
  2094. tErrorNum EvalStrRegExpressionWithResult(const struct sStrComp *pExpr, tRegDescr *pResult, tEvalResult *pEvalResult)
  2095. {
  2096.   PSymbolEntry pEntry;
  2097.  
  2098.   EvalResultClear(pEvalResult);
  2099.  
  2100.   pEntry = ExpandAndFindNode(pExpr, TempReg, True, e_expand_chk_empty_upto, NULL);
  2101.   if (!pEntry)
  2102.     return ErrNum_SymbolUndef;
  2103.  
  2104.   pEntry->Used = True;
  2105.   pEvalResult->DataSize = pEntry->SymWert.DataSize;
  2106.  
  2107.   if (pEntry->SymWert.Typ != TempReg)
  2108.     return ErrNum_ExpectReg;
  2109.   *pResult = pEntry->SymWert.Contents.RegDescr;
  2110.  
  2111.   if (pEntry->SymWert.Contents.RegDescr.Dissect != DissectReg)
  2112.     return ErrNum_RegWrongTarget;
  2113.  
  2114.   pEvalResult->OK = True;
  2115.   return ErrNum_None;
  2116. }
  2117.  
  2118. /*!------------------------------------------------------------------------
  2119.  * \fn     EvalStrRegExpressionAsOperand(const tStrComp *pArg, struct sRegDescr *pResult, struct sEvalResult *pEvalResult, tSymbolSize ReqSize, Boolean MustBeReg)
  2120.  * \brief  check for possible register in instruction operand
  2121.  * \param  pArg source argument
  2122.  * \param  ReqSize possible fixed operand size
  2123.  * \param  MustBeReg operand cannot be anything else but register
  2124.  * \return eIsReg: argument is a register
  2125.            eIsNoReg: argument is no register
  2126.            eRegAbort: argument is faulty, abort anyway (only if !MustBeReg)
  2127.  * ------------------------------------------------------------------------ */
  2128.  
  2129. tRegEvalResult EvalStrRegExpressionAsOperand(const tStrComp *pArg, struct sRegDescr *pResult, struct sEvalResult *pEvalResult, tSymbolSize ReqSize, Boolean MustBeReg)
  2130. {
  2131.   tErrorNum ErrorNum;
  2132.  
  2133.   ErrorNum = EvalStrRegExpressionWithResult(pArg, pResult, pEvalResult);
  2134.   if (pEvalResult->OK && (ReqSize != eSymbolSizeUnknown) && (pEvalResult->DataSize != ReqSize))
  2135.   {
  2136.     pEvalResult->OK = False;
  2137.     ErrorNum = ErrNum_InvOpSize;
  2138.   }
  2139.   switch (ErrorNum)
  2140.   {
  2141.     case ErrNum_None:
  2142.       return eIsReg;
  2143.     case ErrNum_SymbolUndef:
  2144.       if (MustBeReg)
  2145.       {
  2146.         if (PassNo <= MaxSymPass)
  2147.         {
  2148.           pResult->Reg = 0;
  2149.           pResult->Dissect = NULL;
  2150.           pResult->compare = NULL;
  2151.           Repass = True;
  2152.           return eIsReg;
  2153.         }
  2154.         else
  2155.         {
  2156.           WrStrErrorPos(ErrNum_InvReg, pArg);
  2157.           return eIsNoReg;
  2158.         }
  2159.       }
  2160.       else
  2161.         return eIsNoReg;
  2162.     case ErrNum_ExpectReg:
  2163.       if (MustBeReg)
  2164.         WrStrErrorPos(ErrorNum, pArg);
  2165.       return eIsNoReg;
  2166.     default:
  2167.       WrStrErrorPos(ErrorNum, pArg);
  2168.       return MustBeReg ? eIsNoReg : eRegAbort;
  2169.   }
  2170. }
  2171.  
  2172. static void FreeSymbolEntry(PSymbolEntry *Node, Boolean Destroy)
  2173. {
  2174.   PCrossRef Lauf;
  2175.  
  2176.   if ((*Node)->Tree.Name)
  2177.   {
  2178.     free((*Node)->Tree.Name);
  2179.    (*Node)->Tree.Name = NULL;
  2180.   }
  2181.  
  2182.   as_tempres_free(&(*Node)->SymWert);
  2183.  
  2184.   while ((*Node)->RefList)
  2185.   {
  2186.     Lauf = (*Node)->RefList->Next;
  2187.     free((*Node)->RefList);
  2188.     (*Node)->RefList = Lauf;
  2189.   }
  2190.  
  2191.   FreeRelocs(&((*Node)->SymWert.Relocs));
  2192.  
  2193.   if (Destroy)
  2194.   {
  2195.     free(*Node);
  2196.     Node = NULL;
  2197.   }
  2198. }
  2199.  
  2200. static char *serr, *snum;
  2201. typedef struct
  2202. {
  2203.   Boolean MayChange, DoCross;
  2204. } TEnterStruct, *PEnterStruct;
  2205.  
  2206. static Boolean SymbolAdder(PTree *PDest, PTree Neu, void *pData)
  2207. {
  2208.   PSymbolEntry NewEntry = (PSymbolEntry)Neu, *Node;
  2209.   PEnterStruct EnterStruct = (PEnterStruct) pData;
  2210.  
  2211.   /* added to an empty leaf ? */
  2212.  
  2213.   if (!PDest)
  2214.   {
  2215.     NewEntry->Defined = True;
  2216.     NewEntry->Used = False;
  2217.     NewEntry->Changeable = EnterStruct->MayChange;
  2218.     NewEntry->RefList = NULL;
  2219.     if (EnterStruct->DoCross)
  2220.     {
  2221.       NewEntry->FileNum = GetFileNum(CurrFileName);
  2222.       NewEntry->LineNum = CurrLine;
  2223.     }
  2224.     return True;
  2225.   }
  2226.  
  2227.   /* replace en entry: check for validity */
  2228.  
  2229.   Node = (PSymbolEntry*)PDest;
  2230.  
  2231.   /* tried to redefine a symbol with EQU ? */
  2232.  
  2233.   if (((*Node)->Defined) && (!(*Node)->Changeable) && (!EnterStruct->MayChange))
  2234.   {
  2235.     strmaxcpy(serr, (*Node)->Tree.Name, STRINGSIZE);
  2236.     if (EnterStruct->DoCross)
  2237.       as_snprcatf(serr, STRINGSIZE, ",%s %s:%ld",
  2238.                   getmessage(Num_PrevDefMsg),
  2239.                   GetFileName((*Node)->FileNum), (long)((*Node)->LineNum));
  2240.     WrXError(ErrNum_DoubleDef, serr);
  2241.     FreeSymbolEntry(&NewEntry, TRUE);
  2242.     return False;
  2243.   }
  2244.  
  2245.   /* tried to reassign a constant (EQU) a value with SET and vice versa ? */
  2246.  
  2247.   else if ( ((*Node)->Defined) && (EnterStruct->MayChange != (*Node)->Changeable) )
  2248.   {
  2249.     strmaxcpy(serr, (*Node)->Tree.Name, STRINGSIZE);
  2250.     if (EnterStruct->DoCross)
  2251.       as_snprcatf(serr, STRINGSIZE, ",%s %s:%ld",
  2252.                   getmessage(Num_PrevDefMsg),
  2253.                   GetFileName((*Node)->FileNum), (long)((*Node)->LineNum));
  2254.     WrXError((*Node)->Changeable ? ErrNum_VariableRedefinedAsConstant : ErrNum_ConstantRedefinedAsVariable, serr);
  2255.     FreeSymbolEntry(&NewEntry, TRUE);
  2256.     return False;
  2257.   }
  2258.  
  2259.   else
  2260.   {
  2261.     if (!EnterStruct->MayChange)
  2262.     {
  2263.       Boolean value_changed;
  2264.  
  2265. #if 0
  2266.       if (NewEntry->SymWert.Typ == TempInt)
  2267.         fprintf(stderr, "NewEntry 0x%lx Node 0x%lx Node changed %d\n",
  2268.                 NewEntry->SymWert.Contents.Int, (*Node)->SymWert.Contents.Int, (*Node)->changed);
  2269. #endif
  2270.  
  2271.       /* If the symbol value was changed after entry (padding of label),
  2272.          compare to the originally set value, because this is what we get
  2273.          here as initial value to set (before padding) in the next pass: */
  2274.  
  2275.       if (NewEntry->SymWert.Typ != (*Node)->SymWert.Typ)
  2276.         value_changed = True;
  2277.       else switch (NewEntry->SymWert.Typ)
  2278.       {
  2279.         case TempInt:
  2280.           value_changed = NewEntry->SymWert.Contents.Int != ((*Node)->changed ? (*Node)->unchanged_value : (*Node)->SymWert.Contents.Int);
  2281.           break;
  2282.         default:
  2283.           value_changed = !!as_tempres_cmp(&NewEntry->SymWert, &(*Node)->SymWert);
  2284.       }
  2285.       if (value_changed)
  2286.       {
  2287.         if (!Repass && (JmpErrors > 0))
  2288.         {
  2289.           if (ThrowErrors)
  2290.             ErrorCount -= JmpErrors;
  2291.           JmpErrors = 0;
  2292.         }
  2293.         Repass = True;
  2294.         if (MsgIfRepass && (PassNo >= PassNoForMessage))
  2295.         {
  2296.           strmaxcpy(serr, Neu->Name, STRINGSIZE);
  2297.           if (Neu->Attribute != -1)
  2298.           {
  2299.             strmaxcat(serr, "[", STRINGSIZE);
  2300.             strmaxcat(serr, GetSectionName(Neu->Attribute), STRINGSIZE);
  2301.             strmaxcat(serr, "]", STRINGSIZE);
  2302.           }
  2303.           WrXError(ErrNum_PhaseErr, serr);
  2304.         }
  2305.       }
  2306.     }
  2307.     if (EnterStruct->DoCross)
  2308.     {
  2309.       NewEntry->LineNum = (*Node)->LineNum;
  2310.       NewEntry->FileNum = (*Node)->FileNum;
  2311.     }
  2312.  
  2313.     /* take over values from existing node that shall be kept */
  2314.  
  2315.     NewEntry->RefList = (*Node)->RefList;
  2316.     (*Node)->RefList = NULL;
  2317.     NewEntry->Defined = True;
  2318.     NewEntry->Used = (*Node)->Used;
  2319.     NewEntry->Changeable = EnterStruct->MayChange;
  2320.  
  2321.     /* since NewEntry will be copied over Node, free the latter's dynamic data: */
  2322.  
  2323.     FreeSymbolEntry(Node, False);
  2324.     return True;
  2325.   }
  2326. }
  2327.  
  2328. static void EnterLocSymbol(PSymbolEntry Neu)
  2329. {
  2330.   TEnterStruct EnterStruct;
  2331.   PTree TreeRoot;
  2332.  
  2333.   Neu->Tree.Attribute = MomLocHandle;
  2334.   EnterStruct.MayChange = EnterStruct.DoCross = FALSE;
  2335.   TreeRoot = &FirstLocSymbol->Tree;
  2336.   EnterTree(&TreeRoot, (&Neu->Tree), SymbolAdder, &EnterStruct);
  2337.   FirstLocSymbol = (PSymbolEntry)TreeRoot;
  2338. }
  2339.  
  2340. static Boolean EnterSymbol_SearchAndUnchain(PSymbolEntry Neu, PForwardSymbol *pp_root, LongInt *p_override_section)
  2341. {
  2342.   PForwardSymbol p_run, p_prev;
  2343.  
  2344.   for (p_run = *pp_root, p_prev= NULL;
  2345.        p_run;
  2346.        p_prev = p_run, p_run = p_run->Next)
  2347.     if (!strcmp(p_run->Name, Neu->Tree.Name))
  2348.     {
  2349.       *p_override_section = p_run->DestSection;
  2350.       if (!p_prev)
  2351.         *pp_root = p_run->Next;
  2352.       else
  2353.         p_prev->Next = p_run->Next;
  2354.       free_forward_symbol(p_run);
  2355.       return True;
  2356.     }
  2357.   return False;
  2358. }
  2359.  
  2360. static void EnterSymbol(PSymbolEntry Neu, Boolean MayChange, LongInt ResHandle)
  2361. {
  2362.   String CombName;
  2363.   PSaveSection RunSect;
  2364.   LongInt MSect;
  2365.   PSymbolEntry Copy;
  2366.   TEnterStruct EnterStruct;
  2367.   PTree TreeRoot = &(FirstSymbol->Tree);
  2368.  
  2369.   EnterStruct.MayChange = MayChange;
  2370.   EnterStruct.DoCross = MakeCrossList;
  2371.   Neu->Tree.Attribute = (ResHandle == -2) ? MomSectionHandle : ResHandle;
  2372.  
  2373.   /* Within a section: special treatment for FORWARD, PUBLIC and GLOBAL: */
  2374.  
  2375.   if (SectionStack && (Neu->Tree.Attribute == MomSectionHandle))
  2376.   {
  2377.     LongInt override_section;
  2378.  
  2379.     /* FORWARD: just an info to avoid resolution to global symbol.  This symbol remains
  2380.        in current section: */
  2381.  
  2382.     if (EnterSymbol_SearchAndUnchain(Neu, &(SectionStack->LocSyms), &override_section))
  2383.     { }
  2384.  
  2385.     /* PUBLIC: relocate scope of symbol to given section: */
  2386.  
  2387.     else if (EnterSymbol_SearchAndUnchain(Neu, &(SectionStack->GlobSyms), &override_section))
  2388.       Neu->Tree.Attribute = override_section;
  2389.  
  2390.     /* GLOBAL: create copy with scope in given section: */
  2391.  
  2392.     else if (EnterSymbol_SearchAndUnchain(Neu, &(SectionStack->ExportSyms), &override_section))
  2393.     {
  2394.       strmaxcpy(CombName, Neu->Tree.Name, STRINGSIZE);
  2395.       RunSect = SectionStack;
  2396.       MSect = MomSectionHandle;
  2397.       while ((MSect != override_section) && (RunSect))
  2398.       {
  2399.         strmaxprep(CombName, "_", STRINGSIZE);
  2400.         strmaxprep(CombName, GetSectionName(MSect), STRINGSIZE);
  2401.         MSect = RunSect->Handle;
  2402.         RunSect = RunSect->Next;
  2403.       }
  2404.       Copy = (PSymbolEntry) calloc(1, sizeof(TSymbolEntry));
  2405.       *Copy = (*Neu);
  2406.       Copy->Tree.Name = as_strdup(CombName);
  2407.       Copy->Tree.Attribute = override_section;
  2408.       Copy->SymWert.Relocs = DupRelocs(Neu->SymWert.Relocs);
  2409.       if (Copy->SymWert.Typ == TempString)
  2410.       {
  2411.         size_t l = Neu->SymWert.Contents.str.len;
  2412.         Copy->SymWert.Contents.str.p_str = (char*)malloc(l);
  2413.         memcpy(Copy->SymWert.Contents.str.p_str, Neu->SymWert.Contents.str.p_str,
  2414.                Copy->SymWert.Contents.str.len = Copy->SymWert.Contents.str.capacity = l);
  2415.       }
  2416.       EnterTree(&TreeRoot, &(Copy->Tree), SymbolAdder, &EnterStruct);
  2417.     }
  2418.   }
  2419.   EnterTree(&TreeRoot, &(Neu->Tree), SymbolAdder, &EnterStruct);
  2420.   FirstSymbol = (PSymbolEntry)TreeRoot;
  2421. }
  2422.  
  2423. void PrintSymTree(char *Name)
  2424. {
  2425.   fprintf(Debug, "---------------------\n");
  2426.   fprintf(Debug, "Enter Symbol %s\n\n", Name);
  2427.   PrintSymbolTree();
  2428.   PrintSymbolDepth();
  2429. }
  2430.  
  2431. /*!------------------------------------------------------------------------
  2432.  * \fn     ChangeSymbol(PSymbolEntry pEntry, LargeInt Value)
  2433.  * \brief  change value of symbol in symbol table (use with caution)
  2434.  * \param  pEntry symbol entry to modify
  2435.  * \param  Value new (integer)value
  2436.  * ------------------------------------------------------------------------ */
  2437.  
  2438. void ChangeSymbol(PSymbolEntry pEntry, LargeInt Value)
  2439. {
  2440.   if (!pEntry->changed)
  2441.   {
  2442.     pEntry->unchanged_value = (pEntry->SymWert.Typ == TempInt) ? pEntry->SymWert.Contents.Int : 0;
  2443.     pEntry->changed = True;
  2444.   }
  2445.   as_tempres_set_int(&pEntry->SymWert, Value);
  2446. }
  2447.  
  2448. /*!------------------------------------------------------------------------
  2449.  * \fn     CreateSymbolEntry(const tStrComp *pName, LongInt *pDestHandle, tSymbolFlags symbol_flags)
  2450.  * \brief  create empty container for symbol table entry
  2451.  * \param  pName unexpanded symbol name
  2452.  * \param  pDestHandle section handle (out)
  2453.  * \param  symbol_flags symbol flags
  2454.  * \return * to container or NULL
  2455.  * ------------------------------------------------------------------------ */
  2456.  
  2457. PSymbolEntry CreateSymbolEntry(const tStrComp *pName, LongInt *pDestHandle, tSymbolFlags symbol_flags)
  2458. {
  2459.   PSymbolEntry pNeu = NULL;
  2460.   String exp_name_buf;
  2461.   tStrComp *p_exp_name, exp_name;
  2462.  
  2463.   StrCompMkTemp(&exp_name, exp_name_buf, sizeof exp_name_buf);
  2464.   p_exp_name = ExpandStrSymbol(&exp_name, pName, !CaseSensitive);
  2465.   if (!p_exp_name)
  2466.     LEAVE;
  2467.   if (!GetSymSection(p_exp_name, pDestHandle, pName))
  2468.     LEAVE;
  2469.   (void)ChkTmp(p_exp_name->str.p_str, (symbol_flags & eSymbolFlag_Label) ? e_symbol_source_label : e_symbol_source_define);
  2470.   if (!ChkSymbName(p_exp_name->str.p_str))
  2471.   {
  2472.     WrStrErrorPos(ErrNum_InvSymName, pName);
  2473.     LEAVE;
  2474.   }
  2475.   pNeu = (PSymbolEntry) calloc(1, sizeof(TSymbolEntry));
  2476.   pNeu->Tree.Name = as_strdup(p_exp_name->str.p_str);
  2477.   as_tempres_ini(&pNeu->SymWert);
  2478. func_exit:
  2479.   StrCompFree(&exp_name);
  2480.   return pNeu;
  2481. }
  2482.  
  2483. /*!------------------------------------------------------------------------
  2484.  * \fn     EnterIntSymbolWithFlags(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange, tSymbolFlags Flags)
  2485.  * \brief  add integer symbol to symbol table
  2486.  * \param  pName unexpanded name
  2487.  * \param  Wert integer value
  2488.  * \param  addrspace symbol's address space
  2489.  * \param  MayChange constant or variable?
  2490.  * \param  Flags additional flags
  2491.  * \return * to newly created entry in tree
  2492.  * ------------------------------------------------------------------------ */
  2493.  
  2494. PSymbolEntry EnterIntSymbolWithFlags(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange, tSymbolFlags Flags)
  2495. {
  2496.   LongInt DestHandle;
  2497.   PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, Flags);
  2498.  
  2499.   if (!pNeu)
  2500.     return NULL;
  2501.  
  2502.   as_tempres_set_int(&pNeu->SymWert, Wert);
  2503.   pNeu->SymWert.AddrSpaceMask = (addrspace != SegNone) ? 1 << addrspace : 0;
  2504.   pNeu->SymWert.Flags = Flags;
  2505.   pNeu->SymWert.DataSize = eSymbolSizeUnknown;
  2506.   pNeu->RefList = NULL;
  2507.   pNeu->SymWert.Relocs = NULL;
  2508.  
  2509.   if ((MomLocHandle == -1) || (DestHandle != -2))
  2510.   {
  2511.     EnterSymbol(pNeu, MayChange, DestHandle);
  2512.     if (MakeDebug)
  2513.       PrintSymTree(pNeu->Tree.Name);
  2514.   }
  2515.   else
  2516.     EnterLocSymbol(pNeu);
  2517.   return pNeu;
  2518. }
  2519.  
  2520. /*!------------------------------------------------------------------------
  2521.  * \fn     EnterExtSymbol(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange)
  2522.  * \brief  create extended symbol
  2523.  * \param  pName unexpanded name
  2524.  * \param  Wert symbol value
  2525.  * \param  AddrSpace symbol's address space
  2526.  * \param  MayChange variable or constant?
  2527.  * ------------------------------------------------------------------------ */
  2528.  
  2529. void EnterExtSymbol(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange)
  2530. {
  2531.   LongInt DestHandle;
  2532.   PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, eSymbolFlag_None);
  2533.  
  2534.   if (!pNeu)
  2535.     return;
  2536.  
  2537.   as_tempres_set_int(&pNeu->SymWert, Wert);  
  2538.   pNeu->SymWert.AddrSpaceMask = (addrspace != SegNone) ? 1 << addrspace : 0;
  2539.   pNeu->SymWert.Flags = eSymbolFlag_None;
  2540.   pNeu->SymWert.DataSize = eSymbolSizeUnknown;
  2541.   pNeu->RefList = NULL;
  2542.   pNeu->SymWert.Relocs = (PRelocEntry) malloc(sizeof(TRelocEntry));
  2543.   pNeu->SymWert.Relocs->Next = NULL;
  2544.   pNeu->SymWert.Relocs->Ref = as_strdup(pNeu->Tree.Name);
  2545.   pNeu->SymWert.Relocs->Add = True;
  2546.  
  2547.   if ((MomLocHandle == -1) || (DestHandle != -2))
  2548.   {
  2549.     EnterSymbol(pNeu, MayChange, DestHandle);
  2550.     if (MakeDebug)
  2551.       PrintSymTree(pNeu->Tree.Name);
  2552.   }
  2553.   else
  2554.     EnterLocSymbol(pNeu);
  2555. }
  2556.  
  2557. /*!------------------------------------------------------------------------
  2558.  * \fn     EnterRelSymbol(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange)
  2559.  * \brief  enter relocatable symbol
  2560.  * \param  pName unexpanded name
  2561.  * \param  Wert symbol value
  2562.  * \param  addrspace symbol's address space
  2563.  * \param  MayChange variable or constant?
  2564.  * \return * to created entry in tree
  2565.  * ------------------------------------------------------------------------ */
  2566.  
  2567. PSymbolEntry EnterRelSymbol(const tStrComp *pName, LargeInt Wert, as_addrspace_t addrspace, Boolean MayChange)
  2568. {
  2569.   LongInt DestHandle;
  2570.   PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, eSymbolFlag_None);
  2571.  
  2572.   if (!pNeu)
  2573.     return NULL;
  2574.  
  2575.   as_tempres_set_int(&pNeu->SymWert, Wert);
  2576.   pNeu->SymWert.AddrSpaceMask = (addrspace != SegNone) ? 1 << addrspace : 0;
  2577.   pNeu->SymWert.Flags = eSymbolFlag_None;
  2578.   pNeu->SymWert.DataSize = eSymbolSizeUnknown;
  2579.   pNeu->RefList = NULL;
  2580.   pNeu->SymWert.Relocs = (PRelocEntry) malloc(sizeof(TRelocEntry));
  2581.   pNeu->SymWert.Relocs->Next = NULL;
  2582.   pNeu->SymWert.Relocs->Ref = as_strdup(RelName_SegStart);
  2583.   pNeu->SymWert.Relocs->Add = True;
  2584.  
  2585.   if ((MomLocHandle == -1) || (DestHandle != -2))
  2586.   {
  2587.     EnterSymbol(pNeu, MayChange, DestHandle);
  2588.     if (MakeDebug)
  2589.       PrintSymTree(pNeu->Tree.Name);
  2590.   }
  2591.   else
  2592.     EnterLocSymbol(pNeu);
  2593.  
  2594.   return pNeu;
  2595. }
  2596.  
  2597. /*!------------------------------------------------------------------------
  2598.  * \fn     EnterFloatSymbol(const tStrComp *pName, Double Wert, Boolean MayChange)
  2599.  * \brief  enter floating point symbol
  2600.  * \param  pName unexpanded name
  2601.  * \param  Wert symbol value
  2602.  * \param  MayChange variable or constant?
  2603.  * ------------------------------------------------------------------------ */
  2604.  
  2605. void EnterFloatSymbol(const tStrComp *pName, Double Wert, Boolean MayChange)
  2606. {
  2607.   LongInt DestHandle;
  2608.   PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, eSymbolFlag_None);
  2609.  
  2610.   if (!pNeu)
  2611.     return;
  2612.  
  2613.   as_tempres_set_float(&pNeu->SymWert, Wert);
  2614.   pNeu->SymWert.AddrSpaceMask = 0;
  2615.   pNeu->SymWert.Flags = eSymbolFlag_None;
  2616.   pNeu->SymWert.DataSize = eSymbolSizeUnknown;
  2617.   pNeu->RefList = NULL;
  2618.   pNeu->SymWert.Relocs = NULL;
  2619.  
  2620.   if ((MomLocHandle == -1) || (DestHandle != -2))
  2621.   {
  2622.     EnterSymbol(pNeu, MayChange, DestHandle);
  2623.     if (MakeDebug)
  2624.       PrintSymTree(pNeu->Tree.Name);
  2625.   }
  2626.   else
  2627.     EnterLocSymbol(pNeu);
  2628. }
  2629.  
  2630. /*!------------------------------------------------------------------------
  2631.  * \fn     EnterNonZStringSymbolWithFlags(const tStrComp *pName, const as_nonz_dynstr_t *p_value, Boolean MayChange, tSymbolFlags Flags)
  2632.  * \brief  enter string symbol
  2633.  * \param  pName unexpanded name
  2634.  * \param  pValue symbol value
  2635.  * \param  MayChange variable or constant?
  2636.  * \param  Flags special symbol flags to store
  2637.  * ------------------------------------------------------------------------ */
  2638.  
  2639. void EnterNonZStringSymbolWithFlags(const tStrComp *pName, const as_nonz_dynstr_t *p_value, Boolean MayChange, tSymbolFlags Flags)
  2640. {
  2641.   LongInt DestHandle;
  2642.   PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, Flags);
  2643.  
  2644.   if (!pNeu)
  2645.     return;
  2646.  
  2647.   /* TODO: TempRes alloc exact len */
  2648.   pNeu->SymWert.Contents.str.p_str = (char*)malloc(p_value->len);
  2649.   memcpy(pNeu->SymWert.Contents.str.p_str, p_value->p_str, p_value->len);
  2650.   pNeu->SymWert.Contents.str.len =
  2651.   pNeu->SymWert.Contents.str.capacity = p_value->len;
  2652.   pNeu->SymWert.Typ = TempString;
  2653.   pNeu->SymWert.AddrSpaceMask = 0;
  2654.   pNeu->SymWert.Flags = Flags;
  2655.   pNeu->SymWert.DataSize = eSymbolSizeUnknown;
  2656.   pNeu->RefList = NULL;
  2657.   pNeu->SymWert.Relocs = NULL;
  2658.  
  2659.   if ((MomLocHandle == -1) || (DestHandle != -2))
  2660.   {
  2661.     EnterSymbol(pNeu, MayChange, DestHandle);
  2662.     if (MakeDebug)
  2663.       PrintSymTree(pNeu->Tree.Name);
  2664.   }
  2665.   else
  2666.     EnterLocSymbol(pNeu);
  2667. }
  2668.  
  2669. /*!------------------------------------------------------------------------
  2670.  * \fn     EnterStringSymbol(const tStrComp *pName, const char *pValue, Boolean MayChange)
  2671.  * \brief  enter string symbol
  2672.  * \param  pName unexpanded name
  2673.  * \param  pValue symbol value
  2674.  * \param  MayChange variable or constant?
  2675.  * ------------------------------------------------------------------------ */
  2676.  
  2677. void EnterStringSymbol(const tStrComp *pName, const char *pValue, Boolean MayChange)
  2678. {
  2679.   as_nonz_dynstr_t NonZString;
  2680.  
  2681.   as_nonz_dynstr_ini_c_str(&NonZString, pValue);
  2682.   EnterNonZStringSymbol(pName, &NonZString, MayChange);
  2683.   as_nonz_dynstr_free(&NonZString);
  2684. }
  2685.  
  2686. /*!------------------------------------------------------------------------
  2687.  * \fn     EnterRegSymbol(const struct sStrComp *pName, const tRegDescr *pDescr, tSymbolSize Size, Boolean MayChange, Boolean AddList)
  2688.  * \brief  enter register symbol
  2689.  * \param  pName unexpanded name
  2690.  * \param  pDescr register's numeric value & associated dissector
  2691.  * \param  Size register's data size
  2692.  * \param  MayChange variable or constant?
  2693.  * \param  AddList add value to listing?
  2694.  * ------------------------------------------------------------------------ */
  2695.  
  2696. void EnterRegSymbol(const struct sStrComp *pName, const tRegDescr *pDescr, tSymbolSize Size, Boolean MayChange, Boolean AddList)
  2697. {
  2698.   LongInt DestHandle;
  2699.   PSymbolEntry pNeu = CreateSymbolEntry(pName, &DestHandle, eSymbolFlag_None);
  2700.  
  2701.   if (!pNeu)
  2702.     return;
  2703.  
  2704.   as_tempres_set_reg(&pNeu->SymWert, pDescr);
  2705.   pNeu->SymWert.AddrSpaceMask = 0;
  2706.   pNeu->SymWert.Flags = eSymbolFlag_None;
  2707.   pNeu->SymWert.DataSize = Size;
  2708.   pNeu->RefList = NULL;
  2709.   pNeu->SymWert.Relocs = NULL;
  2710.  
  2711.   if ((MomLocHandle == -1) || (DestHandle != -2))
  2712.   {
  2713.     EnterSymbol(pNeu, MayChange, DestHandle);
  2714.     if (MakeDebug)
  2715.       PrintSymTree(pNeu->Tree.Name);
  2716.     RegistersDefined = True;
  2717.   }
  2718.   else
  2719.     EnterLocSymbol(pNeu);
  2720.  
  2721.   if (AddList)
  2722.   {
  2723.     *ListLine = '=';
  2724.     pDescr->Dissect(&ListLine[1], STRINGSIZE - 1, pDescr->Reg, Size);
  2725.   }
  2726. }
  2727.  
  2728. static void AddReference(PSymbolEntry Node)
  2729. {
  2730.   PCrossRef Lauf, Neu;
  2731.  
  2732.   /* Speicher belegen */
  2733.  
  2734.   Neu = (PCrossRef) malloc(sizeof(TCrossRef));
  2735.   Neu->LineNum = CurrLine;
  2736.   Neu->OccNum = 1;
  2737.   Neu->Next = NULL;
  2738.  
  2739.   /* passende Datei heraussuchen */
  2740.  
  2741.   Neu->FileNum = GetFileNum(CurrFileName);
  2742.  
  2743.   /* suchen, ob Eintrag schon existiert */
  2744.  
  2745.   Lauf = Node->RefList;
  2746.   while ((Lauf)
  2747.      && ((Lauf->FileNum != Neu->FileNum) || (Lauf->LineNum != Neu->LineNum)))
  2748.    Lauf = Lauf->Next;
  2749.  
  2750.   /* schon einmal in dieser Datei in dieser Zeile aufgetaucht: nur Zaehler
  2751.     rauf: */
  2752.  
  2753.   if (Lauf)
  2754.   {
  2755.     Lauf->OccNum++;
  2756.    free(Neu);
  2757.   }
  2758.  
  2759.   /* ansonsten an Kettenende anhaengen */
  2760.  
  2761.   else if (!Node->RefList) Node->RefList = Neu;
  2762.  
  2763.   else
  2764.   {
  2765.     Lauf = Node->RefList;
  2766.     while (Lauf->Next)
  2767.       Lauf = Lauf->Next;
  2768.     Lauf->Next = Neu;
  2769.   }
  2770. }
  2771.  
  2772. static PSymbolEntry FindGlobNode_FNode(const char *Name, TempType SearchType, LongInt Handle)
  2773. {
  2774.   PSymbolEntry Lauf;
  2775.  
  2776.   Lauf = (PSymbolEntry) SearchTree((PTree)FirstSymbol, Name, Handle);
  2777.  
  2778.   if (Lauf)
  2779.   {
  2780.     if (Lauf->SymWert.Typ & SearchType)
  2781.     {
  2782.       if (MakeCrossList && DoRefs)
  2783.         AddReference(Lauf);
  2784.     }
  2785.     else
  2786.       Lauf = NULL;
  2787.   }
  2788.  
  2789.   return Lauf;
  2790. }
  2791.  
  2792. static Boolean FindGlobNode_FSpec(const char *Name, PForwardSymbol Root)
  2793. {
  2794.   while ((Root) && (strcmp(Root->Name, Name)))
  2795.     Root = Root->Next;
  2796.   return (Root != NULL);
  2797. }
  2798.  
  2799. static PSymbolEntry FindGlobNode(const char *p_name, TempType SearchType, LongInt DestSection)
  2800. {
  2801.   PSaveSection Lauf;
  2802.   PSymbolEntry Result = NULL;
  2803.  
  2804.   if (SectionStack)
  2805.     if (PassNo <= MaxSymPass)
  2806.       if (FindGlobNode_FSpec(p_name, SectionStack->LocSyms)) DestSection = MomSectionHandle;
  2807.  
  2808.   if (DestSection == -2)
  2809.   {
  2810.     Result = FindGlobNode_FNode(p_name, SearchType, MomSectionHandle);
  2811.     if (Result)
  2812.       return Result;
  2813.     Lauf = SectionStack;
  2814.     while (Lauf)
  2815.     {
  2816.       Result = FindGlobNode_FNode(p_name, SearchType, Lauf->Handle);
  2817.       if (Result)
  2818.         break;
  2819.       Lauf = Lauf->Next;
  2820.     }
  2821.   }
  2822.   else
  2823.     Result = FindGlobNode_FNode(p_name, SearchType, DestSection);
  2824.  
  2825.   return Result;
  2826. }
  2827.  
  2828. static PSymbolEntry FindLocNode_FNode(const char *Name, TempType SearchType, LongInt Handle)
  2829. {
  2830.   PSymbolEntry Lauf;
  2831.  
  2832.   Lauf = (PSymbolEntry) SearchTree((PTree)FirstLocSymbol, Name, Handle);
  2833.  
  2834.   if (Lauf)
  2835.   {
  2836.     if (!(Lauf->SymWert.Typ & SearchType))
  2837.       Lauf = NULL;
  2838.   }
  2839.  
  2840.   return Lauf;
  2841. }
  2842.  
  2843. static PSymbolEntry FindLocNode(const char *p_name, TempType SearchType)
  2844. {
  2845.   PLocHandle RunLocHandle;
  2846.   PSymbolEntry Result = NULL;
  2847.  
  2848.   Result = FindLocNode_FNode(p_name, SearchType, MomLocHandle);
  2849.   if (Result)
  2850.     return Result;
  2851.  
  2852.   RunLocHandle = FirstLocHandle;
  2853.   while ((RunLocHandle) && (RunLocHandle->Cont != -1))
  2854.   {
  2855.     Result = FindLocNode_FNode(p_name, SearchType, RunLocHandle->Cont);
  2856.     if (Result)
  2857.       break;
  2858.     RunLocHandle = RunLocHandle->Next;
  2859.   }
  2860.  
  2861.   return Result;
  2862. }
  2863.  
  2864. /*!------------------------------------------------------------------------
  2865.  * \fn     FindNode(const tStrComp *p_exp_name, TempType SearchType, Boolean SearchLocal, Boolean *p_error_on_find)
  2866.  * \brief  find node in global and/or local symbol table
  2867.  * \param  p_exp_name name of symbol to search
  2868.  * \param  SearchType data type to search for
  2869.  * \param  SearchLocal search in local table as well
  2870.  * \param  p_error_on_find may return True if NULL due to symbol syntax error
  2871.  * \return * to node or NULL
  2872.  * ------------------------------------------------------------------------ */
  2873.  
  2874. static PSymbolEntry FindNode(const tStrComp *p_exp_name, TempType SearchType, Boolean SearchLocal, Boolean *p_error_on_find)
  2875. {
  2876.   String name;
  2877.   tStrComp name_comp;
  2878.   LongInt DestSection = -1;
  2879.  
  2880.   StrCompMkTemp(&name_comp, name, sizeof(name));
  2881.   StrCompCopy(&name_comp, p_exp_name);
  2882.   ChkTmp3(name_comp.str.p_str, e_symbol_source_none);
  2883.   if (p_error_on_find)
  2884.     *p_error_on_find = False;
  2885.  
  2886.   if (!GetSymSection(&name_comp, &DestSection, p_exp_name))
  2887.   {
  2888.     if (p_error_on_find)
  2889.       *p_error_on_find = True;
  2890.     return NULL;
  2891.   }
  2892.   if (DestSection != -2)
  2893.     SearchLocal = False;
  2894.  
  2895.   if (SearchLocal && (MomLocHandle != -1))
  2896.   {
  2897.     PSymbolEntry p_result = FindLocNode(name_comp.str.p_str, SearchType);
  2898.     if (p_result)
  2899.       return p_result;
  2900.   }
  2901.   return FindGlobNode(name_comp.str.p_str, SearchType, DestSection);
  2902. }
  2903.  
  2904. /*!------------------------------------------------------------------------
  2905.  * \fn     ExpandAndFindNode(const struct sStrComp *pComp, TempType SearchType, Boolean SearchLocal, expand_chk_t chk, Boolean *p_error_on_find)
  2906.  * \brief  expand, optionally check and find node in global and/or local symbol table
  2907.  * \param  pComp name of symbol to expand & search
  2908.  * \param  SearchType data type to search for
  2909.  * \param  SearchLocal search in local table as well
  2910.  * \param  chk preliminary checks to perform
  2911.  * \param  p_error_on_find may return True if NULL due to symbol syntax error
  2912.  * \return * to node or NULL
  2913.  * ------------------------------------------------------------------------ */
  2914.  
  2915. PSymbolEntry ExpandAndFindNode(const struct sStrComp *pComp, TempType SearchType, Boolean SearchLocal, expand_chk_t chk, Boolean *p_error_on_find)
  2916. {
  2917.   String exp_name_buf;
  2918.   tStrComp exp_name;
  2919.   const tStrComp *p_exp_name;
  2920.   const char *pKlPos;
  2921.  
  2922.   if (p_error_on_find) *p_error_on_find = False;
  2923.   StrCompMkTemp(&exp_name, exp_name_buf, sizeof(exp_name_buf));
  2924.   p_exp_name = ExpandStrSymbol(&exp_name, pComp, !CaseSensitive);
  2925.   if (!p_exp_name)
  2926.   {
  2927.     if (p_error_on_find) *p_error_on_find = True;
  2928.     return NULL;
  2929.   }
  2930.  
  2931.   if (chk != e_expand_chk_none)
  2932.   {
  2933.     /* just [...] without symbol name itself is not valid */
  2934.  
  2935.     pKlPos = strchr(p_exp_name->str.p_str, '[');
  2936.     if ((pKlPos == p_exp_name->str.p_str) || (ChkSymbNameUpTo(p_exp_name->str.p_str, pKlPos) != pKlPos))
  2937.       return NULL;
  2938.   }
  2939.  
  2940.   return FindNode(p_exp_name, SearchType, SearchLocal, p_error_on_find);
  2941. }
  2942.  
  2943. /**
  2944. void SetSymbolType(const tStrComp *pName, Byte NTyp)
  2945. {
  2946.   PSymbolEntry Lauf;
  2947.   Boolean HRef;
  2948.  
  2949.   HRef = DoRefs;
  2950.   DoRefs = False;
  2951.   Lauf = ExpandAndFindNode(pName, TempInt, True, expand_chk_none, NULL);
  2952.   if (Lauf)
  2953.     Lauf->SymType = NTyp;
  2954.   DoRefs = HRef;
  2955. }
  2956. **/
  2957.  
  2958. void LookupSymbol(const struct sStrComp *pComp, TempResult *pValue, Boolean WantRelocs, TempType ReqType)
  2959. {
  2960.   Boolean error_on_find;
  2961.   PSymbolEntry pEntry = ExpandAndFindNode(pComp, ReqType, True, e_expand_chk_upto, &error_on_find);
  2962.  
  2963.   if (pEntry)
  2964.   {
  2965.     as_tempres_copy_value(pValue, &pEntry->SymWert);
  2966.     if (pValue->Typ != TempNone)
  2967.     {
  2968.       if (WantRelocs)
  2969.         pValue->Relocs = DupRelocs(pEntry->SymWert.Relocs);
  2970.       pValue->Flags = pEntry->SymWert.Flags;
  2971.     }
  2972.     pValue->AddrSpaceMask = pEntry->SymWert.AddrSpaceMask;
  2973.     if ((pEntry->SymWert.DataSize != eSymbolSizeUnknown) && (pValue->DataSize == eSymbolSizeUnknown))
  2974.       pValue->DataSize = pEntry->SymWert.DataSize;
  2975.     if (!pEntry->Defined)
  2976.     {
  2977.       if (Repass)
  2978.         pValue->Flags |= eSymbolFlag_Questionable;
  2979.       pValue->Flags |= eSymbolFlag_UsesForwards;
  2980.     }
  2981.     pEntry->Used = True;
  2982.   }
  2983.  
  2984.   else if (error_on_find)
  2985.     pValue->Typ = TempNone;
  2986.  
  2987.   /* Symbol evtl. im ersten Pass unbekannt */
  2988.  
  2989.   else if (PassNo <= MaxSymPass) /* !pEntry */
  2990.   {
  2991.     as_tempres_set_int(pValue, EProgCounter());
  2992.     Repass = True;
  2993.     if ((MsgIfRepass) && (PassNo >= PassNoForMessage))
  2994.       WrStrErrorPos(ErrNum_RepassUnknown, pComp);
  2995.     pValue->Flags |= eSymbolFlag_FirstPassUnknown;
  2996.   }
  2997.   else
  2998.     WrStrErrorPos(ErrNum_SymbolUndef, pComp);
  2999. }
  3000.  
  3001. /*!------------------------------------------------------------------------
  3002.  * \fn     SetSymbolOrStructElemSize(const struct sStrComp *pName, tSymbolSize Size)
  3003.  * \brief  set (integer) data size associated with a symbol
  3004.  * \param  pName unexpanded name of symbol
  3005.  * \param  Size operand size to set
  3006.  * ------------------------------------------------------------------------ */
  3007.  
  3008. void SetSymbolOrStructElemSize(const struct sStrComp *pName, tSymbolSize Size)
  3009. {
  3010.   if (pInnermostNamedStruct)
  3011.     SetStructElemSize(pInnermostNamedStruct->StructRec, pName, Size);
  3012.   else
  3013.   {
  3014.     PSymbolEntry pEntry;
  3015.     Boolean HRef;
  3016.  
  3017.     HRef = DoRefs;
  3018.     DoRefs = False;
  3019.     pEntry = ExpandAndFindNode(pName, TempInt, True, e_expand_chk_none, NULL);
  3020.     if (pEntry)
  3021.       pEntry->SymWert.DataSize = Size;
  3022.     DoRefs = HRef;
  3023.   }
  3024. }
  3025.  
  3026. /*!------------------------------------------------------------------------
  3027.  * \fn     GetSymbolSize(const struct sStrComp *pName)
  3028.  * \brief  get symbol's integer size
  3029.  * \param  pName unexpanded symbol name
  3030.  * \return symbol size or -1 if symbol does not exist
  3031.  * ------------------------------------------------------------------------ */
  3032.  
  3033. ShortInt GetSymbolSize(const struct sStrComp *pName)
  3034. {
  3035.   Boolean error_on_find;
  3036.   PSymbolEntry pEntry = ExpandAndFindNode(pName, TempInt, True, e_expand_chk_none, &error_on_find);
  3037.  
  3038.   return pEntry ? pEntry->SymWert.DataSize : (error_on_find ? -1 : eSymbolSizeUnknown);
  3039. }
  3040.  
  3041. /*!------------------------------------------------------------------------
  3042.  * \fn     IsSymbolDefined(const struct sStrComp *pName)
  3043.  * \brief  check whether symbol nas been used so far
  3044.  * \param  pName unexpanded symbol name
  3045.  * \return true if symbol exists and has been defined so far
  3046.  * ------------------------------------------------------------------------ */
  3047.  
  3048. Boolean IsSymbolDefined(const struct sStrComp *pName)
  3049. {
  3050.   PSymbolEntry pEntry = ExpandAndFindNode(pName, TempAll, True, e_expand_chk_none, NULL);
  3051.  
  3052.   return pEntry && pEntry->Defined;
  3053. }
  3054.  
  3055. /*!------------------------------------------------------------------------
  3056.  * \fn     IsSymbolUsed(const struct sStrComp *pName)
  3057.  * \brief  check whether symbol nas been used so far
  3058.  * \param  pName unexpanded symbol name
  3059.  * \return true if symbol exists and has been used
  3060.  * ------------------------------------------------------------------------ */
  3061.  
  3062. Boolean IsSymbolUsed(const struct sStrComp *pName)
  3063. {
  3064.   PSymbolEntry pEntry = ExpandAndFindNode(pName, TempAll, True, e_expand_chk_none, NULL);
  3065.  
  3066.   return pEntry && pEntry->Used;
  3067. }
  3068.  
  3069. /*!------------------------------------------------------------------------
  3070.  * \fn     IsSymbolChangeable(const struct sStrComp *pName)
  3071.  * \brief  check whether symbol's value may be changed or is constant
  3072.  * \param  pName unexpanded symbol name
  3073.  * \return true if symbol exists and is changeable
  3074.  * ------------------------------------------------------------------------ */
  3075.  
  3076. Boolean IsSymbolChangeable(const struct sStrComp *pName)
  3077. {
  3078.   PSymbolEntry pEntry = ExpandAndFindNode(pName, TempAll, True, e_expand_chk_none, NULL);
  3079.  
  3080.   return pEntry && pEntry->Changeable;
  3081. }
  3082.  
  3083. /*!------------------------------------------------------------------------
  3084.  * \fn     GetSymbolType(const struct sStrComp *pName)
  3085.  * \brief  retrieve type (int/float/string) of symbol
  3086.  * \param  pName unexpanded name
  3087.  * \return type or -1 if non-existent
  3088.  * ------------------------------------------------------------------------ */
  3089.  
  3090. as_addrspace_t addrspace_from_mask(unsigned mask)
  3091. {
  3092.   as_addrspace_t space;
  3093.  
  3094.   for (space = SegCode; space < SegCount; space++)
  3095.     if (mask & (1 << space))
  3096.       return space;
  3097.   return SegNone;
  3098. }
  3099.  
  3100. Integer GetSymbolType(const struct sStrComp *pName)
  3101. {
  3102.   PSymbolEntry pEntry = ExpandAndFindNode(pName, TempAll, True, e_expand_chk_none, NULL);
  3103.  
  3104.   if (!pEntry)
  3105.     return -1;
  3106.   else if (pEntry->SymWert.Typ == TempReg)
  3107.     return 0x80;
  3108.   else
  3109.     return addrspace_from_mask(pEntry->SymWert.AddrSpaceMask);
  3110. }
  3111.  
  3112. typedef struct
  3113. {
  3114.   int Width, cwidth;
  3115.   LongInt Sum, USum;
  3116.   as_dynstr_t Zeilenrest;
  3117.   int ZeilenrestLen,
  3118.       ZeilenrestVisibleLen;
  3119.   as_dynstr_t s1, sh;
  3120. } TListContext;
  3121.  
  3122. static void PrintSymbolList_AddOut(char *s, TListContext *pContext)
  3123. {
  3124.   int AddVisibleLen = visible_strlen(s),
  3125.       AddLen = strlen(s);
  3126.  
  3127.   if (AddVisibleLen + pContext->ZeilenrestVisibleLen > pContext->Width)
  3128.   {
  3129.     pContext->Zeilenrest.p_str[pContext->ZeilenrestLen - 1] = '\0';
  3130.     WrLstLine(pContext->Zeilenrest.p_str);
  3131.     as_dynstr_copy_c_str(&pContext->Zeilenrest, s);
  3132.     pContext->ZeilenrestLen = AddLen;
  3133.     pContext->ZeilenrestVisibleLen = AddVisibleLen;
  3134.   }
  3135.   else
  3136.   {
  3137.     as_dynstr_append_c_str(&pContext->Zeilenrest, s);
  3138.     pContext->ZeilenrestLen += AddLen;
  3139.     pContext->ZeilenrestVisibleLen += AddVisibleLen;
  3140.   }
  3141. }
  3142.  
  3143. static void PrintSymbolList_PNode(PTree Tree, void *pData)
  3144. {
  3145.   PSymbolEntry Node = (PSymbolEntry) Tree;
  3146.  
  3147.   if (Node->SymWert.Typ != TempReg)
  3148.   {
  3149.     TListContext *pContext = (TListContext*) pData;
  3150.     int l1, nBlanks;
  3151.     const TempResult *pValue = &Node->SymWert;
  3152.  
  3153.     if ((pValue->Typ == TempInt) && DissectBit && (pValue->AddrSpaceMask & (1 << SegBData)))
  3154.       DissectBit(pContext->s1.p_str, pContext->s1.capacity, pValue->Contents.Int);
  3155.     else
  3156.       StrSym(pValue, False, &pContext->s1, ListRadixBase);
  3157.  
  3158.     as_sdprintf(&pContext->sh, "%c%s : ", Node->Used ? ' ' : '*', Tree->Name);
  3159.     if (Tree->Attribute != -1)
  3160.       as_sdprcatf(&pContext->sh, " [%s]", GetSectionName(Tree->Attribute));
  3161.     l1 = (strlen(pContext->s1.p_str) + visible_strlen(pContext->sh.p_str) + 4);
  3162.     for (nBlanks = pContext->cwidth - 1 - l1; nBlanks < 0; nBlanks += pContext->cwidth);
  3163.     as_sdprcatf(&pContext->sh, "%s%s %c | ", Blanks(nBlanks), pContext->s1.p_str, SegShorts[addrspace_from_mask(pValue->AddrSpaceMask)]);
  3164.     PrintSymbolList_AddOut(pContext->sh.p_str, pContext);
  3165.     pContext->Sum++;
  3166.     if (!Node->Used)
  3167.       pContext->USum++;
  3168.   }
  3169. }
  3170.  
  3171. void PrintSymbolList(void)
  3172. {
  3173.   int ActPageWidth;
  3174.   TListContext Context;
  3175.  
  3176.   as_dynstr_ini(&Context.Zeilenrest, STRINGSIZE);
  3177.   as_dynstr_ini(&Context.s1, STRINGSIZE);
  3178.   as_dynstr_ini(&Context.sh, STRINGSIZE);
  3179.   Context.Width = (PageWidth == 0) ? 80 : PageWidth;
  3180.   NewPage(ChapDepth, True);
  3181.   WrLstLine(getmessage(Num_ListSymListHead1));
  3182.   WrLstLine(getmessage(Num_ListSymListHead2));
  3183.   WrLstLine("");
  3184.  
  3185.   Context.ZeilenrestLen =
  3186.   Context.ZeilenrestVisibleLen = 0;
  3187.   Context.Sum = Context.USum = 0;
  3188.   ActPageWidth = (PageWidth == 0) ? 80 : PageWidth;
  3189.   Context.cwidth = ActPageWidth >> 1;
  3190.   IterTree((PTree)FirstSymbol, PrintSymbolList_PNode, &Context);
  3191.   if (Context.Zeilenrest.p_str[0] != '\0')
  3192.   {
  3193.     Context.Zeilenrest.p_str[strlen(Context.Zeilenrest.p_str) - 1] = '\0';
  3194.     WrLstLine(Context.Zeilenrest.p_str);
  3195.   }
  3196.   WrLstLine("");
  3197.   as_sdprintf(&Context.Zeilenrest, "%7lu%s",
  3198.               (unsigned long)Context.Sum,
  3199.               getmessage((Context.Sum == 1) ? Num_ListSymSumMsg : Num_ListSymSumsMsg));
  3200.   WrLstLine(Context.Zeilenrest.p_str);
  3201.   as_sdprintf(&Context.Zeilenrest, "%7lu%s",
  3202.               (unsigned long)Context.USum,
  3203.               getmessage((Context.USum == 1) ? Num_ListUSymSumMsg : Num_ListUSymSumsMsg));
  3204.   WrLstLine(Context.Zeilenrest.p_str);
  3205.   WrLstLine("");
  3206.   as_dynstr_free(&Context.s1);
  3207.   as_dynstr_free(&Context.sh);
  3208.   as_dynstr_free(&Context.Zeilenrest);
  3209. }
  3210.  
  3211. typedef struct
  3212. {
  3213.   FILE *f;
  3214.   Boolean HWritten;
  3215.   as_addrspace_t Space;
  3216.   as_dynstr_t s;
  3217. } TDebContext;
  3218.  
  3219. static Boolean match_space_mask(unsigned mask, as_addrspace_t space)
  3220. {
  3221.   if (SegNone == space)
  3222.     return !mask;
  3223.   else
  3224.     return !!((mask >> space) & 1);
  3225. }
  3226.  
  3227. static void PrintDebSymbols_PNode(PTree Tree, void *pData)
  3228. {
  3229.   PSymbolEntry Node = (PSymbolEntry) Tree;
  3230.   TDebContext *DebContext = (TDebContext*) pData;
  3231.   int l1;
  3232.  
  3233.   if (!match_space_mask(Node->SymWert.AddrSpaceMask, DebContext->Space))
  3234.     return;
  3235.  
  3236.   if (!DebContext->HWritten)
  3237.   {
  3238.     fprintf(DebContext->f, "\n"); ChkIO(ErrNum_FileWriteError);
  3239.     fprintf(DebContext->f, "Symbols in Segment %s\n", SegNames[DebContext->Space]); ChkIO(ErrNum_FileWriteError);
  3240.     DebContext->HWritten = True;
  3241.   }
  3242.  
  3243.   fprintf(DebContext->f, "%s", Node->Tree.Name); ChkIO(ErrNum_FileWriteError);
  3244.   l1 = strlen(Node->Tree.Name);
  3245.   if (Node->Tree.Attribute != -1)
  3246.   {
  3247.     as_sdprintf(&DebContext->s, "[%d]", (int)Node->Tree.Attribute);
  3248.     fprintf(DebContext->f, "%s", DebContext->s.p_str); ChkIO(ErrNum_FileWriteError);
  3249.     l1 += strlen(DebContext->s.p_str);
  3250.   }
  3251.   fprintf(DebContext->f, "%s ", Blanks(37 - l1)); ChkIO(ErrNum_FileWriteError);
  3252.   switch (Node->SymWert.Typ)
  3253.   {
  3254.     case TempInt:
  3255.       fprintf(DebContext->f, "Int    ");
  3256.       break;
  3257.     case TempFloat:
  3258.       fprintf(DebContext->f, "Float  ");
  3259.       break;
  3260.     case TempString:
  3261.       fprintf(DebContext->f, "String ");
  3262.       break;
  3263.     default:
  3264.       break;
  3265.   }
  3266.   ChkIO(ErrNum_FileWriteError);
  3267.   if (Node->SymWert.Typ == TempString)
  3268.   {
  3269.     errno = 0;
  3270.     l1 = fstrlenprint(DebContext->f, Node->SymWert.Contents.str.p_str, Node->SymWert.Contents.str.len);
  3271.     ChkIO(ErrNum_FileWriteError);
  3272.   }
  3273.   else
  3274.   {
  3275.     StrSym(&Node->SymWert, False, &DebContext->s, 16);
  3276.     l1 = strlen(DebContext->s.p_str);
  3277.     fprintf(DebContext->f, "%s", DebContext->s.p_str); ChkIO(ErrNum_FileWriteError);
  3278.   }
  3279.   fprintf(DebContext->f, "%s %-3d %d %d\n", Blanks(25 - l1), Node->SymWert.DataSize, (int)Node->Used, (int)Node->Changeable);
  3280.   ChkIO(ErrNum_FileWriteError);
  3281. }
  3282.  
  3283. void PrintDebSymbols(FILE *f)
  3284. {
  3285.   TDebContext DebContext;
  3286.  
  3287.   as_dynstr_ini(&DebContext.s, 256);
  3288.   DebContext.f = f;
  3289.   for (DebContext.Space = SegNone; DebContext.Space < SegCount; DebContext.Space++)
  3290.   {
  3291.     DebContext.HWritten = False;
  3292.     IterTree((PTree)FirstSymbol, PrintDebSymbols_PNode, &DebContext);
  3293.   }
  3294.   as_dynstr_free(&DebContext.s);
  3295. }
  3296.  
  3297. typedef struct
  3298. {
  3299.   FILE *f;
  3300.   LongInt Handle;
  3301. } TNoISymContext;
  3302.  
  3303. static void PrNoISection(PTree Tree, void *pData)
  3304. {
  3305.   PSymbolEntry Node = (PSymbolEntry)Tree;
  3306.   TNoISymContext *pContext = (TNoISymContext*) pData;
  3307.  
  3308.   if ((Node->SymWert.AddrSpaceMask & NoICEMask) && (Node->Tree.Attribute == pContext->Handle) && (Node->SymWert.Typ == TempInt))
  3309.   {
  3310.     errno = 0; fprintf(pContext->f, "DEFINE %s 0x", Node->Tree.Name); ChkIO(ErrNum_FileWriteError);
  3311.     errno = 0; fprintf(pContext->f, LargeHIntFormat, Node->SymWert.Contents.Int); ChkIO(ErrNum_FileWriteError);
  3312.     errno = 0; fprintf(pContext->f, "\n"); ChkIO(ErrNum_FileWriteError);
  3313.   }
  3314. }
  3315.  
  3316. void PrintNoISymbols(FILE *f)
  3317. {
  3318.   PCToken CurrSection;
  3319.   TNoISymContext Context;
  3320.  
  3321.   Context.f = f;
  3322.   Context.Handle = -1;
  3323.   IterTree((PTree)FirstSymbol, PrNoISection, &Context);
  3324.   Context.Handle++;
  3325.   for (CurrSection = FirstSection; CurrSection; CurrSection = CurrSection->Next)
  3326.    if (ChunkSum(&CurrSection->Usage)>0)
  3327.    {
  3328.      fprintf(f, "FUNCTION %s ", CurrSection->Name); ChkIO(ErrNum_FileWriteError);
  3329.      fprintf(f, LargeIntFormat, ChunkMin(&CurrSection->Usage)); ChkIO(ErrNum_FileWriteError);
  3330.      fprintf(f, "\n"); ChkIO(ErrNum_FileWriteError);
  3331.      IterTree((PTree)FirstSymbol, PrNoISection, &Context);
  3332.      Context.Handle++;
  3333.      fprintf(f, "}FUNC "); ChkIO(ErrNum_FileWriteError);
  3334.      fprintf(f, LargeIntFormat, ChunkMax(&CurrSection->Usage)); ChkIO(ErrNum_FileWriteError);
  3335.      fprintf(f, "\n"); ChkIO(ErrNum_FileWriteError);
  3336.    }
  3337. }
  3338.  
  3339. void PrintSymbolTree(void)
  3340. {
  3341.   DumpTree((PTree)FirstSymbol);
  3342. }
  3343.  
  3344. static void ClearSymbolList_ClearNode(PTree Node, void *pData)
  3345. {
  3346.   PSymbolEntry SymbolEntry = (PSymbolEntry) Node;
  3347.   UNUSED(pData);
  3348.  
  3349.   FreeSymbolEntry(&SymbolEntry, FALSE);
  3350. }
  3351.  
  3352. void ClearSymbolList(void)
  3353. {
  3354.   PTree TreeRoot;
  3355.  
  3356.   TreeRoot = &(FirstSymbol->Tree);
  3357.   FirstSymbol = NULL;
  3358.   DestroyTree(&TreeRoot, ClearSymbolList_ClearNode, NULL);
  3359.   TreeRoot = &(FirstLocSymbol->Tree);
  3360.   FirstLocSymbol = NULL;
  3361.   DestroyTree(&TreeRoot, ClearSymbolList_ClearNode, NULL);
  3362. }
  3363.  
  3364. /*-------------------------------------------------------------------------*/
  3365. /* Stack-Verwaltung */
  3366.  
  3367. static PSymbolStack find_stack(const char *p_name, PSymbolStack *pp_stack_prev, Boolean allow_create)
  3368. {
  3369.   PSymbolStack p_stack_run;
  3370.  
  3371.   p_stack_run = FirstStack;
  3372.   *pp_stack_prev = NULL;
  3373.   while (p_stack_run && (strcmp(p_stack_run->Name, p_name) < 0))
  3374.   {
  3375.     *pp_stack_prev = p_stack_run;
  3376.     p_stack_run = p_stack_run->Next;
  3377.   }
  3378.  
  3379.   if (!p_stack_run || (strcmp(p_stack_run->Name, p_name) > 0))
  3380.   {
  3381.     PSymbolStack p_stack_new;
  3382.  
  3383.     if (!allow_create)
  3384.       return NULL;
  3385.  
  3386.     p_stack_new = (PSymbolStack) malloc(sizeof(TSymbolStack));
  3387.     p_stack_new->Name = as_strdup(p_name);
  3388.     p_stack_new->Contents = NULL;
  3389.     p_stack_new->Next = p_stack_run;
  3390.     if (!*pp_stack_prev)
  3391.       FirstStack = p_stack_new;
  3392.     else
  3393.       (*pp_stack_prev)->Next = p_stack_new;
  3394.     return p_stack_new;
  3395.   }
  3396.   else
  3397.     return p_stack_run;
  3398. }
  3399.  
  3400. Boolean PushSymbol(const tStrComp *pSymName, const tStrComp *pStackName)
  3401. {
  3402.   PSymbolEntry pSrc;
  3403.   PSymbolStack LStack, PStack;
  3404.   PSymbolStackEntry Elem;
  3405.   tStrComp exp_sym_name, exp_stack_name;
  3406.   const tStrComp *p_exp_sym_name, *p_exp_stack_name;
  3407.   String exp_sym_name_buf, exp_stack_name_buf;
  3408.  
  3409.   StrCompMkTemp(&exp_sym_name, exp_sym_name_buf, sizeof(exp_sym_name_buf));
  3410.   p_exp_sym_name = ExpandStrSymbol(&exp_sym_name, pSymName, !CaseSensitive);
  3411.   if (!p_exp_sym_name)
  3412.     return False;
  3413.  
  3414.   pSrc = FindNode(p_exp_sym_name, TempAll, False, NULL);
  3415.   if (!pSrc)
  3416.   {
  3417.     WrStrErrorPos(ErrNum_SymbolUndef, pSymName);
  3418.     return False;
  3419.   }
  3420.  
  3421.   StrCompMkTemp(&exp_stack_name, exp_stack_name_buf, sizeof(exp_stack_name_buf));
  3422.   if (*pStackName->str.p_str)
  3423.   {
  3424.     p_exp_stack_name = ExpandStrSymbol(&exp_stack_name, pStackName, !CaseSensitive);
  3425.     if (!p_exp_stack_name)
  3426.       return False;
  3427.   }
  3428.   else
  3429.   {
  3430.     strmaxcpy(exp_stack_name.str.p_str, DefStackName, exp_stack_name.str.capacity);
  3431.     p_exp_stack_name = &exp_stack_name;
  3432.   }
  3433.   if (!ChkSymbName(p_exp_stack_name->str.p_str))
  3434.   {
  3435.     WrStrErrorPos(ErrNum_InvSymName, pStackName);
  3436.     return False;
  3437.   }
  3438.  
  3439.   LStack = find_stack(p_exp_stack_name->str.p_str, &PStack, True);
  3440.   Elem = (PSymbolStackEntry) malloc(sizeof(TSymbolStackEntry));
  3441.   Elem->Next = LStack->Contents;
  3442.   Elem->Contents = pSrc->SymWert;
  3443.   LStack->Contents = Elem;
  3444.  
  3445.   return True;
  3446. }
  3447.  
  3448. Boolean PopSymbol(const tStrComp *pSymName, const tStrComp *pStackName)
  3449. {
  3450.   PSymbolEntry pDest;
  3451.   PSymbolStack LStack, PStack;
  3452.   PSymbolStackEntry Elem;
  3453.   tStrComp exp_sym_name, exp_stack_name;
  3454.   const tStrComp *p_exp_sym_name, *p_exp_stack_name;
  3455.   String exp_sym_name_buf, exp_stack_name_buf;
  3456.  
  3457.   StrCompMkTemp(&exp_sym_name, exp_sym_name_buf, sizeof(exp_sym_name_buf));
  3458.   p_exp_sym_name = ExpandStrSymbol(&exp_sym_name, pSymName, !CaseSensitive);
  3459.   if (!p_exp_sym_name)
  3460.     return False;
  3461.  
  3462.   pDest = FindNode(p_exp_sym_name, TempAll, False, NULL);
  3463.   if (!pDest)
  3464.   {
  3465.     WrStrErrorPos(ErrNum_SymbolUndef, pSymName);
  3466.     return False;
  3467.   }
  3468.  
  3469.   StrCompMkTemp(&exp_stack_name, exp_stack_name_buf, sizeof(exp_stack_name_buf));
  3470.   if (*pStackName->str.p_str)
  3471.   {
  3472.     p_exp_stack_name = ExpandStrSymbol(&exp_stack_name, pStackName, !CaseSensitive);
  3473.     if (!p_exp_stack_name)
  3474.       return False;
  3475.   }
  3476.   else
  3477.   {
  3478.     strmaxcpy(exp_stack_name.str.p_str, DefStackName, exp_stack_name.str.capacity);
  3479.     p_exp_stack_name = &exp_stack_name;
  3480.   }
  3481.   if (!ChkSymbName(p_exp_stack_name->str.p_str))
  3482.   {
  3483.     WrStrErrorPos(ErrNum_InvSymName, pStackName);
  3484.     return False;
  3485.   }
  3486.  
  3487.   LStack = find_stack(p_exp_stack_name->str.p_str, &PStack, False);
  3488.   if (!LStack)
  3489.   {
  3490.     WrStrErrorPos(ErrNum_StackEmpty, pStackName);
  3491.     return False;
  3492.   }
  3493.  
  3494.   Elem = LStack->Contents;
  3495.   pDest->SymWert = Elem->Contents;
  3496.   LStack->Contents = Elem->Next;
  3497.   if (!LStack->Contents)
  3498.   {
  3499.     if (!PStack)
  3500.       FirstStack = LStack->Next;
  3501.     else
  3502.       PStack->Next = LStack->Next;
  3503.     free(LStack->Name);
  3504.     free(LStack);
  3505.   }
  3506.   free(Elem);
  3507.  
  3508.   return True;
  3509. }
  3510.  
  3511. void ClearStacks(void)
  3512. {
  3513.   PSymbolStack Act;
  3514.   PSymbolStackEntry Elem;
  3515.   int z;
  3516.   String s;
  3517.  
  3518.   while (FirstStack)
  3519.   {
  3520.     z = 0;
  3521.     Act = FirstStack;
  3522.     while (Act->Contents)
  3523.     {
  3524.       Elem = Act->Contents;
  3525.       Act->Contents = Elem->Next;
  3526.       free(Elem);
  3527.       z++;
  3528.     }
  3529.     as_snprintf(s, sizeof(s), "%s(%d)", Act->Name, z);
  3530.     WrXError(ErrNum_StackNotEmpty, s);
  3531.     free(Act->Name);
  3532.     FirstStack = Act->Next;
  3533.     free(Act);
  3534.   }
  3535. }
  3536.  
  3537. /*-------------------------------------------------------------------------*/
  3538. /* Funktionsverwaltung */
  3539.  
  3540. void EnterFunction(const tStrComp *pComp, char *FDefinition, Byte NewCnt)
  3541. {
  3542.   PFunction Neu;
  3543.   String FName_N;
  3544.   const char *pFName;
  3545.  
  3546.   if (!CaseSensitive)
  3547.   {
  3548.     strmaxcpy(FName_N, pComp->str.p_str, STRINGSIZE);
  3549.     NLS_UpString(FName_N);
  3550.     pFName = FName_N;
  3551.   }
  3552.   else
  3553.      pFName = pComp->str.p_str;
  3554.  
  3555.   if (!ChkSymbName(pFName))
  3556.   {
  3557.     WrStrErrorPos(ErrNum_InvSymName, pComp);
  3558.     return;
  3559.   }
  3560.  
  3561.   if (FindFunction(pFName))
  3562.   {
  3563.     if (PassNo == 1)
  3564.       WrStrErrorPos(ErrNum_DoubleDef, pComp);
  3565.     return;
  3566.   }
  3567.  
  3568.   Neu = (PFunction) malloc(sizeof(TFunction));
  3569.   Neu->Next = FirstFunction;
  3570.   Neu->ArguCnt = NewCnt;
  3571.   Neu->Name = as_strdup(pFName);
  3572.   Neu->Definition = as_strdup(FDefinition);
  3573.   FirstFunction = Neu;
  3574. }
  3575.  
  3576. PFunction FindFunction(const char *Name)
  3577. {
  3578.   PFunction Lauf = FirstFunction;
  3579.   String Name_N;
  3580.  
  3581.   if (!CaseSensitive)
  3582.   {
  3583.     strmaxcpy(Name_N, Name, STRINGSIZE);
  3584.     NLS_UpString(Name_N);
  3585.     Name = Name_N;
  3586.   }
  3587.  
  3588.   while ((Lauf) && (strcmp(Lauf->Name, Name)))
  3589.     Lauf = Lauf->Next;
  3590.   return Lauf;
  3591. }
  3592.  
  3593. void PrintFunctionList(void)
  3594. {
  3595.   PFunction Lauf;
  3596.   String OneS;
  3597.   Boolean cnt;
  3598.  
  3599.   if (!FirstFunction)
  3600.     return;
  3601.  
  3602.   NewPage(ChapDepth, True);
  3603.   WrLstLine(getmessage(Num_ListFuncListHead1));
  3604.   WrLstLine(getmessage(Num_ListFuncListHead2));
  3605.   WrLstLine("");
  3606.  
  3607.   OneS[0] = '\0';
  3608.   Lauf = FirstFunction;
  3609.   cnt = False;
  3610.   while (Lauf)
  3611.   {
  3612.     strmaxcat(OneS, Lauf->Name, STRINGSIZE);
  3613.     if (strlen(Lauf->Name) < 37)
  3614.       strmaxcat(OneS, Blanks(37-strlen(Lauf->Name)), STRINGSIZE);
  3615.     if (!cnt) strmaxcat(OneS, " | ", STRINGSIZE);
  3616.     else
  3617.     {
  3618.       WrLstLine(OneS);
  3619.       OneS[0] = '\0';
  3620.     }
  3621.     cnt = !cnt;
  3622.     Lauf = Lauf->Next;
  3623.   }
  3624.   if (cnt)
  3625.   {
  3626.     OneS[strlen(OneS)-1] = '\0';
  3627.     WrLstLine(OneS);
  3628.   }
  3629.   WrLstLine("");
  3630. }
  3631.  
  3632. void ClearFunctionList(void)
  3633. {
  3634.   PFunction Lauf;
  3635.  
  3636.   while (FirstFunction)
  3637.   {
  3638.     Lauf = FirstFunction->Next;
  3639.     free(FirstFunction->Name);
  3640.     free(FirstFunction->Definition);
  3641.     free(FirstFunction);
  3642.     FirstFunction = Lauf;
  3643.   }
  3644. }
  3645.  
  3646. /*-------------------------------------------------------------------------*/
  3647.  
  3648. static void ResetSymbolDefines_ResetNode(PTree Node, void *pData)
  3649. {
  3650.   PSymbolEntry SymbolEntry = (PSymbolEntry) Node;
  3651.   UNUSED(pData);
  3652.  
  3653.   SymbolEntry->Defined = False;
  3654.   SymbolEntry->Used = False;
  3655. }
  3656.  
  3657. void ResetSymbolDefines(void)
  3658. {
  3659.   IterTree(&(FirstSymbol->Tree), ResetSymbolDefines_ResetNode, NULL);
  3660.   IterTree(&(FirstLocSymbol->Tree), ResetSymbolDefines_ResetNode, NULL);
  3661. }
  3662.  
  3663. void SetFlag(Boolean *Flag, const char *Name, Boolean Wert)
  3664. {
  3665.   tStrComp TmpComp;
  3666.  
  3667.   *Flag = Wert;
  3668.   StrCompMkTemp(&TmpComp, (char*)Name, 0);
  3669.   PushLocHandle(-1);
  3670.   EnterIntSymbol(&TmpComp, *Flag ? 1 : 0, SegNone, True);
  3671.   PopLocHandle();
  3672. }
  3673.  
  3674. void AddDefSymbol(char *Name, TempResult *Value)
  3675. {
  3676.   PDefSymbol Neu;
  3677.  
  3678.   Neu = FirstDefSymbol;
  3679.   while (Neu)
  3680.   {
  3681.     if (!strcmp(Neu->SymName, Name))
  3682.       return;
  3683.     Neu = Neu->Next;
  3684.   }
  3685.  
  3686.   Neu = (PDefSymbol) malloc(sizeof(TDefSymbol));
  3687.   Neu->Next = FirstDefSymbol;
  3688.   Neu->SymName = as_strdup(Name);
  3689.   Neu->Wert = (*Value);
  3690.   FirstDefSymbol = Neu;
  3691. }
  3692.  
  3693. void RemoveDefSymbol(char *Name)
  3694. {
  3695.   PDefSymbol Save, Lauf;
  3696.  
  3697.   if (!FirstDefSymbol)
  3698.     return;
  3699.  
  3700.   if (!strcmp(FirstDefSymbol->SymName, Name))
  3701.   {
  3702.     Save = FirstDefSymbol;
  3703.     FirstDefSymbol = FirstDefSymbol->Next;
  3704.   }
  3705.   else
  3706.   {
  3707.     Lauf = FirstDefSymbol;
  3708.     while ((Lauf->Next) && (strcmp(Lauf->Next->SymName, Name)))
  3709.       Lauf = Lauf->Next;
  3710.     if (!Lauf->Next)
  3711.       return;
  3712.     Save = Lauf->Next;
  3713.     Lauf->Next = Lauf->Next->Next;
  3714.   }
  3715.   free(Save->SymName);
  3716.   free(Save);
  3717. }
  3718.  
  3719. void CopyDefSymbols(void)
  3720. {
  3721.   PDefSymbol Lauf;
  3722.   tStrComp TmpComp;
  3723.  
  3724.   Lauf = FirstDefSymbol;
  3725.   while (Lauf)
  3726.   {
  3727.     StrCompMkTemp(&TmpComp, Lauf->SymName, 0);
  3728.     switch (Lauf->Wert.Typ)
  3729.     {
  3730.       case TempInt:
  3731.         EnterIntSymbol(&TmpComp, Lauf->Wert.Contents.Int, SegNone, True);
  3732.         break;
  3733.       case TempFloat:
  3734.         EnterFloatSymbol(&TmpComp, Lauf->Wert.Contents.Float, True);
  3735.         break;
  3736.       case TempString:
  3737.       {
  3738.         EnterNonZStringSymbol(&TmpComp, &Lauf->Wert.Contents.str, True);
  3739.         break;
  3740.       }
  3741.       default:
  3742.         break;
  3743.     }
  3744.     Lauf = Lauf->Next;
  3745.   }
  3746. }
  3747.  
  3748. const TempResult *FindDefSymbol(const char *pName)
  3749. {
  3750.   PDefSymbol pRun;
  3751.  
  3752.   for (pRun = FirstDefSymbol; pRun; pRun = pRun->Next)
  3753.     if (!strcmp(pName, pRun->SymName))
  3754.       return &pRun->Wert;
  3755.   return NULL;
  3756. }
  3757.  
  3758. void PrintSymbolDepth(void)
  3759. {
  3760.   LongInt TreeMin, TreeMax;
  3761.  
  3762.   GetTreeDepth(&(FirstSymbol->Tree), &TreeMin, &TreeMax);
  3763.   fprintf(Debug, " MinTree %ld\n", (long)TreeMin);
  3764.   fprintf(Debug, " MaxTree %ld\n", (long)TreeMax);
  3765. }
  3766.  
  3767. LongInt GetSectionHandle(const char *SName, Boolean AddEmpt, LongInt Parent)
  3768. {
  3769.   PCToken Lauf, Prev;
  3770.   LongInt z;
  3771.  
  3772.   Lauf = FirstSection;
  3773.   Prev = NULL;
  3774.   z = 0;
  3775.   while (Lauf && (strcmp(Lauf->Name, SName) || (Lauf->Parent != Parent)))
  3776.   {
  3777.     z++;
  3778.     Prev = Lauf;
  3779.     Lauf = Lauf->Next;
  3780.   }
  3781.  
  3782.   if (!Lauf)
  3783.   {
  3784.     if (AddEmpt)
  3785.     {
  3786.       Lauf = (PCToken) malloc(sizeof(TCToken));
  3787.       Lauf->Parent = MomSectionHandle;
  3788.       Lauf->Name = as_strdup(SName);
  3789.       Lauf->Next = NULL;
  3790.       InitChunk(&(Lauf->Usage));
  3791.       if (!Prev)
  3792.         FirstSection = Lauf;
  3793.       else
  3794.         Prev->Next = Lauf;
  3795.     }
  3796.     else
  3797.       z = -2;
  3798.   }
  3799.   return z;
  3800. }
  3801.  
  3802. const char *GetSectionName(LongInt Handle)
  3803. {
  3804.   PCToken Lauf = FirstSection;
  3805.   static const char *Dummy = "";
  3806.  
  3807.   if (Handle == -1)
  3808.     return Dummy;
  3809.   while ((Handle > 0) && (Lauf))
  3810.   {
  3811.     Lauf = Lauf->Next;
  3812.     Handle--;
  3813.   }
  3814.   return Lauf ? Lauf->Name : Dummy;
  3815. }
  3816.  
  3817. void SetMomSection(LongInt Handle)
  3818. {
  3819.   LongInt z;
  3820.  
  3821.   MomSectionHandle = Handle;
  3822.   if (Handle < 0)
  3823.     MomSection = NULL;
  3824.   else
  3825.   {
  3826.     MomSection = FirstSection;
  3827.     for (z = 1; z <= Handle; z++)
  3828.       if (MomSection)
  3829.         MomSection = MomSection->Next;
  3830.   }
  3831. }
  3832.  
  3833. void AddSectionUsage(LongInt Start, LongInt Length)
  3834. {
  3835.   if ((ActPC != SegCode) || (!MomSection))
  3836.     return;
  3837.   AddChunk(&(MomSection->Usage), Start, Length, False);
  3838. }
  3839.  
  3840. void ClearSectionUsage(void)
  3841. {
  3842.   PCToken Tmp;
  3843.  
  3844.   for (Tmp = FirstSection; Tmp; Tmp = Tmp->Next)
  3845.     ClearChunk(&(Tmp->Usage));
  3846. }
  3847.  
  3848. static void PrintSectionList_PSection(LongInt Handle, int Indent)
  3849. {
  3850.   PCToken Lauf;
  3851.   LongInt Cnt;
  3852.   String h;
  3853.  
  3854.   ChkStack();
  3855.   if (Handle != -1)
  3856.   {
  3857.     strmaxcpy(h, Blanks(Indent << 1), STRINGSIZE);
  3858.     strmaxcat(h, GetSectionName(Handle), STRINGSIZE);
  3859.     WrLstLine(h);
  3860.   }
  3861.   Lauf = FirstSection;
  3862.   Cnt = 0;
  3863.   while (Lauf)
  3864.   {
  3865.     if (Lauf->Parent == Handle)
  3866.       PrintSectionList_PSection(Cnt, Indent + 1);
  3867.     Lauf = Lauf->Next;
  3868.     Cnt++;
  3869.   }
  3870. }
  3871.  
  3872. void PrintSectionList(void)
  3873. {
  3874.   if (!FirstSection)
  3875.     return;
  3876.  
  3877.   NewPage(ChapDepth, True);
  3878.   WrLstLine(getmessage(Num_ListSectionListHead1));
  3879.   WrLstLine(getmessage(Num_ListSectionListHead2));
  3880.   WrLstLine("");
  3881.   PrintSectionList_PSection(-1, 0);
  3882. }
  3883.  
  3884. void PrintDebSections(FILE *f)
  3885. {
  3886.   PCToken Lauf;
  3887.   LongInt Cnt, z, l, s;
  3888.   char Str[30];
  3889.  
  3890.   Lauf = FirstSection; Cnt = 0;
  3891.   while (Lauf)
  3892.   {
  3893.     fputs("\nInfo for Section ", f); ChkIO(ErrNum_FileWriteError);
  3894.     fprintf(f, LongIntFormat, Cnt); ChkIO(ErrNum_FileWriteError);
  3895.     fputc(' ', f); ChkIO(ErrNum_FileWriteError);
  3896.     fputs(GetSectionName(Cnt), f); ChkIO(ErrNum_FileWriteError);
  3897.     fputc(' ', f); ChkIO(ErrNum_FileWriteError);
  3898.     fprintf(f, LongIntFormat, Lauf->Parent); ChkIO(ErrNum_FileWriteError);
  3899.     fputc('\n', f); ChkIO(ErrNum_FileWriteError);
  3900.     for (z = 0; z < Lauf->Usage.RealLen; z++)
  3901.     {
  3902.       l = Lauf->Usage.Chunks[z].Length;
  3903.       s = Lauf->Usage.Chunks[z].Start;
  3904.       HexString(Str, sizeof(Str), s, 0);
  3905.       fputs(Str, f);
  3906.       ChkIO(ErrNum_FileWriteError);
  3907.       if (l == 1)
  3908.         fprintf(f, "\n");
  3909.       else
  3910.       {
  3911.         HexString(Str, sizeof(Str), s + l - 1, 0);
  3912.         fprintf(f, "-%s\n", Str);
  3913.       }
  3914.       ChkIO(ErrNum_FileWriteError);
  3915.     }
  3916.     Lauf = Lauf->Next;
  3917.     Cnt++;
  3918.   }
  3919. }
  3920.  
  3921. void ClearSectionList(void)
  3922. {
  3923.   PCToken Tmp;
  3924.  
  3925.   while (FirstSection)
  3926.   {
  3927.     Tmp = FirstSection;
  3928.     free(Tmp->Name);
  3929.     ClearChunk(&(Tmp->Usage));
  3930.     FirstSection = Tmp->Next; free(Tmp);
  3931.   }
  3932. }
  3933.  
  3934. /*---------------------------------------------------------------------------------*/
  3935.  
  3936. /*!------------------------------------------------------------------------
  3937.  * \fn     PrintCrossList_PNode(PTree Node, void *pData)
  3938.  * \brief  printf cross refence list of a single symbol table entry
  3939.  * \param  Node node base object
  3940.  * \param  pData actual symbol entry
  3941.  * \return
  3942.  * ------------------------------------------------------------------------ */
  3943.  
  3944. static void PrintCrossList_PNode(PTree Node, void *pData)
  3945. {
  3946.   int FileZ;
  3947.   PCrossRef pCross;
  3948.   String LineAcc;
  3949.   String h;
  3950.   char LineStr[30];
  3951.   PSymbolEntry SymbolEntry = (PSymbolEntry) Node;
  3952.   as_dynstr_t *p_val_str = (as_dynstr_t*)pData;
  3953.   Boolean First;
  3954.  
  3955.   if (!SymbolEntry->RefList)
  3956.     return;
  3957.  
  3958.   StrSym(&SymbolEntry->SymWert, False, p_val_str, ListRadixBase);
  3959.   as_snprintf(LineStr, sizeof(LineStr), LongIntFormat, SymbolEntry->LineNum);
  3960.  
  3961.   as_snprintf(h, sizeof(h), "%s%s",
  3962.               getmessage(Num_ListCrossSymName), Node->Name);
  3963.   if (Node->Attribute != -1)
  3964.     as_snprcatf(h, sizeof(h), "[%s]", GetSectionName(Node->Attribute));
  3965.   as_snprcatf(h, sizeof(h), " (=%s, %s:%s):",
  3966.               p_val_str->p_str, GetFileName(SymbolEntry->FileNum), LineStr);
  3967.  
  3968.   WrLstLine(h);
  3969.  
  3970.   for (FileZ = 0; FileZ < GetFileCount(); FileZ++)
  3971.   {
  3972.     First = True;
  3973.     strcpy(LineAcc, "  ");
  3974.     for (pCross = SymbolEntry->RefList; pCross; pCross = pCross->Next)
  3975.       if (pCross->FileNum == FileZ)
  3976.       {
  3977.         if (First)
  3978.         {
  3979.           strcpy(h, " ");
  3980.           strmaxcat(h, getmessage(Num_ListCrossFileName), STRINGSIZE);
  3981.           strmaxcat(h, GetFileName(FileZ), STRINGSIZE);
  3982.           strmaxcat(h, " :", STRINGSIZE);
  3983.           WrLstLine(h);
  3984.           First = False;
  3985.         }
  3986.         as_snprcatf(LineAcc, sizeof(LineAcc), "%5ld", (long)pCross->LineNum);
  3987.         if (pCross->OccNum != 1)
  3988.           as_snprcatf(LineAcc, sizeof(LineAcc), "(%2ld)", (long)pCross->OccNum);
  3989.         else
  3990.           strmaxcat(LineAcc, "    ", STRINGSIZE);
  3991.         if (strlen(LineAcc) >= 72)
  3992.         {
  3993.           WrLstLine(LineAcc);
  3994.           strcpy(LineAcc, "  ");
  3995.         }
  3996.       }
  3997.     if (strcmp(LineAcc, "  "))
  3998.       WrLstLine(LineAcc);
  3999.   }
  4000.   WrLstLine("");
  4001. }
  4002.  
  4003. void PrintCrossList(void)
  4004. {
  4005.   as_dynstr_t val_str;
  4006.  
  4007.   as_dynstr_ini(&val_str, 256);
  4008.   WrLstLine("");
  4009.   WrLstLine(getmessage(Num_ListCrossListHead1));
  4010.   WrLstLine(getmessage(Num_ListCrossListHead2));
  4011.   WrLstLine("");
  4012.   IterTree(&(FirstSymbol->Tree), PrintCrossList_PNode, &val_str);
  4013.   WrLstLine("");
  4014.   as_dynstr_free(&val_str);
  4015. }
  4016.  
  4017. static void ClearCrossList_CNode(PTree Tree, void *pData)
  4018. {
  4019.   PCrossRef Lauf;
  4020.   PSymbolEntry SymbolEntry = (PSymbolEntry) Tree;
  4021.   UNUSED(pData);
  4022.  
  4023.   while (SymbolEntry->RefList)
  4024.   {
  4025.     Lauf = SymbolEntry->RefList->Next;
  4026.     free(SymbolEntry->RefList);
  4027.     SymbolEntry->RefList = Lauf;
  4028.   }
  4029. }
  4030.  
  4031. void ClearCrossList(void)
  4032. {
  4033.   IterTree(&(FirstSymbol->Tree), ClearCrossList_CNode, NULL);
  4034. }
  4035.  
  4036. /*--------------------------------------------------------------------------*/
  4037.  
  4038. LongInt GetLocHandle(void)
  4039. {
  4040.   return LocHandleCnt++;
  4041. }
  4042.  
  4043. void PushLocHandle(LongInt NewLoc)
  4044. {
  4045.   PLocHandle NewLocHandle;
  4046.  
  4047.   NewLocHandle = (PLocHandle) malloc(sizeof(TLocHeap));
  4048.   NewLocHandle->Cont = MomLocHandle;
  4049.   NewLocHandle->Next = FirstLocHandle;
  4050.   FirstLocHandle = NewLocHandle; MomLocHandle = NewLoc;
  4051. }
  4052.  
  4053. void PopLocHandle(void)
  4054. {
  4055.   PLocHandle OldLocHandle;
  4056.  
  4057.   OldLocHandle = FirstLocHandle;
  4058.   if (!OldLocHandle) return;
  4059.   MomLocHandle = OldLocHandle->Cont;
  4060.   FirstLocHandle = OldLocHandle->Next;
  4061.   free(OldLocHandle);
  4062. }
  4063.  
  4064. void ClearLocStack(void)
  4065. {
  4066.   while (MomLocHandle != -1)
  4067.     PopLocHandle();
  4068. }
  4069.  
  4070. /*--------------------------------------------------------------------------*/
  4071.  
  4072. static void PrintRegList_PNode(PTree Tree, void *pData)
  4073. {
  4074.   PSymbolEntry Node = (PSymbolEntry) Tree;
  4075.  
  4076.   if (Node->SymWert.Typ == TempReg)
  4077.   {
  4078.     TListContext *pContext = (TListContext*) pData;
  4079.     String tmp, tmp2;
  4080.  
  4081.     if (Node->SymWert.Contents.RegDescr.Dissect)
  4082.       Node->SymWert.Contents.RegDescr.Dissect(tmp2, sizeof(tmp2), Node->SymWert.Contents.RegDescr.Reg, Node->SymWert.DataSize);
  4083.     else
  4084.       *tmp2 = '\0';
  4085.     *tmp = '\0';
  4086.     if (Tree->Attribute != -1)
  4087.       as_snprcatf(tmp, sizeof(tmp), "[%s]", GetSectionName(Tree->Attribute));
  4088.     as_snprcatf(tmp, sizeof(tmp), "%c%s --> %s", Node->Used ? ' ' : '*', Tree->Name, tmp2);
  4089.     if ((int)strlen(tmp) > pContext->cwidth - 3)
  4090.     {
  4091.       if (*pContext->Zeilenrest.p_str)
  4092.         WrLstLine(pContext->Zeilenrest.p_str);
  4093.       *pContext->Zeilenrest.p_str = '\0';
  4094.       WrLstLine(tmp);
  4095.     }
  4096.     else
  4097.     {
  4098.       strmaxcat(tmp, Blanks(pContext->cwidth - 3 - strlen(tmp)), STRINGSIZE);
  4099.       if (!*pContext->Zeilenrest.p_str)
  4100.         as_dynstr_copy_c_str(&pContext->Zeilenrest, tmp);
  4101.       else
  4102.       {
  4103.         as_sdprcatf(&pContext->Zeilenrest, " | %s", tmp);
  4104.         WrLstLine(pContext->Zeilenrest.p_str);
  4105.         *pContext->Zeilenrest.p_str = '\0';
  4106.       }
  4107.     }
  4108.     pContext->Sum++;
  4109.     if (!Node->Used)
  4110.       pContext->USum++;
  4111.   }
  4112. }
  4113.  
  4114. void PrintRegDefs(void)
  4115. {
  4116.   String buf;
  4117.   LongInt ActPageWidth;
  4118.   TListContext Context;
  4119.  
  4120.   if (!RegistersDefined)
  4121.     return;
  4122.  
  4123.   NewPage(ChapDepth, True);
  4124.   WrLstLine(getmessage(Num_ListRegDefListHead1));
  4125.   WrLstLine(getmessage(Num_ListRegDefListHead2));
  4126.   WrLstLine("");
  4127.  
  4128.   as_dynstr_ini(&Context.Zeilenrest, STRINGSIZE);
  4129.   as_dynstr_ini(&Context.s1, 1);
  4130.   as_dynstr_ini(&Context.sh, 1);
  4131.   Context.Sum = Context.USum = 0;
  4132.   ActPageWidth = (PageWidth == 0) ? 80 : PageWidth;
  4133.   Context.cwidth = ActPageWidth >> 1;
  4134.   IterTree((PTree)FirstSymbol, PrintRegList_PNode, &Context);
  4135.  
  4136.   if (*Context.Zeilenrest.p_str)
  4137.     WrLstLine(Context.Zeilenrest.p_str);
  4138.   WrLstLine("");
  4139.   as_snprintf(buf, sizeof(buf), "%7ld%s",
  4140.               (long) Context.Sum,
  4141.               getmessage((Context.Sum == 1) ? Num_ListRegDefSumMsg : Num_ListRegDefSumsMsg));
  4142.   WrLstLine(buf);
  4143.   as_snprintf(buf, sizeof(buf), "%7ld%s",
  4144.               (long)Context.USum,
  4145.               getmessage((Context.USum == 1) ? Num_ListRegDefUSumMsg : Num_ListRegDefUSumsMsg));
  4146.   WrLstLine("");
  4147.   as_dynstr_free(&Context.Zeilenrest);
  4148.   as_dynstr_free(&Context.s1);
  4149.   as_dynstr_free(&Context.sh);
  4150. }
  4151.  
  4152. /*--------------------------------------------------------------------------*/
  4153.  
  4154. /*!------------------------------------------------------------------------
  4155.  * \fn     FindCodepage(const char *p_name, PTransTable p_source)
  4156.  * \brief  look up a code page by name
  4157.  * \param  p_name name to look for
  4158.  * \param  p_source source to copy from if creation allowed, otehrwise NULL
  4159.  * \return * to found/created code page
  4160.  * ------------------------------------------------------------------------ */
  4161.  
  4162. PTransTable FindCodepage(const char *p_name, PTransTable p_source)
  4163. {
  4164.   PTransTable p_prev, p_run, p_new;
  4165.   /* If TransTables is empty, p_name is right behind non-existing
  4166.      last entry: */
  4167.   int cmp_res = 1;
  4168.  
  4169.   for (p_run = TransTables, p_prev = NULL; p_run; p_prev = p_run, p_run = p_run->Next)
  4170.   {
  4171.     cmp_res = CaseSensitive ? strcmp(p_name, p_run->Name) : as_strcasecmp(p_name, p_run->Name);
  4172.     if (cmp_res <= 0)
  4173.       break;
  4174.   }
  4175.   if (!cmp_res)
  4176.     return p_run;
  4177.   else if (!p_source)
  4178.     return NULL;
  4179.   else
  4180.   {
  4181.     p_new = (PTransTable) malloc(sizeof(TTransTable));
  4182.     if (p_new)
  4183.     {
  4184.       p_new->Next = p_run;
  4185.       p_new->Name = as_strdup(p_name);
  4186.       if (!CaseSensitive)
  4187.         UpString(p_new->Name);
  4188.       p_new->p_table = as_chartrans_table_dup(p_source->p_table);
  4189.       if (p_prev)
  4190.         p_prev->Next = p_new;
  4191.       else
  4192.         TransTables = p_new;
  4193.     }
  4194.     return p_new;
  4195.   }
  4196. }
  4197.  
  4198. void ClearCodepages(void)
  4199. {
  4200.   PTransTable Old;
  4201.  
  4202.   while (TransTables)
  4203.   {
  4204.     Old = TransTables;
  4205.     TransTables = Old->Next;
  4206.     free(Old->Name);
  4207.     as_chartrans_table_free(Old->p_table);
  4208.     free(Old);
  4209.   }
  4210. }
  4211.  
  4212. void PrintCodepages(void)
  4213. {
  4214.   char buf[500];
  4215.   PTransTable Table;
  4216.   int z, cnt, cnt2;
  4217.  
  4218.   NewPage(ChapDepth, True);
  4219.   WrLstLine(getmessage(Num_ListCodepageListHead1));
  4220.   WrLstLine(getmessage(Num_ListCodepageListHead2));
  4221.   WrLstLine("");
  4222.  
  4223.   cnt2 = 0;
  4224.   for (Table = TransTables; Table; Table = Table->Next)
  4225.   {
  4226.     for (z = cnt = 0; z < 256; z++)
  4227.       if (Table->p_table->mapping[z] != z)
  4228.         cnt++;
  4229.     as_snprintf(buf, sizeof(buf), "%s (%d%s)", Table->Name, cnt,
  4230.                 getmessage((cnt == 1) ? Num_ListCodepageChange : Num_ListCodepagePChange));
  4231.     WrLstLine(buf);
  4232.     cnt2++;
  4233.   }
  4234.   WrLstLine("");
  4235.   as_snprintf(buf, sizeof(buf), "%d%s", cnt2,
  4236.               getmessage((cnt2 == 1) ? Num_ListCodepageSumMsg : Num_ListCodepageSumsMsg));
  4237.   WrLstLine(buf);
  4238. }
  4239.  
  4240. /*--------------------------------------------------------------------------*/
  4241.  
  4242. void asmpars_init(void)
  4243. {
  4244.   tIntTypeDef *pCurr;
  4245.  
  4246.   serr = (char*)malloc(sizeof(char) * STRINGSIZE);
  4247.   snum = (char*)malloc(sizeof(char) * STRINGSIZE);
  4248.   FirstDefSymbol = NULL;
  4249.   FirstFunction = NULL;
  4250.   BalanceTrees = False;
  4251.  
  4252.   for (pCurr = IntTypeDefs; pCurr < IntTypeDefs + (sizeof(IntTypeDefs) / sizeof(*IntTypeDefs)); pCurr++)
  4253.   {
  4254.     unsigned SignType = Hi(pCurr->SignAndWidth);
  4255.     unsigned Bits, Cnt;
  4256.  
  4257.     Bits = Lo(pCurr->SignAndWidth) - ((SignType == 0x80) ? 1 : 0);
  4258.     for (Cnt = 0, pCurr->Mask = 0; Cnt < Bits; Cnt++)
  4259.       pCurr->Mask = (pCurr->Mask << 1) | 1;
  4260.  
  4261.     pCurr->Max = (LargeInt)pCurr->Mask;
  4262.  
  4263.     switch (SignType & 0xc0)
  4264.     {
  4265.       case 0x80:
  4266.         pCurr->Min = -pCurr->Max - 1;
  4267.         break;
  4268.       case 0xc0:
  4269.         pCurr->Min = (LargeInt)(pCurr->Mask / 2);
  4270.         pCurr->Min = -pCurr->Min - 1;
  4271.         break;
  4272.       default:
  4273.         pCurr->Min = 0;
  4274.         break;
  4275.     }
  4276.   }
  4277.  
  4278.   LastGlobSymbol = (char*)malloc(sizeof(char) * STRINGSIZE);
  4279. }
  4280.