1 /* asmallg.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4 /*                                                                           */
5 /* AS-Portierung                                                             */
6 /*                                                                           */
7 /* von allen Codegeneratoren benutzte Pseudobefehle                          */
8 /*                                                                           */
9 /*****************************************************************************/
10 
11 #include "stdinc.h"
12 #include <string.h>
13 #include <ctype.h>
14 
15 #include "nls.h"
16 #include "strutil.h"
17 #include "stringlists.h"
18 #include "bpemu.h"
19 #include "console.h"
20 #include "chunks.h"
21 #include "asmdef.h"
22 #include "asmsub.h"
23 #include "errmsg.h"
24 #include "as.h"
25 #include "as.rsc"
26 #include "asmpars.h"
27 #include "asmmac.h"
28 #include "asmstructs.h"
29 #include "asmcode.h"
30 #include "asmrelocs.h"
31 #include "asmitree.h"
32 #include "codepseudo.h"
33 #include "nlmessages.h"
34 #include "asmallg.h"
35 
36 /*--------------------------------------------------------------------------*/
37 
38 
39 static PInstTable PseudoTable = NULL, ONOFFTable;
40 
41 /*--------------------------------------------------------------------------*/
42 
DefChkPC(LargeWord Addr)43 static Boolean DefChkPC(LargeWord Addr)
44 {
45   if (!((1 << ActPC) & ValidSegs))
46     return False;
47   else
48     return (Addr <= SegLimits[ActPC]);
49 }
50 
51 /*!------------------------------------------------------------------------
52  * \fn     ParseCPUArgs(tStrComp *pArgs, const tCPUArg *pCPUArgs)
53  * \brief  parse possible arguments of CPU
54  * \param  pArgs arguments set by user (may be NULL)
55  * \param  pCPUArgs arguments provided by target (may be NULL)
56  * ------------------------------------------------------------------------ */
57 
ParseCPUArgs(const tStrComp * pArgs,const tCPUArg * pCPUArgs)58 static void ParseCPUArgs(const tStrComp *pArgs, const tCPUArg *pCPUArgs)
59 {
60   const tCPUArg *pCPUArg;
61   char *pNext, *pSep;
62   tStrComp Args, Remainder, NameComp, ValueComp;
63   LongInt VarValue;
64   Boolean OK;
65   String ArgStr;
66 
67   /* always reset to defaults, also when no user arguments are given */
68 
69   if (!pCPUArgs)
70     return;
71   for (pCPUArg = pCPUArgs; pCPUArg->pName; pCPUArg++)
72     *pCPUArg->pValue = pCPUArg->DefValue;
73 
74   if (!pArgs)
75     return;
76   StrCompMkTemp(&Args, ArgStr);
77   StrCompCopy(&Args, pArgs);
78   do
79   {
80     pNext = strchr(Args.Str, ':');
81     if (pNext)
82       StrCompSplitRef(&Args, &Remainder, &Args, pNext);
83     pSep = strchr(Args.Str, '=');
84     if (!pSep) WrStrErrorPos(ErrNum_ArgValueMissing, &Args);
85     else
86     {
87       StrCompSplitRef(&NameComp, &ValueComp, &Args, pSep);
88       KillPrefBlanksStrCompRef(&NameComp); KillPostBlanksStrComp(&NameComp);
89       KillPrefBlanksStrCompRef(&ValueComp); KillPostBlanksStrComp(&ValueComp);
90 
91       VarValue = EvalStrIntExpression(&ValueComp, Int32, &OK);
92       if (OK)
93       {
94         for (pCPUArg = pCPUArgs; pCPUArg->pName; pCPUArg++)
95         if (!as_strcasecmp(NameComp.Str, pCPUArg->pName))
96           break;
97         if (!pCPUArg->pName) WrStrErrorPos(ErrNum_UnknownArg, &NameComp);
98         else if (ChkRange(VarValue, pCPUArg->Min, pCPUArg->Max))
99           *pCPUArg->pValue = VarValue;
100       }
101     }
102     if (pNext)
103       Args = Remainder;
104   }
105   while (pNext);
106 }
107 
SetCPUCore(const tCPUDef * pCPUDef,const tStrComp * pCPUArgs)108 static void SetCPUCore(const tCPUDef *pCPUDef, const tStrComp *pCPUArgs)
109 {
110   LargeInt HCPU;
111   int Digit, Base;
112   const char *pRun;
113 
114   tStrComp TmpComp;
115   String TmpCompStr;
116   StrCompMkTemp(&TmpComp, TmpCompStr);
117 
118   strmaxcpy(MomCPUIdent, pCPUDef->Name, sizeof(MomCPUIdent));
119   MomCPU = pCPUDef->Orig;
120   MomVirtCPU = pCPUDef->Number;
121   HCPU = 0;
122   Base = 10;
123   for (pRun = MomCPUIdent; *pRun; pRun++)
124   {
125     if (isdigit(*pRun))
126       Base = 16;
127     Digit = DigitVal(*pRun, Base);
128     if (Digit >= 0)
129       HCPU = (HCPU << 4) + Digit;
130   }
131 
132   strmaxcpy(TmpCompStr, MomCPUName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, HCPU, SegNone, True);
133   strmaxcpy(TmpCompStr, MomCPUIdentName, sizeof(TmpCompStr)); EnterStringSymbol(&TmpComp, MomCPUIdent, True);
134 
135   InternSymbol = Default_InternSymbol;
136   ConstModeWeirdNoTerm = False;
137   DissectBit = Default_DissectBit;
138   DissectReg = NULL;
139   QualifyQuote = NULL;
140   SetIsOccupiedFnc = NULL;
141   DecodeAttrPart = NULL;
142   SwitchIsOccupied =
143   PageIsOccupied =
144   ShiftIsOccupied = False;
145   ChkPC = DefChkPC;
146   ASSUMERecCnt = 0;
147   pASSUMERecs = NULL;
148   pASSUMEOverride = NULL;
149   if (SwitchFrom)
150   {
151     SwitchFrom();
152     SwitchFrom = NULL;
153   }
154   strmaxcpy(MomCPUArgs, pCPUArgs ? pCPUArgs->Str : "", sizeof(MomCPUArgs));
155   ParseCPUArgs(pCPUArgs, pCPUDef->pArgs);
156   pCPUDef->SwitchProc(pCPUDef->pUserData);
157 
158   DontPrint = True;
159 }
160 
SetCPUByType(CPUVar NewCPU,const tStrComp * pCPUArgs)161 void SetCPUByType(CPUVar NewCPU, const tStrComp *pCPUArgs)
162 {
163   const tCPUDef *pCPUDef;
164 
165   pCPUDef = LookupCPUDefByVar(NewCPU);
166   if (pCPUDef)
167     SetCPUCore(pCPUDef, pCPUArgs);
168 }
169 
SetCPUByName(const tStrComp * pName)170 Boolean SetCPUByName(const tStrComp *pName)
171 {
172   const tCPUDef *pCPUDef;
173 
174   pCPUDef = LookupCPUDefByName(pName->Str);
175   if (!pCPUDef)
176     return False;
177   else
178   {
179     int l = strlen(pCPUDef->Name);
180 
181     if (pName->Str[l] == ':')
182     {
183       tStrComp ArgComp;
184 
185       StrCompRefRight(&ArgComp, pName, l + 1);
186       SetCPUCore(pCPUDef, &ArgComp);
187     }
188     else
189       SetCPUCore(pCPUDef, NULL);
190     return True;
191   }
192 }
193 
SetNSeg(Byte NSeg)194 static void SetNSeg(Byte NSeg)
195 {
196   if ((ActPC != NSeg) || (!PCsUsed[ActPC]))
197   {
198     ActPC = NSeg;
199     if (!PCsUsed[ActPC])
200       PCs[ActPC] = SegInits[ActPC];
201     PCsUsed[ActPC] = True;
202     DontPrint = True;
203   }
204 }
205 
IntLine(char * pDest,size_t DestSize,LargeWord Inp,TConstMode ThisConstMode)206 static void IntLine(char *pDest, size_t DestSize, LargeWord Inp, TConstMode ThisConstMode)
207 {
208   switch (ThisConstMode)
209   {
210     case ConstModeIntel:
211       as_snprintf(pDest, DestSize, "%lllx%s", Inp, GetIntelSuffix(16));
212       if (*pDest > '9')
213         strmaxprep(pDest, "0", DestSize);
214       break;
215     case ConstModeMoto:
216       as_snprintf(pDest, DestSize, "$%lllx", Inp);
217       break;
218     case ConstModeC:
219       as_snprintf(pDest, DestSize, "0x%lllx", Inp);
220       break;
221     case ConstModeWeird:
222       as_snprintf(pDest, DestSize, "x'%lllx'", Inp);
223       break;
224   }
225 }
226 
227 
CodeSECTION(Word Index)228 static void CodeSECTION(Word Index)
229 {
230   PSaveSection Neu;
231   String ExpName;
232   UNUSED(Index);
233 
234   if (ChkArgCnt(1, 1)
235    && ExpandStrSymbol(ExpName, sizeof(ExpName), &ArgStr[1]))
236   {
237     if (!ChkSymbName(ExpName)) WrStrErrorPos(ErrNum_InvSymName, &ArgStr[1]);
238     else if ((PassNo == 1) && (GetSectionHandle(ExpName, False, MomSectionHandle) != -2)) WrError(ErrNum_DoubleSection);
239     else
240     {
241       Neu = (PSaveSection) malloc(sizeof(TSaveSection));
242       Neu->Next = SectionStack;
243       Neu->Handle = MomSectionHandle;
244       Neu->LocSyms = NULL;
245       Neu->GlobSyms = NULL;
246       Neu->ExportSyms = NULL;
247       SetMomSection(GetSectionHandle(ExpName, True, MomSectionHandle));
248       SectionStack = Neu;
249     }
250   }
251 }
252 
253 
CodeENDSECTION_ChkEmptList(PForwardSymbol * Root)254 static void CodeENDSECTION_ChkEmptList(PForwardSymbol *Root)
255 {
256   PForwardSymbol Tmp;
257   String XError;
258 
259   while (*Root)
260   {
261     strmaxcpy(XError, (*Root)->Name, STRINGSIZE);
262     strmaxcat(XError, ", ", STRINGSIZE);
263     strmaxcat(XError, (*Root)->pErrorPos, STRINGSIZE);
264     WrXError(ErrNum_UndefdForward, XError);
265     free((*Root)->Name);
266     free((*Root)->pErrorPos);
267     Tmp = (*Root);
268     *Root = Tmp->Next; free(Tmp);
269   }
270 }
271 
CodeENDSECTION(Word Index)272 static void CodeENDSECTION(Word Index)
273 {
274   PSaveSection Tmp;
275   String ExpName;
276   UNUSED(Index);
277 
278   if (!ChkArgCnt(0, 1));
279   else if (!SectionStack) WrError(ErrNum_NotInSection);
280   else if ((ArgCnt == 0) || (ExpandStrSymbol(ExpName, sizeof(ExpName), &ArgStr[1])))
281   {
282     if ((ArgCnt == 1) && (GetSectionHandle(ExpName, False, SectionStack->Handle) != MomSectionHandle)) WrStrErrorPos(ErrNum_WrongEndSect, &ArgStr[1]);
283     else
284     {
285       Tmp = SectionStack;
286       SectionStack = Tmp->Next;
287       CodeENDSECTION_ChkEmptList(&(Tmp->LocSyms));
288       CodeENDSECTION_ChkEmptList(&(Tmp->GlobSyms));
289       CodeENDSECTION_ChkEmptList(&(Tmp->ExportSyms));
290       if (ArgCnt == 0)
291         as_snprintf(ListLine, STRINGSIZE, "[%s]", GetSectionName(MomSectionHandle));
292       SetMomSection(Tmp->Handle);
293       free(Tmp);
294     }
295   }
296 }
297 
298 
CodeCPU(Word Index)299 static void CodeCPU(Word Index)
300 {
301   UNUSED(Index);
302 
303   if (!ChkArgCnt(1, 1));
304   else if (*AttrPart.Str != '\0') WrError(ErrNum_UseLessAttr);
305   else
306   {
307     NLS_UpString(ArgStr[1].Str);
308     if (SetCPUByName(&ArgStr[1]))
309       SetNSeg(SegCode);
310     else
311       WrStrErrorPos(ErrNum_InvCPUType, &ArgStr[1]);
312   }
313 }
314 
315 
CodeSETEQU(Word MayChange)316 static void CodeSETEQU(Word MayChange)
317 {
318   TempResult t;
319   Integer DestSeg;
320   int ValIndex = *LabPart.Str ? 1 : 2;
321 
322   if (ChkArgCnt(ValIndex, ValIndex + 1))
323   {
324     EvalStrExpression(&ArgStr[ValIndex], &t);
325     if (!mFirstPassUnknown(t.Flags))
326     {
327       if (ArgCnt == ValIndex)
328         DestSeg = SegNone;
329       else
330       {
331         NLS_UpString(ArgStr[ValIndex + 1].Str);
332         if (!strcmp(ArgStr[ValIndex + 1].Str, "MOMSEGMENT"))
333           DestSeg = ActPC;
334         else if (*ArgStr[ValIndex + 1].Str == '\0')
335           DestSeg = SegNone;
336         else
337         {
338           for (DestSeg = 0; DestSeg <= PCMax; DestSeg++)
339             if (!strcmp(ArgStr[ValIndex + 1].Str, SegNames[DestSeg]))
340               break;
341         }
342       }
343       if (DestSeg > PCMax) WrStrErrorPos(ErrNum_UnknownSegment, &ArgStr[ValIndex + 1]);
344       else
345       {
346         const tStrComp *pName = *LabPart.Str ? &LabPart : &ArgStr[1];
347 
348         SetListLineVal(&t);
349         PushLocHandle(-1);
350         switch (t.Typ)
351         {
352           case TempInt:
353             EnterIntSymbol(pName, t.Contents.Int, DestSeg, MayChange);
354             if (AttrPartOpSize != eSymbolSizeUnknown)
355               SetSymbolOrStructElemSize(pName, AttrPartOpSize);
356             break;
357           case TempFloat:
358             EnterFloatSymbol(pName, t.Contents.Float, MayChange);
359             break;
360           case TempString:
361             EnterDynStringSymbolWithFlags(pName, &t.Contents.Ascii, MayChange, t.Flags);
362             break;
363           case TempReg:
364             EnterRegSymbol(pName, &t.Contents.RegDescr, t.DataSize, MayChange, False);
365             break;
366           default:
367             break;
368         }
369         PopLocHandle();
370       }
371     }
372   }
373 }
374 
CodeREGCore(const tStrComp * pNameArg,const tStrComp * pValueArg)375 static void CodeREGCore(const tStrComp *pNameArg, const tStrComp *pValueArg)
376 {
377  if (InternSymbol)
378  {
379    TempResult t;
380 
381    t.Typ = TempNone;
382    InternSymbol(pValueArg->Str, &t);
383    switch (t.Typ)
384    {
385      case TempReg:
386        goto Set;
387      case TempNone:
388      {
389        tEvalResult EvalResult;
390        tErrorNum ErrorNum;
391 
392        ErrorNum = EvalStrRegExpressionWithResult(pValueArg, &t.Contents.RegDescr, &EvalResult);
393 
394        switch (ErrorNum)
395        {
396          case ErrNum_SymbolUndef:
397            /* ignore undefined symbols in first pass */
398            if (PassNo <= MaxSymPass)
399            {
400              Repass = True;
401              return;
402            }
403            break;
404          case ErrNum_RegWrongTarget:
405            /* REG is architecture-agnostic */
406            EvalResult.OK = True;
407            break;
408          default:
409            break;
410        }
411 
412        if (EvalResult.OK)
413        {
414          t.DataSize = EvalResult.DataSize;
415          goto Set;
416        }
417        else
418          WrStrErrorPos(ErrorNum, pValueArg);
419 
420        break;
421      }
422      Set:
423        EnterRegSymbol(pNameArg, &t.Contents.RegDescr, t.DataSize, False, True);
424        break;
425      default:
426        WrStrErrorPos(ErrNum_ExpectReg, pValueArg);
427        return;
428    }
429  }
430 }
431 
CodeREG(Word Index)432 void CodeREG(Word Index)
433 {
434   UNUSED(Index);
435 
436   if (ChkArgCnt(1, 1))
437     CodeREGCore(&LabPart, &ArgStr[1]);
438 }
439 
CodeNAMEREG(Word Index)440 void CodeNAMEREG(Word Index)
441 {
442   UNUSED(Index);
443 
444   if (ChkArgCnt(2, 2))
445     CodeREGCore(&ArgStr[2], &ArgStr[1]);
446 }
447 
CodeORG(Word Index)448 static void CodeORG(Word Index)
449 {
450   LargeWord HVal;
451   Boolean ValOK;
452   tSymbolFlags Flags;
453   UNUSED(Index);
454 
455   if (*AttrPart.Str != '\0') WrError(ErrNum_UseLessAttr);
456   else if (ChkArgCnt(1, 1))
457   {
458 #ifndef HAS64
459     HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &ValOK, &Flags);
460 #else
461     HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int64, &ValOK, &Flags);
462 #endif
463     if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
464     if (ValOK && !mFirstPassUnknown(Flags) && (PCs[ActPC] != HVal))
465     {
466       PCs[ActPC] = HVal;
467       DontPrint = True;
468     }
469   }
470 }
471 
CodeRORG(Word Index)472 static void CodeRORG(Word Index)
473 {
474   LargeInt HVal;
475   Boolean ValOK;
476   tSymbolFlags Flags;
477   UNUSED(Index);
478 
479   if (*AttrPart.Str != '\0') WrError(ErrNum_UseLessAttr);
480   else if (ChkArgCnt(1, 1))
481   {
482 #ifndef HAS64
483     HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], SInt32, &ValOK, &Flags);
484 #else
485     HVal = EvalStrIntExpressionWithFlags(&ArgStr[1], Int64, &ValOK, &Flags);
486 #endif
487     if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
488     else if (ValOK)
489     {
490       PCs[ActPC] += HVal;
491       DontPrint = True;
492     }
493   }
494 }
495 
CodeSHARED_BuildComment(char * c,size_t DestSize)496 static void CodeSHARED_BuildComment(char *c, size_t DestSize)
497 {
498   switch (ShareMode)
499   {
500     case 1:
501       as_snprintf(c, DestSize, "(* %s *)", CommPart.Str);
502       break;
503     case 2:
504       as_snprintf(c, DestSize, "/* %s */", CommPart.Str);
505       break;
506     case 3:
507       as_snprintf(c, DestSize, "; %s", CommPart.Str);
508       break;
509   }
510 }
511 
CodeSHARED(Word Index)512 static void CodeSHARED(Word Index)
513 {
514   tStrComp *pArg;
515   String s, c;
516   TempResult t;
517   UNUSED(Index);
518 
519   if (ShareMode == 0) WrError(ErrNum_NoShareFile);
520   else if ((ArgCnt == 0) && (*CommPart.Str != '\0'))
521   {
522     CodeSHARED_BuildComment(c, sizeof(c));
523     errno = 0;
524     fprintf(ShareFile, "%s\n", c); ChkIO(ErrNum_FileWriteError);
525   }
526   else
527    forallargs (pArg, True)
528    {
529      LookupSymbol(pArg, &t, False, TempAll);
530 
531      switch (t.Typ)
532      {
533        case TempInt:
534          switch (ShareMode)
535          {
536            case 1:
537              IntLine(s, sizeof(s), t.Contents.Int, ConstModeMoto);
538              break;
539            case 2:
540              IntLine(s, sizeof(s), t.Contents.Int, ConstModeC);
541              break;
542            case 3:
543              IntLine(s, sizeof(s), t.Contents.Int, ConstMode);
544              break;
545          }
546          break;
547        case TempFloat:
548          as_snprintf(s, sizeof(s), "%0.17g", t.Contents.Float);
549          break;
550        case TempString:
551          DynString2CString(s + 1, &t.Contents.Ascii, sizeof(s) - 1);
552          if (ShareMode == 1)
553          {
554            *s = '\'';
555            strmaxcat(s, "\'", STRINGSIZE);
556          }
557          else
558          {
559            *s = '\"';
560            strmaxcat(s, "\"", STRINGSIZE);
561          }
562          break;
563        default:
564          continue;
565      }
566 
567      if ((pArg == ArgStr + 1) && (*CommPart.Str != '\0'))
568      {
569        CodeSHARED_BuildComment(c, sizeof(c));
570        strmaxprep(c, " ", STRINGSIZE);
571      }
572      else
573        *c = '\0';
574      errno = 0;
575      switch (ShareMode)
576      {
577        case 1:
578          fprintf(ShareFile, "%s = %s;%s\n", pArg->Str, s, c);
579          break;
580        case 2:
581          fprintf(ShareFile, "#define %s %s%s\n", pArg->Str, s, c);
582          break;
583        case 3:
584          strmaxprep(s, IsSymbolChangeable(pArg) ? "set " : "equ ", STRINGSIZE);
585          fprintf(ShareFile, "%s %s%s\n", pArg->Str, s, c);
586          break;
587      }
588      ChkIO(ErrNum_FileWriteError);
589    }
590 }
591 
CodeEXPORT(Word Index)592 static void CodeEXPORT(Word Index)
593 {
594   tStrComp *pArg;
595   TempResult t;
596   UNUSED(Index);
597 
598   forallargs (pArg, True)
599   {
600     LookupSymbol(pArg, &t, True, TempInt);
601     if (TempNone == t.Typ)
602       continue;
603     if (t.Relocs == NULL)
604       AddExport(pArg->Str, t.Contents.Int, 0);
605     else if ((t.Relocs->Next != NULL) || (strcmp(t.Relocs->Ref, RelName_SegStart)))
606       WrStrErrorPos(ErrNum_Unexportable, pArg);
607     else
608       AddExport(pArg->Str, t.Contents.Int, RelFlag_Relative);
609     if (t.Relocs)
610       FreeRelocs(&t.Relocs);
611   }
612 }
613 
CodePAGE(Word Index)614 static void CodePAGE(Word Index)
615 {
616   Integer LVal, WVal;
617   Boolean ValOK;
618   UNUSED(Index);
619 
620   if (!ChkArgCnt(1, 2));
621   else if (*AttrPart.Str != '\0') WrError(ErrNum_UseLessAttr);
622   else
623   {
624     LVal = EvalStrIntExpression(&ArgStr[1], UInt8, &ValOK);
625     if (ValOK)
626     {
627       if ((LVal < 5) && (LVal != 0))
628         LVal = 5;
629       if (ArgCnt == 1)
630       {
631         WVal = 0;
632         ValOK = True;
633       }
634       else
635         WVal = EvalStrIntExpression(&ArgStr[2], UInt8, &ValOK);
636       if (ValOK)
637       {
638         if ((WVal < 5) && (WVal != 0))
639           WVal = 5;
640         PageLength = LVal;
641         PageWidth = WVal;
642       }
643     }
644   }
645 }
646 
647 
CodeNEWPAGE(Word Index)648 static void CodeNEWPAGE(Word Index)
649 {
650   ShortInt HVal8;
651   Boolean ValOK;
652   UNUSED(Index);
653 
654   if (!ChkArgCnt(0, 1));
655   else if (*AttrPart.Str != '\0') WrError(ErrNum_UseLessAttr);
656   else
657   {
658     if (ArgCnt == 0)
659     {
660       HVal8 = 0;
661       ValOK = True;
662     }
663     else
664       HVal8 = EvalStrIntExpression(&ArgStr[1], Int8, &ValOK);
665     if ((ValOK) || (ArgCnt == 0))
666     {
667       if (HVal8 > ChapMax)
668         HVal8 = ChapMax;
669       else if (HVal8 < 0)
670         HVal8 = 0;
671       NewPage(HVal8, True);
672     }
673   }
674 }
675 
676 
CodeString(Word Index)677 static void CodeString(Word Index)
678 {
679   String tmp;
680   Boolean OK;
681 
682   if (ChkArgCnt(1, 1))
683   {
684     EvalStrStringExpression(&ArgStr[1], &OK, tmp);
685     if (!OK) WrError(ErrNum_InvString);
686     else
687     {
688       switch (Index)
689       {
690         case 0:
691           strmaxcpy(PrtInitString, tmp, STRINGSIZE);
692           break;
693         case 1:
694           strmaxcpy(PrtExitString, tmp, STRINGSIZE);
695           break;
696         case 2:
697           strmaxcpy(PrtTitleString, tmp, STRINGSIZE);
698           break;
699       }
700     }
701   }
702 }
703 
704 
CodePHASE(Word Index)705 static void CodePHASE(Word Index)
706 {
707   Boolean OK;
708   LongInt HVal;
709   UNUSED(Index);
710 
711   if (!ChkArgCnt(1, 1));
712   else if (ActPC == StructSeg) WrError(ErrNum_PhaseDisallowed);
713   else
714   {
715     HVal = EvalStrIntExpression(&ArgStr[1], Int32, &OK);
716     if (OK)
717     {
718       tSavePhase *pSavePhase;
719 
720       pSavePhase = (tSavePhase*)calloc(1, sizeof (*pSavePhase));
721       pSavePhase->SaveValue = Phases[ActPC];
722       pSavePhase->pNext = pPhaseStacks[ActPC];
723       pPhaseStacks[ActPC] = pSavePhase;
724       Phases[ActPC] = HVal - ProgCounter();
725     }
726   }
727 }
728 
729 
CodeDEPHASE(Word Index)730 static void CodeDEPHASE(Word Index)
731 {
732   UNUSED(Index);
733 
734   if (!ChkArgCnt(0, 0));
735   else if (ActPC == StructSeg) WrError(ErrNum_PhaseDisallowed);
736   else if (pPhaseStacks[ActPC])
737   {
738     tSavePhase *pSavePhase;
739 
740     pSavePhase = pPhaseStacks[ActPC];
741     pPhaseStacks[ActPC] = pSavePhase->pNext;
742     Phases[ActPC] = pSavePhase->SaveValue;
743     free(pSavePhase);
744   }
745   else
746     Phases[ActPC] = 0;
747 }
748 
749 
CodeWARNING(Word Index)750 static void CodeWARNING(Word Index)
751 {
752   String mess;
753   Boolean OK;
754   UNUSED(Index);
755 
756   if (ChkArgCnt(1, 1))
757   {
758     EvalStrStringExpression(&ArgStr[1], &OK, mess);
759     if (!OK) WrError(ErrNum_InvString);
760     else
761       WrErrorString(mess, "", True, False, NULL, NULL);
762   }
763 }
764 
765 
CodeMESSAGE(Word Index)766 static void CodeMESSAGE(Word Index)
767 {
768   String mess;
769   Boolean OK;
770   UNUSED(Index);
771 
772   if (ChkArgCnt(1, 1))
773   {
774     EvalStrStringExpression(&ArgStr[1], &OK, mess);
775     if (!OK) WrError(ErrNum_InvString);
776     else
777     {
778       WrConsoleLine(mess, True);
779       if (strcmp(LstName, "/dev/null"))
780         WrLstLine(mess);
781     }
782   }
783 }
784 
785 
CodeERROR(Word Index)786 static void CodeERROR(Word Index)
787 {
788   String mess;
789   Boolean OK;
790   UNUSED(Index);
791 
792   if (ChkArgCnt(1, 1))
793   {
794     EvalStrStringExpression(&ArgStr[1], &OK, mess);
795     if (!OK) WrError(ErrNum_InvString);
796     else
797       WrErrorString(mess, "", False, False, NULL, NULL);
798   }
799 }
800 
801 
CodeFATAL(Word Index)802 static void CodeFATAL(Word Index)
803 {
804   String mess;
805   Boolean OK;
806   UNUSED(Index);
807 
808   if (ChkArgCnt(1, 1))
809   {
810     EvalStrStringExpression(&ArgStr[1], &OK, mess);
811     if (!OK) WrError(ErrNum_InvString);
812     else
813       WrErrorString(mess, "", False, True, NULL, NULL);
814   }
815 }
816 
CodeCHARSET(Word Index)817 static void CodeCHARSET(Word Index)
818 {
819   TempResult t;
820   FILE *f;
821   unsigned char tfield[256];
822   LongWord Start, l, TStart, Stop, z;
823   Boolean OK;
824   UNUSED(Index);
825 
826   if (!ChkArgCnt(0, 3));
827   else if (ArgCnt == 0)
828   {
829     for (z = 0; z < 256; z++)
830       CharTransTable[z] = z;
831   }
832   else
833   {
834     EvalStrExpression(&ArgStr[1], &t);
835     if ((t.Typ == TempString) && (t.Flags & eSymbolFlag_StringSingleQuoted))
836       TempResultToInt(&t);
837     switch (t.Typ)
838     {
839       case TempInt:
840         if (mFirstPassUnknown(t.Flags))
841           t.Contents.Int &= 255;
842         if (ChkRange(t.Contents.Int, 0, 255))
843         {
844           if (ChkArgCnt(2, 3))
845           {
846             Start = t.Contents.Int;
847             EvalStrExpression(&ArgStr[2], &t);
848             if ((t.Typ == TempString) && (t.Flags & eSymbolFlag_StringSingleQuoted))
849               TempResultToInt(&t);
850             switch (t.Typ)
851             {
852               case TempInt: /* �bersetzungsbereich als Character-Angabe */
853                 if (mFirstPassUnknown(t.Flags))
854                   t.Contents.Int &= 255;
855                 if (ArgCnt == 2)
856                 {
857                   Stop = Start;
858                   TStart = t.Contents.Int;
859                   OK = ChkRange(TStart, 0, 255);
860                 }
861                 else
862                 {
863                   Stop = t.Contents.Int;
864                   OK = ChkRange(Stop, Start, 255);
865                   if (OK)
866                     TStart = EvalStrIntExpression(&ArgStr[3], UInt8, &OK);
867                   else
868                     TStart = 0;
869                 }
870                 if (OK)
871                   for (z = Start; z <= Stop; z++)
872                     CharTransTable[z] = TStart + (z - Start);
873                 break;
874               case TempString:
875                 l = t.Contents.Ascii.Length; /* Uebersetzungsstring ab Start */
876                 if (Start + l > 256) WrError(ErrNum_OverRange);
877                 else
878                   for (z = 0; z < l; z++)
879                     CharTransTable[Start + z] = t.Contents.Ascii.Contents[z];
880                 break;
881               case TempFloat:
882                 WrStrErrorPos(ErrNum_StringOrIntButFloat, &ArgStr[2]);
883                 break;
884               default:
885                 break;
886             }
887           }
888         }
889         break;
890       case TempString:
891         if (ChkArgCnt(1, 1)) /* Tabelle von Datei lesen */
892         {
893           String Tmp;
894 
895           DynString2CString(Tmp, &t.Contents.Ascii, sizeof(Tmp));
896           f = fopen(Tmp, OPENRDMODE);
897           if (!f) ChkIO(ErrNum_OpeningFile);
898           if (fread(tfield, sizeof(char), 256, f) != 256) ChkIO(ErrNum_FileReadError);
899           fclose(f);
900           memcpy(CharTransTable, tfield, sizeof(char) * 256);
901         }
902         break;
903       case TempFloat:
904         WrStrErrorPos(ErrNum_StringOrIntButFloat, &ArgStr[1]);
905         break;
906       default:
907         break;
908     }
909   }
910 }
911 
CodePRSET(Word Index)912 static void CodePRSET(Word Index)
913 {
914   int z, z2;
915   UNUSED(Index);
916 
917   for (z = 0; z < 16; z++)
918   {
919     for (z2 = 0; z2 < 16; z2++)
920       printf(" %02x", CharTransTable[z*16 + z2]);
921     printf("  ");
922     for (z2 = 0; z2 < 16; z2++)
923       printf("%c", CharTransTable[z * 16 + z2] > ' ' ? CharTransTable[z*16 + z2] : '.');
924     putchar('\n');
925   }
926 }
927 
CodeCODEPAGE(Word Index)928 static void CodeCODEPAGE(Word Index)
929 {
930   PTransTable Prev, Run, New, Source;
931   int erg = 0;
932   UNUSED(Index);
933 
934   if (!ChkArgCnt(1, 2));
935   else if (!ChkSymbName(ArgStr[1].Str)) WrStrErrorPos(ErrNum_InvSymName, &ArgStr[1]);
936   else
937   {
938     if (!CaseSensitive)
939     {
940       UpString(ArgStr[1].Str);
941       if (ArgCnt == 2)
942         UpString(ArgStr[2].Str);
943     }
944 
945     if (ArgCnt == 1)
946       Source = CurrTransTable;
947     else
948     {
949       for (Source = TransTables; Source; Source = Source->Next)
950         if (!strcmp(Source->Name, ArgStr[2].Str))
951           break;
952     }
953 
954     if (!Source) WrStrErrorPos(ErrNum_UnknownCodepage, &ArgStr[2]);
955     else
956     {
957       for (Prev = NULL, Run = TransTables; Run; Prev = Run, Run = Run->Next)
958         if ((erg = strcmp(ArgStr[1].Str, Run->Name)) <= 0)
959           break;
960 
961       if ((!Run) || (erg < 0))
962       {
963         New = (PTransTable) malloc(sizeof(TTransTable));
964         New->Next = Run;
965         New->Name = as_strdup(ArgStr[1].Str);
966         New->Table = (unsigned char *) malloc(256 * sizeof(char));
967         memcpy(New->Table, Source->Table, 256 * sizeof(char));
968         if (!Prev)
969           TransTables = New;
970         else
971           Prev->Next = New;
972         CurrTransTable = New;
973       }
974       else
975         CurrTransTable = Run;
976     }
977   }
978 }
979 
980 
CodeFUNCTION(Word Index)981 static void CodeFUNCTION(Word Index)
982 {
983   String FName;
984   Boolean OK;
985   int z;
986   UNUSED(Index);
987 
988   if (ChkArgCnt(2, ArgCntMax))
989   {
990     OK = True;
991     z = 1;
992     do
993     {
994       OK = (OK && ChkMacSymbName(ArgStr[z].Str));
995       if (!OK)
996         WrStrErrorPos(ErrNum_InvSymName, &ArgStr[z]);
997       z++;
998     }
999     while ((z < ArgCnt) && (OK));
1000     if (OK)
1001     {
1002       strmaxcpy(FName, ArgStr[ArgCnt].Str, STRINGSIZE);
1003       for (z = 1; z < ArgCnt; z++)
1004         CompressLine(ArgStr[z].Str, z, FName, STRINGSIZE, CaseSensitive);
1005       EnterFunction(&LabPart, FName, ArgCnt - 1);
1006     }
1007   }
1008 }
1009 
1010 
CodeSAVE(Word Index)1011 static void CodeSAVE(Word Index)
1012 {
1013   PSaveState Neu;
1014   UNUSED(Index);
1015 
1016   if (ChkArgCnt(0, 0))
1017   {
1018     Neu = (PSaveState) malloc(sizeof(TSaveState));
1019     Neu->Next = FirstSaveState;
1020     Neu->SaveCPU = MomCPU;
1021     Neu->pSaveCPUArgs = as_strdup(MomCPUArgs);
1022     Neu->SavePC = ActPC;
1023     Neu->SaveListOn = ListOn;
1024     Neu->SaveLstMacroExp = GetLstMacroExp();
1025     Neu->SaveLstMacroExpModDefault = LstMacroExpModDefault;
1026     Neu->SaveLstMacroExpModOverride = LstMacroExpModOverride;
1027     Neu->SaveTransTable = CurrTransTable;
1028     Neu->SaveEnumSegment = EnumSegment;
1029     Neu->SaveEnumIncrement = EnumIncrement;
1030     Neu->SaveEnumCurrentValue = EnumCurrentValue;
1031     FirstSaveState = Neu;
1032   }
1033 }
1034 
1035 
CodeRESTORE(Word Index)1036 static void CodeRESTORE(Word Index)
1037 {
1038   PSaveState Old;
1039   UNUSED(Index);
1040 
1041   if (!ChkArgCnt(0, 0));
1042   else if (!FirstSaveState) WrError(ErrNum_NoSaveFrame);
1043   else
1044   {
1045     tStrComp TmpComp;
1046     String TmpCompStr;
1047     StrCompMkTemp(&TmpComp, TmpCompStr);
1048 
1049     Old = FirstSaveState; FirstSaveState = Old->Next;
1050     if (Old->SavePC != ActPC)
1051     {
1052       ActPC = Old->SavePC;
1053       DontPrint = True;
1054     }
1055     if (Old->SaveCPU != MomCPU)
1056     {
1057       StrCompMkTemp(&TmpComp, Old->pSaveCPUArgs);
1058       SetCPUByType(Old->SaveCPU, &TmpComp);
1059     }
1060     strmaxcpy(TmpCompStr, ListOnName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, ListOn = Old->SaveListOn, 0, True);
1061     SetLstMacroExp(Old->SaveLstMacroExp);
1062     LstMacroExpModDefault = Old->SaveLstMacroExpModDefault;
1063     LstMacroExpModOverride = Old->SaveLstMacroExpModOverride;
1064     CurrTransTable = Old->SaveTransTable;
1065     free(Old->pSaveCPUArgs);
1066     free(Old);
1067   }
1068 }
1069 
1070 
CodeMACEXP(Word Index)1071 static void CodeMACEXP(Word Index)
1072 {
1073   /* will deprecate this in 1..2 years, 2018-01-21 */
1074 
1075 #if 0
1076   if (Index & 0x10)
1077   {
1078     char Msg[70];
1079 
1080     as_snprintf(Msg, sizeof(Msg), getmessage(Num_ErrMsgDeprecated_Instead), "MACEXP_DFT");
1081     WrXError(ErrNum_Deprecated, Msg);
1082   }
1083 #endif
1084 
1085   /* allow zero arguments for MACEXP_OVR, to remove all overrides */
1086 
1087   if (!ChkArgCnt((Index & 0x0f) ? 0 : 1, ArgCntMax));
1088   else if (*AttrPart.Str != '\0') WrError(ErrNum_UseLessAttr);
1089   else
1090   {
1091     tStrComp *pArg;
1092     tLstMacroExpMod LstMacroExpMod;
1093     tLstMacroExp Mod;
1094     Boolean Set;
1095     Boolean OK = True;
1096 
1097     InitLstMacroExpMod(&LstMacroExpMod);
1098     forallargs (pArg, True)
1099     {
1100       if (!as_strcasecmp(pArg->Str, "ON"))
1101       {
1102         Mod = eLstMacroExpAll; Set = True;
1103       }
1104       else if (!as_strcasecmp(pArg->Str, "OFF"))
1105       {
1106         Mod = eLstMacroExpAll; Set = False;
1107       }
1108       else if (!as_strcasecmp(pArg->Str, "NOIF"))
1109       {
1110         Mod= eLstMacroExpIf; Set = False;
1111       }
1112       else if (!as_strcasecmp(pArg->Str, "NOMACRO"))
1113       {
1114         Mod = eLstMacroExpMacro; Set = False;
1115       }
1116       else if (!as_strcasecmp(pArg->Str, "NOREST"))
1117       {
1118         Mod = eLstMacroExpRest; Set = False;
1119       }
1120       else if (!as_strcasecmp(pArg->Str, "IF"))
1121       {
1122         Mod = eLstMacroExpIf; Set = True;
1123       }
1124       else if (!as_strcasecmp(pArg->Str, "MACRO"))
1125       {
1126         Mod = eLstMacroExpMacro; Set = True;
1127       }
1128       else if (!as_strcasecmp(pArg->Str, "REST"))
1129       {
1130         Mod = eLstMacroExpRest; Set = True;
1131       }
1132       else
1133         OK = False;
1134       if (!OK)
1135       {
1136         WrStrErrorPos(ErrNum_TooManyMacExpMod, pArg);
1137         break;
1138       }
1139       else if (!AddLstMacroExpMod(&LstMacroExpMod, Set, Mod))
1140       {
1141         WrStrErrorPos(ErrNum_TooManyArgs, pArg);
1142         break;
1143       }
1144     }
1145     if (OK)
1146     {
1147       if (!ChkLstMacroExpMod(&LstMacroExpMod)) WrError(ErrNum_ConflictingMacExpMod);
1148       else if (Index) /* Override */
1149         LstMacroExpModOverride = LstMacroExpMod;
1150       else
1151       {
1152         /* keep LstMacroExp and LstMacroExpModDefault in sync! */
1153         LstMacroExpModDefault = LstMacroExpMod;
1154         SetLstMacroExp(ApplyLstMacroExpMod(eLstMacroExpAll, &LstMacroExpModDefault));
1155       }
1156     }
1157   }
1158 }
1159 
DecodeSegment(const tStrComp * pArg,Integer StartSeg,Integer * pResult)1160 static Boolean DecodeSegment(const tStrComp *pArg, Integer StartSeg, Integer *pResult)
1161 {
1162   Integer SegZ;
1163   Word Mask;
1164 
1165   for (SegZ = StartSeg, Mask = 1 << StartSeg; SegZ <= PCMax; SegZ++, Mask <<= 1)
1166     if ((ValidSegs & Mask) && !as_strcasecmp(pArg->Str, SegNames[SegZ]))
1167     {
1168       *pResult = SegZ;
1169       return True;
1170     }
1171   WrStrErrorPos(ErrNum_UnknownSegment, pArg);
1172   return False;
1173 }
1174 
CodeSEGMENT(Word Index)1175 static void CodeSEGMENT(Word Index)
1176 {
1177   Integer NewSegment;
1178   UNUSED(Index);
1179 
1180   if (ChkArgCnt(1, 1)
1181    && DecodeSegment(&ArgStr[1], SegCode, &NewSegment))
1182     SetNSeg(NewSegment);
1183 }
1184 
1185 
CodeLABEL(Word Index)1186 static void CodeLABEL(Word Index)
1187 {
1188   LongInt Erg;
1189   Boolean OK;
1190   tSymbolFlags Flags;
1191   UNUSED(Index);
1192 
1193   if (ChkArgCnt(1, 1))
1194   {
1195     Erg = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
1196     if (OK && !mFirstPassUnknown(Flags))
1197     {
1198       PushLocHandle(-1);
1199       EnterIntSymbol(&LabPart, Erg, SegCode, False);
1200       *ListLine = '=';
1201       IntLine(ListLine + 1, STRINGSIZE - 1, Erg, ConstMode);
1202       PopLocHandle();
1203     }
1204   }
1205 }
1206 
1207 
CodeREAD(Word Index)1208 static void CodeREAD(Word Index)
1209 {
1210   String ExpStr;
1211   tStrComp Exp;
1212   TempResult Erg;
1213   Boolean OK;
1214   LongInt SaveLocHandle;
1215   UNUSED(Index);
1216 
1217   StrCompMkTemp(&Exp, ExpStr);
1218   if (ChkArgCnt(1, 2))
1219   {
1220     if (ArgCnt == 2) EvalStrStringExpression(&ArgStr[1], &OK, Exp.Str);
1221     else
1222     {
1223       as_snprintf(Exp.Str, sizeof(ExpStr), "Read %s ? ", ArgStr[1].Str);
1224       OK = True;
1225     }
1226     if (OK)
1227     {
1228       printf("%s", Exp.Str);
1229       fflush(stdout);
1230       if (!fgets(Exp.Str, STRINGSIZE, stdin))
1231         OK = False;
1232       else
1233       {
1234         UpString(Exp.Str);
1235         EvalStrExpression(&Exp, &Erg);
1236       }
1237       if (OK)
1238       {
1239         SetListLineVal(&Erg);
1240         SaveLocHandle = MomLocHandle;
1241         MomLocHandle = -1;
1242         if (mFirstPassUnknown(Erg.Flags)) WrError(ErrNum_FirstPassCalc);
1243         else switch (Erg.Typ)
1244         {
1245           case TempInt:
1246             EnterIntSymbol(&ArgStr[ArgCnt], Erg.Contents.Int, SegNone, True);
1247             break;
1248           case TempFloat:
1249             EnterFloatSymbol(&ArgStr[ArgCnt], Erg.Contents.Float, True);
1250             break;
1251           case TempString:
1252             EnterDynStringSymbol(&ArgStr[ArgCnt], &Erg.Contents.Ascii, True);
1253             break;
1254           default:
1255             break;
1256         }
1257         MomLocHandle = SaveLocHandle;
1258       }
1259     }
1260   }
1261 }
1262 
CodeRADIX(Word Index)1263 static void CodeRADIX(Word Index)
1264 {
1265   Boolean OK;
1266   LargeWord tmp;
1267 
1268   if (ChkArgCnt(1, 1))
1269   {
1270     tmp = ConstLongInt(ArgStr[1].Str, &OK, 10);
1271     if (!OK) WrError(ErrNum_ExpectInt);
1272     else if (ChkRange(tmp, 2, 36))
1273     {
1274       if (Index == 1)
1275         OutRadixBase = tmp;
1276       else
1277         RadixBase = tmp;
1278     }
1279   }
1280 }
1281 
CodeALIGN(Word Index)1282 static void CodeALIGN(Word Index)
1283 {
1284   UNUSED(Index);
1285 
1286   if (ChkArgCnt(1, 2))
1287   {
1288     Word AlignValue;
1289     Byte AlignFill = 0;
1290     Boolean OK = True;
1291     tSymbolFlags Flags = eSymbolFlag_None;
1292     LongInt NewPC;
1293 
1294     if (2 == ArgCnt)
1295       AlignFill = EvalStrIntExpressionWithFlags(&ArgStr[2], Int8, &OK, &Flags);
1296     if (OK)
1297       AlignValue = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
1298     if (OK)
1299     {
1300       if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
1301       else
1302       {
1303         NewPC = EProgCounter() + AlignValue - 1;
1304         NewPC -= NewPC % AlignValue;
1305         CodeLen = NewPC - EProgCounter();
1306         if (1 == ArgCnt)
1307         {
1308           DontPrint = !!CodeLen;
1309           BookKeeping();
1310         }
1311         else if (CodeLen > (LongInt)MaxCodeLen) WrError(ErrNum_CodeOverflow);
1312         else
1313         {
1314           memset(BAsmCode, AlignFill, CodeLen);
1315           DontPrint = False;
1316         }
1317       }
1318     }
1319   }
1320 }
1321 
CodeASSUME(Word Index)1322 static void CodeASSUME(Word Index)
1323 {
1324   int z1;
1325   unsigned z2;
1326   Boolean OK;
1327   tSymbolFlags Flags;
1328   LongInt HVal;
1329   tStrComp RegPart, ValPart;
1330   char *pSep, EmptyStr[] = "";
1331 
1332   UNUSED(Index);
1333 
1334   /* CPU-specific override? */
1335 
1336   if (pASSUMEOverride)
1337   {
1338     pASSUMEOverride();
1339     return;
1340   }
1341 
1342   if (ChkArgCnt(1, ArgCntMax))
1343   {
1344     z1 = 1;
1345     OK = True;
1346     while ((z1 <= ArgCnt) && (OK))
1347     {
1348       pSep = QuotPos(ArgStr[z1].Str, ':');
1349       if (pSep)
1350         StrCompSplitRef(&RegPart, &ValPart, &ArgStr[z1], pSep);
1351       else
1352       {
1353         RegPart = ArgStr[z1];
1354         StrCompMkTemp(&ValPart, EmptyStr);
1355       }
1356       z2 = 0;
1357       NLS_UpString(RegPart.Str);
1358       while ((z2 < ASSUMERecCnt) && (strcmp(pASSUMERecs[z2].Name, RegPart.Str)))
1359         z2++;
1360       OK = (z2 < ASSUMERecCnt);
1361       if (!OK) WrStrErrorPos(ErrNum_InvRegName, &RegPart);
1362       else
1363       {
1364         if (!as_strcasecmp(ValPart.Str, "NOTHING"))
1365         {
1366           if (pASSUMERecs[z2].NothingVal == -1) WrError(ErrNum_InvAddrMode);
1367           else
1368             *(pASSUMERecs[z2].Dest) = pASSUMERecs[z2].NothingVal;
1369         }
1370         else
1371         {
1372           HVal = EvalStrIntExpressionWithFlags(&ValPart, Int32, &OK, &Flags);
1373           if (OK)
1374           {
1375             if (mFirstPassUnknown(Flags))
1376             {
1377               WrError(ErrNum_FirstPassCalc);
1378               OK = False;
1379             }
1380             else if (ChkRange(HVal, pASSUMERecs[z2].Min, pASSUMERecs[z2].Max))
1381               *(pASSUMERecs[z2].Dest) = HVal;
1382           }
1383         }
1384         if (pASSUMERecs[z2].pPostProc)
1385           pASSUMERecs[z2].pPostProc();
1386       }
1387       z1++;
1388     }
1389   }
1390 }
1391 
CodeENUM(Word IsNext)1392 static void CodeENUM(Word IsNext)
1393 {
1394   int z;
1395   char *p = NULL;
1396   Boolean OK;
1397   tSymbolFlags Flags;
1398   LongInt  First = 0, Last = 0;
1399   tStrComp SymPart;
1400 
1401   if (!IsNext)
1402     EnumCurrentValue = 0;
1403   if (ChkArgCnt(1, ArgCntMax))
1404   {
1405     for (z = 1; z <= ArgCnt; z++)
1406     {
1407       p = QuotPos(ArgStr[z].Str, '=');
1408       if (p)
1409       {
1410         StrCompSplitRef(&ArgStr[z], &SymPart, &ArgStr[z], p);
1411         EnumCurrentValue = EvalStrIntExpressionWithFlags(&SymPart, Int32, &OK, &Flags);
1412         if (!OK)
1413           return;
1414         if (mFirstPassUnknown(Flags))
1415         {
1416           WrStrErrorPos(ErrNum_FirstPassCalc, &SymPart);
1417           return;
1418         }
1419         *p = '\0';
1420       }
1421       EnterIntSymbol(&ArgStr[z], EnumCurrentValue, EnumSegment, False);
1422       if (z == 1)
1423         First = EnumCurrentValue;
1424       else if (z == ArgCnt)
1425         Last = EnumCurrentValue;
1426       EnumCurrentValue += EnumIncrement;
1427     }
1428   }
1429   *ListLine = '=';
1430   IntLine(ListLine + 1, STRINGSIZE - 1, First, ConstMode);
1431   if (ArgCnt != 1)
1432   {
1433     int l;
1434 
1435     strmaxcat(ListLine, "..", STRINGSIZE);
1436     l = strlen(ListLine);
1437     IntLine(ListLine + l, STRINGSIZE - l, Last, ConstMode);
1438   }
1439 }
1440 
CodeENUMCONF(Word Index)1441 static void CodeENUMCONF(Word Index)
1442 {
1443   UNUSED(Index);
1444 
1445   if (ChkArgCnt(1, 2))
1446   {
1447     Boolean OK;
1448     LongInt NewIncrement;
1449 
1450     NewIncrement = EvalStrIntExpression(&ArgStr[1], Int32, &OK);
1451     if (!OK)
1452       return;
1453     EnumIncrement = NewIncrement;
1454 
1455     if (ArgCnt >= 2)
1456     {
1457       Integer NewSegment;
1458 
1459       if (DecodeSegment(&ArgStr[2], SegNone, &NewSegment))
1460         EnumSegment = NewSegment;
1461     }
1462   }
1463 }
1464 
CodeEND(Word Index)1465 static void CodeEND(Word Index)
1466 {
1467   UNUSED(Index);
1468 
1469   if (ChkArgCnt(0, 1))
1470   {
1471     if (ArgCnt == 1)
1472     {
1473       LongInt HVal;
1474       tEvalResult EvalResult;
1475 
1476       HVal = EvalStrIntExpressionWithResult(&ArgStr[1], Int32, &EvalResult);
1477       if (EvalResult.OK)
1478       {
1479         ChkSpace(SegCode, EvalResult.AddrSpaceMask);
1480         StartAdr = HVal;
1481         StartAdrPresent = True;
1482       }
1483     }
1484    ENDOccured = True;
1485   }
1486 }
1487 
1488 
CodeLISTING(Word Index)1489 static void CodeLISTING(Word Index)
1490 {
1491   Byte Value = 0xff;
1492   Boolean OK;
1493   UNUSED(Index);
1494 
1495   if (!ChkArgCnt(1, 1));
1496   else if (*AttrPart.Str != '\0') WrError(ErrNum_UseLessAttr);
1497   else
1498   {
1499     OK = True;
1500     NLS_UpString(ArgStr[1].Str);
1501     if (!strcmp(ArgStr[1].Str, "OFF"))
1502       Value = 0;
1503     else if (!strcmp(ArgStr[1].Str, "ON"))
1504       Value = 1;
1505     else if (!strcmp(ArgStr[1].Str, "NOSKIPPED"))
1506       Value = 2;
1507     else if (!strcmp(ArgStr[1].Str, "PURECODE"))
1508       Value = 3;
1509     else
1510       OK = False;
1511     if (!OK) WrStrErrorPos(ErrNum_OnlyOnOff, &ArgStr[1]);
1512     else
1513     {
1514       tStrComp TmpComp;
1515       String TmpCompStr;
1516 
1517       StrCompMkTemp(&TmpComp, TmpCompStr);
1518       strmaxcpy(TmpCompStr, ListOnName, sizeof(TmpCompStr));
1519       EnterIntSymbol(&TmpComp, ListOn = Value, 0, True);
1520     }
1521   }
1522 }
1523 
INCLUDE_SearchCore(tStrComp * pDest,const tStrComp * pArg,Boolean SearchPath)1524 void INCLUDE_SearchCore(tStrComp *pDest, const tStrComp *pArg, Boolean SearchPath)
1525 {
1526   StrCompCopy(pDest, &ArgStr[1]);
1527 
1528   if (pDest->Str[0] == '"')
1529   {
1530     int l;
1531 
1532     StrCompIncRefLeft(pDest, 1);
1533     l = strlen(pDest->Str);
1534     if ((l > 0) && (pDest->Str[l - 1]  == '"'))
1535       StrCompShorten(pDest, 1);
1536     else
1537     {
1538       WrStrErrorPos(ErrNum_BrackErr, pArg);
1539       return;
1540     }
1541   }
1542   AddSuffix(pDest->Str, IncSuffix);
1543 
1544   if (SearchPath)
1545   {
1546     String FoundFileName;
1547 
1548     if (FSearch(FoundFileName, sizeof(FoundFileName), pDest->Str, CurrFileName, SearchPath ? IncludeList : ""))
1549       ChkStrIO(ErrNum_OpeningFile, &ArgStr[1]);
1550     strmaxcpy(pDest->Str, FExpand(FoundFileName), STRINGSIZE - 1);
1551   }
1552 }
1553 
CodeBINCLUDE(Word Index)1554 static void CodeBINCLUDE(Word Index)
1555 {
1556   FILE *F;
1557   LongInt Len = -1;
1558   LongWord Ofs = 0, Curr, Rest, FSize;
1559   Word RLen;
1560   Boolean OK, SaveTurnWords;
1561   tSymbolFlags Flags;
1562   LargeWord OldPC;
1563   UNUSED(Index);
1564 
1565   if (!ChkArgCnt(1, 3));
1566   else if (ActPC == StructSeg) WrError(ErrNum_NotInStruct);
1567   else
1568   {
1569     if (ArgCnt == 1)
1570       OK = True;
1571     else
1572     {
1573       Ofs = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &OK, &Flags);
1574       if (mFirstPassUnknown(Flags))
1575       {
1576         WrError(ErrNum_FirstPassCalc);
1577         OK = False;
1578       }
1579       if (OK)
1580       {
1581         if (ArgCnt == 2)
1582           Len = -1;
1583         else
1584         {
1585           Len = EvalStrIntExpressionWithFlags(&ArgStr[3], Int32, &OK, &Flags);
1586           if (mFirstPassUnknown(Flags))
1587           {
1588             WrError(ErrNum_FirstPassCalc);
1589             OK = False;
1590           }
1591         }
1592       }
1593     }
1594     if (OK)
1595     {
1596       tStrComp FNameArg;
1597       String FNameArgStr;
1598 
1599       StrCompMkTemp(&FNameArg, FNameArgStr);
1600       INCLUDE_SearchCore(&FNameArg, &ArgStr[1], True);
1601 
1602       F = fopen(FNameArg.Str, OPENRDMODE);
1603       if (F == NULL) ChkIO(ErrNum_OpeningFile);
1604       errno = 0; FSize = FileSize(F); ChkIO(ErrNum_FileReadError);
1605       if (Len == -1)
1606       {
1607         if ((Len = FSize - Ofs) < 0)
1608         {
1609           fclose(F); WrError(ErrNum_ShortRead); return;
1610         }
1611       }
1612       if (!ChkPC(PCs[ActPC] + Len - 1)) WrError(ErrNum_AdrOverflow);
1613       else
1614       {
1615         errno = 0; fseek(F, Ofs, SEEK_SET); ChkIO(ErrNum_FileReadError);
1616         Rest = Len;
1617         SaveTurnWords = TurnWords;
1618         TurnWords = False;
1619         OldPC = ProgCounter();
1620         do
1621         {
1622           Curr = (Rest <= 256) ? Rest : 256;
1623           errno = 0; RLen = fread(BAsmCode, 1, Curr, F); ChkIO(ErrNum_FileReadError);
1624           CodeLen = RLen;
1625           WriteBytes();
1626           PCs[ActPC] += CodeLen;
1627           Rest -= RLen;
1628         }
1629         while ((Rest != 0) && (RLen == Curr));
1630         if (Rest != 0) WrError(ErrNum_ShortRead);
1631         TurnWords = SaveTurnWords;
1632         DontPrint = True;
1633         CodeLen = ProgCounter() - OldPC;
1634         PCs[ActPC] = OldPC;
1635       }
1636       fclose(F);
1637     }
1638   }
1639 }
1640 
CodePUSHV(Word Index)1641 static void CodePUSHV(Word Index)
1642 {
1643   int z;
1644   UNUSED(Index);
1645 
1646   if (ChkArgCnt(2, ArgCntMax))
1647   {
1648     if (!CaseSensitive)
1649       NLS_UpString(ArgStr[1].Str);
1650     for (z = 2; z <= ArgCnt; z++)
1651       PushSymbol(&ArgStr[z], &ArgStr[1]);
1652   }
1653 }
1654 
CodePOPV(Word Index)1655 static void CodePOPV(Word Index)
1656 {
1657   int z;
1658   UNUSED(Index);
1659 
1660   if (ChkArgCnt(2, ArgCntMax))
1661   {
1662     if (!CaseSensitive)
1663       NLS_UpString(ArgStr[1].Str);
1664     for (z = 2; z <= ArgCnt; z++)
1665       PopSymbol(&ArgStr[z], &ArgStr[1]);
1666   }
1667 }
1668 
CodePPSyms_SearchSym(PForwardSymbol Root,char * Comp)1669 static PForwardSymbol CodePPSyms_SearchSym(PForwardSymbol Root, char *Comp)
1670 {
1671   PForwardSymbol Lauf = Root;
1672   UNUSED(Comp);
1673 
1674   while (Lauf && strcmp(Lauf->Name, Comp))
1675     Lauf = Lauf->Next;
1676   return Lauf;
1677 }
1678 
1679 
CodeSTRUCT(Word IsUnion)1680 static void CodeSTRUCT(Word IsUnion)
1681 {
1682   PStructStack NStruct;
1683   tStrComp *pArg;
1684   Boolean OK, DoExt;
1685   char ExtChar;
1686   String StructName;
1687 
1688   if (!ChkArgCnt(0, ArgCntMax))
1689     return;
1690 
1691   /* unnamed struct/union only allowed if embedded into at least one named struct/union */
1692 
1693   if (!*LabPart.Str)
1694   {
1695     if (!pInnermostNamedStruct)
1696     {
1697       WrError(ErrNum_FreestandingUnnamedStruct);
1698       return;
1699     }
1700   }
1701   else
1702   {
1703     if (!ChkSymbName(LabPart.Str))
1704     {
1705       WrXError(ErrNum_InvSymName, LabPart.Str);
1706       return;
1707     }
1708     if (!CaseSensitive)
1709       NLS_UpString(LabPart.Str);
1710   }
1711 
1712   /* compose name of nested structures */
1713 
1714   if (*LabPart.Str)
1715     BuildStructName(StructName, sizeof(StructName), LabPart.Str);
1716   else
1717     *StructName = '\0';
1718 
1719   /* If named and embedded into another struct, add as element to innermost named parent struct.
1720      Add up all offsets of unnamed structs in between. */
1721 
1722   if (StructStack && (*LabPart.Str))
1723   {
1724     PStructStack pRun;
1725     LargeWord Offset = ProgCounter();
1726     PStructElem pElement = CreateStructElem(LabPart.Str);
1727 
1728     for (pRun = StructStack; pRun && pRun != pInnermostNamedStruct; pRun = pRun->Next)
1729       Offset += pRun->SaveCurrPC;
1730     pElement->Offset = Offset;
1731     pElement->IsStruct = True;
1732     AddStructElem(pInnermostNamedStruct->StructRec, pElement);
1733     AddStructSymbol(LabPart.Str, ProgCounter());
1734   }
1735 
1736   NStruct = (PStructStack) malloc(sizeof(TStructStack));
1737   NStruct->Name = as_strdup(StructName);
1738   NStruct->pBaseName = NStruct->Name + strlen(NStruct->Name) - strlen(LabPart.Str); /* NULL -> complain too long */
1739   NStruct->SaveCurrPC = ProgCounter();
1740   DoExt = True;
1741   ExtChar = DottedStructs ? '.' : '_';
1742   NStruct->Next = StructStack;
1743   OK = True;
1744   forallargs (pArg, True)
1745     if (OK)
1746     {
1747       if (!as_strcasecmp(pArg->Str, "EXTNAMES"))
1748         DoExt = True;
1749       else if (!as_strcasecmp(pArg->Str, "NOEXTNAMES"))
1750         DoExt = False;
1751       else if (!as_strcasecmp(pArg->Str, "DOTS"))
1752         ExtChar = '.';
1753       else if (!as_strcasecmp(pArg->Str, "NODOTS"))
1754         ExtChar = '_';
1755       else
1756       {
1757         WrStrErrorPos(ErrNum_InvStructDir, pArg);
1758         OK = False;
1759       }
1760     }
1761   if (OK)
1762   {
1763     NStruct->StructRec = CreateStructRec();
1764     NStruct->StructRec->ExtChar = ExtChar;
1765     NStruct->StructRec->DoExt = DoExt;
1766     NStruct->StructRec->IsUnion = IsUnion;
1767     StructStack = NStruct;
1768     if (ActPC != StructSeg)
1769       StructSaveSeg = ActPC;
1770     if (NStruct->Name[0])
1771       pInnermostNamedStruct = NStruct;
1772     ActPC = StructSeg;
1773     PCs[ActPC] = 0;
1774     Phases[ActPC] = 0;
1775     Grans[ActPC] = Grans[SegCode];
1776     ListGrans[ActPC] = ListGrans[SegCode];
1777     ClearChunk(SegChunks + StructSeg);
1778     CodeLen = 0;
1779     DontPrint = True;
1780   }
1781   else
1782   {
1783     free(NStruct->Name);
1784     free(NStruct);
1785   }
1786 }
1787 
CodeENDSTRUCT(Word IsUnion)1788 static void CodeENDSTRUCT(Word IsUnion)
1789 {
1790   Boolean OK;
1791   PStructStack OStruct;
1792   TempResult t;
1793 
1794   if (!ChkArgCnt(0, 1));
1795   else if (!StructStack) WrError(ErrNum_MissingStruct);
1796   else
1797   {
1798     if (IsUnion && !StructStack->StructRec->IsUnion)
1799       WrXError(ErrNum_STRUCTEndedByENDUNION, StructStack->Name);
1800 
1801     if (*LabPart.Str == '\0') OK = True;
1802     else
1803     {
1804       if (!CaseSensitive)
1805         NLS_UpString(LabPart.Str);
1806       OK = !strcmp(LabPart.Str, StructStack->pBaseName);
1807       if (!OK) WrError(ErrNum_WrongStruct);
1808     }
1809     if (OK)
1810     {
1811       LargeWord TotLen;
1812 
1813       /* unchain current struct from stack */
1814 
1815       OStruct = StructStack;
1816       StructStack = OStruct->Next;
1817 
1818       /* resolve referenced symbols in structure */
1819 
1820       ResolveStructReferences(OStruct->StructRec);
1821 
1822       /* find new innermost named struct */
1823 
1824       for (pInnermostNamedStruct = StructStack;
1825            pInnermostNamedStruct;
1826            pInnermostNamedStruct = pInnermostNamedStruct->Next)
1827       {
1828         if (pInnermostNamedStruct->Name[0])
1829           break;
1830       }
1831 
1832       BumpStructLength(OStruct->StructRec, ProgCounter());
1833       TotLen = OStruct->StructRec->TotLen;
1834 
1835       /* add symbol for struct length if not nameless */
1836 
1837       if (ArgCnt == 0)
1838       {
1839         if (OStruct->Name[0])
1840         {
1841           String tmp2;
1842           tStrComp TmpComp;
1843 
1844           as_snprintf(tmp2, sizeof(tmp2), "%s%clen", OStruct->Name, OStruct->StructRec->ExtChar);
1845           StrCompMkTemp(&TmpComp, tmp2);
1846           EnterIntSymbol(&TmpComp, TotLen, SegNone, False);
1847         }
1848       }
1849       else
1850         EnterIntSymbol(&ArgStr[1], TotLen, SegNone, False);
1851 
1852       t.Typ = TempInt;
1853       t.Contents.Int = TotLen;
1854       SetListLineVal(&t);
1855 
1856       /* If named, store completed structure.
1857          Otherwise, discard temporary struct. */
1858 
1859       if (OStruct->Name[0])
1860         AddStruct(OStruct->StructRec, OStruct->Name, True);
1861       else
1862         DestroyStructRec(OStruct->StructRec);
1863       OStruct->StructRec = NULL;
1864 
1865       /* set PC back to outer's struct value, plus size of
1866          just completed struct, or non-struct value: */
1867 
1868       PCs[ActPC] = OStruct->SaveCurrPC;
1869       if (!StructStack)
1870       {
1871         ActPC = StructSaveSeg;
1872         CodeLen = 0;
1873       }
1874       else
1875       {
1876         CodeLen = TotLen;
1877       }
1878 
1879       /* free struct stack elements no longer needed */
1880 
1881       free(OStruct->Name);
1882       free(OStruct);
1883       ClearChunk(SegChunks + StructSeg);
1884       DontPrint = True;
1885     }
1886   }
1887 }
1888 
CodeEXTERN(Word Index)1889 static void CodeEXTERN(Word Index)
1890 {
1891   char *Split;
1892   int i;
1893   Boolean OK;
1894   Byte Type;
1895   UNUSED(Index);
1896 
1897   if (ChkArgCnt(1, ArgCntMax))
1898   {
1899     i = 1;
1900     OK = True;
1901     while ((OK) && (i <= ArgCnt))
1902     {
1903       Split = strrchr(ArgStr[i].Str, ':');
1904       if (Split == NULL)
1905         Type = SegNone;
1906       else
1907       {
1908         *Split = '\0';
1909         for (Type = SegNone + 1; Type <= PCMax; Type++)
1910           if (!as_strcasecmp(Split + 1, SegNames[Type]))
1911             break;
1912       }
1913       if (Type > PCMax) WrXError(ErrNum_UnknownSegment, Split + 1);
1914       else
1915       {
1916         EnterExtSymbol(&ArgStr[i], 0, Type, FALSE);
1917       }
1918       i++;
1919     }
1920   }
1921 }
1922 
CodeNESTMAX(Word Index)1923 static void CodeNESTMAX(Word Index)
1924 {
1925   LongInt Temp;
1926   Boolean OK;
1927   tSymbolFlags Flags;
1928   UNUSED(Index);
1929 
1930   if (ChkArgCnt(1, 1))
1931   {
1932     Temp = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags);
1933     if (OK)
1934     {
1935       if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
1936       else NestMax = Temp;
1937     }
1938   }
1939 }
1940 
CodeSEGTYPE(Word Index)1941 static void CodeSEGTYPE(Word Index)
1942 {
1943   UNUSED(Index);
1944 
1945   if (ChkArgCnt(0, 0))
1946     RelSegs = (as_toupper(*OpPart.Str) == 'R');
1947 }
1948 
CodePPSyms(PForwardSymbol * Orig,PForwardSymbol * Alt1,PForwardSymbol * Alt2)1949 static void CodePPSyms(PForwardSymbol *Orig,
1950                        PForwardSymbol *Alt1,
1951                        PForwardSymbol *Alt2)
1952 {
1953   PForwardSymbol Lauf;
1954   tStrComp *pArg, SymArg, SectionArg;
1955   String Sym, Section;
1956   char *pSplit;
1957 
1958   if (ChkArgCnt(1, ArgCntMax))
1959     forallargs (pArg, True)
1960     {
1961       pSplit = QuotPos(pArg->Str, ':');
1962       if (pSplit)
1963       {
1964         StrCompSplitRef(&SymArg, &SectionArg, pArg, pSplit);
1965         if (!ExpandStrSymbol(Sym, sizeof(Sym), &SymArg))
1966           return;
1967       }
1968       else
1969       {
1970         if (!ExpandStrSymbol(Sym, sizeof(Sym), pArg))
1971           return;
1972         *Section = '\0';
1973         StrCompMkTemp(&SectionArg, Section);
1974       }
1975       if (!CaseSensitive)
1976         NLS_UpString(Sym);
1977       Lauf = CodePPSyms_SearchSym(*Alt1, Sym);
1978       if (Lauf) WrStrErrorPos(ErrNum_ContForward, pArg);
1979       else
1980       {
1981         Lauf = CodePPSyms_SearchSym(*Alt2, Sym);
1982         if (Lauf) WrStrErrorPos(ErrNum_ContForward, pArg);
1983         else
1984         {
1985           Lauf = CodePPSyms_SearchSym(*Orig, Sym);
1986           if (!Lauf)
1987           {
1988             Lauf = (PForwardSymbol) malloc(sizeof(TForwardSymbol));
1989             Lauf->Next = (*Orig); *Orig = Lauf;
1990             Lauf->Name = as_strdup(Sym);
1991             Lauf->pErrorPos = GetErrorPos();
1992           }
1993           IdentifySection(&SectionArg, &Lauf->DestSection);
1994         }
1995       }
1996     }
1997 }
1998 
1999 /*------------------------------------------------------------------------*/
2000 
2001 #define ONOFFMax 32
2002 static int ONOFFCnt = 0;
2003 typedef struct
2004 {
2005   Boolean Persist, *FlagAddr;
2006   const char *FlagName;
2007   const char *InstName;
2008 } ONOFFTab;
2009 static ONOFFTab *ONOFFList;
2010 
DecodeONOFF(Word Index)2011 static void DecodeONOFF(Word Index)
2012 {
2013   ONOFFTab *Tab = ONOFFList + Index;
2014 
2015   if (ChkArgCnt(1, 1))
2016   {
2017     NLS_UpString(ArgStr[1].Str);
2018     if (*AttrPart.Str != '\0') WrError(ErrNum_UseLessAttr);
2019     else
2020     {
2021       Boolean IsON = !as_strcasecmp(ArgStr[1].Str, "ON");
2022       if ((!IsON) && (as_strcasecmp(ArgStr[1].Str, "OFF"))) WrStrErrorPos(ErrNum_OnlyOnOff, &ArgStr[1]);
2023       else
2024         SetFlag(Tab->FlagAddr, Tab->FlagName, IsON);
2025     }
2026   }
2027 }
2028 
AddONOFF(const char * InstName,Boolean * Flag,const char * FlagName,Boolean Persist)2029 void AddONOFF(const char *InstName, Boolean *Flag, const char *FlagName, Boolean Persist)
2030 {
2031   if (ONOFFCnt == ONOFFMax) exit(255);
2032   ONOFFList[ONOFFCnt].Persist = Persist;
2033   ONOFFList[ONOFFCnt].FlagAddr = Flag;
2034   ONOFFList[ONOFFCnt].FlagName = FlagName;
2035   ONOFFList[ONOFFCnt].InstName = InstName;
2036   AddInstTable(ONOFFTable, InstName, ONOFFCnt++, DecodeONOFF);
2037 }
2038 
ClearONOFF(void)2039 void ClearONOFF(void)
2040 {
2041   int z, z2;
2042 
2043   for (z = 0; z < ONOFFCnt; z++)
2044     if (!ONOFFList[z].Persist)
2045       break;
2046 
2047   for (z2 = ONOFFCnt - 1; z2 >= z; z2--)
2048     RemoveInstTable(ONOFFTable, ONOFFList[z2].InstName);
2049 
2050   ONOFFCnt = z;
2051 }
2052 
2053 /*------------------------------------------------------------------------*/
2054 
2055 typedef struct
2056 {
2057   const char *Name;
2058   InstProc Proc;
2059   Word Index;
2060 } PseudoOrder;
2061 static const PseudoOrder Pseudos[] =
2062 {
2063   {"ALIGN",      CodeALIGN      , 0 },
2064   {"ASEG",       CodeSEGTYPE    , 0 },
2065   {"ASSUME",     CodeASSUME     , 0 },
2066   {"BINCLUDE",   CodeBINCLUDE   , 0 },
2067   {"CHARSET",    CodeCHARSET    , 0 },
2068   {"CODEPAGE",   CodeCODEPAGE   , 0 },
2069   {"CPU",        CodeCPU        , 0 },
2070   {"DEPHASE",    CodeDEPHASE    , 0 },
2071   {"END",        CodeEND        , 0 },
2072   {"ENDEXPECT",  CodeENDEXPECT  , 0 },
2073   {"ENDS",       CodeENDSTRUCT  , 0 },
2074   {"ENDSECTION", CodeENDSECTION , 0 },
2075   {"ENDSTRUC",   CodeENDSTRUCT  , 0 },
2076   {"ENDSTRUCT",  CodeENDSTRUCT  , 0 },
2077   {"ENDUNION",   CodeENDSTRUCT  , 1 },
2078   {"ENUM",       CodeENUM       , 0 },
2079   {"ENUMCONF",   CodeENUMCONF   , 0 },
2080   {"EQU",        CodeSETEQU     , 0 },
2081   {"ERROR",      CodeERROR      , 0 },
2082   {"EXPECT",     CodeEXPECT     , 0 },
2083   {"EXPORT_SYM", CodeEXPORT     , 0 },
2084   {"EXTERN_SYM", CodeEXTERN     , 0 },
2085   {"FATAL",      CodeFATAL      , 0 },
2086   {"FUNCTION",   CodeFUNCTION   , 0 },
2087   {"LABEL",      CodeLABEL      , 0 },
2088   {"LISTING",    CodeLISTING    , 0 },
2089   {"MESSAGE",    CodeMESSAGE    , 0 },
2090   {"NEWPAGE",    CodeNEWPAGE    , 0 },
2091   {"NESTMAX",    CodeNESTMAX    , 0 },
2092   {"NEXTENUM",   CodeENUM       , 1 },
2093   {"ORG",        CodeORG        , 0 },
2094   {"OUTRADIX",   CodeRADIX      , 1 },
2095   {"PHASE",      CodePHASE      , 0 },
2096   {"POPV",       CodePOPV       , 0 },
2097   {"PRSET",      CodePRSET      , 0 },
2098   {"PRTINIT",    CodeString     , 0 },
2099   {"PRTEXIT",    CodeString     , 1 },
2100   {"TITLE",      CodeString     , 2 },
2101   {"PUSHV",      CodePUSHV      , 0 },
2102   {"RADIX",      CodeRADIX      , 0 },
2103   {"READ",       CodeREAD       , 0 },
2104   {"RESTORE",    CodeRESTORE    , 0 },
2105   {"MACEXP",     CodeMACEXP     , 0x10 },
2106   {"MACEXP_DFT", CodeMACEXP     , 0 },
2107   {"MACEXP_OVR", CodeMACEXP     , 1 },
2108   {"RORG",       CodeRORG       , 0 },
2109   {"RSEG",       CodeSEGTYPE    , 0 },
2110   {"SAVE",       CodeSAVE       , 0 },
2111   {"SECTION",    CodeSECTION    , 0 },
2112   {"SEGMENT",    CodeSEGMENT    , 0 },
2113   {"SHARED",     CodeSHARED     , 0 },
2114   {"STRUC",      CodeSTRUCT     , 0 },
2115   {"STRUCT",     CodeSTRUCT     , 0 },
2116   {"UNION",      CodeSTRUCT     , 1 },
2117   {"WARNING",    CodeWARNING    , 0 },
2118   {"=",          CodeSETEQU     , 0 },
2119   {":=",         CodeSETEQU     , 1 },
2120   {""       ,    NULL           , 0 }
2121 };
2122 
CodeGlobalPseudo(void)2123 Boolean CodeGlobalPseudo(void)
2124 {
2125   switch (*OpPart.Str)
2126   {
2127     case 'S':
2128       if (!SetIsOccupied() && Memo("SET"))
2129       {
2130         CodeSETEQU(True);
2131         return True;
2132       }
2133       break;
2134     case 'E':
2135       if (Memo("EVAL"))
2136       {
2137         CodeSETEQU(True);
2138         return True;
2139       }
2140       break;
2141     case 'P':
2142       if ((!PageIsOccupied && Memo("PAGE"))
2143        || (PageIsOccupied && Memo("PAGESIZE")))
2144       {
2145         CodePAGE(0);
2146         return True;
2147       }
2148       break;
2149   }
2150 
2151   if (LookupInstTable(ONOFFTable, OpPart.Str))
2152     return True;
2153 
2154   if (LookupInstTable(PseudoTable, OpPart.Str))
2155     return True;
2156 
2157   if (SectionStack)
2158   {
2159     if (Memo("FORWARD"))
2160     {
2161       if (PassNo <= MaxSymPass)
2162         CodePPSyms(&(SectionStack->LocSyms),
2163                    &(SectionStack->GlobSyms),
2164                    &(SectionStack->ExportSyms));
2165       return True;
2166     }
2167     if (Memo("PUBLIC"))
2168     {
2169       CodePPSyms(&(SectionStack->GlobSyms),
2170                  &(SectionStack->LocSyms),
2171                  &(SectionStack->ExportSyms));
2172       return True;
2173     }
2174     if (Memo("GLOBAL"))
2175     {
2176       CodePPSyms(&(SectionStack->ExportSyms),
2177                  &(SectionStack->LocSyms),
2178                  &(SectionStack->GlobSyms));
2179       return True;
2180     }
2181   }
2182 
2183   return False;
2184 }
2185 
2186 
codeallg_init(void)2187 void codeallg_init(void)
2188 {
2189   const PseudoOrder *POrder;
2190 
2191   ONOFFList = (ONOFFTab*)calloc(ONOFFMax, sizeof(*ONOFFList));
2192 
2193   PseudoTable = CreateInstTable(201);
2194   for (POrder = Pseudos; POrder->Proc; POrder++)
2195     AddInstTable(PseudoTable, POrder->Name, POrder->Index, POrder->Proc);
2196   ONOFFTable = CreateInstTable(47);
2197   AddONOFF("RELAXED", &RelaxedMode, RelaxedName, True);
2198   AddONOFF("DOTTEDSTRUCTS", &DottedStructs, DottedStructsName, True);
2199 }
2200