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.   pPotMonadicOperator = NULL;
  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.  
  597.   UNUSED(Index);
  598.   as_tempres_ini(&t);
  599.  
  600.   if (ShareMode == 0) WrError(ErrNum_NoShareFile);
  601.   else if ((ArgCnt == 0) && (*CommPart.str.p_str != '\0'))
  602.   {
  603.     CodeSHARED_BuildComment(c, sizeof(c));
  604.     errno = 0;
  605.     fprintf(ShareFile, "%s\n", c); ChkIO(ErrNum_FileWriteError);
  606.   }
  607.   else
  608.    forallargs (pArg, True)
  609.    {
  610.      LookupSymbol(pArg, &t, False, TempAll);
  611.  
  612.      switch (t.Typ)
  613.      {
  614.        case TempInt:
  615.          switch (ShareMode)
  616.          {
  617.            case 1:
  618.              IntLine(s, sizeof(s), t.Contents.Int, eIntConstModeMoto);
  619.              break;
  620.            case 2:
  621.              IntLine(s, sizeof(s), t.Contents.Int, eIntConstModeC);
  622.              break;
  623.            case 3:
  624.              IntLine(s, sizeof(s), t.Contents.Int, IntConstMode);
  625.              break;
  626.          }
  627.          break;
  628.        case TempFloat:
  629.          as_snprintf(s, sizeof(s), "%0.17g", t.Contents.Float);
  630.          break;
  631.        case TempString:
  632.          as_nonz_dynstr_to_c_str(s + 1, &t.Contents.str, sizeof(s) - 1);
  633.          if (ShareMode == 1)
  634.          {
  635.            *s = '\'';
  636.            strmaxcat(s, "\'", STRINGSIZE);
  637.          }
  638.          else
  639.          {
  640.            *s = '\"';
  641.            strmaxcat(s, "\"", STRINGSIZE);
  642.          }
  643.          break;
  644.        default:
  645.          continue;
  646.      }
  647.  
  648.      if ((pArg == ArgStr + 1) && (*CommPart.str.p_str != '\0'))
  649.      {
  650.        CodeSHARED_BuildComment(c, sizeof(c));
  651.        strmaxprep(c, " ", STRINGSIZE);
  652.      }
  653.      else
  654.        *c = '\0';
  655.      errno = 0;
  656.      switch (ShareMode)
  657.      {
  658.        case 1:
  659.          fprintf(ShareFile, "%s = %s;%s\n", pArg->str.p_str, s, c);
  660.          break;
  661.        case 2:
  662.          fprintf(ShareFile, "#define %s %s%s\n", pArg->str.p_str, s, c);
  663.          break;
  664.        case 3:
  665.          strmaxprep(s, IsSymbolChangeable(pArg) ? "set " : "equ ", STRINGSIZE);
  666.          fprintf(ShareFile, "%s %s%s\n", pArg->str.p_str, s, c);
  667.          break;
  668.      }
  669.      ChkIO(ErrNum_FileWriteError);
  670.    }
  671.   as_tempres_free(&t);
  672. }
  673.  
  674. static void CodeEXPORT(Word Index)
  675. {
  676.   tStrComp *pArg;
  677.   TempResult t;
  678.  
  679.   UNUSED(Index);
  680.   as_tempres_ini(&t);
  681.  
  682.   forallargs (pArg, True)
  683.   {
  684.     LookupSymbol(pArg, &t, True, TempInt);
  685.     if (TempNone == t.Typ)
  686.       continue;
  687.     if (t.Relocs == NULL)
  688.       AddExport(pArg->str.p_str, t.Contents.Int, 0);
  689.     else if ((t.Relocs->Next != NULL) || (strcmp(t.Relocs->Ref, RelName_SegStart)))
  690.       WrStrErrorPos(ErrNum_Unexportable, pArg);
  691.     else
  692.       AddExport(pArg->str.p_str, t.Contents.Int, RelFlag_Relative);
  693.     if (t.Relocs)
  694.       FreeRelocs(&t.Relocs);
  695.   }
  696.   as_tempres_free(&t);
  697. }
  698.  
  699. static void CodePAGE(Word Index)
  700. {
  701.   Integer LVal, WVal;
  702.   Boolean ValOK;
  703.   UNUSED(Index);
  704.  
  705.   if (!ChkArgCnt(1, 2));
  706.   else if (*AttrPart.str.p_str != '\0') WrError(ErrNum_UseLessAttr);
  707.   else
  708.   {
  709.     LVal = EvalStrIntExpression(&ArgStr[1], UInt8, &ValOK);
  710.     if (ValOK)
  711.     {
  712.       if ((LVal < 5) && (LVal != 0))
  713.         LVal = 5;
  714.       if (ArgCnt == 1)
  715.       {
  716.         WVal = 0;
  717.         ValOK = True;
  718.       }
  719.       else
  720.         WVal = EvalStrIntExpression(&ArgStr[2], UInt8, &ValOK);
  721.       if (ValOK)
  722.       {
  723.         if ((WVal < 5) && (WVal != 0))
  724.           WVal = 5;
  725.         PageLength = LVal;
  726.         PageWidth = WVal;
  727.       }
  728.     }
  729.   }
  730. }
  731.  
  732.  
  733. static void CodeNEWPAGE(Word Index)
  734. {
  735.   ShortInt HVal8;
  736.   Boolean ValOK;
  737.   UNUSED(Index);
  738.  
  739.   if (!ChkArgCnt(0, 1));
  740.   else if (*AttrPart.str.p_str != '\0') WrError(ErrNum_UseLessAttr);
  741.   else
  742.   {
  743.     if (ArgCnt == 0)
  744.     {
  745.       HVal8 = 0;
  746.       ValOK = True;
  747.     }
  748.     else
  749.       HVal8 = EvalStrIntExpression(&ArgStr[1], Int8, &ValOK);
  750.     if ((ValOK) || (ArgCnt == 0))
  751.     {
  752.       if (HVal8 > ChapMax)
  753.         HVal8 = ChapMax;
  754.       else if (HVal8 < 0)
  755.         HVal8 = 0;
  756.       NewPage(HVal8, True);
  757.     }
  758.   }
  759. }
  760.  
  761.  
  762. static void CodeString(Word Index)
  763. {
  764.   String tmp;
  765.   Boolean OK;
  766.  
  767.   if (ChkArgCnt(1, 1))
  768.   {
  769.     EvalStrStringExpression(&ArgStr[1], &OK, tmp);
  770.     if (!OK) WrError(ErrNum_InvString);
  771.     else
  772.     {
  773.       switch (Index)
  774.       {
  775.         case 0:
  776.           strmaxcpy(PrtInitString, tmp, STRINGSIZE);
  777.           break;
  778.         case 1:
  779.           strmaxcpy(PrtExitString, tmp, STRINGSIZE);
  780.           break;
  781.         case 2:
  782.           strmaxcpy(PrtTitleString, tmp, STRINGSIZE);
  783.           break;
  784.       }
  785.     }
  786.   }
  787. }
  788.  
  789.  
  790. static void CodePHASE(Word Index)
  791. {
  792.   Boolean OK;
  793.   LongInt HVal;
  794.   UNUSED(Index);
  795.  
  796.   if (!ChkArgCnt(1, 1));
  797.   else if (ActPC == StructSeg) WrError(ErrNum_PhaseDisallowed);
  798.   else
  799.   {
  800.     HVal = EvalStrIntExpression(&ArgStr[1], Int32, &OK);
  801.     if (OK)
  802.     {
  803.       tSavePhase *pSavePhase;
  804.  
  805.       pSavePhase = (tSavePhase*)calloc(1, sizeof (*pSavePhase));
  806.       pSavePhase->SaveValue = Phases[ActPC];
  807.       pSavePhase->pNext = pPhaseStacks[ActPC];
  808.       pPhaseStacks[ActPC] = pSavePhase;
  809.       Phases[ActPC] = HVal - ProgCounter();
  810.     }
  811.   }
  812. }
  813.  
  814.  
  815. static void CodeDEPHASE(Word Index)
  816. {
  817.   UNUSED(Index);
  818.  
  819.   if (!ChkArgCnt(0, 0));
  820.   else if (ActPC == StructSeg) WrError(ErrNum_PhaseDisallowed);
  821.   else if (pPhaseStacks[ActPC])
  822.   {
  823.     tSavePhase *pSavePhase;
  824.  
  825.     pSavePhase = pPhaseStacks[ActPC];
  826.     pPhaseStacks[ActPC] = pSavePhase->pNext;
  827.     Phases[ActPC] = pSavePhase->SaveValue;
  828.     free(pSavePhase);
  829.   }
  830.   else
  831.     Phases[ActPC] = 0;
  832. }
  833.  
  834.  
  835. static void CodeWARNING(Word Index)
  836. {
  837.   String mess;
  838.   Boolean OK;
  839.   UNUSED(Index);
  840.  
  841.   if (ChkArgCnt(1, 1))
  842.   {
  843.     EvalStrStringExpression(&ArgStr[1], &OK, mess);
  844.     if (!OK) WrError(ErrNum_InvString);
  845.     else
  846.       WrErrorString(mess, "", True, False, NULL, NULL);
  847.   }
  848. }
  849.  
  850.  
  851. static void CodeMESSAGE(Word Index)
  852. {
  853.   String mess;
  854.   Boolean OK;
  855.   UNUSED(Index);
  856.  
  857.   if (ChkArgCnt(1, 1))
  858.   {
  859.     EvalStrStringExpression(&ArgStr[1], &OK, mess);
  860.     if (!OK) WrError(ErrNum_InvString);
  861.     else
  862.     {
  863.       if (msg_level >= e_msg_level_normal)
  864.         WrConsoleLine(mess, True);
  865.       if (strcmp(LstName, "/dev/null"))
  866.         WrLstLine(mess);
  867.     }
  868.   }
  869. }
  870.  
  871.  
  872. static void CodeERROR(Word Index)
  873. {
  874.   String mess;
  875.   Boolean OK;
  876.   UNUSED(Index);
  877.  
  878.   if (ChkArgCnt(1, 1))
  879.   {
  880.     if (FindAndTakeExpectError(ErrNum_UserError))
  881.       return;
  882.  
  883.     EvalStrStringExpression(&ArgStr[1], &OK, mess);
  884.     if (!OK) WrError(ErrNum_InvString);
  885.     else
  886.       WrErrorString(mess, "", False, False, NULL, NULL);
  887.   }
  888. }
  889.  
  890.  
  891. static void CodeFATAL(Word Index)
  892. {
  893.   String mess;
  894.   Boolean OK;
  895.   UNUSED(Index);
  896.  
  897.   if (ChkArgCnt(1, 1))
  898.   {
  899.     EvalStrStringExpression(&ArgStr[1], &OK, mess);
  900.     if (!OK) WrError(ErrNum_InvString);
  901.     else
  902.       WrErrorString(mess, "", False, True, NULL, NULL);
  903.   }
  904. }
  905.  
  906. static void CodeCHARSET(Word Index)
  907. {
  908.   UNUSED(Index);
  909.  
  910.   if (!ChkArgCnt(0, 3));
  911.   else if (ArgCnt == 0)
  912.     as_chartrans_table_reset(CurrTransTable->p_table);
  913.   else
  914.   {
  915.     TempResult t;
  916.  
  917.     as_tempres_ini(&t);
  918.     EvalStrExpression(&ArgStr[1], &t);
  919.     if ((t.Typ == TempString) && (t.Flags & eSymbolFlag_StringSingleQuoted))
  920.       TempResultToInt(&t);
  921.     switch (t.Typ)
  922.     {
  923.       case TempInt:
  924.         if (mFirstPassUnknown(t.Flags))
  925.           t.Contents.Int &= 255;
  926.         if (ChkRange(t.Contents.Int, 0, 255))
  927.         {
  928.           if (ChkArgCnt(2, 3))
  929.           {
  930.             LongWord Start = t.Contents.Int;
  931.             if ((ArgCnt == 2) && (!ArgStr[2].str.p_str[0]))
  932.             {
  933.               as_chartrans_table_unset(CurrTransTable->p_table, Start);
  934.             }
  935.             else
  936.             {
  937.               EvalStrExpression(&ArgStr[2], &t);
  938.               if ((t.Typ == TempString) && (t.Flags & eSymbolFlag_StringSingleQuoted))
  939.                 TempResultToInt(&t);
  940.               switch (t.Typ)
  941.               {
  942.                 case TempInt: /* Uebersetzungsbereich als Character-Angabe */
  943.                   if (mFirstPassUnknown(t.Flags))
  944.                     t.Contents.Int &= 255;
  945.                   if (ChkRange(t.Contents.Int, 0, 255))
  946.                   {
  947.                     if (ArgCnt == 2)
  948.                       as_chartrans_table_set(CurrTransTable->p_table, Start, t.Contents.Int);
  949.                     else if (!ArgStr[3].str.p_str[0])
  950.                       as_chartrans_table_unset_mult(CurrTransTable->p_table, Start, t.Contents.Int);
  951.                     else if (ChkRange(t.Contents.Int, Start, 255))
  952.                     {
  953.                       Boolean OK;
  954.                       LongWord Stop = t.Contents.Int,
  955.                                TStart = EvalStrIntExpression(&ArgStr[3], UInt8, &OK);
  956.                       if (OK)
  957.                         as_chartrans_table_set_mult(CurrTransTable->p_table, Start, Stop, TStart);
  958.                     }
  959.                   }
  960.                   break;
  961.                 case TempString:
  962.                 {
  963.                   LongWord l = t.Contents.str.len; /* Uebersetzungsstring ab Start */
  964.  
  965.                   if (Start + l > 256) WrError(ErrNum_OverRange);
  966.                   else
  967.                   {
  968.                     LongWord z;
  969.  
  970.                     for (z = 0; z < l; z++)
  971.                       as_chartrans_table_set(CurrTransTable->p_table, Start + z, t.Contents.str.p_str[z]);
  972.                   }
  973.                   break;
  974.                 }
  975.                 case TempFloat:
  976.                   WrStrErrorPos(ErrNum_StringOrIntButFloat, &ArgStr[2]);
  977.                   break;
  978.                 default:
  979.                   break;
  980.               }
  981.             }
  982.           }
  983.         }
  984.         break;
  985.       case TempString:
  986.         if (ChkArgCnt(1, 1)) /* Tabelle von Datei lesen */
  987.         {
  988.           String Tmp;
  989.           FILE *f;
  990.           unsigned char tfield[256];
  991.           LongWord z;
  992.  
  993.           as_nonz_dynstr_to_c_str(Tmp, &t.Contents.str, sizeof(Tmp));
  994.           f = fopen(Tmp, OPENRDMODE);
  995.           if (!f) ChkIO(ErrNum_OpeningFile);
  996.           if (fread(tfield, sizeof(char), 256, f) != 256) ChkIO(ErrNum_FileReadError);
  997.           fclose(f);
  998.           for (z = 0; z < 256; z++)
  999.             as_chartrans_table_set(CurrTransTable->p_table, z, tfield[z]);
  1000.         }
  1001.         break;
  1002.       case TempFloat:
  1003.         WrStrErrorPos(ErrNum_StringOrIntButFloat, &ArgStr[1]);
  1004.         break;
  1005.       default:
  1006.         break;
  1007.     }
  1008.     as_tempres_free(&t);
  1009.   }
  1010. }
  1011.  
  1012. static void CodePRSET(Word Index)
  1013. {
  1014.   UNUSED(Index);
  1015.  
  1016.   as_chartrans_table_print(CurrTransTable->p_table, stdout);
  1017. }
  1018.  
  1019. static void CodeCODEPAGE(Word Index)
  1020. {
  1021.   PTransTable Source;
  1022.   UNUSED(Index);
  1023.  
  1024.   if (!ChkArgCnt(1, 2));
  1025.   else if (!ChkSymbName(ArgStr[1].str.p_str)) WrStrErrorPos(ErrNum_InvSymName, &ArgStr[1]);
  1026.   else
  1027.   {
  1028.     Source = (ArgCnt == 1) ? CurrTransTable : FindCodepage(ArgStr[2].str.p_str, NULL);
  1029.     if (!Source) WrStrErrorPos(ErrNum_UnknownCodepage, &ArgStr[2]);
  1030.     else
  1031.     {
  1032.       Source = FindCodepage(ArgStr[1].str.p_str, Source);
  1033.       if (Source)
  1034.         CurrTransTable = Source;
  1035.     }
  1036.   }
  1037. }
  1038.  
  1039. static void CodeFUNCTION(Word Index)
  1040. {
  1041.   Boolean OK;
  1042.   int z;
  1043.   UNUSED(Index);
  1044.  
  1045.   if (ChkArgCnt(2, ArgCntMax))
  1046.   {
  1047.     OK = True;
  1048.     z = 1;
  1049.     do
  1050.     {
  1051.       OK = (OK && ChkMacSymbName(ArgStr[z].str.p_str));
  1052.       if (!OK)
  1053.         WrStrErrorPos(ErrNum_InvSymName, &ArgStr[z]);
  1054.       z++;
  1055.     }
  1056.     while ((z < ArgCnt) && (OK));
  1057.     if (OK)
  1058.     {
  1059.       as_dynstr_t FName;
  1060.  
  1061.       as_dynstr_ini_c_str(&FName, ArgStr[ArgCnt].str.p_str);
  1062.       for (z = 1; z < ArgCnt; z++)
  1063.         CompressLine(ArgStr[z].str.p_str, z, &FName, CaseSensitive);
  1064.       EnterFunction(&LabPart, FName.p_str, ArgCnt - 1);
  1065.       as_dynstr_free(&FName);
  1066.     }
  1067.   }
  1068. }
  1069.  
  1070.  
  1071. static void CodeSAVE(Word Index)
  1072. {
  1073.   PSaveState Neu;
  1074.   UNUSED(Index);
  1075.  
  1076.   if (ChkArgCnt(0, 0))
  1077.   {
  1078.     Neu = (PSaveState) malloc(sizeof(TSaveState));
  1079.     Neu->Next = FirstSaveState;
  1080.     Neu->SaveCPU = MomCPU;
  1081.     Neu->pSaveCPUArgs = as_strdup(MomCPUArgs);
  1082.     Neu->SavePC = ActPC;
  1083.     Neu->SaveListOn = ListOn;
  1084.     Neu->SaveLstMacroExp = GetLstMacroExp();
  1085.     Neu->SaveLstMacroExpModDefault = LstMacroExpModDefault;
  1086.     Neu->SaveLstMacroExpModOverride = LstMacroExpModOverride;
  1087.     Neu->SaveTransTable = CurrTransTable;
  1088.     Neu->SaveEnumSegment = EnumSegment;
  1089.     Neu->SaveEnumIncrement = EnumIncrement;
  1090.     Neu->SaveEnumCurrentValue = EnumCurrentValue;
  1091.     FirstSaveState = Neu;
  1092.   }
  1093. }
  1094.  
  1095.  
  1096. static void CodeRESTORE(Word Index)
  1097. {
  1098.   PSaveState Old;
  1099.   UNUSED(Index);
  1100.  
  1101.   if (!ChkArgCnt(0, 0));
  1102.   else if (!FirstSaveState) WrError(ErrNum_NoSaveFrame);
  1103.   else
  1104.   {
  1105.     tStrComp TmpComp;
  1106.     String TmpCompStr;
  1107.  
  1108.     Old = FirstSaveState; FirstSaveState = Old->Next;
  1109.     if (Old->SavePC != ActPC)
  1110.     {
  1111.       ActPC = Old->SavePC;
  1112.       DontPrint = True;
  1113.     }
  1114.     if (Old->SaveCPU != MomCPU)
  1115.     {
  1116.       StrCompMkTemp(&TmpComp, Old->pSaveCPUArgs, 0);
  1117.       SetCPUByType(Old->SaveCPU, &TmpComp);
  1118.     }
  1119.     StrCompMkTemp(&TmpComp, TmpCompStr, sizeof(TmpCompStr));
  1120.     strmaxcpy(TmpCompStr, ListOnName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, ListOn = Old->SaveListOn, SegNone, True);
  1121.     SetLstMacroExp(Old->SaveLstMacroExp);
  1122.     LstMacroExpModDefault = Old->SaveLstMacroExpModDefault;
  1123.     LstMacroExpModOverride = Old->SaveLstMacroExpModOverride;
  1124.     CurrTransTable = Old->SaveTransTable;
  1125.     free(Old->pSaveCPUArgs);
  1126.     free(Old);
  1127.   }
  1128. }
  1129.  
  1130.  
  1131. static void CodeMACEXP(Word Index)
  1132. {
  1133.   /* will deprecate this in 1..2 years, 2018-01-21 */
  1134.  
  1135. #if 0
  1136.   if (Index & 0x10)
  1137.   {
  1138.     char Msg[70];
  1139.  
  1140.     as_snprintf(Msg, sizeof(Msg), getmessage(Num_ErrMsgDeprecated_Instead), "MACEXP_DFT");
  1141.     WrXError(ErrNum_Deprecated, Msg);
  1142.   }
  1143. #endif
  1144.  
  1145.   /* allow zero arguments for MACEXP_OVR, to remove all overrides */
  1146.  
  1147.   if (!ChkArgCnt((Index & 0x0f) ? 0 : 1, ArgCntMax));
  1148.   else if (*AttrPart.str.p_str != '\0') WrError(ErrNum_UseLessAttr);
  1149.   else
  1150.   {
  1151.     tStrComp *pArg;
  1152.     tLstMacroExpMod LstMacroExpMod;
  1153.     tLstMacroExp Mod;
  1154.     Boolean Set;
  1155.     Boolean OK = True;
  1156.  
  1157.     InitLstMacroExpMod(&LstMacroExpMod);
  1158.     forallargs (pArg, True)
  1159.     {
  1160.       if (!as_strcasecmp(pArg->str.p_str, "ON"))
  1161.       {
  1162.         Mod = eLstMacroExpAll; Set = True;
  1163.       }
  1164.       else if (!as_strcasecmp(pArg->str.p_str, "OFF"))
  1165.       {
  1166.         Mod = eLstMacroExpAll; Set = False;
  1167.       }
  1168.       else if (!as_strcasecmp(pArg->str.p_str, "NOIF"))
  1169.       {
  1170.         Mod= eLstMacroExpIf; Set = False;
  1171.       }
  1172.       else if (!as_strcasecmp(pArg->str.p_str, "NOMACRO"))
  1173.       {
  1174.         Mod = eLstMacroExpMacro; Set = False;
  1175.       }
  1176.       else if (!as_strcasecmp(pArg->str.p_str, "NOREST"))
  1177.       {
  1178.         Mod = eLstMacroExpRest; Set = False;
  1179.       }
  1180.       else if (!as_strcasecmp(pArg->str.p_str, "IF"))
  1181.       {
  1182.         Mod = eLstMacroExpIf; Set = True;
  1183.       }
  1184.       else if (!as_strcasecmp(pArg->str.p_str, "MACRO"))
  1185.       {
  1186.         Mod = eLstMacroExpMacro; Set = True;
  1187.       }
  1188.       else if (!as_strcasecmp(pArg->str.p_str, "REST"))
  1189.       {
  1190.         Mod = eLstMacroExpRest; Set = True;
  1191.       }
  1192.       else
  1193.         OK = False;
  1194.       if (!OK)
  1195.       {
  1196.         WrStrErrorPos(ErrNum_TooManyMacExpMod, pArg);
  1197.         break;
  1198.       }
  1199.       else if (!AddLstMacroExpMod(&LstMacroExpMod, Set, Mod))
  1200.       {
  1201.         WrStrErrorPos(ErrNum_TooManyArgs, pArg);
  1202.         break;
  1203.       }
  1204.     }
  1205.     if (OK)
  1206.     {
  1207.       if (!ChkLstMacroExpMod(&LstMacroExpMod)) WrError(ErrNum_ConflictingMacExpMod);
  1208.       else if (Index) /* Override */
  1209.         LstMacroExpModOverride = LstMacroExpMod;
  1210.       else
  1211.       {
  1212.         /* keep LstMacroExp and LstMacroExpModDefault in sync! */
  1213.         LstMacroExpModDefault = LstMacroExpMod;
  1214.         SetLstMacroExp(ApplyLstMacroExpMod(eLstMacroExpAll, &LstMacroExpModDefault));
  1215.       }
  1216.     }
  1217.   }
  1218. }
  1219.  
  1220. static Boolean DecodeSegment(const tStrComp *pArg, as_addrspace_t StartSeg, as_addrspace_t *pResult)
  1221. {
  1222.   as_addrspace_t SegZ;
  1223.   Word Mask;
  1224.  
  1225.   for (SegZ = StartSeg, Mask = 1 << StartSeg; SegZ < SegCount; SegZ++, Mask <<= 1)
  1226.     if ((ValidSegs & Mask) && !as_strcasecmp(pArg->str.p_str, SegNames[SegZ]))
  1227.     {
  1228.       *pResult = SegZ;
  1229.       return True;
  1230.     }
  1231.   WrStrErrorPos(ErrNum_UnknownSegment, pArg);
  1232.   return False;
  1233. }
  1234.  
  1235. static void CodeSEGMENT(Word Index)
  1236. {
  1237.   as_addrspace_t NewSegment;
  1238.   UNUSED(Index);
  1239.  
  1240.   if (ChkArgCnt(1, 1)
  1241.    && DecodeSegment(&ArgStr[1], SegCode, &NewSegment))
  1242.     SetNSeg(NewSegment, False);
  1243. }
  1244.  
  1245.  
  1246. static void CodeLABEL(Word Index)
  1247. {
  1248.   LongInt Erg;
  1249.   Boolean OK;
  1250.   tSymbolFlags Flags;
  1251.   UNUSED(Index);
  1252.  
  1253.   if (ChkArgCnt(1, 1))
  1254.   {
  1255.     Erg = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
  1256.     if (OK && !mFirstPassUnknown(Flags))
  1257.     {
  1258.       PushLocHandle(-1);
  1259.       EnterIntSymbol(&LabPart, Erg, SegCode, False);
  1260.       *ListLine = '=';
  1261.       IntLine(ListLine + 1, STRINGSIZE - 1, Erg, IntConstMode);
  1262.       PopLocHandle();
  1263.     }
  1264.   }
  1265. }
  1266.  
  1267.  
  1268. static void CodeREAD(Word Index)
  1269. {
  1270.   String ExpStr;
  1271.   tStrComp Exp;
  1272.   Boolean OK;
  1273.   LongInt SaveLocHandle;
  1274.   UNUSED(Index);
  1275.  
  1276.   StrCompMkTemp(&Exp, ExpStr, sizeof(ExpStr));
  1277.   if (ChkArgCnt(1, 2))
  1278.   {
  1279.     if (ArgCnt == 2) EvalStrStringExpression(&ArgStr[1], &OK, Exp.str.p_str);
  1280.     else
  1281.     {
  1282.       as_snprintf(Exp.str.p_str, sizeof(ExpStr), "Read %s ? ", ArgStr[1].str.p_str);
  1283.       OK = True;
  1284.     }
  1285.     if (OK)
  1286.     {
  1287.       TempResult Erg;
  1288.  
  1289.       as_tempres_ini(&Erg);
  1290.       printf("%s", Exp.str.p_str);
  1291.       fflush(stdout);
  1292.       if (!fgets(Exp.str.p_str, STRINGSIZE, stdin))
  1293.         OK = False;
  1294.       else
  1295.       {
  1296.         UpString(Exp.str.p_str);
  1297.         EvalStrExpression(&Exp, &Erg);
  1298.       }
  1299.       if (OK)
  1300.       {
  1301.         SetListLineVal(&Erg);
  1302.         SaveLocHandle = MomLocHandle;
  1303.         MomLocHandle = -1;
  1304.         if (mFirstPassUnknown(Erg.Flags)) WrError(ErrNum_FirstPassCalc);
  1305.         else switch (Erg.Typ)
  1306.         {
  1307.           case TempInt:
  1308.             EnterIntSymbol(&ArgStr[ArgCnt], Erg.Contents.Int, SegNone, True);
  1309.             break;
  1310.           case TempFloat:
  1311.             EnterFloatSymbol(&ArgStr[ArgCnt], Erg.Contents.Float, True);
  1312.             break;
  1313.           case TempString:
  1314.             EnterNonZStringSymbol(&ArgStr[ArgCnt], &Erg.Contents.str, True);
  1315.             break;
  1316.           default:
  1317.             break;
  1318.         }
  1319.         MomLocHandle = SaveLocHandle;
  1320.       }
  1321.       as_tempres_free(&Erg);
  1322.     }
  1323.   }
  1324. }
  1325.  
  1326. static void CodeRADIX(Word Index)
  1327. {
  1328.   Boolean OK;
  1329.   LargeWord tmp;
  1330.  
  1331.   if (ChkArgCnt(1, 1))
  1332.   {
  1333.     tmp = ConstLongInt(ArgStr[1].str.p_str, &OK, 10);
  1334.     if (!OK) WrError(ErrNum_ExpectInt);
  1335.     else if (ChkRange(tmp, 2, 36))
  1336.     {
  1337.       if (Index == 1)
  1338.         OutRadixBase = tmp;
  1339.       else
  1340.         RadixBase = tmp;
  1341.     }
  1342.   }
  1343. }
  1344.  
  1345. static void CodeALIGN(Word Index)
  1346. {
  1347.   UNUSED(Index);
  1348.  
  1349.   if (ChkArgCnt(1, 2))
  1350.   {
  1351.     Word AlignValue;
  1352.     Byte AlignFill = 0;
  1353.     Boolean OK = True;
  1354.     tSymbolFlags Flags = eSymbolFlag_None;
  1355.     LongInt NewPC;
  1356.  
  1357.     if (2 == ArgCnt)
  1358.       AlignFill = EvalStrIntExpressionWithFlags(&ArgStr[2], Int8, &OK, &Flags);
  1359.     if (OK)
  1360.       AlignValue = EvalStrIntExpression(&ArgStr[1], Int16, &OK);
  1361.     if (OK)
  1362.     {
  1363.       if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
  1364.       else
  1365.       {
  1366.         NewPC = EProgCounter() + AlignValue - 1;
  1367.         NewPC -= NewPC % AlignValue;
  1368.         CodeLen = NewPC - EProgCounter();
  1369.         if (1 == ArgCnt)
  1370.         {
  1371.           DontPrint = !!CodeLen;
  1372.           BookKeeping();
  1373.         }
  1374.         else if (CodeLen > (LongInt)MaxCodeLen) WrError(ErrNum_CodeOverflow);
  1375.         else
  1376.         {
  1377.           memset(BAsmCode, AlignFill, CodeLen);
  1378.           DontPrint = False;
  1379.         }
  1380.       }
  1381.     }
  1382.   }
  1383. }
  1384.  
  1385. static void CodeASSUME(Word Index)
  1386. {
  1387.   int z1;
  1388.   unsigned z2, z3;
  1389.   Boolean OK;
  1390.   tSymbolFlags Flags;
  1391.   LongInt HVal;
  1392.   tStrComp RegPart, ValPart;
  1393.   char *pSep, EmptyStr[] = "";
  1394.   void (*pPostProcs[5])(void);
  1395.   unsigned PostProcCount = 0;
  1396.  
  1397.   UNUSED(Index);
  1398.  
  1399.   /* CPU-specific override? */
  1400.  
  1401.   if (pASSUMEOverride)
  1402.   {
  1403.     pASSUMEOverride();
  1404.     return;
  1405.   }
  1406.  
  1407.   if (ChkArgCnt(1, ArgCntMax))
  1408.   {
  1409.     z1 = 1;
  1410.     OK = True;
  1411.     while ((z1 <= ArgCnt) && OK)
  1412.     {
  1413.       pSep = QuotPos(ArgStr[z1].str.p_str, ':');
  1414.       if (pSep)
  1415.         StrCompSplitRef(&RegPart, &ValPart, &ArgStr[z1], pSep);
  1416.       else
  1417.       {
  1418.         RegPart = ArgStr[z1];
  1419.         StrCompMkTemp(&ValPart, EmptyStr, 0);
  1420.       }
  1421.       z2 = 0;
  1422.       NLS_UpString(RegPart.str.p_str);
  1423.       while ((z2 < ASSUMERecCnt) && (strcmp(pASSUMERecs[z2].Name, RegPart.str.p_str)))
  1424.         z2++;
  1425.       OK = (z2 < ASSUMERecCnt);
  1426.       if (!OK) WrStrErrorPos(ErrNum_InvRegName, &RegPart);
  1427.       else
  1428.       {
  1429.         if (!as_strcasecmp(ValPart.str.p_str, "NOTHING"))
  1430.         {
  1431.           if (pASSUMERecs[z2].NothingVal == -1) WrError(ErrNum_InvAddrMode);
  1432.           else
  1433.             *(pASSUMERecs[z2].Dest) = pASSUMERecs[z2].NothingVal;
  1434.         }
  1435.         else
  1436.         {
  1437.           HVal = EvalStrIntExpressionWithFlags(&ValPart, Int32, &OK, &Flags);
  1438.           if (OK)
  1439.           {
  1440.             if (mFirstPassUnknown(Flags))
  1441.             {
  1442.               WrError(ErrNum_FirstPassCalc);
  1443.               OK = False;
  1444.             }
  1445.             else if (ChkRange(HVal, pASSUMERecs[z2].Min, pASSUMERecs[z2].Max))
  1446.               *(pASSUMERecs[z2].Dest) = HVal;
  1447.           }
  1448.         }
  1449.         /* collect different post procs so same proc is called only once */
  1450.         if (pASSUMERecs[z2].pPostProc)
  1451.         {
  1452.           for (z3 = 0; z3 < PostProcCount; z3++)
  1453.             if (pASSUMERecs[z2].pPostProc == pPostProcs[z3])
  1454.               break;
  1455.           if (z3 >= PostProcCount)
  1456.           {
  1457.             if (PostProcCount >= as_array_size(pPostProcs))
  1458.             {
  1459.               for (z3 = 0; z3 < PostProcCount; z3++)
  1460.                 pPostProcs[z3]();
  1461.               PostProcCount = 0;
  1462.             }
  1463.             pPostProcs[PostProcCount++] = pASSUMERecs[z2].pPostProc;
  1464.           }
  1465.         }
  1466.       }
  1467.       z1++;
  1468.     }
  1469.     for (z3 = 0; z3 < PostProcCount; z3++)
  1470.       pPostProcs[z3]();
  1471.   }
  1472. }
  1473.  
  1474. static void CodeENUM(Word IsNext)
  1475. {
  1476.   int z;
  1477.   char *p = NULL;
  1478.   Boolean OK;
  1479.   tSymbolFlags Flags;
  1480.   LongInt  First = 0, Last = 0;
  1481.   tStrComp SymPart;
  1482.  
  1483.   if (!IsNext)
  1484.     EnumCurrentValue = 0;
  1485.   if (ChkArgCnt(1, ArgCntMax))
  1486.   {
  1487.     for (z = 1; z <= ArgCnt; z++)
  1488.     {
  1489.       p = QuotPos(ArgStr[z].str.p_str, '=');
  1490.       if (p)
  1491.       {
  1492.         StrCompSplitRef(&ArgStr[z], &SymPart, &ArgStr[z], p);
  1493.         EnumCurrentValue = EvalStrIntExpressionWithFlags(&SymPart, Int32, &OK, &Flags);
  1494.         if (!OK)
  1495.           return;
  1496.         if (mFirstPassUnknown(Flags))
  1497.         {
  1498.           WrStrErrorPos(ErrNum_FirstPassCalc, &SymPart);
  1499.           return;
  1500.         }
  1501.         *p = '\0';
  1502.       }
  1503.       EnterIntSymbol(&ArgStr[z], EnumCurrentValue, (as_addrspace_t)EnumSegment, False);
  1504.       if (z == 1)
  1505.         First = EnumCurrentValue;
  1506.       else if (z == ArgCnt)
  1507.         Last = EnumCurrentValue;
  1508.       EnumCurrentValue += EnumIncrement;
  1509.     }
  1510.   }
  1511.   *ListLine = '=';
  1512.   IntLine(ListLine + 1, STRINGSIZE - 1, First, IntConstMode);
  1513.   if (ArgCnt != 1)
  1514.   {
  1515.     int l;
  1516.  
  1517.     strmaxcat(ListLine, "..", STRINGSIZE);
  1518.     l = strlen(ListLine);
  1519.     IntLine(ListLine + l, STRINGSIZE - l, Last, IntConstMode);
  1520.   }
  1521. }
  1522.  
  1523. static void CodeENUMCONF(Word Index)
  1524. {
  1525.   UNUSED(Index);
  1526.  
  1527.   if (ChkArgCnt(1, 2))
  1528.   {
  1529.     Boolean OK;
  1530.     LongInt NewIncrement;
  1531.  
  1532.     NewIncrement = EvalStrIntExpression(&ArgStr[1], Int32, &OK);
  1533.     if (!OK)
  1534.       return;
  1535.     EnumIncrement = NewIncrement;
  1536.  
  1537.     if (ArgCnt >= 2)
  1538.     {
  1539.       as_addrspace_t NewSegment;
  1540.  
  1541.       if (DecodeSegment(&ArgStr[2], SegNone, &NewSegment))
  1542.         EnumSegment = NewSegment;
  1543.     }
  1544.   }
  1545. }
  1546.  
  1547. static void CodeEND(Word Index)
  1548. {
  1549.   UNUSED(Index);
  1550.  
  1551.   if (ChkArgCnt(0, 1))
  1552.   {
  1553.     if (ArgCnt == 1)
  1554.     {
  1555.       LongInt HVal;
  1556.       tEvalResult EvalResult;
  1557.  
  1558.       HVal = EvalStrIntExpressionWithResult(&ArgStr[1], Int32, &EvalResult);
  1559.       if (EvalResult.OK)
  1560.       {
  1561.         ChkSpace(SegCode, EvalResult.AddrSpaceMask);
  1562.         StartAdr = HVal;
  1563.         StartAdrPresent = True;
  1564.       }
  1565.     }
  1566.    ENDOccured = True;
  1567.   }
  1568. }
  1569.  
  1570.  
  1571. static void CodeLISTING(Word Index)
  1572. {
  1573.   Byte Value = 0xff;
  1574.   Boolean OK;
  1575.   UNUSED(Index);
  1576.  
  1577.   if (!ChkArgCnt(1, 1));
  1578.   else if (*AttrPart.str.p_str != '\0') WrError(ErrNum_UseLessAttr);
  1579.   else
  1580.   {
  1581.     OK = True;
  1582.     NLS_UpString(ArgStr[1].str.p_str);
  1583.     if (!strcmp(ArgStr[1].str.p_str, "OFF"))
  1584.       Value = 0;
  1585.     else if (!strcmp(ArgStr[1].str.p_str, "ON"))
  1586.       Value = 1;
  1587.     else if (!strcmp(ArgStr[1].str.p_str, "NOSKIPPED"))
  1588.       Value = 2;
  1589.     else if (!strcmp(ArgStr[1].str.p_str, "PURECODE"))
  1590.       Value = 3;
  1591.     else
  1592.       OK = False;
  1593.     if (!OK) WrStrErrorPos(ErrNum_OnlyOnOff, &ArgStr[1]);
  1594.     else
  1595.     {
  1596.       tStrComp TmpComp;
  1597.       String TmpCompStr;
  1598.  
  1599.       StrCompMkTemp(&TmpComp, TmpCompStr, sizeof(TmpCompStr));
  1600.       strmaxcpy(TmpCompStr, ListOnName, sizeof(TmpCompStr));
  1601.       EnterIntSymbol(&TmpComp, ListOn = Value, SegNone, True);
  1602.     }
  1603.   }
  1604. }
  1605.  
  1606. void INCLUDE_SearchCore(tStrComp *pDest, const tStrComp *pArg, Boolean SearchPath)
  1607. {
  1608.   size_t l = strlen(pArg->str.p_str), offs = 0;
  1609.  
  1610.   if (pArg->str.p_str[0] == '"')
  1611.   {
  1612.     offs++;
  1613.     if ((l > 1) && (pArg->str.p_str[l - 1]  == '"'))
  1614.       l -= 2;
  1615.     else
  1616.     {
  1617.       WrStrErrorPos(ErrNum_BrackErr, pArg);
  1618.       return;
  1619.     }
  1620.   }
  1621.   StrCompCopySub(pDest, pArg, offs, l);
  1622.  
  1623.   AddSuffix(pDest->str.p_str, IncSuffix);
  1624.  
  1625.   if (SearchPath)
  1626.   {
  1627.     String FoundFileName;
  1628.  
  1629.     if (FSearch(FoundFileName, sizeof(FoundFileName), pDest->str.p_str, CurrFileName, SearchPath ? IncludeList : ""))
  1630.       ChkStrIO(ErrNum_OpeningFile, pArg);
  1631.     strmaxcpy(pDest->str.p_str, FExpand(FoundFileName), STRINGSIZE - 1);
  1632.   }
  1633. }
  1634.  
  1635. static void CodeBINCLUDE(Word Index)
  1636. {
  1637.   FILE *F;
  1638.   LongInt Len = -1;
  1639.   LongWord Ofs = 0, Curr, Rest, FSize;
  1640.   Word RLen;
  1641.   Boolean OK, SaveTurnWords;
  1642.   tSymbolFlags Flags;
  1643.   LargeWord OldPC;
  1644.   UNUSED(Index);
  1645.  
  1646.   if (!ChkArgCnt(1, 3));
  1647.   else if (ActPC == StructSeg) WrError(ErrNum_NotInStruct);
  1648.   else
  1649.   {
  1650.     if (ArgCnt == 1)
  1651.       OK = True;
  1652.     else
  1653.     {
  1654.       Ofs = EvalStrIntExpressionWithFlags(&ArgStr[2], Int32, &OK, &Flags);
  1655.       if (mFirstPassUnknown(Flags))
  1656.       {
  1657.         WrError(ErrNum_FirstPassCalc);
  1658.         OK = False;
  1659.       }
  1660.       if (OK)
  1661.       {
  1662.         if (ArgCnt == 2)
  1663.           Len = -1;
  1664.         else
  1665.         {
  1666.           Len = EvalStrIntExpressionWithFlags(&ArgStr[3], Int32, &OK, &Flags);
  1667.           if (mFirstPassUnknown(Flags))
  1668.           {
  1669.             WrError(ErrNum_FirstPassCalc);
  1670.             OK = False;
  1671.           }
  1672.         }
  1673.       }
  1674.     }
  1675.     if (OK)
  1676.     {
  1677.       tStrComp FNameArg;
  1678.       String FNameArgStr;
  1679.  
  1680.       StrCompMkTemp(&FNameArg, FNameArgStr, sizeof(FNameArgStr));
  1681.       INCLUDE_SearchCore(&FNameArg, &ArgStr[1], True);
  1682.  
  1683.       F = fopen(FNameArg.str.p_str, OPENRDMODE);
  1684.       if (F == NULL) ChkXIO(ErrNum_OpeningFile, FNameArg.str.p_str);
  1685.       errno = 0; FSize = FileSize(F); ChkIO(ErrNum_FileReadError);
  1686.       if (Len == -1)
  1687.       {
  1688.         if ((Len = FSize - Ofs) < 0)
  1689.         {
  1690.           fclose(F); WrError(ErrNum_ShortRead); return;
  1691.         }
  1692.       }
  1693.       if (!ChkPC(PCs[ActPC] + Len - 1)) WrError(ErrNum_AdrOverflow);
  1694.       else
  1695.       {
  1696.         errno = 0; fseek(F, Ofs, SEEK_SET); ChkIO(ErrNum_FileReadError);
  1697.         Rest = Len;
  1698.         SaveTurnWords = TurnWords;
  1699.         TurnWords = False;
  1700.         OldPC = ProgCounter();
  1701.         do
  1702.         {
  1703.           Curr = (Rest <= 256) ? Rest : 256;
  1704.           errno = 0; RLen = fread(BAsmCode, 1, Curr, F); ChkIO(ErrNum_FileReadError);
  1705.           CodeLen = RLen;
  1706.           WriteBytes();
  1707.           PCs[ActPC] += CodeLen;
  1708.           Rest -= RLen;
  1709.         }
  1710.         while ((Rest != 0) && (RLen == Curr));
  1711.         if (Rest != 0) WrError(ErrNum_ShortRead);
  1712.         TurnWords = SaveTurnWords;
  1713.         DontPrint = True;
  1714.         CodeLen = ProgCounter() - OldPC;
  1715.         PCs[ActPC] = OldPC;
  1716.       }
  1717.       fclose(F);
  1718.     }
  1719.   }
  1720. }
  1721.  
  1722. static void CodePUSHV(Word Index)
  1723. {
  1724.   int z;
  1725.   UNUSED(Index);
  1726.  
  1727.   if (ChkArgCnt(2, ArgCntMax))
  1728.   {
  1729.     for (z = 2; z <= ArgCnt; z++)
  1730.       PushSymbol(&ArgStr[z], &ArgStr[1]);
  1731.   }
  1732. }
  1733.  
  1734. static void CodePOPV(Word Index)
  1735. {
  1736.   int z;
  1737.   UNUSED(Index);
  1738.  
  1739.   if (ChkArgCnt(2, ArgCntMax))
  1740.   {
  1741.     for (z = 2; z <= ArgCnt; z++)
  1742.       PopSymbol(&ArgStr[z], &ArgStr[1]);
  1743.   }
  1744. }
  1745.  
  1746. static PForwardSymbol CodePPSyms_SearchSym(PForwardSymbol Root, char *Comp)
  1747. {
  1748.   PForwardSymbol Lauf = Root;
  1749.   UNUSED(Comp);
  1750.  
  1751.   while (Lauf && strcmp(Lauf->Name, Comp))
  1752.     Lauf = Lauf->Next;
  1753.   return Lauf;
  1754. }
  1755.  
  1756.  
  1757. static void CodeSTRUCT(Word IsUnion)
  1758. {
  1759.   PStructStack NStruct;
  1760.   tStrComp *pArg;
  1761.   Boolean OK, DoExt;
  1762.   char ExtChar;
  1763.   String StructName;
  1764.  
  1765.   if (!ChkArgCnt(0, ArgCntMax))
  1766.     return;
  1767.  
  1768.   /* unnamed struct/union only allowed if embedded into at least one named struct/union */
  1769.  
  1770.   if (!*LabPart.str.p_str)
  1771.   {
  1772.     if (!pInnermostNamedStruct)
  1773.     {
  1774.       WrError(ErrNum_FreestandingUnnamedStruct);
  1775.       return;
  1776.     }
  1777.   }
  1778.   else
  1779.   {
  1780.     if (!ChkSymbName(LabPart.str.p_str))
  1781.     {
  1782.       WrXError(ErrNum_InvSymName, LabPart.str.p_str);
  1783.       return;
  1784.     }
  1785.     if (!CaseSensitive)
  1786.       NLS_UpString(LabPart.str.p_str);
  1787.   }
  1788.  
  1789.   /* compose name of nested structures */
  1790.  
  1791.   if (*LabPart.str.p_str)
  1792.     BuildStructName(StructName, sizeof(StructName), LabPart.str.p_str);
  1793.   else
  1794.     *StructName = '\0';
  1795.  
  1796.   /* If named and embedded into another struct, add as element to innermost named parent struct.
  1797.      Add up all offsets of unnamed structs in between. */
  1798.  
  1799.   if (StructStack && (*LabPart.str.p_str))
  1800.   {
  1801.     PStructStack pRun;
  1802.     LargeWord Offset = ProgCounter();
  1803.     PStructElem pElement = CreateStructElem(&LabPart);
  1804.     if (!pElement)
  1805.       return;
  1806.  
  1807.     for (pRun = StructStack; pRun && pRun != pInnermostNamedStruct; pRun = pRun->Next)
  1808.       Offset += pRun->SaveCurrPC;
  1809.     pElement->Offset = Offset;
  1810.     pElement->IsStruct = True;
  1811.     AddStructElem(pInnermostNamedStruct->StructRec, pElement);
  1812.     AddStructSymbol(LabPart.str.p_str, ProgCounter());
  1813.   }
  1814.  
  1815.   NStruct = (PStructStack) malloc(sizeof(TStructStack));
  1816.   NStruct->Name = as_strdup(StructName);
  1817.   NStruct->pBaseName = NStruct->Name + strlen(NStruct->Name) - strlen(LabPart.str.p_str); /* NULL -> complain too long */
  1818.   NStruct->SaveCurrPC = ProgCounter();
  1819.   DoExt = True;
  1820.   ExtChar = DottedStructs ? '.' : '_';
  1821.   NStruct->Next = StructStack;
  1822.   OK = True;
  1823.   forallargs (pArg, True)
  1824.     if (OK)
  1825.     {
  1826.       if (!as_strcasecmp(pArg->str.p_str, "EXTNAMES"))
  1827.         DoExt = True;
  1828.       else if (!as_strcasecmp(pArg->str.p_str, "NOEXTNAMES"))
  1829.         DoExt = False;
  1830.       else if (!as_strcasecmp(pArg->str.p_str, "DOTS"))
  1831.         ExtChar = '.';
  1832.       else if (!as_strcasecmp(pArg->str.p_str, "NODOTS"))
  1833.         ExtChar = '_';
  1834.       else
  1835.       {
  1836.         WrStrErrorPos(ErrNum_InvStructDir, pArg);
  1837.         OK = False;
  1838.       }
  1839.     }
  1840.   if (OK)
  1841.   {
  1842.     NStruct->StructRec = CreateStructRec();
  1843.     NStruct->StructRec->ExtChar = ExtChar;
  1844.     NStruct->StructRec->DoExt = DoExt;
  1845.     NStruct->StructRec->IsUnion = IsUnion;
  1846.     StructStack = NStruct;
  1847.     if (ActPC != StructSeg)
  1848.       StructSaveSeg = ActPC;
  1849.     if (NStruct->Name[0])
  1850.       pInnermostNamedStruct = NStruct;
  1851.     ActPC = StructSeg;
  1852.     PCs[ActPC] = 0;
  1853.     Phases[ActPC] = 0;
  1854.     Grans[ActPC] = Grans[SegCode];
  1855.     ListGrans[ActPC] = ListGrans[SegCode];
  1856.     ClearChunk(SegChunks + StructSeg);
  1857.     CodeLen = 0;
  1858.     DontPrint = True;
  1859.   }
  1860.   else
  1861.   {
  1862.     free(NStruct->Name);
  1863.     free(NStruct);
  1864.   }
  1865. }
  1866.  
  1867. static void CodeENDSTRUCT(Word IsUnion)
  1868. {
  1869.   Boolean OK;
  1870.   PStructStack OStruct;
  1871.  
  1872.   if (!ChkArgCnt(0, 1));
  1873.   else if (!StructStack) WrError(ErrNum_MissingStruct);
  1874.   else
  1875.   {
  1876.     if (IsUnion && !StructStack->StructRec->IsUnion)
  1877.       WrXError(ErrNum_STRUCTEndedByENDUNION, StructStack->Name);
  1878.  
  1879.     if (*LabPart.str.p_str == '\0') OK = True;
  1880.     else
  1881.     {
  1882.       if (!CaseSensitive)
  1883.         NLS_UpString(LabPart.str.p_str);
  1884.       OK = !strcmp(LabPart.str.p_str, StructStack->pBaseName);
  1885.       if (!OK) WrError(ErrNum_WrongStruct);
  1886.     }
  1887.     if (OK)
  1888.     {
  1889.       LargeWord TotLen;
  1890.  
  1891.       /* unchain current struct from stack */
  1892.  
  1893.       OStruct = StructStack;
  1894.       StructStack = OStruct->Next;
  1895.  
  1896.       /* resolve referenced symbols in structure */
  1897.  
  1898.       ResolveStructReferences(OStruct->StructRec);
  1899.  
  1900.       /* find new innermost named struct */
  1901.  
  1902.       for (pInnermostNamedStruct = StructStack;
  1903.            pInnermostNamedStruct;
  1904.            pInnermostNamedStruct = pInnermostNamedStruct->Next)
  1905.       {
  1906.         if (pInnermostNamedStruct->Name[0])
  1907.           break;
  1908.       }
  1909.  
  1910.       BumpStructLength(OStruct->StructRec, ProgCounter());
  1911.       TotLen = OStruct->StructRec->TotLen;
  1912.  
  1913.       /* add symbol for struct length if not nameless */
  1914.  
  1915.       if (ArgCnt == 0)
  1916.       {
  1917.         if (OStruct->Name[0])
  1918.         {
  1919.           String tmp2;
  1920.           tStrComp TmpComp;
  1921.  
  1922.           as_snprintf(tmp2, sizeof(tmp2), "%s%clen", OStruct->Name, OStruct->StructRec->ExtChar);
  1923.           StrCompMkTemp(&TmpComp, tmp2, sizeof(tmp2));
  1924.           EnterIntSymbol(&TmpComp, TotLen, SegNone, False);
  1925.         }
  1926.       }
  1927.       else
  1928.         EnterIntSymbol(&ArgStr[1], TotLen, SegNone, False);
  1929.  
  1930.       {
  1931.         TempResult t;
  1932.  
  1933.         as_tempres_ini(&t);
  1934.         as_tempres_set_int(&t, TotLen);
  1935.         SetListLineVal(&t);
  1936.         as_tempres_free(&t);
  1937.       }
  1938.  
  1939.       /* If named, store completed structure.
  1940.          Otherwise, discard temporary struct. */
  1941.  
  1942.       if (OStruct->Name[0])
  1943.         AddStruct(OStruct->StructRec, OStruct->Name, True);
  1944.       else
  1945.         DestroyStructRec(OStruct->StructRec);
  1946.       OStruct->StructRec = NULL;
  1947.  
  1948.       /* set PC back to outer's struct value, plus size of
  1949.          just completed struct, or non-struct value: */
  1950.  
  1951.       PCs[ActPC] = OStruct->SaveCurrPC;
  1952.       if (!StructStack)
  1953.       {
  1954.         ActPC = StructSaveSeg;
  1955.         CodeLen = 0;
  1956.       }
  1957.       else
  1958.       {
  1959.         CodeLen = TotLen;
  1960.       }
  1961.  
  1962.       /* free struct stack elements no longer needed */
  1963.  
  1964.       free(OStruct->Name);
  1965.       free(OStruct);
  1966.       ClearChunk(SegChunks + StructSeg);
  1967.       DontPrint = True;
  1968.     }
  1969.   }
  1970. }
  1971.  
  1972. static void CodeEXTERN(Word Index)
  1973. {
  1974.   char *Split;
  1975.   int i;
  1976.   Boolean OK;
  1977.   as_addrspace_t Type;
  1978.   UNUSED(Index);
  1979.  
  1980.   if (ChkArgCnt(1, ArgCntMax))
  1981.   {
  1982.     i = 1;
  1983.     OK = True;
  1984.     while ((OK) && (i <= ArgCnt))
  1985.     {
  1986.       Split = strrchr(ArgStr[i].str.p_str, ':');
  1987.       if (Split == NULL)
  1988.         Type = SegNone;
  1989.       else
  1990.       {
  1991.         *Split = '\0';
  1992.         for (Type = SegNone + 1; Type < SegCount; Type++)
  1993.           if (!as_strcasecmp(Split + 1, SegNames[Type]))
  1994.             break;
  1995.       }
  1996.       if (Type >= SegCount) WrXError(ErrNum_UnknownSegment, Split + 1);
  1997.       else
  1998.       {
  1999.         EnterExtSymbol(&ArgStr[i], 0, Type, FALSE);
  2000.       }
  2001.       i++;
  2002.     }
  2003.   }
  2004. }
  2005.  
  2006. static void CodeNESTMAX(Word Index)
  2007. {
  2008.   LongInt Temp;
  2009.   Boolean OK;
  2010.   tSymbolFlags Flags;
  2011.   UNUSED(Index);
  2012.  
  2013.   if (ChkArgCnt(1, 1))
  2014.   {
  2015.     Temp = EvalStrIntExpressionWithFlags(&ArgStr[1], UInt32, &OK, &Flags);
  2016.     if (OK)
  2017.     {
  2018.       if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
  2019.       else NestMax = Temp;
  2020.     }
  2021.   }
  2022. }
  2023.  
  2024. static void CodeSEGTYPE(Word Index)
  2025. {
  2026.   UNUSED(Index);
  2027.  
  2028.   if (ChkArgCnt(0, 0))
  2029.     RelSegs = (as_toupper(*OpPart.str.p_str) == 'R');
  2030. }
  2031.  
  2032. static void CodePPSyms(PForwardSymbol *Orig,
  2033.                        PForwardSymbol *Alt1,
  2034.                        PForwardSymbol *Alt2)
  2035. {
  2036.   PForwardSymbol Lauf;
  2037.   tStrComp *pArg, SymArg, SectionArg, exp_sym, *p_exp_sym;
  2038.   String exp_sym_buf, Section;
  2039.   char *pSplit;
  2040.  
  2041.   StrCompMkTemp(&exp_sym, exp_sym_buf, sizeof(exp_sym_buf));
  2042.   if (ChkArgCnt(1, ArgCntMax))
  2043.     forallargs (pArg, True)
  2044.     {
  2045.       pSplit = QuotPos(pArg->str.p_str, ':');
  2046.       if (pSplit)
  2047.       {
  2048.         StrCompSplitRef(&SymArg, &SectionArg, pArg, pSplit);
  2049.         p_exp_sym = ExpandStrSymbol(&exp_sym, &SymArg, !CaseSensitive);
  2050.         if (!p_exp_sym)
  2051.           return;
  2052.       }
  2053.       else
  2054.       {
  2055.         p_exp_sym = ExpandStrSymbol(&exp_sym, pArg, !CaseSensitive);
  2056.         if (!p_exp_sym)
  2057.           return;
  2058.         *Section = '\0';
  2059.         StrCompMkTemp(&SectionArg, Section, sizeof(Section));
  2060.       }
  2061.       Lauf = CodePPSyms_SearchSym(*Alt1, p_exp_sym->str.p_str);
  2062.       if (Lauf) WrStrErrorPos(ErrNum_ContForward, pArg);
  2063.       else
  2064.       {
  2065.         Lauf = CodePPSyms_SearchSym(*Alt2, p_exp_sym->str.p_str);
  2066.         if (Lauf) WrStrErrorPos(ErrNum_ContForward, pArg);
  2067.         else
  2068.         {
  2069.           Lauf = CodePPSyms_SearchSym(*Orig, p_exp_sym->str.p_str);
  2070.           if (!Lauf)
  2071.           {
  2072.             Lauf = (PForwardSymbol) malloc(sizeof(TForwardSymbol));
  2073.             Lauf->Next = (*Orig); *Orig = Lauf;
  2074.             Lauf->Name = as_strdup(p_exp_sym->str.p_str);
  2075.             Lauf->pErrorPos = GetErrorPos();
  2076.           }
  2077.           IdentifySection(&SectionArg, &Lauf->DestSection);
  2078.         }
  2079.       }
  2080.     }
  2081. }
  2082.  
  2083. /*------------------------------------------------------------------------*/
  2084.  
  2085. typedef struct
  2086. {
  2087.   Boolean Persist, *FlagAddr;
  2088.   const char *FlagName;
  2089.   const char *InstName;
  2090. } ONOFFTab;
  2091. static ONOFFTab *ONOFFList = NULL;
  2092. static size_t ONOFFCnt = 0;
  2093.  
  2094. Boolean CheckONOFFArg(const tStrComp *pArg, Boolean *pResult)
  2095. {
  2096.   *pResult = !as_strcasecmp(ArgStr[1].str.p_str, "ON");
  2097.   if (!*pResult && as_strcasecmp(ArgStr[1].str.p_str, "OFF"))
  2098.   {
  2099.     WrStrErrorPos(ErrNum_OnlyOnOff, pArg);
  2100.     return False;
  2101.   }
  2102.   return True;
  2103. }
  2104.  
  2105. static void DecodeONOFF(Word Index)
  2106. {
  2107.   ONOFFTab *Tab = ONOFFList + Index;
  2108.  
  2109.   if (ChkArgCnt(1, 1))
  2110.   {
  2111.     Boolean IsON;
  2112.  
  2113.     if (*AttrPart.str.p_str != '\0') WrError(ErrNum_UseLessAttr);
  2114.     else if (CheckONOFFArg(&ArgStr[1], &IsON))
  2115.       SetFlag(Tab->FlagAddr, Tab->FlagName, IsON);
  2116.   }
  2117. }
  2118.  
  2119. void AddONOFF(const char *InstName, Boolean *Flag, const char *FlagName, Boolean Persist)
  2120. {
  2121.   dyn_array_rsv_end(ONOFFList, ONOFFTab, ONOFFCnt);
  2122.   ONOFFList[ONOFFCnt].Persist = Persist;
  2123.   ONOFFList[ONOFFCnt].FlagAddr = Flag;
  2124.   ONOFFList[ONOFFCnt].FlagName = FlagName;
  2125.   ONOFFList[ONOFFCnt].InstName = InstName;
  2126.   AddInstTable(ONOFFTable, InstName, ONOFFCnt++, DecodeONOFF);
  2127. }
  2128.  
  2129. void ClearONOFF(void)
  2130. {
  2131.   size_t z, z2;
  2132.  
  2133.   for (z = 0; z < ONOFFCnt; z++)
  2134.     if (!ONOFFList[z].Persist)
  2135.       break;
  2136.  
  2137.   if (z < ONOFFCnt)
  2138.   {
  2139.     for (z2 = ONOFFCnt - 1; z2 >= z; z2--)
  2140.       RemoveInstTable(ONOFFTable, ONOFFList[z2].InstName);
  2141.  
  2142.     dyn_array_realloc(ONOFFList, ONOFFTab, ONOFFCnt, z);
  2143.     ONOFFCnt = z;
  2144.   }
  2145. }
  2146.  
  2147. /*!------------------------------------------------------------------------
  2148.  * \fn     CodeRELAXED(Word Index)
  2149.  * \brief  handle RELAXED statement
  2150.  * ------------------------------------------------------------------------ */
  2151.  
  2152. static void CodeRELAXED(Word Index)
  2153. {
  2154.   UNUSED(Index);
  2155.  
  2156.   if (ChkArgCnt(1, 1))
  2157.   {
  2158.     Boolean NewRelaxed;
  2159.  
  2160.     NLS_UpString(ArgStr[1].str.p_str);
  2161.     if (*AttrPart.str.p_str != '\0') WrError(ErrNum_UseLessAttr);
  2162.     else if (CheckONOFFArg(&ArgStr[1], &NewRelaxed))
  2163.     {
  2164.       SetFlag(&RelaxedMode, RelaxedName, NewRelaxed);
  2165.       SetIntConstRelaxedMode(NewRelaxed);
  2166.     }
  2167.   }
  2168. }
  2169.  
  2170. /*!------------------------------------------------------------------------
  2171.  * \fn     CodeINTSYNTAX(Word Index)
  2172.  * \brief  process INTSYNTAX statement
  2173.  * ------------------------------------------------------------------------ */
  2174.  
  2175. static void CodeINTSYNTAX(Word Index)
  2176. {
  2177.   UNUSED(Index);
  2178.  
  2179.   if (ChkArgCnt(1, ArgCntMax))
  2180.   {
  2181.     LongWord ANDMask = 0, ORMask = 0;
  2182.     tStrComp Ident, *pArg;
  2183.     tIntFormatId Id;
  2184.     Boolean OK = True;
  2185.  
  2186.     forallargs(pArg, OK)
  2187.     {
  2188.       StrCompRefRight(&Ident, pArg, 1);
  2189.       Id = GetIntFormatId(Ident.str.p_str);
  2190.       if (!Id)
  2191.       {
  2192.         WrStrErrorPos(ErrNum_InvIntFormat, &Ident);
  2193.         OK = False;
  2194.       }
  2195.       else switch (pArg->str.p_str[0])
  2196.       {
  2197.         case '+':
  2198.           ORMask |= 1ul << Id;
  2199.           break;
  2200.         case '-':
  2201.           ANDMask |= 1ul << Id;
  2202.           break;
  2203.         default:
  2204.           WrStrErrorPos(ErrNum_InvIntFormat, pArg);
  2205.         OK = False;
  2206.       }
  2207.     }
  2208.     if (OK)
  2209.     {
  2210.       if (!ModifyIntConstModeByMask(ANDMask, ORMask))
  2211.         WrError(ErrNum_InvIntFormatList);
  2212.     }
  2213.   }
  2214. }
  2215.  
  2216. /*!------------------------------------------------------------------------
  2217.  * \fn     code_set_cond(Word may_change)
  2218.  * \brief  process SET pseudo statement if no machine instruction
  2219.  * \param  may_change fixed True for SET
  2220.  * \return True if instruction was processed
  2221.  * ------------------------------------------------------------------------ */
  2222.  
  2223. static Boolean code_set_cond(Word may_change)
  2224. {
  2225.   if (is_set_pseudo())
  2226.   {
  2227.     CodeSETEQU(may_change);
  2228.     return True;
  2229.   }
  2230.   else
  2231.     return False;
  2232. }
  2233.  
  2234. /*!------------------------------------------------------------------------
  2235.  * \fn     code_save_cond(Word may_change)
  2236.  * \brief  process SAVE pseudo statement if no machine instruction
  2237.  * \param  may_change fixed 0 for SAVE
  2238.  * \return True if instruction was processed
  2239.  * ------------------------------------------------------------------------ */
  2240.  
  2241. static Boolean code_save_cond(Word arg)
  2242. {
  2243.   if (is_save_pseudo())
  2244.   {
  2245.     CodeSAVE(arg);
  2246.     return True;
  2247.   }
  2248.   else
  2249.     return False;
  2250. }
  2251.  
  2252. /*!------------------------------------------------------------------------
  2253.  * \fn     code_page_cond(Word may_change)
  2254.  * \brief  process PAGE pseudo statement if no machine instruction
  2255.  * \param  may_change fixed 0 for PAGE
  2256.  * \return True if instruction was processed
  2257.  * ------------------------------------------------------------------------ */
  2258.  
  2259. static Boolean code_page_cond(Word arg)
  2260. {
  2261.   if (is_page_pseudo())
  2262.   {
  2263.     CodePAGE(arg);
  2264.     return True;
  2265.   }
  2266.   else
  2267.     return False;
  2268. }
  2269.  
  2270. /*!------------------------------------------------------------------------
  2271.  * \fn     code_pagesize_cond(Word may_change)
  2272.  * \brief  process PAGESIZE pseudo statement if PAGE is a machine instruction
  2273.  * \param  may_change fixed 0 for PAGESIZE
  2274.  * \return True if instruction was processed
  2275.  * ------------------------------------------------------------------------ */
  2276.  
  2277. static Boolean code_pagesize_cond(Word arg)
  2278. {
  2279.   if (PageIsOccupied)
  2280.   {
  2281.     CodePAGE(arg);
  2282.     return True;
  2283.   }
  2284.   else
  2285.     return False;
  2286. }
  2287.  
  2288. /*!------------------------------------------------------------------------
  2289.  * \fn     code_restore_cond(Word may_change)
  2290.  * \brief  process RESTORE pseudo statement if no machine instruction
  2291.  * \param  may_change fixed 0 for RESTORE
  2292.  * \return True if instruction was processed
  2293.  * ------------------------------------------------------------------------ */
  2294.  
  2295. static Boolean code_restore_cond(Word arg)
  2296. {
  2297.   if (is_restore_pseudo())
  2298.   {
  2299.     CodeRESTORE(arg);
  2300.     return True;
  2301.   }
  2302.   else
  2303.     return False;
  2304. }
  2305.  
  2306. /*!------------------------------------------------------------------------
  2307.  * \fn     code_forward_cond(Word arg)
  2308.  * \brief  process FORWARD pseudo statement if within section
  2309.  * \param  arg constant 0 for FORWARD
  2310.  * \return True if processed
  2311.  * ------------------------------------------------------------------------ */
  2312.  
  2313. static Boolean code_forward_cond(Word arg)
  2314. {
  2315.   UNUSED(arg);
  2316.  
  2317.   if (SectionStack)
  2318.   {
  2319.     if (PassNo <= MaxSymPass)
  2320.         CodePPSyms(&(SectionStack->LocSyms),
  2321.                    &(SectionStack->GlobSyms),
  2322.                    &(SectionStack->ExportSyms));
  2323.     return True;
  2324.   }
  2325.   else
  2326.     return False;
  2327. }
  2328.  
  2329. /*!------------------------------------------------------------------------
  2330.  * \fn     code_public_cond(Word arg)
  2331.  * \brief  process PUBLIC pseudo statement if within section
  2332.  * \param  arg constant 0 for PUBLIC
  2333.  * \return True if processed
  2334.  * ------------------------------------------------------------------------ */
  2335.  
  2336. static Boolean code_public_cond(Word arg)
  2337. {
  2338.   UNUSED(arg);
  2339.  
  2340.   if (SectionStack)
  2341.   {
  2342.     CodePPSyms(&(SectionStack->GlobSyms),
  2343.                &(SectionStack->LocSyms),
  2344.                &(SectionStack->ExportSyms));
  2345.     return True;
  2346.   }
  2347.   else
  2348.     return False;
  2349. }
  2350.  
  2351. /*!------------------------------------------------------------------------
  2352.  * \fn     code_global_cond(Word arg)
  2353.  * \brief  process GLOBAL pseudo statement if within section
  2354.  * \param  arg constant 0 for GLOBAL
  2355.  * \return True if processed
  2356.  * ------------------------------------------------------------------------ */
  2357.  
  2358. static Boolean code_global_cond(Word arg)
  2359. {
  2360.   UNUSED(arg);
  2361.  
  2362.   if (SectionStack)
  2363.   {
  2364.     CodePPSyms(&(SectionStack->ExportSyms),
  2365.                &(SectionStack->LocSyms),
  2366.                &(SectionStack->GlobSyms));
  2367.     return True;
  2368.   }
  2369.   else
  2370.     return False;
  2371. }
  2372.  
  2373. /*------------------------------------------------------------------------*/
  2374.  
  2375.  
  2376. Boolean CodeGlobalPseudo(void)
  2377. {
  2378.   return
  2379.       LookupInstTable(ONOFFTable, OpPart.str.p_str)
  2380.    || LookupInstTable(PseudoTable, OpPart.str.p_str)
  2381.    || inst_fnc_table_lookup(pseudo_inst_fnc_table, OpPart.str.p_str);
  2382. }
  2383.  
  2384. void codeallg_init(void)
  2385. {
  2386.   PseudoTable = CreateInstTable(201);
  2387.   AddInstTable(PseudoTable, "ALIGN",      0,  CodeALIGN     );
  2388.   AddInstTable(PseudoTable, "ASEG",       0,  CodeSEGTYPE   );
  2389.   AddInstTable(PseudoTable, "ASSUME",     0,  CodeASSUME    );
  2390.   AddInstTable(PseudoTable, "BINCLUDE",   0,  CodeBINCLUDE  );
  2391.   AddInstTable(PseudoTable, "CHARSET",    0,  CodeCHARSET   );
  2392.   AddInstTable(PseudoTable, "CODEPAGE",   0,  CodeCODEPAGE  );
  2393.   AddInstTable(PseudoTable, "CPU",        0,  CodeCPU       );
  2394.   AddInstTable(PseudoTable, "DEPHASE",    0,  CodeDEPHASE   );
  2395.   AddInstTable(PseudoTable, "END",        0,  CodeEND       );
  2396.   AddInstTable(PseudoTable, "ENDEXPECT",  0,  CodeENDEXPECT );
  2397.   AddInstTable(PseudoTable, "ENDS",       0,  CodeENDSTRUCT );
  2398.   AddInstTable(PseudoTable, "ENDSECTION", 0,  CodeENDSECTION);
  2399.   AddInstTable(PseudoTable, "ENDSTRUC",   0,  CodeENDSTRUCT );
  2400.   AddInstTable(PseudoTable, "ENDSTRUCT",  0,  CodeENDSTRUCT );
  2401.   AddInstTable(PseudoTable, "ENDUNION",   1,  CodeENDSTRUCT );
  2402.   AddInstTable(PseudoTable, "ENUM",       0,  CodeENUM      );
  2403.   AddInstTable(PseudoTable, "ENUMCONF",   0,  CodeENUMCONF  );
  2404.   AddInstTable(PseudoTable, "EQU",        0,  CodeSETEQU    );
  2405.   AddInstTable(PseudoTable, "ERROR",      0,  CodeERROR     );
  2406.   AddInstTable(PseudoTable, "EXPECT",     0,  CodeEXPECT    );
  2407.   AddInstTable(PseudoTable, "EXPORT_SYM", 0,  CodeEXPORT    );
  2408.   AddInstTable(PseudoTable, "EXTERN_SYM", 0,  CodeEXTERN    );
  2409.   AddInstTable(PseudoTable, "EVAL",       1,  CodeSETEQU    );
  2410.   AddInstTable(PseudoTable, "FATAL",      0,  CodeFATAL     );
  2411.   AddInstTable(PseudoTable, "FUNCTION",   0,  CodeFUNCTION  );
  2412.   AddInstTable(PseudoTable, "INTSYNTAX",  0,  CodeINTSYNTAX );
  2413.   AddInstTable(PseudoTable, "LABEL",      0,  CodeLABEL     );
  2414.   AddInstTable(PseudoTable, "LISTING",    0,  CodeLISTING   );
  2415.   AddInstTable(PseudoTable, "MESSAGE",    0,  CodeMESSAGE   );
  2416.   AddInstTable(PseudoTable, "NEWPAGE",    0,  CodeNEWPAGE   );
  2417.   AddInstTable(PseudoTable, "NESTMAX",    0,  CodeNESTMAX   );
  2418.   AddInstTable(PseudoTable, "NEXTENUM",   1,  CodeENUM      );
  2419.   AddInstTable(PseudoTable, "ORG",        0,  CodeORG       );
  2420.   AddInstTable(PseudoTable, "OUTRADIX",   1,  CodeRADIX     );
  2421.   AddInstTable(PseudoTable, "PHASE",      0,  CodePHASE     );
  2422.   AddInstTable(PseudoTable, "POPV",       0,  CodePOPV      );
  2423.   AddInstTable(PseudoTable, "PRSET",      0,  CodePRSET     );
  2424.   AddInstTable(PseudoTable, "PRTINIT",    0,  CodeString    );
  2425.   AddInstTable(PseudoTable, "PRTEXIT",    1,  CodeString    );
  2426.   AddInstTable(PseudoTable, "TITLE",      2,  CodeString    );
  2427.   AddInstTable(PseudoTable, "PUSHV",      0,  CodePUSHV     );
  2428.   AddInstTable(PseudoTable, "RADIX",      0,  CodeRADIX     );
  2429.   AddInstTable(PseudoTable, "READ",       0,  CodeREAD      );
  2430.   AddInstTable(PseudoTable, "RELAXED",    0,  CodeRELAXED   );
  2431.   AddInstTable(PseudoTable, "MACEXP",     0x10, CodeMACEXP  );
  2432.   AddInstTable(PseudoTable, "MACEXP_DFT", 0,  CodeMACEXP    );
  2433.   AddInstTable(PseudoTable, "MACEXP_OVR", 1,  CodeMACEXP    );
  2434.   AddInstTable(PseudoTable, "RESTOREENV", 0,  CodeRESTORE   );
  2435.   AddInstTable(PseudoTable, "RORG",       0,  CodeRORG      );
  2436.   AddInstTable(PseudoTable, "RSEG",       0,  CodeSEGTYPE   );
  2437.   AddInstTable(PseudoTable, "SAVEENV",    0,  CodeSAVE      );
  2438.   AddInstTable(PseudoTable, "SECTION",    0,  CodeSECTION   );
  2439.   AddInstTable(PseudoTable, "SEGMENT",    0,  CodeSEGMENT   );
  2440.   AddInstTable(PseudoTable, "SHARED",     0,  CodeSHARED    );
  2441.   AddInstTable(PseudoTable, "STRUC",      0,  CodeSTRUCT    );
  2442.   AddInstTable(PseudoTable, "STRUCT",     0,  CodeSTRUCT    );
  2443.   AddInstTable(PseudoTable, "UNION",      1,  CodeSTRUCT    );
  2444.   AddInstTable(PseudoTable, "WARNING",    0,  CodeWARNING   );
  2445.   AddInstTable(PseudoTable, "=",          0,  CodeSETEQU    );
  2446.   AddInstTable(PseudoTable, ":=",         1,  CodeSETEQU    );
  2447.  
  2448.   /* NOTE: These will only be selected if the current target does
  2449.      NOT use the dot to separate an attribute part.  If it does,
  2450.      the oppart_leading_dot flag gets set and the appropriate
  2451.      rules kick in: */
  2452.  
  2453.   AddInstTable(PseudoTable, ".EQU",        0, CodeSETEQU );
  2454.   AddInstTable(PseudoTable, ".SET",        1, CodeSETEQU );
  2455.   AddInstTable(PseudoTable, ".SAVE",       0, CodeSAVE   );
  2456.   AddInstTable(PseudoTable, ".RESTORE",    0, CodeRESTORE);
  2457.   AddInstTable(PseudoTable, ".PAGE",       0, CodePAGE   );
  2458.  
  2459.   ONOFFTable = CreateInstTable(47);
  2460.   AddONOFF("DOTTEDSTRUCTS", &DottedStructs, DottedStructsName, True);
  2461.  
  2462.   pseudo_inst_fnc_table = inst_fnc_table_create(103);
  2463.   inst_fnc_table_add(pseudo_inst_fnc_table, "SET", True, code_set_cond);
  2464.   inst_fnc_table_add(pseudo_inst_fnc_table, "SAVE", 0, code_save_cond);
  2465.   inst_fnc_table_add(pseudo_inst_fnc_table, "PAGE", 0, code_page_cond);
  2466.   inst_fnc_table_add(pseudo_inst_fnc_table, "PAGESIZE", 0, code_pagesize_cond);
  2467.   inst_fnc_table_add(pseudo_inst_fnc_table, "RESTORE", 0, code_restore_cond);
  2468.   inst_fnc_table_add(pseudo_inst_fnc_table, "FORWARD", 0, code_forward_cond);
  2469.   inst_fnc_table_add(pseudo_inst_fnc_table, "PUBLIC", 0, code_public_cond);
  2470.   inst_fnc_table_add(pseudo_inst_fnc_table, "GLOBAL", 0, code_global_cond);
  2471. }
  2472.