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