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