Subversion Repositories pentevo

Rev

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

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