Subversion Repositories pentevo

Rev

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

  1. /* as.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Hauptmodul                                                                */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <setjmp.h>
  15. #include <float.h>
  16. #include <assert.h>
  17.  
  18. #include "version.h"
  19. #include "be_le.h"
  20. #include "bpemu.h"
  21.  
  22. #include "stdhandl.h"
  23. #include "nls.h"
  24. #include "nlmessages.h"
  25. #include "as.rsc"
  26. #ifdef _USE_MSH
  27. # include "as.msh"
  28. #endif
  29. #include "ioerrs.h"
  30. #include "strutil.h"
  31. #include "stringlists.h"
  32. #include "cmdarg.h"
  33. #include "msg_level.h"
  34. #include "asmitree.h"
  35. #include "trees.h"
  36. #include "chunks.h"
  37. #include "console.h"
  38. #include "asminclist.h"
  39. #include "asmfnums.h"
  40. #include "asmdef.h"
  41. #include "cpulist.h"
  42. #include "asmerr.h"
  43. #include "asmsub.h"
  44. #include "asmpars.h"
  45. #include "asmmac.h"
  46. #include "asmstructs.h"
  47. #include "asmif.h"
  48. #include "asmcode.h"
  49. #include "asmlist.h"
  50. #include "asmlabel.h"
  51. #include "asmdebug.h"
  52. #include "asmrelocs.h"
  53. #include "literals.h"
  54. #include "asmallg.h"
  55. #include "onoff_common.h"
  56. #include "codepseudo.h"
  57. #include "as.h"
  58.  
  59. #include "codenone.h"
  60. #include "code68k.h"
  61. #include "code56k.h"
  62. #include "code601.h"
  63. #include "codepalm.h"
  64. #include "codemcore.h"
  65. #include "codexgate.h"
  66. #include "code68.h"
  67. #include "code6805.h"
  68. #include "code6809.h"
  69. #include "code6812.h"
  70. #include "codes12z.h"
  71. #include "code6816.h"
  72. #include "code68rs08.h"
  73. #include "codeh8_3.h"
  74. #include "codeh8_5.h"
  75. #include "code7000.h"
  76. #include "codeko09.h"
  77. #include "code65.h"
  78. #include "codepps4.h"
  79. #include "codeh16.h"
  80. #include "code7700.h"
  81. #include "codehmcs400.h"
  82. #include "code4500.h"
  83. #include "codem16.h"
  84. #include "codem16c.h"
  85. #include "codepdp11.h"
  86. #include "codevax.h"
  87. #include "code4004.h"
  88. #include "code8008.h"
  89. #include "code48.h"
  90. #include "code51.h"
  91. #include "code96.h"
  92. #include "code85.h"
  93. #include "code86.h"
  94. #include "code960.h"
  95. #include "code8x30x.h"
  96. #include "code2650.h"
  97. #include "codexa.h"
  98. #include "codeavr.h"
  99. #include "code29k.h"
  100. #include "code166.h"
  101. #include "codez80.h"
  102. #include "codez8.h"
  103. #include "codez8000.h"
  104. #include "codekcpsm.h"
  105. #include "codekcp3.h"
  106. #include "codemic8.h"
  107. #include "code96c141.h"
  108. #include "code90c141.h"
  109. #include "code87c800.h"
  110. #include "code870c.h"
  111. #include "code47c00.h"
  112. #include "code97c241.h"
  113. #include "code9331.h"
  114. #include "code16c5x.h"
  115. #include "code16c8x.h"
  116. #include "code17c4x.h"
  117. #include "codesx20.h"
  118. #include "codepdk.h"
  119. #include "codest6.h"
  120. #include "codest7.h"
  121. #include "codest9.h"
  122. #include "code6804.h"
  123. #include "code3201x.h"
  124. #include "code3202x.h"
  125. #include "code3203x.h"
  126. #include "code3205x.h"
  127. #include "code3254x.h"
  128. #include "code3206x.h"
  129. #include "code9900.h"
  130. #include "codetms7.h"
  131. #include "code370.h"
  132. #include "codemsp.h"
  133. #include "codetms1.h"
  134. #include "codescmp.h"
  135. #include "codeimp16.h"
  136. #include "code807x.h"
  137. #include "codecop4.h"
  138. #include "codecop8.h"
  139. #include "codesc14xxx.h"
  140. #include "codens32k.h"
  141. #include "codeace.h"
  142. #include "codecp3f.h"
  143. #include "codef8.h"
  144. #include "code78c10.h"
  145. #include "code75xx.h"
  146. #include "code75k0.h"
  147. #include "code78k0.h"
  148. #include "code78k2.h"
  149. #include "code78k3.h"
  150. #include "code78k4.h"
  151. #include "code7720.h"
  152. #include "code77230.h"
  153. #include "codev60.h"
  154. #include "codeuc43.h"
  155. #include "code53c8xx.h"
  156. #include "codefmc8.h"
  157. #include "codefmc16.h"
  158. #include "codemn1610.h"
  159. #include "codemn2610.h"
  160. #include "codeol40.h"
  161. #include "codeol50.h"
  162. #include "code1802.h"
  163. #include "codevector.h"
  164. #include "codexcore.h"
  165. #include "code1750.h"
  166. #include "codekenbak.h"
  167. #include "codecp1600.h"
  168. #include "codenano.h"
  169. #include "code6100.h"
  170. #include "coderx.h"
  171. #include "code61860.h"
  172. #include "code62015.h"
  173. /**          Code21xx};**/
  174.  
  175. static long StartTime, StopTime;
  176. static Boolean GlobErrFlag;
  177. static unsigned MacroNestLevel = 0;
  178.  
  179. /*=== Zeilen einlesen ======================================================*/
  180.  
  181.  
  182. #if 0
  183. # define dbgentry(str) printf("***enter %s\n", str);
  184. # define dbgexit(str) printf("***exit %s\n", str);
  185. #else
  186. # define dbgentry(str) {}
  187. # define dbgexit(str) {}
  188. #endif
  189.  
  190. #define LEAVE goto func_exit
  191.  
  192. static void NULL_Restorer(PInputTag PInp)
  193. {
  194.   UNUSED(PInp);
  195. }
  196.  
  197. static Boolean NULL_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
  198. {
  199.   UNUSED(PInp);
  200.   UNUSED(ActGNUErrors);
  201.  
  202.   if (DestSize)
  203.     *dest = '\0';
  204.   return False;
  205. }
  206.  
  207. static Boolean INCLUDE_Processor(PInputTag PInp, as_dynstr_t *p_dest);
  208.  
  209. static PInputTag GenerateProcessor(void)
  210. {
  211.   PInputTag PInp = (PInputTag)malloc(sizeof(TInputTag));
  212.  
  213.   PInp->IsMacro = False;
  214.   PInp->Next = NULL;
  215.   PInp->First = True;
  216.   PInp->OrigDoLst = DoLst;
  217.   PInp->StartLine = CurrLine;
  218.   PInp->ParCnt = 0; PInp->ParZ = 0;
  219.   InitStringList(&(PInp->Params));
  220.   PInp->LineCnt = PInp->ContLineCnt = 0; PInp->LineZ = 1;
  221.   PInp->Lines = PInp->LineRun = NULL;
  222.   StrCompMkTemp(&PInp->SpecName, PInp->SpecNameStr, sizeof(PInp->SpecNameStr));
  223.   StrCompReset(&PInp->SpecName);
  224.   PInp->AllArgs[0] = '\0';
  225.   PInp->NumArgs[0] = '\0';
  226.   PInp->IsEmpty = False;
  227.   PInp->Buffer = NULL;
  228.   PInp->Datei = NULL;
  229.   PInp->IfLevel = SaveIFs();
  230.   PInp->IncludeLevel = CurrIncludeLevel;
  231.   PInp->Restorer = NULL_Restorer;
  232.   PInp->GetPos = NULL_GetPos;
  233.   PInp->Macro = NULL;
  234.   PInp->SaveAttr[0] = '\0';
  235.   PInp->SaveLabel[0] = '\0';
  236.   PInp->GlobalSymbols = False;
  237.   PInp->UsesNumArgs =
  238.   PInp->UsesAllArgs = False;
  239.  
  240.   /* in case the input tag chain is empty, this must be the master file */
  241.  
  242.   PInp->FromFile = !FirstInputTag || (FirstInputTag->Processor == INCLUDE_Processor);
  243.  
  244.   return PInp;
  245. }
  246.  
  247. static POutputTag GenerateOUTProcessor(SimpProc Processor, tErrorNum OpenErrMsg)
  248. {
  249.   POutputTag POut;
  250.  
  251.   POut = (POutputTag) malloc(sizeof(TOutputTag));
  252.   POut->Processor = Processor;
  253.   POut->NestLevel = 0;
  254.   POut->Tag = NULL;
  255.   POut->Mac = NULL;
  256.   POut->ParamNames = NULL;
  257.   POut->ParamDefVals = NULL;
  258.   POut->PubSect = 0;
  259.   POut->GlobSect = 0;
  260.   POut->DoExport = False;
  261.   POut->DoGlobCopy= False;
  262.   POut->UsesNumArgs =
  263.   POut->UsesAllArgs = False;
  264.   POut->LstMacroExpMod = LstMacroExpModDefault;
  265.   *POut->GName = '\0';
  266.   POut->OpenErrMsg = OpenErrMsg;
  267.  
  268.   return POut;
  269. }
  270.  
  271. /*=========================================================================*/
  272. /* Makroprozessor */
  273.  
  274. /*-------------------------------------------------------------------------*/
  275. /* allgemein gebrauchte Subfunktionen */
  276.  
  277. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  278. /* werden gebraucht, um festzustellen, ob innerhalb eines Makrorumpfes weitere
  279.    Makroschachtelungen auftreten */
  280.  
  281. static Boolean MacroStart(void)
  282. {
  283.   return ((Memo("MACRO")) || (Memo("IRP")) || (Memo("IRPC")) || (Memo("REPT")) || (Memo("WHILE")));
  284. }
  285.  
  286. static Boolean MacroEnd(void)
  287. {
  288.   if (Memo("ENDM"))
  289.   {
  290.     WasMACRO = True;
  291.     return True;
  292.   }
  293.   else
  294.     return False;
  295. }
  296.  
  297. typedef void (*tMacroArgCallback)(Boolean CtrlArg, const tStrComp *pArg, void *pUser);
  298.  
  299. static void ProcessMacroArgs(tMacroArgCallback Callback, void *pUser)
  300. {
  301.   tStrComp *pArg;
  302.   int l;
  303.  
  304.   for (pArg = ArgStr + 1; pArg <= ArgStr + ArgCnt; pArg++)
  305.   {
  306.     l = strlen(pArg->str.p_str);
  307.     if ((l >= 2) && (pArg->str.p_str[0] == '{') && (pArg->str.p_str[l - 1] == '}'))
  308.     {
  309.       tStrComp Arg;
  310.  
  311.       StrCompRefRight(&Arg, pArg, 1);
  312.       StrCompShorten(&Arg, 1);
  313.       Callback(TRUE, &Arg, pUser);
  314.     }
  315.     else
  316.     {
  317.       Callback(FALSE, pArg, pUser);
  318.     }
  319.   }
  320. }
  321.  
  322. /*-------------------------------------------------------------------------*/
  323. /* Dieser Einleseprozessor dient nur dazu, eine fehlerhafte Makrodefinition
  324.   bis zum Ende zu ueberlesen */
  325.  
  326. static void WaitENDM_Processor(void)
  327. {
  328.   POutputTag Tmp;
  329.  
  330.   if (MacroStart())
  331.     FirstOutputTag->NestLevel++;
  332.   else if (MacroEnd())
  333.     FirstOutputTag->NestLevel--;
  334.   if (FirstOutputTag->NestLevel <= -1)
  335.   {
  336.     Tmp = FirstOutputTag;
  337.     FirstOutputTag = Tmp->Next;
  338.     free(Tmp);
  339.   }
  340. }
  341.  
  342. static void AddWaitENDM_Processor(void)
  343. {
  344.   POutputTag Neu;
  345.  
  346.   Neu = GenerateOUTProcessor(WaitENDM_Processor, ErrNum_OpenMacro);
  347.   Neu->Next = FirstOutputTag;
  348.   FirstOutputTag = Neu;
  349. }
  350.  
  351. static Boolean SearchMacroArg(const char *pTest, const char *pComp, Boolean *pErg)
  352. {
  353.   if (!as_strcasecmp(pTest, pComp))
  354.   {
  355.     *pErg = True;
  356.     return True;
  357.   }
  358.   else if ((strlen(pTest) > 2) && !as_strncasecmp(pTest, "NO", 2) && !as_strcasecmp(pTest + 2, pComp))
  359.   {
  360.     *pErg = False;
  361.     return True;
  362.   }
  363.   else
  364.     return False;
  365. }
  366.  
  367. /*!------------------------------------------------------------------------
  368.  * \fn     SearchLstMacroExpArg(const tStrComp *p_arg, tLstMacroExpMod *p_exp_mod)
  369.  * \brief  check macro control argument for listing expansion directives
  370.  * \param  p_arg argument to check
  371.  * \param  p_exp_mod destination to possibly update
  372.  * \return True if this was a listing expansion directive
  373.  * ------------------------------------------------------------------------ */
  374.  
  375. static Boolean SearchLstMacroExpArg(const tStrComp *p_arg, tLstMacroExpMod *p_exp_mod)
  376. {
  377.   tLstMacroExp macro_exp;
  378.   Boolean do_mac_exp;
  379.  
  380.   if (SearchMacroArg(p_arg->str.p_str, "EXPAND", &do_mac_exp))
  381.     macro_exp = eLstMacroExpAll;
  382.   else if (SearchMacroArg(p_arg->str.p_str, "EXPIF", &do_mac_exp))
  383.     macro_exp = eLstMacroExpIf;
  384.   else if (SearchMacroArg(p_arg->str.p_str, "EXPMACRO", &do_mac_exp))
  385.     macro_exp = eLstMacroExpMacro;
  386.   else if (SearchMacroArg(p_arg->str.p_str, "EXPREST", &do_mac_exp))
  387.     macro_exp = eLstMacroExpRest;
  388.   else
  389.     return False;
  390.  
  391.   if (!AddLstMacroExpMod(p_exp_mod, do_mac_exp, macro_exp))
  392.     WrStrErrorPos(ErrNum_TooManyMacExpMod, p_arg);
  393.   return True;
  394. }
  395.  
  396. /*-------------------------------------------------------------------------*/
  397. /* normale Makros */
  398.  
  399. static void ComputeMacroStrings(PInputTag Tag)
  400. {
  401.   StringRecPtr Lauf;
  402.  
  403.   /* recompute # of params */
  404.  
  405.   if (Tag->UsesNumArgs)
  406.     as_snprintf(Tag->NumArgs, sizeof(Tag->NumArgs), Integ32Format, Tag->ParCnt);
  407.  
  408.   /* recompute 'all string' parameter */
  409.  
  410.   if (Tag->UsesAllArgs)
  411.   {
  412.     Tag->AllArgs[0] = '\0';
  413.     Lauf = Tag->Params;
  414.     while (Lauf)
  415.     {
  416.       if (Tag->AllArgs[0] != '\0')
  417.         strmaxcat(Tag->AllArgs, ",", STRINGSIZE);
  418.       strmaxcat(Tag->AllArgs, Lauf->Content, STRINGSIZE);
  419.       Lauf = Lauf->Next;
  420.     }
  421.   }
  422. }
  423.  
  424. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  425. /* Diese Routine leitet die Quellcodezeilen bei der Makrodefinition in den
  426.    Makro-Record um */
  427.  
  428. static void MACRO_OutProcessor(void)
  429. {
  430.   POutputTag Tmp;
  431.   int z;
  432.   StringRecPtr l;
  433.   PMacroRec GMacro;
  434.  
  435.   WasMACRO = True;
  436.  
  437.   /* write preprocessed output to file ? */
  438.  
  439.   if ((MacroOutput) && (FirstOutputTag->DoExport))
  440.   {
  441.     errno = 0;
  442.     fprintf(MacroFile, "%s\n", OneLine.p_str);
  443.     ChkIO(ErrNum_FileWriteError);
  444.   }
  445.  
  446.   /* check for additional nested macros resp. end of definition */
  447.  
  448.   if (MacroStart())
  449.     FirstOutputTag->NestLevel++;
  450.   else if (MacroEnd())
  451.     FirstOutputTag->NestLevel--;
  452.  
  453.   /* still lines to put into the macro body ? */
  454.  
  455.   if (FirstOutputTag->NestLevel != -1)
  456.   {
  457.     as_dynstr_t s;
  458.  
  459.     as_dynstr_ini_clone(&s, &OneLine);
  460.     KillCtrl(s.p_str);
  461.  
  462.     /* compress into tokens */
  463.  
  464.     l = FirstOutputTag->ParamNames;
  465.     for (z = 1; z <= FirstOutputTag->Mac->ParamCount; z++)
  466.     {
  467.       const char *p_param_name = GetStringListNext(&l);
  468.       CompressLine(p_param_name ? p_param_name : "", z, &s, CaseSensitive);
  469.     }
  470.  
  471.     /* reserved argument names are never case-sensitive */
  472.  
  473.     if (HasAttrs)
  474.       CompressLine(AttrName, ArgCntMax + 1, &s, FALSE);
  475.     if (CompressLine(ArgCName, ArgCntMax + 2, &s, FALSE) > 0)
  476.       FirstOutputTag->UsesNumArgs = TRUE;
  477.     if (CompressLine(AllArgName, ArgCntMax + 3, &s, FALSE) > 0)
  478.       FirstOutputTag->UsesAllArgs = TRUE;
  479.     if (FirstOutputTag->Mac->LocIntLabel)
  480.       CompressLine(LabelName, ArgCntMax + 4, &s, FALSE);
  481.  
  482.     AddStringListLast(&(FirstOutputTag->Mac->FirstLine), s.p_str);
  483.     as_dynstr_free(&s);
  484.   }
  485.  
  486.   /* otherwise, finish definition */
  487.  
  488.   if (FirstOutputTag->NestLevel == -1)
  489.   {
  490.     if (IfAsm)
  491.     {
  492.       FirstOutputTag->Mac->UsesNumArgs = FirstOutputTag->UsesNumArgs;
  493.       FirstOutputTag->Mac->UsesAllArgs = FirstOutputTag->UsesAllArgs;
  494.       FirstOutputTag->Mac->ParamNames = FirstOutputTag->ParamNames;
  495.       FirstOutputTag->ParamNames = NULL;
  496.       FirstOutputTag->Mac->ParamDefVals = FirstOutputTag->ParamDefVals;
  497.       FirstOutputTag->ParamDefVals = NULL;
  498.       AddMacro(FirstOutputTag->Mac, FirstOutputTag->PubSect, True);
  499.       if ((FirstOutputTag->DoGlobCopy) && (SectionStack))
  500.       {
  501.         GMacro = (PMacroRec) malloc(sizeof(MacroRec));
  502.         GMacro->Name = as_strdup(FirstOutputTag->GName);
  503.         GMacro->ParamCount = FirstOutputTag->Mac->ParamCount;
  504.         GMacro->FirstLine = DuplicateStringList(FirstOutputTag->Mac->FirstLine);
  505.         GMacro->ParamNames = DuplicateStringList(FirstOutputTag->Mac->ParamNames);
  506.         GMacro->ParamDefVals = DuplicateStringList(FirstOutputTag->Mac->ParamDefVals);
  507.         GMacro->UsesNumArgs = FirstOutputTag->Mac->UsesNumArgs;
  508.         GMacro->UsesAllArgs = FirstOutputTag->Mac->UsesAllArgs;
  509.         AddMacro(GMacro, FirstOutputTag->GlobSect, False);
  510.       }
  511.     }
  512.     else
  513.     {
  514.       ClearMacroRec(&(FirstOutputTag->Mac), TRUE);
  515.     }
  516.  
  517.     Tmp = FirstOutputTag;
  518.     FirstOutputTag = Tmp->Next;
  519.     ClearStringList(&(Tmp->ParamNames));
  520.     ClearStringList(&(Tmp->ParamDefVals));
  521.     free(Tmp);
  522.   }
  523. }
  524.  
  525. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  526. /* Von hier her kommen bei einem Makroaufruf die expandierten Zeilen */
  527.  
  528. Boolean MACRO_Processor(PInputTag PInp, as_dynstr_t *p_dest)
  529. {
  530.   StringRecPtr Lauf;
  531.   int z;
  532.   Boolean Result;
  533.  
  534.   Result = True;
  535.  
  536.   /* run to current line */
  537.  
  538.   Lauf = PInp->Lines;
  539.   for (z = 1; z <= PInp->LineZ - 1; z++)
  540.     Lauf = Lauf->Next;
  541.   as_dynstr_copy_c_str(p_dest, Lauf->Content);
  542.  
  543.   /* process parameters */
  544.  
  545.   Lauf = PInp->Params;
  546.   for (z = 1; z <= PInp->ParCnt; z++)
  547.   {
  548.     ExpandLine(Lauf->Content, z, p_dest);
  549.     Lauf = Lauf->Next;
  550.   }
  551.  
  552.   /* process special parameters */
  553.  
  554.   if (HasAttrs)
  555.     ExpandLine(PInp->SaveAttr, ArgCntMax + 1, p_dest);
  556.   if (PInp->UsesNumArgs)
  557.     ExpandLine(PInp->NumArgs, ArgCntMax + 2, p_dest);
  558.   if (PInp->UsesAllArgs)
  559.     ExpandLine(PInp->AllArgs, ArgCntMax + 3, p_dest);
  560.   if (PInp->Macro->LocIntLabel)
  561.     ExpandLine(PInp->SaveLabel, ArgCntMax + 4, p_dest);
  562.  
  563.   CurrLine = PInp->StartLine;
  564.   InMacroFlag = True;
  565.  
  566.   /* before the first line, start a new local symbol space */
  567.  
  568.   if ((PInp->LineZ == 1) && (!PInp->GlobalSymbols))
  569.     PushLocHandle(PInp->LocHandle);
  570.  
  571.   /* signal the end of the macro */
  572.  
  573.   if (++(PInp->LineZ) > PInp->LineCnt)
  574.     Result = False;
  575.  
  576.   return Result;
  577. }
  578.  
  579. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  580. /* Initialisierung des Makro-Einleseprozesses */
  581.  
  582. static Boolean ReadMacro_SearchSect(char *Test_O, const char *Comp, Boolean *Erg, LongInt *Section)
  583. {
  584.   char *p;
  585.   String Test, Sect;
  586.  
  587.   strmaxcpy(Test, Test_O, STRINGSIZE); KillBlanks(Test);
  588.   p = strchr(Test, ':');
  589.   if (!p)
  590.     *Sect = '\0';
  591.   else
  592.   {
  593.     strmaxcpy(Sect, p + 1, STRINGSIZE);
  594.     *p = '\0';
  595.   }
  596.   if ((strlen(Test) > 2) && (!as_strncasecmp(Test, "NO", 2)) && (!as_strcasecmp(Test + 2, Comp)))
  597.   {
  598.     *Erg = False;
  599.     return True;
  600.   }
  601.   else if (!as_strcasecmp(Test, Comp))
  602.   {
  603.     tStrComp TmpComp;
  604.  
  605.     *Erg = True;
  606.     StrCompMkTemp(&TmpComp, Sect, sizeof(Sect));
  607.     return (IdentifySection(&TmpComp, Section));
  608.   }
  609.   else
  610.     return False;
  611. }
  612.  
  613. typedef struct
  614. {
  615.   String PList;
  616.   POutputTag pOutputTag;
  617.   tLstMacroExpMod LstMacroExpMod;
  618.   Boolean DoPublic, DoIntLabel, GlobalSymbols;
  619.   Boolean ErrFlag;
  620.   int ParamCount;
  621. } tReadMacroContext;
  622.  
  623. static void ExpandPList(String PList, const char *pArg, Boolean CtrlArg)
  624. {
  625.   if (!*PList)
  626.     strmaxcat(PList, ",", STRINGSIZE);
  627.   if (CtrlArg)
  628.     strmaxcat(PList, "{", STRINGSIZE);
  629.   strmaxcat(PList, pArg, STRINGSIZE);
  630.   if (CtrlArg)
  631.     strmaxcat(PList, "}", STRINGSIZE);
  632. }
  633.  
  634. static void ProcessMACROArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
  635. {
  636.   tReadMacroContext *pContext = (tReadMacroContext*)pUser;
  637.  
  638.   if (CtrlArg)
  639.   {
  640.     if (SearchMacroArg(pArg->str.p_str, "EXPORT", &(pContext->pOutputTag->DoExport)));
  641.     else if (SearchMacroArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
  642.     else if (SearchLstMacroExpArg(pArg, &pContext->LstMacroExpMod))
  643.     {
  644.       ExpandPList(pContext->PList, pArg->str.p_str, CtrlArg);
  645.     }
  646.     else if (SearchMacroArg(pArg->str.p_str, "INTLABEL", &pContext->DoIntLabel))
  647.     {
  648.       ExpandPList(pContext->PList, pArg->str.p_str, CtrlArg);
  649.     }
  650.     else if (ReadMacro_SearchSect(pArg->str.p_str, "GLOBAL", &(pContext->pOutputTag->DoGlobCopy), &(pContext->pOutputTag->GlobSect)));
  651.     else if (ReadMacro_SearchSect(pArg->str.p_str, "PUBLIC", &pContext->DoPublic, &(pContext->pOutputTag->PubSect)));
  652.     else
  653.     {
  654.       WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
  655.       pContext->ErrFlag = True;
  656.     }
  657.   }
  658.   else
  659.   {
  660.     char *pDefault;
  661.     tStrComp Arg;
  662.  
  663.     StrCompRefRight(&Arg, pArg, 0);
  664.     ExpandPList(pContext->PList, Arg.str.p_str, CtrlArg);
  665.     pDefault = QuotPos(Arg.str.p_str, '=');
  666.     if (pDefault)
  667.     {
  668.       Arg.Pos.Len = pDefault - Arg.str.p_str;
  669.       *pDefault++ = '\0';
  670.       KillPostBlanksStrComp(&Arg);
  671.       KillPrefBlanksStrComp(&Arg);
  672.     }
  673.     if (!ChkMacSymbName(Arg.str.p_str))
  674.     {
  675.       WrStrErrorPos(ErrNum_InvSymName, &Arg);
  676.       pContext->ErrFlag = True;
  677.     }
  678.     if (!CaseSensitive)
  679.       UpString(Arg.str.p_str);
  680.     AddStringListLast(&(pContext->pOutputTag->ParamNames), Arg.str.p_str);
  681.     AddStringListLast(&(pContext->pOutputTag->ParamDefVals), pDefault ? pDefault : "");
  682.     pContext->ParamCount++;
  683.   }
  684. }
  685.  
  686. static void ReadMacro(void)
  687. {
  688.   PSaveSection RunSection;
  689.   PMacroRec OneMacro;
  690.   tReadMacroContext Context;
  691.   LongInt HSect;
  692.   String macro_name_buf;
  693.   tStrComp macro_name;
  694.   const tStrComp *p_macro_name;
  695.  
  696.   WasMACRO = True;
  697.  
  698.   CodeLen = 0;
  699.   Context.ErrFlag = False;
  700.  
  701.   /* Makronamen pruefen */
  702.   /* Definition nur im ersten Pass */
  703.  
  704.   StrCompMkTemp(&macro_name, macro_name_buf, sizeof(macro_name_buf));
  705.   if (PassNo != 1)
  706.   {
  707.     Context.ErrFlag = True;
  708.     p_macro_name = &LabPart;
  709.   }
  710.   else
  711.   {
  712.     p_macro_name = ExpandStrSymbol(&macro_name, &LabPart, False);
  713.     if (!p_macro_name)
  714.     {
  715.       Context.ErrFlag = True;
  716.       p_macro_name = &LabPart;
  717.     }
  718.     else if (!ChkSymbName(p_macro_name->str.p_str))
  719.     {
  720.       WrStrErrorPos(ErrNum_InvSymName, &LabPart);
  721.       Context.ErrFlag = True;
  722.     }
  723.   }
  724.  
  725.   /* create tag */
  726.  
  727.   Context.pOutputTag = GenerateOUTProcessor(MACRO_OutProcessor, ErrNum_OpenMacro);
  728.   Context.pOutputTag->Next = FirstOutputTag;
  729.  
  730.   /* check arguments, sort out control directives */
  731.  
  732.   Context.LstMacroExpMod = LstMacroExpModDefault;
  733.   Context.DoPublic = False;
  734.   Context.DoIntLabel = False;
  735.   Context.GlobalSymbols = False;
  736.   *Context.PList = '\0';
  737.   Context.ParamCount = 0;
  738.   ProcessMacroArgs(ProcessMACROArgs, &Context);
  739.  
  740.   /* contradicting macro expansion? */
  741.  
  742.   if (!ChkLstMacroExpMod(&Context.LstMacroExpMod))
  743.   {
  744.     WrError(ErrNum_ConflictingMacExpMod);
  745.     Context.ErrFlag = True;
  746.   }
  747.  
  748.   /* Abbruch bei Fehler */
  749.  
  750.   if (Context.ErrFlag)
  751.   {
  752.     ClearStringList(&(Context.pOutputTag->ParamNames));
  753.     ClearStringList(&(Context.pOutputTag->ParamDefVals));
  754.     free(Context.pOutputTag);
  755.     AddWaitENDM_Processor();
  756.     return;
  757.   }
  758.  
  759.   /* Bei Globalisierung Namen des Extramakros ermitteln */
  760.  
  761.   if (Context.pOutputTag->DoGlobCopy)
  762.   {
  763.     strmaxcpy(Context.pOutputTag->GName, MacroName, STRINGSIZE);
  764.     RunSection = SectionStack;
  765.     HSect = MomSectionHandle;
  766.     while ((HSect != Context.pOutputTag->GlobSect) && (RunSection != NULL))
  767.     {
  768.       strmaxprep(Context.pOutputTag->GName, "_", STRINGSIZE);
  769.       strmaxprep(Context.pOutputTag->GName, GetSectionName(HSect), STRINGSIZE);
  770.       HSect = RunSection->Handle;
  771.       RunSection = RunSection->Next;
  772.     }
  773.   }
  774.   if (!Context.DoPublic)
  775.     Context.pOutputTag->PubSect = MomSectionHandle;
  776.  
  777.   /* chain in */
  778.  
  779.   OneMacro = (PMacroRec) calloc(1, sizeof(MacroRec));
  780.   OneMacro->FirstLine =
  781.   OneMacro->ParamNames =
  782.   OneMacro->ParamDefVals = NULL;
  783.   Context.pOutputTag->Mac = OneMacro;
  784.  
  785.   if ((MacroOutput) && (Context.pOutputTag->DoExport))
  786.   {
  787.     errno = 0;
  788.     fprintf(MacroFile, "%s MACRO %s\n",
  789.             Context.pOutputTag->DoGlobCopy ? Context.pOutputTag->GName : MacroName,
  790.             Context.PList);
  791.     ChkIO(ErrNum_FileWriteError);
  792.   }
  793.  
  794.   OneMacro->UseCounter = 0;
  795.   OneMacro->Name = as_strdup(p_macro_name->str.p_str);
  796.   OneMacro->ParamCount = Context.ParamCount;
  797.   OneMacro->FirstLine = NULL;
  798.   OneMacro->LstMacroExpMod = Context.LstMacroExpMod;
  799.   OneMacro->LocIntLabel = Context.DoIntLabel;
  800.   OneMacro->GlobalSymbols = Context.GlobalSymbols;
  801.  
  802.   FirstOutputTag = Context.pOutputTag;
  803. }
  804.  
  805. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  806. /* Beendigung der Expansion eines Makros */
  807.  
  808. static void MACRO_Cleanup(PInputTag PInp)
  809. {
  810.   ClearStringList(&(PInp->Params));
  811. }
  812.  
  813. static Boolean MACRO_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
  814. {
  815.   UNUSED(ActGNUErrors);
  816.   as_snprintf(dest, DestSize, "%s(%lu) ", PInp->SpecName.str.p_str, (unsigned long)(PInp->LineZ - 1));
  817.   return False;
  818. }
  819.  
  820. static void MACRO_Restorer(PInputTag PInp)
  821. {
  822.   /* discard the local symbol space */
  823.  
  824.   if (!PInp->GlobalSymbols)
  825.     PopLocHandle();
  826.  
  827.   /* undo the recursion counter by one */
  828.  
  829.   if ((PInp->Macro) && (PInp->Macro->UseCounter > 0))
  830.     PInp->Macro->UseCounter--;
  831.  
  832.   /* restore list flag */
  833.  
  834.   DoLst = PInp->OrigDoLst;
  835.  
  836.   /* decrement macro nesting counter only if this actually was a macro */
  837.  
  838.   if (PInp->Processor == MACRO_Processor)
  839.     MacroNestLevel--;
  840. }
  841.  
  842. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  843. /* Dies initialisiert eine Makroexpansion */
  844.  
  845. static Boolean ExpandMacro(PMacroRec OneMacro)
  846. {
  847.   int z1, z2;
  848.   StringRecPtr Lauf, pDefault, pParamName, pArg;
  849.   PInputTag Tag = NULL;
  850.   Boolean NamedArgs;
  851.   char *p;
  852.  
  853.   CodeLen = 0;
  854.  
  855.   if ((NestMax > 0) && (OneMacro->UseCounter > NestMax)) WrError(ErrNum_RekMacro);
  856.   else
  857.   {
  858.     OneMacro->UseCounter++;
  859.  
  860.     /* 1. Tag erzeugen */
  861.  
  862.     Tag = GenerateProcessor();
  863.     Tag->Processor = MACRO_Processor;
  864.     Tag->Restorer  = MACRO_Restorer;
  865.     Tag->Cleanup   = MACRO_Cleanup;
  866.     Tag->GetPos    = MACRO_GetPos;
  867.     Tag->Macro     = OneMacro;
  868.     Tag->LocHandle = GetLocHandle();
  869.     Tag->GlobalSymbols = OneMacro->GlobalSymbols;
  870.     Tag->UsesNumArgs = OneMacro->UsesNumArgs;
  871.     Tag->UsesAllArgs = OneMacro->UsesAllArgs;
  872.     strmaxcpy(Tag->SpecName.str.p_str, OneMacro->Name, STRINGSIZE);
  873.     strmaxcpy(Tag->SaveAttr, AttrPart.str.p_str, STRINGSIZE);
  874.     if (OneMacro->LocIntLabel)
  875.       strmaxcpy(Tag->SaveLabel, LabPart.str.p_str, STRINGSIZE);
  876.     Tag->IsMacro   = True;
  877.  
  878.     /* 2. Store special parameters - in the original form.
  879.           Omit this if they aren't used at all in the macro's body. */
  880.  
  881.     Tag->NumArgs[0] = '\0';
  882.     if (Tag->UsesNumArgs)
  883.       as_snprintf(Tag->NumArgs, sizeof(Tag->NumArgs), "%d", ArgCnt);
  884.     Tag->AllArgs[0] = '\0';
  885.     if (Tag->UsesAllArgs)
  886.     {
  887.       for (z1 = 1; z1 <= ArgCnt; z1++)
  888.       {
  889.         if (z1 != 1) strmaxcat(Tag->AllArgs, ",", STRINGSIZE);
  890.         strmaxcat(Tag->AllArgs, ArgStr[z1].str.p_str, STRINGSIZE);
  891.       }
  892.     }
  893.     Tag->ParCnt = OneMacro->ParamCount;
  894.  
  895.     /* 3. generate argument list */
  896.  
  897.     /* 3a. initialize with empty defaults - order is irrelevant at this point: */
  898.  
  899.     for (z1 = OneMacro->ParamCount; z1 >= 1; z1--)
  900.       AddStringListFirst(&(Tag->Params), NULL);
  901.  
  902.     /* 3b. walk over given arguments */
  903.  
  904.     NamedArgs = False;
  905.     for (z1 = 1; z1 <= ArgCnt; z1++)
  906.     {
  907.       if (!CaseSensitive) UpString(ArgStr[z1].str.p_str);
  908.  
  909.       /* explicit name given? */
  910.  
  911.       p = QuotPos(ArgStr[z1].str.p_str, '=');
  912.  
  913.       /* if parameter name given... */
  914.  
  915.       if (p)
  916.       {
  917.         /* split it off */
  918.  
  919.         *p++ = '\0';
  920.         KillPostBlanksStrComp(&ArgStr[z1]);
  921.         KillPrefBlanks(p);
  922.  
  923.         /* search parameter by name */
  924.  
  925.         for (pParamName = OneMacro->ParamNames, pArg = Tag->Params;
  926.              pParamName; pParamName = pParamName->Next, pArg = pArg->Next)
  927.           if (!strcmp(ArgStr[z1].str.p_str, pParamName->Content))
  928.           {
  929.             if (pArg->Content)
  930.             {
  931.               WrXError(ErrNum_MacArgRedef, pParamName->Content);
  932.               free(pArg->Content);
  933.             }
  934.             pArg->Content = as_strdup(p);
  935.             break;
  936.           }
  937.         if (!pParamName)
  938.           WrStrErrorPos(ErrNum_UndefKeyArg, &ArgStr[z1]);
  939.  
  940.         /* set flag that no unnamed args are any longer allowed */
  941.  
  942.         NamedArgs = True;
  943.       }
  944.  
  945.       /* do not mix unnamed with named arguments: */
  946.  
  947.       else if (NamedArgs)
  948.         WrError(ErrNum_NoPosArg);
  949.  
  950.       /* empty positional parameters mean using defaults - insert non-empty args here: */
  951.  
  952.       else if ((z1 <= OneMacro->ParamCount) && (strlen(ArgStr[z1].str.p_str) > 0))
  953.       {
  954.         pArg = Tag->Params;
  955.         pParamName = OneMacro->ParamNames;
  956.         for (z2 = 0; z2 < z1 - 1; z2++)
  957.         {
  958.           pParamName = pParamName->Next;
  959.           pArg = pArg->Next;
  960.         }
  961.         if (pArg->Content)
  962.         {
  963.           WrXError(ErrNum_MacArgRedef, pParamName->Content);
  964.           free(pArg->Content);
  965.         }
  966.         pArg->Content = as_strdup(ArgStr[z1].str.p_str);
  967.       }
  968.  
  969.       /* excess unnamed arguments: append at end of list */
  970.  
  971.       else if (z1 > OneMacro->ParamCount)
  972.         AddStringListLast(&(Tag->Params), ArgStr[z1].str.p_str);
  973.     }
  974.  
  975.     /* 3c. fill in defaults */
  976.  
  977.     for (pParamName = OneMacro->ParamNames, pArg = Tag->Params, pDefault = OneMacro->ParamDefVals;
  978.              pParamName; pParamName = pParamName->Next, pArg = pArg->Next, pDefault = pDefault->Next)
  979.       if (!pArg->Content)
  980.         pArg->Content = as_strdup(pDefault->Content);
  981.  
  982.     /* 4. Zeilenliste anhaengen */
  983.  
  984.     Tag->Lines = OneMacro->FirstLine;
  985.     Tag->IsEmpty = !OneMacro->FirstLine;
  986.     Lauf = OneMacro->FirstLine;
  987.     while (Lauf)
  988.     {
  989.       Tag->LineCnt++;
  990.       Lauf = Lauf->Next;
  991.     }
  992.   }
  993.  
  994.   /* 5. anhaengen */
  995.  
  996.   if (Tag)
  997.   {
  998.     if (IfAsm)
  999.     {
  1000.       /* override has higher prio, so apply as second */
  1001.  
  1002.       NextDoLst = ApplyLstMacroExpMod(DoLst, &OneMacro->LstMacroExpMod);
  1003.       NextDoLst = ApplyLstMacroExpMod(NextDoLst, &LstMacroExpModOverride);
  1004.       Tag->Next = FirstInputTag;
  1005.       FirstInputTag = Tag;
  1006.       MacroNestLevel++;
  1007.       return True;
  1008.     }
  1009.     else
  1010.     {
  1011.       ClearStringList(&(Tag->Params)); free(Tag);
  1012.       return False;
  1013.     }
  1014.   }
  1015.   else
  1016.     return False;
  1017. }
  1018.  
  1019. /*-------------------------------------------------------------------------*/
  1020. /* vorzeitiger Abbruch eines Makros */
  1021.  
  1022. static void ExpandEXITM(void)
  1023. {
  1024.   WasMACRO = True;
  1025.  
  1026.   if (!ChkArgCnt(0, 0));
  1027.   else if (!FirstInputTag) WrError(ErrNum_EXITMOutsideMacro);
  1028.   else if (!FirstInputTag->IsMacro) WrError(ErrNum_EXITMOutsideMacro);
  1029.   else if (IfAsm)
  1030.   {
  1031.     FirstInputTag->Cleanup(FirstInputTag);
  1032.     RestoreIFs(FirstInputTag->IfLevel);
  1033.     FirstInputTag->IsEmpty = True;
  1034.   }
  1035. }
  1036.  
  1037. /*-------------------------------------------------------------------------*/
  1038. /* discard first argument */
  1039.  
  1040. static void ExpandSHIFT(void)
  1041. {
  1042.   PInputTag RunTag;
  1043.  
  1044.   WasMACRO = True;
  1045.  
  1046.   if (!ChkArgCnt(0, 0));
  1047.   else if (!FirstInputTag) WrError(ErrNum_EXITMOutsideMacro);
  1048.   else if (!FirstInputTag->IsMacro) WrError(ErrNum_EXITMOutsideMacro);
  1049.   else if (IfAsm)
  1050.   {
  1051.     for (RunTag = FirstInputTag; RunTag; RunTag = RunTag->Next)
  1052.       if (RunTag->Processor == MACRO_Processor)
  1053.         break;
  1054.  
  1055.     if (RunTag && RunTag->Params)
  1056.     {
  1057.       char *p_arg = MoveAndCutStringListFirst(&RunTag->Params);
  1058.       if (p_arg)
  1059.         free(p_arg);
  1060.       RunTag->ParCnt--;
  1061.       ComputeMacroStrings(RunTag);
  1062.     }
  1063.   }
  1064. }
  1065.  
  1066. /*-------------------------------------------------------------------------*/
  1067. /*--- IRP (was das bei MASM auch immer heissen mag...)
  1068.       Ach ja: Individual Repeat! Danke Bernhard, jetzt hab'
  1069.       ich's gerafft! -----------------------*/
  1070.  
  1071. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1072. /* Diese Routine liefert bei der Expansion eines IRP-Statements die expan-
  1073.   dierten Zeilen */
  1074.  
  1075. Boolean IRP_Processor(PInputTag PInp, as_dynstr_t *p_dest)
  1076. {
  1077.   StringRecPtr Lauf;
  1078.   int z;
  1079.   Boolean Result;
  1080.  
  1081.   Result = True;
  1082.  
  1083.   /* increment line counter only if contents came from a true file */
  1084.  
  1085.   CurrLine = PInp->StartLine;
  1086.   if (PInp->FromFile)
  1087.     CurrLine += PInp->LineZ;
  1088.  
  1089.   /* first line? Then open new symbol space and reset line pointer */
  1090.  
  1091.   if (PInp->LineZ == 1)
  1092.   {
  1093.     if (!PInp->GlobalSymbols)
  1094.     {
  1095.       if (!PInp->First) PopLocHandle();
  1096.       PushLocHandle(GetLocHandle());
  1097.     }
  1098.     PInp->First = False;
  1099.     PInp->LineRun = PInp->Lines;
  1100.   }
  1101.  
  1102.   /* extract line */
  1103.  
  1104.   as_dynstr_copy_c_str(p_dest, PInp->LineRun->Content);
  1105.   PInp->LineRun = PInp->LineRun->Next;
  1106.  
  1107.   /* expand iteration parameter */
  1108.  
  1109.   Lauf = PInp->Params; for (z = 1; z <= PInp->ParZ - 1; z++)
  1110.     Lauf = Lauf->Next;
  1111.   ExpandLine(Lauf->Content, 1, p_dest);
  1112.  
  1113.   /* end of body? then reset to line 1 and exit if this was the last iteration */
  1114.  
  1115.   if (++(PInp->LineZ) > PInp->LineCnt)
  1116.   {
  1117.     PInp->LineZ = 1;
  1118.     if (++(PInp->ParZ) > PInp->ParCnt)
  1119.       Result = False;
  1120.   }
  1121.  
  1122.   return Result;
  1123. }
  1124.  
  1125. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1126. /* Aufraeumroutine IRP/IRPC */
  1127.  
  1128. static void IRP_Cleanup(PInputTag PInp)
  1129. {
  1130.   StringRecPtr Lauf;
  1131.  
  1132.   /* letzten Parameter sichern, wird evtl. noch fuer GetPos gebraucht!
  1133.      ... SaveAttr ist aber frei */
  1134.   if (PInp->Processor == IRP_Processor)
  1135.   {
  1136.     for (Lauf = PInp->Params; Lauf->Next; Lauf = Lauf->Next);
  1137.     strmaxcpy(PInp->SaveAttr, Lauf->Content, STRINGSIZE);
  1138.   }
  1139.  
  1140.   ClearStringList(&(PInp->Lines));
  1141.   ClearStringList(&(PInp->Params));
  1142. }
  1143.  
  1144. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1145. /* Posisionsangabe im IRP(C) fuer Fehlermeldungen */
  1146.  
  1147. static Boolean IRP_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
  1148. {
  1149.   int z, ParZ = PInp->ParZ, LineZ = PInp->LineZ;
  1150.   const char *IRPType;
  1151.   char *IRPVal, tmp[20];
  1152.  
  1153.   UNUSED(ActGNUErrors);
  1154.  
  1155.   /* LineZ/ParZ already hopped to next line - step one back: */
  1156.  
  1157.   if (--LineZ <= 0)
  1158.   {
  1159.     LineZ = PInp->LineCnt;
  1160.     ParZ--;
  1161.   }
  1162.  
  1163.   if (PInp->Processor == IRP_Processor)
  1164.   {
  1165.     IRPType = "IRP";
  1166.     if (*PInp->SaveAttr != '\0')
  1167.       IRPVal = PInp->SaveAttr;
  1168.     else
  1169.     {
  1170.       StringRecPtr Lauf = PInp->Params;
  1171.  
  1172.       for (z = 1; z <= ParZ - 1; z++)
  1173.         Lauf = Lauf->Next;
  1174.       IRPVal = Lauf->Content;
  1175.     }
  1176.   }
  1177.   else
  1178.   {
  1179.     IRPType = "IRPC";
  1180.     as_snprintf(tmp, sizeof(tmp), "'%c'", PInp->SpecName.str.p_str[ParZ - 1]);
  1181.     IRPVal = tmp;
  1182.   }
  1183.  
  1184.   as_snprintf(dest, DestSize, "%s:%s(%lu) ", IRPType, IRPVal, (unsigned long)LineZ);
  1185.  
  1186.   return False;
  1187. }
  1188.  
  1189. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1190. /* Diese Routine sammelt waehrend der Definition eines IRP(C)-Statements die
  1191.   Quellzeilen ein */
  1192.  
  1193. static void IRP_OutProcessor(void)
  1194. {
  1195.   WasMACRO = True;
  1196.  
  1197.   /* Schachtelungen mitzaehlen */
  1198.  
  1199.   if (MacroStart())
  1200.     FirstOutputTag->NestLevel++;
  1201.   else if (MacroEnd())
  1202.     FirstOutputTag->NestLevel--;
  1203.  
  1204.   /* falls noch nicht zuende, weiterzaehlen */
  1205.  
  1206.   if (FirstOutputTag->NestLevel > -1)
  1207.   {
  1208.     as_dynstr_t s;
  1209.     StringRecPtr Dummy;
  1210.     const char *p_first_param = GetStringListFirst(FirstOutputTag->ParamNames, &Dummy);
  1211.  
  1212.     as_dynstr_ini_clone(&s, &OneLine); KillCtrl(s.p_str);
  1213.     CompressLine(p_first_param ? p_first_param : "", 1, &s, CaseSensitive);
  1214.     AddStringListLast(&(FirstOutputTag->Tag->Lines), s.p_str);
  1215.     as_dynstr_free(&s);
  1216.     FirstOutputTag->Tag->LineCnt++;
  1217.   }
  1218.  
  1219.   /* alles zusammen? Dann umhaengen */
  1220.  
  1221.   if (FirstOutputTag->NestLevel == -1)
  1222.   {
  1223.     POutputTag p_this_output_tag = FirstOutputTag;
  1224.     FirstOutputTag = FirstOutputTag->Next;
  1225.     p_this_output_tag->Tag->IsEmpty = !p_this_output_tag->Tag->Lines;
  1226.     if (IfAsm)
  1227.     {
  1228.       NextDoLst = ApplyLstMacroExpMod(DoLst, &p_this_output_tag->LstMacroExpMod);
  1229.       NextDoLst = ApplyLstMacroExpMod(NextDoLst, &LstMacroExpModOverride);
  1230.       p_this_output_tag->Tag->Next = FirstInputTag;
  1231.       FirstInputTag = p_this_output_tag->Tag;
  1232.     }
  1233.     else
  1234.     {
  1235.       ClearStringList(&(p_this_output_tag->Tag->Lines));
  1236.       ClearStringList(&(p_this_output_tag->Tag->Params));
  1237.       free(p_this_output_tag->Tag);
  1238.     }
  1239.     ClearStringList(&(p_this_output_tag->ParamNames));
  1240.     free(p_this_output_tag);
  1241.   }
  1242. }
  1243.  
  1244. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1245. /* Initialisierung der IRP-Bearbeitung */
  1246.  
  1247. typedef struct
  1248. {
  1249.   Boolean ErrFlag;
  1250.   Boolean GlobalSymbols;
  1251.   int ArgCnt;
  1252.   POutputTag pOutputTag;
  1253.   StringList Params;
  1254. } tExpandIRPContext;
  1255.  
  1256. static void ProcessIRPArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
  1257. {
  1258.   tExpandIRPContext *pContext = (tExpandIRPContext*)pUser;
  1259.  
  1260.   if (CtrlArg)
  1261.   {
  1262.     if (SearchMacroArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
  1263.     else if (SearchLstMacroExpArg(pArg, &pContext->pOutputTag->LstMacroExpMod));
  1264.     else
  1265.     {
  1266.       WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
  1267.       pContext->ErrFlag = True;
  1268.     }
  1269.   }
  1270.   else
  1271.   {
  1272.     /* differentiate placeholder & arguments */
  1273.  
  1274.     if (0 == pContext->ArgCnt)
  1275.     {
  1276.       if (!ChkMacSymbName(pArg->str.p_str))
  1277.       {
  1278.         WrStrErrorPos(ErrNum_InvSymName, pArg);
  1279.         pContext->ErrFlag = True;
  1280.       }
  1281.       else
  1282.         AddStringListFirst(&(pContext->pOutputTag->ParamNames), pArg->str.p_str);
  1283.     }
  1284.     else
  1285.     {
  1286.       if (!CaseSensitive)
  1287.         UpString(pArg->str.p_str);
  1288.       AddStringListLast(&(pContext->Params), pArg->str.p_str);
  1289.     }
  1290.     pContext->ArgCnt++;
  1291.   }
  1292. }
  1293.  
  1294. static Boolean ExpandIRP(void)
  1295. {
  1296.   PInputTag Tag;
  1297.   tExpandIRPContext Context;
  1298.  
  1299.   WasMACRO = True;
  1300.  
  1301.   /* 0. terminate if conditional assembly bites */
  1302.  
  1303.   if (!IfAsm)
  1304.   {
  1305.     AddWaitENDM_Processor();
  1306.     return True;
  1307.   }
  1308.  
  1309.   /* 1. Parameter pruefen */
  1310.  
  1311.   Context.ErrFlag = False;
  1312.   Context.GlobalSymbols = False;
  1313.   Context.ArgCnt = 0;
  1314.   Context.Params = NULL;
  1315.  
  1316.   Context.pOutputTag = GenerateOUTProcessor(IRP_OutProcessor, ErrNum_OpenIRP);
  1317.   Context.pOutputTag->Next      = FirstOutputTag;
  1318.   ProcessMacroArgs(ProcessIRPArgs, &Context);
  1319.  
  1320.   /* at least parameter & one arg */
  1321.  
  1322.   if (!ChkArgCntExt(Context.ArgCnt, 2, ArgCntMax))
  1323.     Context.ErrFlag = True;
  1324.   if (Context.ErrFlag)
  1325.   {
  1326.     ClearStringList(&(Context.pOutputTag->ParamNames));
  1327.     ClearStringList(&(Context.pOutputTag->ParamDefVals));
  1328.     ClearStringList(&(Context.Params));
  1329.     free(Context.pOutputTag);
  1330.     AddWaitENDM_Processor();
  1331.     return False;
  1332.   }
  1333.  
  1334.   /* 2. Tag erzeugen */
  1335.  
  1336.   Tag = GenerateProcessor();
  1337.   Tag->ParCnt    = Context.ArgCnt - 1;
  1338.   Tag->Params    = Context.Params;
  1339.   Tag->Processor = IRP_Processor;
  1340.   Tag->Restorer  = MACRO_Restorer;
  1341.   Tag->Cleanup   = IRP_Cleanup;
  1342.   Tag->GetPos    = IRP_GetPos;
  1343.   Tag->GlobalSymbols = Context.GlobalSymbols;
  1344.   Tag->ParZ      = 1;
  1345.   Tag->IsMacro   = True;
  1346.   *Tag->SaveAttr = '\0';
  1347.   Context.pOutputTag->Tag = Tag;
  1348.  
  1349.   /* 4. einbetten */
  1350.  
  1351.   FirstOutputTag = Context.pOutputTag;
  1352.  
  1353.   return True;
  1354. }
  1355.  
  1356. /*--- IRPC: dito fuer Zeichen eines Strings ---------------------------------*/
  1357.  
  1358. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1359. /* Diese Routine liefert bei der Expansion eines IRPC-Statements die expan-
  1360.   dierten Zeilen */
  1361.  
  1362. Boolean IRPC_Processor(PInputTag PInp, as_dynstr_t *p_dest)
  1363. {
  1364.   Boolean Result;
  1365.   char tmp[5];
  1366.  
  1367.   Result = True;
  1368.  
  1369.   /* increment line counter only if contents came from a true file */
  1370.  
  1371.   CurrLine = PInp->StartLine;
  1372.   if (PInp->FromFile)
  1373.     CurrLine += PInp->LineZ;
  1374.  
  1375.   /* first line? Then open new symbol space and reset line pointer */
  1376.  
  1377.   if (PInp->LineZ == 1)
  1378.   {
  1379.     if (!PInp->GlobalSymbols)
  1380.     {
  1381.       if (!PInp->First) PopLocHandle();
  1382.       PushLocHandle(GetLocHandle());
  1383.     }
  1384.     PInp->First = False;
  1385.     PInp->LineRun = PInp->Lines;
  1386.   }
  1387.  
  1388.   /* extract line */
  1389.  
  1390.   as_dynstr_copy_c_str(p_dest, PInp->LineRun->Content);
  1391.   PInp->LineRun = PInp->LineRun->Next;
  1392.  
  1393.   /* extract iteration parameter */
  1394.  
  1395.   *tmp = PInp->SpecName.str.p_str[PInp->ParZ - 1];
  1396.   tmp[1] = '\0';
  1397.   ExpandLine(tmp, 1, p_dest);
  1398.  
  1399.   /* end of body? then reset to line 1 and exit if this was the last iteration */
  1400.  
  1401.   if (++(PInp->LineZ) > PInp->LineCnt)
  1402.   {
  1403.     PInp->LineZ = 1;
  1404.     if (++(PInp->ParZ) > PInp->ParCnt)
  1405.       Result = False;
  1406.   }
  1407.  
  1408.   return Result;
  1409. }
  1410.  
  1411. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  1412. /* Initialisierung der IRPC-Bearbeitung */
  1413.  
  1414. typedef struct
  1415. {
  1416.   Boolean ErrFlag;
  1417.   Boolean GlobalSymbols;
  1418.   int ArgCnt;
  1419.   POutputTag pOutputTag;
  1420.   String ParameterStr;
  1421.   tStrComp Parameter;
  1422. } tExpandIRPCContext;
  1423.  
  1424. static void ProcessIRPCArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
  1425. {
  1426.   tExpandIRPCContext *pContext = (tExpandIRPCContext*)pUser;
  1427.  
  1428.   if (CtrlArg)
  1429.   {
  1430.     if (SearchMacroArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
  1431.     else if (SearchLstMacroExpArg(pArg, &pContext->pOutputTag->LstMacroExpMod));
  1432.     else
  1433.     {
  1434.       WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
  1435.       pContext->ErrFlag = True;
  1436.     }
  1437.   }
  1438.   else
  1439.   {
  1440.     if (0 == pContext->ArgCnt)
  1441.     {
  1442.       if (!ChkMacSymbName(pArg->str.p_str))
  1443.       {
  1444.         WrStrErrorPos(ErrNum_InvSymName, pArg);
  1445.         pContext->ErrFlag = True;
  1446.       }
  1447.       else
  1448.         AddStringListFirst(&(pContext->pOutputTag->ParamNames), pArg->str.p_str);
  1449.     }
  1450.     else
  1451.     {
  1452.       Boolean OK;
  1453.  
  1454.       EvalStrStringExpression(pArg, &OK, pContext->Parameter.str.p_str);
  1455.       pContext->Parameter.Pos = pArg->Pos;
  1456.       if (!OK)
  1457.         pContext->ErrFlag = True;
  1458.     }
  1459.     pContext->ArgCnt++;
  1460.   }
  1461. }
  1462.  
  1463. static Boolean ExpandIRPC(void)
  1464. {
  1465.   PInputTag Tag;
  1466.   tExpandIRPCContext Context;
  1467.  
  1468.   WasMACRO = True;
  1469.  
  1470.   /* 0. terminate if conditinal assembly bites */
  1471.  
  1472.   if (!IfAsm)
  1473.   {
  1474.     AddWaitENDM_Processor();
  1475.     return True;
  1476.   }
  1477.  
  1478.   /* 1.Parameter pruefen */
  1479.  
  1480.   Context.ErrFlag = False;
  1481.   Context.GlobalSymbols = False;
  1482.   Context.ArgCnt = 0;
  1483.   StrCompMkTemp(&Context.Parameter, Context.ParameterStr, sizeof(Context.ParameterStr));
  1484.   StrCompReset(&Context.Parameter);
  1485.  
  1486.   Context.pOutputTag = GenerateOUTProcessor(IRP_OutProcessor, ErrNum_OpenIRPC);
  1487.   Context.pOutputTag->Next = FirstOutputTag;
  1488.   ProcessMacroArgs(ProcessIRPCArgs, &Context);
  1489.  
  1490.   /* parameter & string */
  1491.  
  1492.   if (!ChkArgCntExt(Context.ArgCnt, 2, ArgCntMax))
  1493.     Context.ErrFlag = True;
  1494.   if (Context.ErrFlag)
  1495.   {
  1496.     ClearStringList(&(Context.pOutputTag->ParamNames));
  1497.     AddWaitENDM_Processor();
  1498.     return False;
  1499.   }
  1500.  
  1501.   /* 2. Tag erzeugen */
  1502.  
  1503.   Tag = GenerateProcessor();
  1504.   Tag->ParCnt    = strlen(Context.Parameter.str.p_str);
  1505.   Tag->Processor = IRPC_Processor;
  1506.   Tag->Restorer  = MACRO_Restorer;
  1507.   Tag->Cleanup   = IRP_Cleanup;
  1508.   Tag->GetPos    = IRP_GetPos;
  1509.   Tag->GlobalSymbols = Context.GlobalSymbols;
  1510.   Tag->ParZ      = 1;
  1511.   Tag->IsMacro   = True;
  1512.   *Tag->SaveAttr = '\0';
  1513.   StrCompCopy(&Tag->SpecName, &Context.Parameter);
  1514.  
  1515.   /* 4. einbetten */
  1516.  
  1517.   Context.pOutputTag->Tag = Tag;
  1518.   FirstOutputTag = Context.pOutputTag;
  1519.  
  1520.   return True;
  1521. }
  1522.  
  1523. /*--- Repetition -----------------------------------------------------------*/
  1524.  
  1525. static void REPT_Cleanup(PInputTag PInp)
  1526. {
  1527.   ClearStringList(&(PInp->Lines));
  1528. }
  1529.  
  1530. static Boolean REPT_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
  1531. {
  1532.   int z1 = PInp->ParZ, z2 = PInp->LineZ;
  1533.  
  1534.   UNUSED(ActGNUErrors);
  1535.  
  1536.   if (--z2 <= 0)
  1537.   {
  1538.     z2 = PInp->LineCnt;
  1539.     z1--;
  1540.   }
  1541.   as_snprintf(dest, DestSize, "REPT %lu(%lu)", (unsigned long)z1, (unsigned long)z2);
  1542.   return False;
  1543. }
  1544.  
  1545. Boolean REPT_Processor(PInputTag PInp, as_dynstr_t *p_dest)
  1546. {
  1547.   Boolean Result;
  1548.  
  1549.   Result = True;
  1550.  
  1551.   /* increment line counter only if contents came from a true file */
  1552.  
  1553.   CurrLine = PInp->StartLine;
  1554.   if (PInp->FromFile)
  1555.     CurrLine += PInp->LineZ;
  1556.  
  1557.   /* first line? Then open new symbol space and reset line pointer */
  1558.  
  1559.   if (PInp->LineZ == 1)
  1560.   {
  1561.     if (!PInp->GlobalSymbols)
  1562.     {
  1563.       if (!PInp->First) PopLocHandle();
  1564.       PushLocHandle(GetLocHandle());
  1565.     }
  1566.     PInp->First = False;
  1567.     PInp->LineRun = PInp->Lines;
  1568.   }
  1569.  
  1570.   /* extract line */
  1571.  
  1572.   as_dynstr_copy_c_str(p_dest, PInp->LineRun->Content);
  1573.   PInp->LineRun = PInp->LineRun->Next;
  1574.  
  1575.   /* last line of body? Then increment count and stop if last iteration */
  1576.  
  1577.   if ((++PInp->LineZ) > PInp->LineCnt)
  1578.   {
  1579.     PInp->LineZ = 1;
  1580.     if ((++PInp->ParZ) > PInp->ParCnt)
  1581.       Result = False;
  1582.   }
  1583.  
  1584.   return Result;
  1585. }
  1586.  
  1587. static void REPT_OutProcessor(void)
  1588. {
  1589.   WasMACRO = True;
  1590.  
  1591.   /* Schachtelungen mitzaehlen */
  1592.  
  1593.   if (MacroStart())
  1594.     FirstOutputTag->NestLevel++;
  1595.   else if (MacroEnd())
  1596.     FirstOutputTag->NestLevel--;
  1597.  
  1598.   /* falls noch nicht zuende, weiterzaehlen */
  1599.  
  1600.   if (FirstOutputTag->NestLevel > -1)
  1601.   {
  1602.     AddStringListLast(&(FirstOutputTag->Tag->Lines), OneLine.p_str);
  1603.     FirstOutputTag->Tag->LineCnt++;
  1604.   }
  1605.  
  1606.   /* alles zusammen? Dann umhaengen */
  1607.  
  1608.   if (FirstOutputTag->NestLevel == -1)
  1609.   {
  1610.     POutputTag p_this_output_tag = FirstOutputTag;
  1611.  
  1612.     FirstOutputTag = FirstOutputTag->Next;
  1613.     p_this_output_tag->Tag->IsEmpty = !p_this_output_tag->Tag->Lines;
  1614.     if (IfAsm && (p_this_output_tag->Tag->ParCnt > 0))
  1615.     {
  1616.       NextDoLst = ApplyLstMacroExpMod(DoLst, &p_this_output_tag->LstMacroExpMod);
  1617.       NextDoLst = ApplyLstMacroExpMod(NextDoLst, &LstMacroExpModOverride);
  1618.       p_this_output_tag->Tag->Next = FirstInputTag;
  1619.       FirstInputTag = p_this_output_tag->Tag;
  1620.       p_this_output_tag->Tag = NULL;
  1621.     }
  1622.     else
  1623.     {
  1624.       ClearStringList(&(p_this_output_tag->Tag->Lines));
  1625.       free(p_this_output_tag->Tag);
  1626.     }
  1627.     free(p_this_output_tag);
  1628.   }
  1629. }
  1630.  
  1631. typedef struct
  1632. {
  1633.   Boolean ErrFlag;
  1634.   Boolean GlobalSymbols;
  1635.   tLstMacroExpMod LstMacroExpMod;
  1636.   int ArgCnt;
  1637.   LongInt ReptCount;
  1638. } tExpandREPTContext;
  1639.  
  1640. static void ProcessREPTArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
  1641. {
  1642.   tExpandREPTContext *pContext = (tExpandREPTContext*)pUser;
  1643.  
  1644.   if (CtrlArg)
  1645.   {
  1646.     if (SearchMacroArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
  1647.     else if (SearchLstMacroExpArg(pArg, &pContext->LstMacroExpMod));
  1648.     else
  1649.     {
  1650.       WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
  1651.       pContext->ErrFlag = True;
  1652.     }
  1653.   }
  1654.   else
  1655.   {
  1656.     Boolean ValOK;
  1657.     tSymbolFlags SymbolFlags;
  1658.  
  1659.     pContext->ReptCount = EvalStrIntExpressionWithFlags(pArg, Int32, &ValOK, &SymbolFlags);
  1660.     if (mFirstPassUnknown(SymbolFlags))
  1661.       WrStrErrorPos(ErrNum_FirstPassCalc, pArg);
  1662.     if (!ValOK || mFirstPassUnknown(SymbolFlags))
  1663.       pContext->ErrFlag = True;
  1664.     pContext->ArgCnt++;
  1665.   }
  1666. }
  1667.  
  1668. static Boolean ExpandREPT(void)
  1669. {
  1670.   PInputTag Tag;
  1671.   POutputTag Neu;
  1672.   tExpandREPTContext Context;
  1673.  
  1674.   WasMACRO = True;
  1675.  
  1676.   /* 0. skip everything when conditional assembly is off */
  1677.  
  1678.   if (!IfAsm)
  1679.   {
  1680.     AddWaitENDM_Processor();
  1681.     return True;
  1682.   }
  1683.  
  1684.   /* 1. Repetitionszahl ermitteln */
  1685.  
  1686.   Context.LstMacroExpMod = LstMacroExpModDefault;
  1687.   Context.GlobalSymbols = False;
  1688.   Context.ReptCount = 0;
  1689.   Context.ErrFlag = False;
  1690.   Context.ArgCnt = 0;
  1691.   ProcessMacroArgs(ProcessREPTArgs, &Context);
  1692.  
  1693.   /* rept count must be present only once */
  1694.  
  1695.   if (!ChkArgCntExt(Context.ArgCnt, 1, 1))
  1696.     Context.ErrFlag = True;
  1697.   if (Context.ErrFlag)
  1698.   {
  1699.     AddWaitENDM_Processor();
  1700.     return False;
  1701.   }
  1702.  
  1703.   /* 2. Tag erzeugen */
  1704.  
  1705.   Tag = GenerateProcessor();
  1706.   Tag->ParCnt    = Context.ReptCount;
  1707.   Tag->Processor = REPT_Processor;
  1708.   Tag->Restorer  = MACRO_Restorer;
  1709.   Tag->Cleanup   = REPT_Cleanup;
  1710.   Tag->GetPos    = REPT_GetPos;
  1711.   Tag->GlobalSymbols = Context.GlobalSymbols;
  1712.   Tag->IsMacro   = True;
  1713.   Tag->ParZ      = 1;
  1714.  
  1715.   /* 3. einbetten */
  1716.  
  1717.   Neu = GenerateOUTProcessor(REPT_OutProcessor, ErrNum_OpenREPT);
  1718.   Neu->LstMacroExpMod = Context.LstMacroExpMod;
  1719.   Neu->Next      = FirstOutputTag;
  1720.   Neu->Tag       = Tag;
  1721.   FirstOutputTag = Neu;
  1722.  
  1723.   return True;
  1724. }
  1725.  
  1726. /*- bedingte Wiederholung -------------------------------------------------------*/
  1727.  
  1728. static void WHILE_Cleanup(PInputTag PInp)
  1729. {
  1730.   ClearStringList(&(PInp->Lines));
  1731. }
  1732.  
  1733. static Boolean WHILE_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
  1734. {
  1735.   int z1 = PInp->ParZ, z2 = PInp->LineZ;
  1736.  
  1737.   UNUSED(ActGNUErrors);
  1738.  
  1739.   if (--z2 <= 0)
  1740.   {
  1741.     z2 = PInp->LineCnt;
  1742.     z1--;
  1743.   }
  1744.   as_snprintf(dest, DestSize, "WHILE %lu/%lu", (unsigned long)z1, (unsigned long)z2);
  1745.   return False;
  1746. }
  1747.  
  1748. Boolean WHILE_Processor(PInputTag PInp, as_dynstr_t *p_dest)
  1749. {
  1750.   int z;
  1751.   Boolean OK, Result;
  1752.  
  1753.   /* increment line counter only if this came from a true file */
  1754.  
  1755.   CurrLine = PInp->StartLine;
  1756.   if (PInp->FromFile)
  1757.     CurrLine += PInp->LineZ;
  1758.  
  1759.   /* if this is the first line of the loop body, open a new handle
  1760.      for macro-local symbols and drop the old one if this was not the
  1761.      first pass through the body. */
  1762.  
  1763.   if (PInp->LineZ == 1)
  1764.   {
  1765.     if (!PInp->GlobalSymbols)
  1766.     {
  1767.       if (!PInp->First)
  1768.         PopLocHandle();
  1769.       PushLocHandle(GetLocHandle());
  1770.     }
  1771.     PInp->First = False;
  1772.     PInp->LineRun = PInp->Lines;
  1773.   }
  1774.  
  1775.   /* evaluate condition before first line */
  1776.  
  1777.   if (PInp->LineZ == 1)
  1778.   {
  1779.     z = EvalStrIntExpression(&PInp->SpecName, Int32, &OK);
  1780.     Result = (OK && (z != 0));
  1781.   }
  1782.   else
  1783.     Result = True;
  1784.  
  1785.   if (Result)
  1786.   {
  1787.     /* get line of body */
  1788.  
  1789.     as_dynstr_copy_c_str(p_dest, PInp->LineRun->Content);
  1790.     PInp->LineRun = PInp->LineRun->Next;
  1791.  
  1792.     /* in case this is the last line of the body, reset counters */
  1793.  
  1794.     if ((++PInp->LineZ) > PInp->LineCnt)
  1795.     {
  1796.       PInp->LineZ = 1;
  1797.       PInp->ParZ++;
  1798.     }
  1799.   }
  1800.  
  1801.   /* nasty last line... */
  1802.  
  1803.   else
  1804.     *p_dest->p_str = '\0';
  1805.  
  1806.   return Result;
  1807. }
  1808.  
  1809. static void WHILE_OutProcessor(void)
  1810. {
  1811.   Boolean OK;
  1812.   tSymbolFlags SymbolFlags;
  1813.   LongInt Erg;
  1814.  
  1815.   WasMACRO = True;
  1816.  
  1817.   /* Schachtelungen mitzaehlen */
  1818.  
  1819.   if (MacroStart())
  1820.     FirstOutputTag->NestLevel++;
  1821.   else if (MacroEnd())
  1822.     FirstOutputTag->NestLevel--;
  1823.  
  1824.   /* falls noch nicht zuende, weiterzaehlen */
  1825.  
  1826.   if (FirstOutputTag->NestLevel > -1)
  1827.   {
  1828.     AddStringListLast(&(FirstOutputTag->Tag->Lines), OneLine.p_str);
  1829.     FirstOutputTag->Tag->LineCnt++;
  1830.   }
  1831.  
  1832.   /* alles zusammen? Dann umhaengen */
  1833.  
  1834.   if (FirstOutputTag->NestLevel == -1)
  1835.   {
  1836.     POutputTag p_this_output_tag;
  1837.     p_this_output_tag = FirstOutputTag;
  1838.     FirstOutputTag = FirstOutputTag->Next;
  1839.     p_this_output_tag->Tag->IsEmpty = !p_this_output_tag->Tag->Lines;
  1840.     Erg = EvalStrIntExpressionWithFlags(&p_this_output_tag->Tag->SpecName, Int32, &OK, &SymbolFlags);
  1841.     if (mFirstPassUnknown(SymbolFlags))
  1842.     {
  1843.       WrError(ErrNum_FirstPassCalc);
  1844.       OK = False;
  1845.     }
  1846.     OK = (OK && (Erg != 0));
  1847.     if (IfAsm && OK)
  1848.     {
  1849.       NextDoLst = ApplyLstMacroExpMod(DoLst, &p_this_output_tag->LstMacroExpMod);
  1850.       NextDoLst = ApplyLstMacroExpMod(NextDoLst, &LstMacroExpModOverride);
  1851.       p_this_output_tag->Tag->Next = FirstInputTag;
  1852.       FirstInputTag = p_this_output_tag->Tag;
  1853.     }
  1854.     else
  1855.     {
  1856.       ClearStringList(&(p_this_output_tag->Tag->Lines));
  1857.       free(p_this_output_tag->Tag);
  1858.     }
  1859.     free(p_this_output_tag);
  1860.   }
  1861. }
  1862.  
  1863. typedef struct
  1864. {
  1865.   Boolean ErrFlag;
  1866.   Boolean GlobalSymbols;
  1867.   tLstMacroExpMod LstMacroExpMod;
  1868.   int ArgCnt;
  1869.   String SpecNameStr;
  1870.   tStrComp SpecName;
  1871. } tExpandWHILEContext;
  1872.  
  1873. static void ProcessWHILEArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
  1874. {
  1875.   tExpandWHILEContext *pContext = (tExpandWHILEContext*)pUser;
  1876.  
  1877.   if (CtrlArg)
  1878.   {
  1879.     if (SearchMacroArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
  1880.     else if (SearchLstMacroExpArg(pArg, &pContext->LstMacroExpMod));
  1881.     else
  1882.     {
  1883.       WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
  1884.       pContext->ErrFlag = True;
  1885.     }
  1886.   }
  1887.   else
  1888.   {
  1889.     StrCompCopy(&pContext->SpecName, pArg);
  1890.     pContext->ArgCnt++;
  1891.   }
  1892. }
  1893.  
  1894. static Boolean ExpandWHILE(void)
  1895. {
  1896.   PInputTag Tag;
  1897.   POutputTag Neu;
  1898.   tExpandWHILEContext Context;
  1899.  
  1900.   WasMACRO = True;
  1901.  
  1902.   /* 0. turned off ? */
  1903.  
  1904.   if (!IfAsm)
  1905.   {
  1906.     AddWaitENDM_Processor();
  1907.     return True;
  1908.   }
  1909.  
  1910.   /* 1. Bedingung ermitteln */
  1911.  
  1912.   Context.LstMacroExpMod = LstMacroExpModDefault;
  1913.   Context.GlobalSymbols = False;
  1914.   Context.ErrFlag = False;
  1915.   Context.ArgCnt = 0;
  1916.   StrCompMkTemp(&Context.SpecName, Context.SpecNameStr, sizeof(Context.SpecNameStr));
  1917.   StrCompReset(&Context.SpecName);
  1918.   ProcessMacroArgs(ProcessWHILEArgs, &Context);
  1919.  
  1920.   /* condition must be present only once */
  1921.  
  1922.   if (!ChkArgCntExt(Context.ArgCnt, 1, 1))
  1923.     Context.ErrFlag = True;
  1924.   if (Context.ErrFlag)
  1925.   {
  1926.     AddWaitENDM_Processor();
  1927.     return False;
  1928.   }
  1929.  
  1930.   /* 2. Tag erzeugen */
  1931.  
  1932.   Tag = GenerateProcessor();
  1933.   Tag->Processor = WHILE_Processor;
  1934.   Tag->Restorer  = MACRO_Restorer;
  1935.   Tag->Cleanup   = WHILE_Cleanup;
  1936.   Tag->GetPos    = WHILE_GetPos;
  1937.   Tag->GlobalSymbols = Context.GlobalSymbols;
  1938.   Tag->IsMacro   = True;
  1939.   Tag->ParZ      = 1;
  1940.   StrCompCopy(&Tag->SpecName, &Context.SpecName);
  1941.  
  1942.   /* 3. einbetten */
  1943.  
  1944.   Neu = GenerateOUTProcessor(WHILE_OutProcessor, ErrNum_OpenWHILE);
  1945.   Neu->LstMacroExpMod = Context.LstMacroExpMod;
  1946.   Neu->Next      = FirstOutputTag;
  1947.   Neu->Tag       = Tag;
  1948.   FirstOutputTag = Neu;
  1949.  
  1950.   return True;
  1951. }
  1952.  
  1953. /*--------------------------------------------------------------------------*/
  1954. /* Einziehen von Include-Files */
  1955.  
  1956. static void INCLUDE_Cleanup(PInputTag PInp)
  1957. {
  1958.   fclose(PInp->Datei);
  1959.   free(PInp->Buffer);
  1960.  
  1961.   /* if last line in file was continued, do not forget to add up
  1962.      continuation lines: */
  1963.  
  1964.   LineSum += PInp->LineZ + PInp->ContLineCnt;
  1965.   if ((*LstName != '\0') && (msg_level >= e_msg_level_normal))
  1966.   {
  1967.     String Tmp;
  1968.  
  1969.     as_snprintf(Tmp, sizeof(Tmp), "%s(%lu)", NamePart(CurrFileName), (unsigned long)CurrLine);
  1970.     WrConsoleLine(Tmp, True);
  1971.     fflush(stdout);
  1972.   }
  1973.   if (MakeIncludeList)
  1974.     PopInclude();
  1975.   CurrIncludeLevel = PInp->IncludeLevel;
  1976. }
  1977.  
  1978. static Boolean INCLUDE_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
  1979. {
  1980.   UNUSED(PInp);
  1981.  
  1982.   as_snprintf(dest, DestSize, ActGNUErrors ? "%s:%lu" : "%s(%lu) ", NamePart(PInp->SpecName.str.p_str), (unsigned long)PInp->LineZ);
  1983.   return !GNUErrors;
  1984. }
  1985.  
  1986. Boolean INCLUDE_Processor(PInputTag PInp, as_dynstr_t *p_dest)
  1987. {
  1988.   Boolean Result;
  1989.   int Count = 1;
  1990.  
  1991.   /* add up # of continuation lines from previous source line */
  1992.  
  1993.   if (PInp->ContLineCnt)
  1994.   {
  1995.     CurrLine = (PInp->LineZ += PInp->ContLineCnt);
  1996.     PInp->ContLineCnt = 0;
  1997.   }
  1998.  
  1999.   Result = True;
  2000.  
  2001.   if (feof(PInp->Datei))
  2002.     *p_dest->p_str = '\0';
  2003.   else
  2004.   {
  2005.     Count = ReadLnCont(PInp->Datei, p_dest);
  2006.     /**ChkIO(ErrNum_FileReadError);**/
  2007.   }
  2008.  
  2009.   /* Even if we had continuation lines, only increment line counter
  2010.      by one at this place so the first line's # is the number of the
  2011.      concatenated line: */
  2012.  
  2013.   if (Count > 0)
  2014.   {
  2015.     PInp->LineZ++;
  2016.     CurrLine = PInp->LineZ;
  2017.     PInp->ContLineCnt = Count - 1;
  2018.   }
  2019.   if (feof(PInp->Datei))
  2020.     Result = False;
  2021.  
  2022.   return Result;
  2023. }
  2024.  
  2025. static void INCLUDE_Restorer(PInputTag PInp)
  2026. {
  2027.   CurrLine = PInp->StartLine;
  2028.   strmaxcpy(CurrFileName, PInp->SaveAttr, STRINGSIZE);
  2029.   IncDepth--;
  2030. }
  2031.  
  2032. /*!------------------------------------------------------------------------
  2033.  * \fn     ExpandINCLUDE_Core(const tStrComp *pArg, Boolean SearchPath)
  2034.  * \brief  The actual core code to open a source file for assembly
  2035.  * \param  pArg file's name to open
  2036.  * \param  SearchPath search file in include path?
  2037.  * ------------------------------------------------------------------------ */
  2038.  
  2039. static void ExpandINCLUDE_Core(const tStrComp *pArg, Boolean SearchPath)
  2040. {
  2041.   tStrComp FNameArg;
  2042.   String FNameArgStr;
  2043.   PInputTag Tag;
  2044.  
  2045.   StrCompMkTemp(&FNameArg, FNameArgStr, sizeof(FNameArgStr));
  2046.   INCLUDE_SearchCore(&FNameArg, pArg, SearchPath);
  2047.  
  2048.   /* Tag erzeugen */
  2049.  
  2050.   Tag = GenerateProcessor();
  2051.   Tag->Processor = INCLUDE_Processor;
  2052.   Tag->Restorer  = INCLUDE_Restorer;
  2053.   Tag->Cleanup   = INCLUDE_Cleanup;
  2054.   Tag->GetPos    = INCLUDE_GetPos;
  2055.   Tag->Buffer    = (void *) malloc(BufferArraySize);
  2056.  
  2057.   /* Sicherung alter Daten */
  2058.  
  2059.   Tag->StartLine = CurrLine;
  2060.   strmaxcpy(Tag->SpecName.str.p_str, FNameArg.str.p_str, STRINGSIZE);
  2061.   LineCompReset(&Tag->SpecName.Pos);
  2062.   strmaxcpy(Tag->SaveAttr, CurrFileName, STRINGSIZE);
  2063.  
  2064.   /* Datei oeffnen */
  2065.  
  2066. #ifdef __CYGWIN32__
  2067.   DeCygwinPath(FNameArg.str.p_str);
  2068. #endif
  2069.   Tag->Datei = fopen(FNameArg.str.p_str, "r");
  2070.   if (!Tag->Datei) ChkStrIO(ErrNum_OpeningFile, pArg);
  2071.   setvbuf(Tag->Datei, (char*)Tag->Buffer, _IOFBF, BufferArraySize);
  2072.  
  2073.   /* neu besetzen */
  2074.  
  2075.   strmaxcpy(CurrFileName, FNameArg.str.p_str, STRINGSIZE);
  2076.   Tag->LineZ = 0;
  2077.   AddFile(FNameArg.str.p_str);
  2078.   PushInclude(FNameArg.str.p_str);
  2079.   if (++CurrIncludeLevel > MaxIncludeLevel)
  2080.     WrStrErrorPos(ErrNum_MaxIncLevelExceeded, pArg);
  2081.  
  2082.   /* einhaengen */
  2083.  
  2084.   Tag->Next = FirstInputTag; FirstInputTag = Tag;
  2085. }
  2086.  
  2087. /*!------------------------------------------------------------------------
  2088.  * \fn     ExpandINCLUDE(void)
  2089.  * \brief  Handle INCLUDE statement
  2090.  * ------------------------------------------------------------------------ */
  2091.  
  2092. static void ExpandINCLUDE(void)
  2093. {
  2094.   if (!IfAsm)
  2095.     return;
  2096.  
  2097.   if (!ChkArgCnt(1, 1))
  2098.     return;
  2099.  
  2100.   ExpandINCLUDE_Core(&ArgStr[1], True);
  2101.   NextIncDepth++;
  2102. }
  2103.  
  2104. /*=========================================================================*/
  2105. /* Einlieferung von Zeilen */
  2106.  
  2107. static void GetNextLine(as_dynstr_t *pLine)
  2108. {
  2109.   PInputTag HTag;
  2110.  
  2111.   InMacroFlag = False;
  2112.  
  2113.   while (FirstInputTag && FirstInputTag->IsEmpty)
  2114.   {
  2115.     FirstInputTag->Cleanup(FirstInputTag);
  2116.     FirstInputTag->Restorer(FirstInputTag);
  2117.     HTag = FirstInputTag;
  2118.     FirstInputTag = HTag->Next;
  2119.     free(HTag);
  2120.   }
  2121.  
  2122.   if (!FirstInputTag)
  2123.   {
  2124.     *pLine->p_str = '\0';
  2125.     return;
  2126.   }
  2127.  
  2128.   if (!FirstInputTag->Processor(FirstInputTag, pLine))
  2129.   {
  2130.     FirstInputTag->IsEmpty = True;
  2131.   }
  2132.  
  2133.   MacLineSum++;
  2134. }
  2135.  
  2136. typedef struct
  2137. {
  2138.   char *pStr;
  2139.   size_t AllocLen;
  2140. } tAllocStr;
  2141.  
  2142. static void InitStr(tAllocStr *pStr)
  2143. {
  2144.   pStr->pStr = NULL;
  2145.   pStr->AllocLen = 0;
  2146. }
  2147.  
  2148. static void ReallocStr(tAllocStr *pStr, unsigned NewAllocLen)
  2149. {
  2150.   if (NewAllocLen > pStr->AllocLen)
  2151.   {
  2152.     char *pNewStr;
  2153.  
  2154.     /* round up, and implicitly avoid allocating 4/8 bytes (sizeof pointer)
  2155.        so size check in as_vsnprcatf() does not generate false positive: */
  2156.  
  2157.     NewAllocLen = (NewAllocLen + 15) &~15;
  2158.     pNewStr = pStr->AllocLen
  2159.             ? (char*)realloc(pStr->pStr, NewAllocLen)
  2160.             : (char*)malloc(NewAllocLen);
  2161.  
  2162.     if (pNewStr)
  2163.     {
  2164.       pStr->pStr = pNewStr;
  2165.       pStr->pStr[pStr->AllocLen] = '\0';
  2166.       pStr->AllocLen = NewAllocLen;
  2167.     }
  2168.   }
  2169. }
  2170.  
  2171. char *GetErrorPos(void)
  2172. {
  2173.   String ActPos;
  2174.   PInputTag RunTag;
  2175.   tAllocStr Str;
  2176.   int CurrStrLen, NewLen;
  2177.   Boolean Last;
  2178.  
  2179.   InitStr(&Str);
  2180.   CurrStrLen = 0;
  2181.  
  2182.   /* no file has yet been opened: */
  2183.  
  2184.   if (!FirstInputTag)
  2185.   {
  2186.     const char FixedName[] = "INTERNAL";
  2187.  
  2188.     ReallocStr(&Str, strlen(FixedName) + 1);
  2189.     strmaxcat(Str.pStr, FixedName, Str.AllocLen);
  2190.   }
  2191.  
  2192.   /* for GNU error message style: */
  2193.  
  2194.   else if (GNUErrors)
  2195.   {
  2196.     PInputTag pInnerTag = NULL;
  2197.     const char *pMsg;
  2198.  
  2199.     /* we only honor the include positions.  First, print the upper include layers... */
  2200.  
  2201.     for (RunTag = FirstInputTag; RunTag; RunTag = RunTag->Next)
  2202.       if (RunTag->GetPos == INCLUDE_GetPos)
  2203.       {
  2204.         if (!pInnerTag)
  2205.           pInnerTag = RunTag;
  2206.         else
  2207.         {
  2208.           Last = RunTag->GetPos(RunTag, ActPos, sizeof(ActPos), GNUErrors);
  2209.           if (!Str.AllocLen)
  2210.           {
  2211.             pMsg = getmessage(Num_GNUErrorMsg1);
  2212.             NewLen = strlen(pMsg) + 1 + strlen(ActPos) + 1;
  2213.             ReallocStr(&Str, NewLen);
  2214.             as_snprintf(Str.pStr, Str.AllocLen, "%s %s", pMsg, ActPos);
  2215.             CurrStrLen = NewLen;
  2216.           }
  2217.           else
  2218.           {
  2219.             pMsg = getmessage(Num_GNUErrorMsgN);
  2220.             NewLen = CurrStrLen + 2 + strlen(pMsg) + 1 + strlen(ActPos) + 1;
  2221.             ReallocStr(&Str, NewLen);
  2222.             as_snprcatf(Str.pStr, Str.AllocLen, ",\n%s %s", pMsg, ActPos);
  2223.             CurrStrLen = NewLen;
  2224.           }
  2225.         }
  2226.       }
  2227.  
  2228.     /* ...append something... */
  2229.  
  2230.     if (CurrStrLen > 0)
  2231.     {
  2232.       NewLen = CurrStrLen + 3;
  2233.  
  2234.       ReallocStr(&Str, NewLen);
  2235.       as_snprcatf(Str.pStr, Str.AllocLen, ":\n");
  2236.       CurrStrLen = NewLen;
  2237.     }
  2238.  
  2239.     /* ...then the innermost one */
  2240.  
  2241.     if (pInnerTag)
  2242.     {
  2243.       pInnerTag->GetPos(pInnerTag, ActPos, sizeof(ActPos), GNUErrors);
  2244.       NewLen = CurrStrLen + strlen(ActPos) + 1;
  2245.       ReallocStr(&Str, NewLen);
  2246.       as_snprcatf(Str.pStr, Str.AllocLen, "%s", ActPos);
  2247.       CurrStrLen = NewLen;
  2248.     }
  2249.   }
  2250.  
  2251.   /* otherwise the standard AS position generator: */
  2252.  
  2253.   else
  2254.   {
  2255.     int ThisLen;
  2256.  
  2257.     for (RunTag = FirstInputTag; RunTag; RunTag = RunTag->Next)
  2258.     {
  2259.       Last = RunTag->GetPos(RunTag, ActPos, sizeof(ActPos), GNUErrors);
  2260.       ThisLen = strlen(ActPos);
  2261.       ReallocStr(&Str, NewLen = CurrStrLen + ThisLen + 1);
  2262.       strmaxprep(Str.pStr, ActPos, Str.AllocLen);
  2263.       CurrStrLen = NewLen;
  2264.       if (Last)
  2265.         break;
  2266.     }
  2267.   }
  2268.  
  2269.   return Str.pStr;
  2270. }
  2271.  
  2272. static Boolean InputEnd(void)
  2273. {
  2274.   PInputTag Lauf;
  2275.  
  2276.   Lauf = FirstInputTag;
  2277.   while (Lauf)
  2278.   {
  2279.     if (!Lauf->IsEmpty)
  2280.       return False;
  2281.     Lauf = Lauf->Next;
  2282.   }
  2283.  
  2284.   return True;
  2285. }
  2286.  
  2287. /*=== Eine Quelldatei ( Haupt-oder Includedatei ) bearbeiten ===============*/
  2288.  
  2289. /*--- aus der zerlegten Zeile Code erzeugen --------------------------------*/
  2290.  
  2291. void WriteCode(void)
  2292. {
  2293.   unsigned z;
  2294.  
  2295.   for (z = 0; z < StopfZahl; z++)
  2296.   {
  2297.     switch (ActListGran)
  2298.     {
  2299.       case 4:
  2300.         DAsmCode[CodeLen >> 2] = NOPCode;
  2301.         break;
  2302.       case 2:
  2303.         WAsmCode[CodeLen >> 1] = NOPCode;
  2304.         break;
  2305.       case 1:
  2306.         BAsmCode[CodeLen] = NOPCode;
  2307.         break;
  2308.     }
  2309.     CodeLen += ActListGran/Granularity();
  2310.   }
  2311.  
  2312.   if ((ActPC != StructSeg) && (!ChkPC(PCs[ActPC] + CodeLen - 1)) && (CodeLen != 0))
  2313.   {
  2314.     WrError(ErrNum_AdrOverflow);
  2315.     CodeLen = 0;
  2316.   }
  2317.   else
  2318.   {
  2319.     LargeWord NewPC = PCs[ActPC] + CodeLen;
  2320.  
  2321.     if ((!DontPrint) && (ActPC != StructSeg) && (CodeLen > 0))
  2322.       BookKeeping();
  2323.     if (ActPC == StructSeg)
  2324.     {
  2325.       if ((CodeLen != 0) && (!DontPrint)) WrError(ErrNum_NotInStruct);
  2326.       if (StructStack->StructRec->IsUnion)
  2327.       {
  2328.         BumpStructLength(StructStack->StructRec, CodeLen);
  2329.         CodeLen = 0;
  2330.         NewPC = 0;
  2331.       }
  2332.     }
  2333.     else if (CodeOutput)
  2334.     {
  2335.       PCsUsed[ActPC] = True;
  2336.       if (DontPrint)
  2337.         NewRecord(PCs[ActPC] + CodeLen);
  2338.       else
  2339.         WriteBytes();
  2340.     }
  2341.     PCs[ActPC] = NewPC;
  2342.   }
  2343. }
  2344.  
  2345. static void Produce_Code(void)
  2346. {
  2347.   PMacroRec OneMacro;
  2348.   PStructRec OneStruct;
  2349.   Boolean SearchMacros, Found, IsMacro = False, IsStruct = False, ResetLastLabel = True;
  2350.   tStrComp non_upper_case_op_part;
  2351.   String non_upper_case_op_part_buf;
  2352.   const tStrComp *p_search_op_part;
  2353.  
  2354.   ActListGran = ListGran();
  2355.   WasIF = WasMACRO = False;
  2356.  
  2357.   /* Makrosuche unterdruecken ? */
  2358.  
  2359.   /* We need the OpPart also in a variant not converted to all-uppercase,
  2360.      since structure and macro names may be case sensitive: */
  2361.  
  2362.   StrCompMkTemp(&non_upper_case_op_part, non_upper_case_op_part_buf, sizeof(non_upper_case_op_part_buf));
  2363.   if (*OpPart.str.p_str == '!')
  2364.   {
  2365.     SearchMacros = False;
  2366.     StrCompCutLeft(&OpPart, 1);
  2367.     StrCompCopy(&non_upper_case_op_part, &OpPart);
  2368.   }
  2369.   else
  2370.   {
  2371.     const tStrComp *p_lop_part;
  2372.  
  2373.     SearchMacros = True;
  2374.     p_lop_part = ExpandStrSymbol(&non_upper_case_op_part, &OpPart, False);
  2375.     if (p_lop_part && (p_lop_part != &OpPart))
  2376.       as_dynstr_copy(&OpPart.str, &p_lop_part->str);
  2377.   }
  2378.   NLS_UpString(OpPart.str.p_str);
  2379.   p_search_op_part = CaseSensitive ? &non_upper_case_op_part : &OpPart;
  2380.  
  2381.   /* Prozessor eingehaengt ? */
  2382.  
  2383.   if (FirstOutputTag)
  2384.   {
  2385.     FirstOutputTag->Processor();
  2386.     return;
  2387.   }
  2388.  
  2389.   /* otherwise generate code: check for macro/structs here */
  2390.  
  2391.   IsMacro = (SearchMacros) && (FoundMacro(&OneMacro, p_search_op_part));
  2392.   if (IsMacro)
  2393.     WasMACRO = True;
  2394.   if (!IsMacro)
  2395.     IsStruct = FoundStruct(&OneStruct, p_search_op_part->str.p_str);
  2396.  
  2397.   /* no longer at an address right after a BSR? */
  2398.  
  2399.   if (EProgCounter() != AfterBSRAddr)
  2400.     AfterBSRAddr = 0;
  2401.  
  2402.   /* evtl. voranstehendes Label ablegen */
  2403.  
  2404.   if (IfAsm && (!IsMacro || !OneMacro->LocIntLabel))
  2405.   {
  2406.     if (LabelPresent())
  2407.       LabelHandle(&LabPart, EProgCounter(), False);
  2408.   }
  2409.  
  2410.   Found = False;
  2411.   switch (*OpPart.str.p_str)
  2412.   {
  2413.     case 'I':
  2414.       /* Makroliste ? */
  2415.       Found = True;
  2416.       if (Memo("IRP")) ResetLastLabel = !ExpandIRP();
  2417.       else if (Memo("IRPC")) ResetLastLabel = !ExpandIRPC();
  2418.       else Found = False;
  2419.       break;
  2420.     case 'R':
  2421.       /* Repetition ? */
  2422.       Found = True;
  2423.       if (Memo("REPT")) ResetLastLabel = !ExpandREPT();
  2424.       else Found = False;
  2425.       break;
  2426.     case 'W':
  2427.       /* bedingte Repetition ? */
  2428.       Found = True;
  2429.       if (Memo("WHILE")) ResetLastLabel = !ExpandWHILE();
  2430.       else Found = False;
  2431.       break;
  2432.   }
  2433.  
  2434.   /* bedingte Assemblierung ? */
  2435.  
  2436.   if (!Found)
  2437.     WasIF = Found = CodeIFs();
  2438.  
  2439.   if (!Found)
  2440.     switch (*OpPart.str.p_str)
  2441.     {
  2442.       case 'M':
  2443.         /* Makrodefinition ? */
  2444.         Found = True;
  2445.         if (Memo("MACRO")) ReadMacro();
  2446.         else Found = False;
  2447.         break;
  2448.       case 'E':
  2449.         /* Abbruch Makroexpansion ? */
  2450.         Found = True;
  2451.         if (Memo("EXITM")) ExpandEXITM();
  2452.         else Found = False;
  2453.         break;
  2454.       case 'S':
  2455.         /* shift macro arguments ? */
  2456.         Found = True;
  2457.         if (memo_shift_pseudo() || (ShiftIsOccupied && Memo("SHFT"))) ExpandSHIFT();
  2458.         else Found = False;
  2459.         break;
  2460.       case 'I':
  2461.         /* Includefile? */
  2462.         Found = True;
  2463.         if (Memo("INCLUDE"))
  2464.           ExpandINCLUDE();
  2465.         else
  2466.           Found = False;
  2467.         break;
  2468.     }
  2469.  
  2470.   if (Found);
  2471.  
  2472.   /* Makroaufruf ? */
  2473.  
  2474.   else if (IsMacro)
  2475.   {
  2476.     ResetLastLabel = False;
  2477.     if (IfAsm)
  2478.     {
  2479.       Boolean expanded = ExpandMacro(OneMacro);
  2480.       if ((MacroNestLevel > 1) && (MacroNestLevel < 100))
  2481.         as_snprintf(ListLine, STRINGSIZE, "%*s(MACRO-%u)", MacroNestLevel - 1, "", MacroNestLevel);
  2482.       else
  2483.         strmaxcpy(ListLine, "(MACRO)", STRINGSIZE);
  2484.       if (expanded)
  2485.         as_snprcatf(ListLine, STRINGSIZE, "[%lu]", (unsigned long)FirstInputTag->LocHandle);
  2486.  
  2487.       /* Macro call itself must not appear in expanded output.  However, a label
  2488.          in the same line that is not consumed by the macro must.  In this case,
  2489.          dump the source line with the OpPart (macro's name) muted out. */
  2490.  
  2491.       if (MacProOutput && (LabPart.Pos.StartCol >= 0) && !OneMacro->LocIntLabel)
  2492.         PrintOneLineMuted(MacProFile, OneLine.p_str, &OpPart.Pos, &ArgPart.Pos);
  2493.     }
  2494.   }
  2495.  
  2496.   else
  2497.   {
  2498.     StopfZahl = 0;
  2499.     CodeLen = 0;
  2500.     DontPrint = False;
  2501.  
  2502. #ifdef PROFILE_MEMO
  2503.     NumMemo = 0;
  2504. #endif
  2505.  
  2506.     if (IfAsm)
  2507.     {
  2508.       /* structure declaration ? */
  2509.  
  2510.       if (IsStruct)
  2511.       {
  2512.         ExpandStruct(OneStruct, p_search_op_part->str.p_str);
  2513.         strmaxcpy(ListLine, OneStruct->IsUnion ? "(UNION)" : "(STRUCT)", STRINGSIZE);
  2514.       }
  2515.       else
  2516.       {
  2517.         AttrPartOpSize[0] = AttrPartOpSize[1] = eSymbolSizeUnknown;
  2518.         if (DecodeAttrPart ? DecodeAttrPart() : True)
  2519.         {
  2520.           if (!CodeGlobalPseudo())
  2521.             MakeCode();
  2522.         }
  2523.       }
  2524.       if (MacProOutput && ((*OpPart.str.p_str != '\0') || (*LabPart.str.p_str != '\0') || (*CommPart.str.p_str != '\0')))
  2525.       {
  2526.         errno = 0;
  2527.         fprintf(MacProFile, "%s\n", OneLine.p_str);
  2528.         ChkIO(ErrNum_ListWrError);
  2529.       }
  2530.     }
  2531.  
  2532. #ifdef PROFILE_MEMO
  2533.     NumMemoSum += NumMemo;
  2534.     NumMemoCnt++;
  2535. #endif
  2536.  
  2537.     WriteCode();
  2538.   }
  2539.  
  2540.   /* reset memory about previous label if it is a non-empty instruction */
  2541.  
  2542.   if (*OpPart.str.p_str && ResetLastLabel)
  2543.     LabelReset();
  2544.  
  2545.   /* dies ueberprueft implizit, ob von der letzten Eval...-Operation noch
  2546.      externe Referenzen liegengeblieben sind. */
  2547.  
  2548.   SetRelocs(NULL);
  2549. }
  2550.  
  2551. /*--- Zeile in Listing zerteilen -------------------------------------------*/
  2552.  
  2553. static void adjust_copy_comp(tStrComp *p_comp, const char *p_src, size_t newsz)
  2554. {
  2555.   if (newsz + 1 > p_comp->str.capacity)
  2556.     as_dynstr_realloc(&p_comp->str, as_dynstr_roundup_len(newsz));
  2557.   p_comp->Pos.Len = strmemcpy(p_comp->str.p_str, p_comp->str.capacity, p_src, newsz);
  2558. }
  2559.  
  2560. static void split_arguments(tStrComp *p_args, const char *p_divide_chars)
  2561. {
  2562.   const char *p_div_pos, *p_act_div, *p_act_div_pos, *p_run, *p_end;
  2563.  
  2564.   p_run = p_args->str.p_str;
  2565.   p_end = p_run + strlen(p_run);
  2566.   p_act_div_pos = NULL;
  2567.  
  2568.   /* A separator found in the previous iteration forces another argument,
  2569.      even if it will be empty because the separator is right at the end: */
  2570.  
  2571.   while ((p_run < p_end) || p_act_div_pos)
  2572.   {
  2573.     while (*p_run && as_isspace(*p_run))
  2574.       p_run++;
  2575. #if 0 /* TODO: should work, but doesn't yet */
  2576.     p_div_pos = QuotMultPosFixup(p_run, p_divide_chars, NULL);
  2577.     if (!p_div_pos)
  2578.       p_div_pos = p_end;
  2579. #endif
  2580.     p_div_pos = p_end;
  2581.     for (p_act_div = p_divide_chars; *p_act_div; p_act_div++)
  2582.     {
  2583.       p_act_div_pos = QuotPosQualify(p_run, *p_act_div, QualifyQuote);
  2584.       if (p_act_div_pos && (p_act_div_pos < p_div_pos))
  2585.         p_div_pos = p_act_div_pos;
  2586.     }
  2587.     if (ArgCnt >= ArgCntMax)
  2588.     {
  2589.       WrError(ErrNum_TooManyArgs);
  2590.       break;
  2591.     }
  2592.     AppendArg(p_div_pos - p_run);
  2593.     adjust_copy_comp(&ArgStr[ArgCnt], p_run, p_div_pos - p_run);
  2594.     ArgStr[ArgCnt].Pos.StartCol = p_args->Pos.StartCol + (p_run - p_args->str.p_str);
  2595.     KillPostBlanksStrComp(&ArgStr[ArgCnt]);
  2596.     p_run = (p_div_pos < p_end) ? p_div_pos + 1 : p_end;
  2597.   }
  2598. }
  2599.  
  2600. static void SplitLine(void)
  2601. {
  2602.   const char *pRun, *pEnd, *pPos;
  2603.  
  2604.   Retracted = False;
  2605.  
  2606.   /* run preprocessor */
  2607.  
  2608.   ExpandDefines(OneLine.p_str);
  2609.   pRun = OneLine.p_str;
  2610.   pEnd = pRun + strlen(pRun);
  2611.  
  2612.   /* If comment is present, ignore everything after it: */
  2613.  
  2614.   pPos = QuotSMultPosQualify(pRun, pCommentLeadIn, QualifyQuote);
  2615.   if (pPos)
  2616.   {
  2617.     adjust_copy_comp(&CommPart, pPos, pEnd - pPos);
  2618.     CommPart.Pos.StartCol = pPos - OneLine.p_str;
  2619.     pEnd = pPos;
  2620.   }
  2621.   else
  2622.     StrCompReset(&CommPart);
  2623.  
  2624.   /* Non-blank character in first column is always label: */
  2625.  
  2626.   if ((pRun < pEnd) && *pRun && !as_isspace(*pRun))
  2627.   {
  2628.     for (pPos = pRun; pPos < pEnd; pPos++)
  2629.       if (as_isspace(*pPos) || (*pPos == ':'))
  2630.         break;
  2631.     LabPart.Pos.StartCol = pRun - OneLine.p_str;
  2632.     if (pPos >= pEnd)
  2633.     {
  2634.       LabPart.Pos.Len = strmemcpy(LabPart.str.p_str, STRINGSIZE, pRun, pEnd - pRun);
  2635.       pRun = pEnd;
  2636.     }
  2637.     else
  2638.     {
  2639.       LabPart.Pos.Len = strmemcpy(LabPart.str.p_str, STRINGSIZE, pRun, pPos - pRun);
  2640.       pRun = pPos + 1;
  2641.     }
  2642.     if ((LabPart.Pos.Len > 0) && (LabPart.str.p_str[LabPart.Pos.Len - 1] == ':')) /* needed? */
  2643.       LabPart.str.p_str[--LabPart.Pos.Len] = '\0';
  2644.   }
  2645.   else
  2646.     StrCompReset(&LabPart);
  2647.  
  2648.   /* Opcode & Argument trennen */
  2649.  
  2650.   while (True)
  2651.   {
  2652.     for (; (pRun < pEnd) && as_isspace(*pRun); pRun++);
  2653.     for (pPos = pRun; (pPos < pEnd) && !as_isspace(*pPos); pPos++);
  2654.  
  2655.     /* If potential OpPart starts with argument divider,
  2656.        OpPart is empty and rest of line is all-arguments: */
  2657.  
  2658.     if (strchr(DivideChars, *pRun))
  2659.     {
  2660.       StrCompReset(&OpPart);
  2661.       adjust_copy_comp(&ArgPart, pRun, pEnd - pRun);
  2662.       ArgPart.Pos.StartCol = pRun - OneLine.p_str;
  2663.     }
  2664.     else
  2665.     {
  2666.       /* copy out OpPart */
  2667.  
  2668.       OpPart.Pos.StartCol = pRun - OneLine.p_str;
  2669.       OpPart.Pos.Len = strmemcpy(OpPart.str.p_str, OpPart.str.capacity, pRun, pPos - pRun);
  2670.  
  2671.       /* continue after OpPart separator */
  2672.  
  2673.       pRun = (pPos < pEnd) ? pPos + 1 : pEnd;
  2674.  
  2675.       /* Falls noch kein Label da war, kann es auch ein Label sein */
  2676.  
  2677.       if ((*LabPart.str.p_str == '\0') && OpPart.Pos.Len && (OpPart.str.p_str[OpPart.Pos.Len - 1] == ':'))
  2678.       {
  2679.         OpPart.str.p_str[--OpPart.Pos.Len] = '\0';
  2680.         StrCompCopy(&LabPart, &OpPart);
  2681.         continue; /* -> retry finding opcode */
  2682.       }
  2683.  
  2684.       /* save remainder to ArgPart */
  2685.  
  2686.       adjust_copy_comp(&ArgPart, pRun, pEnd - pRun);
  2687.       ArgPart.Pos.StartCol = pRun - OneLine.p_str;
  2688.     }
  2689.     break;
  2690.   }
  2691.  
  2692.   ArgCnt = 0;
  2693.  
  2694.   /* trailing separator on OpPart means we have to push in another empty argument */
  2695.  
  2696.   if (OpPart.Pos.Len && strchr(DivideChars, OpPart.str.p_str[OpPart.Pos.Len - 1]))
  2697.   {
  2698.     const char EmptyArg[] = "";
  2699.  
  2700.     OpPart.str.p_str[--OpPart.Pos.Len] = '\0';
  2701.     AppendArg(strlen(EmptyArg));
  2702.     strcpy(ArgStr[ArgCnt].str.p_str, EmptyArg);
  2703.     ArgStr[ArgCnt].Pos = ArgPart.Pos;
  2704.   }
  2705.  
  2706.   /* Attribut abspalten */
  2707.  
  2708.   oppart_leading_dot = False;
  2709.   if (HasAttrs)
  2710.   {
  2711.     const char *pActAttrChar;
  2712.     char *pAttrPos, *pActAttrPos;
  2713.     int Tries = 0;
  2714.  
  2715. again:
  2716.     pAttrPos = NULL; AttrSplit = ' ';
  2717.     for (pActAttrChar = AttrChars; *pActAttrChar; pActAttrChar++)
  2718.     {
  2719.       pActAttrPos = strchr(OpPart.str.p_str, *pActAttrChar);
  2720.       if (pActAttrPos && ((!pAttrPos) || (pActAttrPos < pAttrPos)))
  2721.         pAttrPos = pActAttrPos;
  2722.     }
  2723.     if (pAttrPos)
  2724.     {
  2725.       AttrSplit = (*pAttrPos);
  2726.       AttrPart.Pos.StartCol = OpPart.Pos.StartCol + (pAttrPos + 1 - OpPart.str.p_str);
  2727.       AttrPart.Pos.Len = strmemcpy(AttrPart.str.p_str, STRINGSIZE, pAttrPos + 1, strlen(pAttrPos + 1));
  2728.       *pAttrPos = '\0';
  2729.       OpPart.Pos.Len = pAttrPos - OpPart.str.p_str;
  2730.  
  2731.       /* The dot-prefixed OpPart may itself contain an attribute (.instr.attr).  So reiterate
  2732.          splitting off attribute, but only once ;-) */
  2733.  
  2734.       if ((*OpPart.str.p_str == '\0') && (*AttrPart.str.p_str != '\0'))
  2735.       {
  2736.         StrCompCopy(&OpPart, &AttrPart);
  2737.         StrCompReset(&AttrPart);
  2738.         if (!Tries && (AttrSplit == '.'))
  2739.           oppart_leading_dot = True;
  2740.         if (++Tries < 2)
  2741.           goto again;
  2742.       }
  2743.     }
  2744.     else
  2745.       StrCompReset(&AttrPart);
  2746.   }
  2747.   else
  2748.     StrCompReset(&AttrPart);
  2749.  
  2750.   KillPostBlanksStrComp(&ArgPart);
  2751.  
  2752.   /* Argumente zerteilen: */
  2753.  
  2754.   if (*ArgPart.str.p_str)
  2755.     split_arguments(&ArgPart, DivideChars);
  2756. }
  2757.  
  2758. /*------------------------------------------------------------------------*/
  2759.  
  2760. static void ProcessFile(char *pFileName)
  2761. {
  2762.   long NxtTime, ListTime;
  2763.   char *Run;
  2764.   tStrComp FileArg;
  2765.  
  2766.   dbgentry("ProcessFile");
  2767.  
  2768.   *OneLine.p_str = *CurrFileName = '\0';
  2769.   StrCompMkTemp(&FileArg, pFileName, 0);
  2770.   ExpandINCLUDE_Core(&FileArg, False);
  2771.  
  2772.   ListTime = GTime();
  2773.  
  2774.   while (!InputEnd() && !ENDOccured)
  2775.   {
  2776.     /* Zeile lesen */
  2777.  
  2778.     GetNextLine(&OneLine);
  2779.  
  2780.     /* Ergebnisfelder vorinitialisieren */
  2781.  
  2782.     DontPrint = False;
  2783.     CodeLen = 0;
  2784.     *ListLine = '\0';
  2785.  
  2786.     NextDoLst = DoLst;
  2787.     NextIncDepth = IncDepth;
  2788.  
  2789.     for (Run = OneLine.p_str; *Run != '\0'; Run++)
  2790.       if (!as_isspace(*Run))
  2791.         break;
  2792.     if (*Run == '#')
  2793.       Preprocess();
  2794.     else
  2795.     {
  2796.       SplitLine();
  2797.       Produce_Code();
  2798.     }
  2799.  
  2800.     MakeList(OneLine.p_str);
  2801.     DoLst = NextDoLst;
  2802.     IncDepth = NextIncDepth;
  2803.     if (MaxIncDepth < IncDepth)
  2804.       MaxIncDepth = IncDepth;
  2805.  
  2806.     /* Zeilenzaehler */
  2807.  
  2808.     if (msg_level >= e_msg_level_normal)
  2809.     {
  2810.       NxtTime = GTime();
  2811.       if (((!ListToStdout) || ((ListMask&1) == 0)) && (DTime(ListTime, NxtTime) > 50))
  2812.       {
  2813.         String Num;
  2814.         PInputTag p_input_tag;
  2815.  
  2816.         /* search innermost file currently being read, and request its position */
  2817.  
  2818.         for (p_input_tag = FirstInputTag; p_input_tag; p_input_tag = p_input_tag->Next)
  2819.           if (p_input_tag->Processor == INCLUDE_Processor)
  2820.             break;
  2821.         p_input_tag->GetPos(p_input_tag, Num, sizeof(Num), False);
  2822.         WrConsoleLine(Num, False);
  2823.         fflush(stdout);
  2824.         ListTime = NxtTime;
  2825.       }
  2826.     }
  2827.  
  2828.     /* bei Ende Makroprozessor ausraeumen
  2829.        OK - das ist eine Hauruckmethode... */
  2830.  
  2831.     if (ENDOccured)
  2832.       while (FirstInputTag)
  2833.         GetNextLine(&OneLine);
  2834.   }
  2835.  
  2836.   while (FirstInputTag)
  2837.     GetNextLine(&OneLine);
  2838.  
  2839.   /* irgendeine Makrodefinition nicht abgeschlossen ? */
  2840.  
  2841.   if (FirstOutputTag)
  2842.   {
  2843.     WrError(FirstOutputTag->OpenErrMsg);
  2844.   }
  2845.  
  2846.   dbgexit("ProcessFile");
  2847. }
  2848.  
  2849. /****************************************************************************/
  2850.  
  2851. static const char *TWrite_Plur(int n)
  2852. {
  2853.   return (n != 1) ? getmessage(Num_ListPlurName) : "";
  2854. }
  2855.  
  2856. static void TWrite(long DTime, char *dest, size_t DestSize)
  2857. {
  2858.   int h;
  2859.  
  2860.   *dest = '\0';
  2861.   h = DTime / 360000;
  2862.   DTime %= 360000;
  2863.   if (h > 0)
  2864.     as_snprcatf(dest, DestSize, "%d%s%s, ", h, getmessage(Num_ListHourName), TWrite_Plur(h));
  2865.  
  2866.   h = DTime / 6000;
  2867.   DTime %= 6000;
  2868.   if (h > 0)
  2869.     as_snprcatf(dest, DestSize, "%d%s%s, ", h, getmessage(Num_ListMinuName), TWrite_Plur(h));
  2870.  
  2871.   h = DTime / 100;
  2872.   DTime %= 100;
  2873.   as_snprcatf(dest, DestSize, "%d.%02d%s%s", h, (int)DTime, getmessage(Num_ListSecoName), TWrite_Plur(h));
  2874. }
  2875.  
  2876. /*--------------------------------------------------------------------------*/
  2877.  
  2878. static void AssembleFile_InitPass(void)
  2879. {
  2880.   static char DateS[31], TimeS[31];
  2881.   int z;
  2882.   String ArchVal;
  2883.  
  2884.   String TmpCompStr;
  2885.   tStrComp TmpComp;
  2886.   StrCompMkTemp(&TmpComp, TmpCompStr, sizeof(TmpCompStr));
  2887.  
  2888.   dbgentry("AssembleFile_InitPass");
  2889.  
  2890.   FirstInputTag = NULL;
  2891.   FirstOutputTag = NULL;
  2892.  
  2893.   MomLocHandle = -1;
  2894.   LocHandleCnt = 0;
  2895.   SectSymbolCounter = 0;
  2896.  
  2897.   SectionStack = NULL;
  2898.   FirstIfSave = NULL;
  2899.   FirstSaveState = NULL;
  2900.   StructStack =
  2901.   pInnermostNamedStruct = NULL;
  2902.   for (z = 0; z < SegCount; z++)
  2903.     pPhaseStacks[z] = NULL;
  2904.  
  2905.   InitPass();
  2906.   AsmLabelPassInit();
  2907.  
  2908.   ActPC = SegCode;
  2909.   PCs[ActPC] = 0;
  2910.   RelSegs = False;
  2911.   ENDOccured = False;
  2912.   ErrorCount = 0;
  2913.   WarnCount = 0;
  2914.   LineSum = 0;
  2915.   MacLineSum = 0;
  2916.   for (z = 1; z <= StructSeg; z++)
  2917.   {
  2918.     PCsUsed[z] = FALSE;
  2919.     Phases[z] = 0;
  2920.     InitChunk(SegChunks + z);
  2921.   }
  2922.  
  2923.   TransTables =
  2924.   CurrTransTable = (PTransTable) malloc(sizeof(TTransTable));
  2925.   CurrTransTable->Next = NULL;
  2926.   CurrTransTable->Name = as_strdup("STANDARD");
  2927.   CurrTransTable->p_table = as_chartrans_table_new();
  2928.  
  2929.   EnumSegment = SegNone;
  2930.   EnumIncrement = 1;
  2931.   EnumCurrentValue = 0;
  2932.  
  2933.   strmaxcpy(CurrFileName, "INTERNAL", STRINGSIZE);
  2934.   AddFile(CurrFileName);
  2935.   CurrLine = 0;
  2936.  
  2937.   IncDepth = 0;
  2938.   DoLst = eLstMacroExpAll;
  2939.  
  2940.   /* Pseudovariablen initialisieren */
  2941.  
  2942.   ResetSymbolDefines();
  2943.   ResetMacroDefines();
  2944.   ResetStructDefines();
  2945.   strmaxcpy(TmpCompStr, FlagTrueName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, 1, SegNone, True);
  2946.   strmaxcpy(TmpCompStr, FlagFalseName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, 0, SegNone, True);
  2947.   strmaxcpy(TmpCompStr, PiName, sizeof(TmpCompStr)); EnterFloatSymbol(&TmpComp, 4.0 * as_atan(1.0), True);
  2948.  
  2949.   /* Valgrind breaks usage of long doubles on x86.  Limit
  2950.      to double if using it: */
  2951.  
  2952.   strmaxcpy(TmpCompStr, FloatMaxName, sizeof(TmpCompStr));
  2953. #if defined(IEEEFLOAT_10_16_LONG_DOUBLE) || defined (IEEEFLOAT_10_12_LONG_DOUBLE)
  2954.   if (getenv("VALGRIND") && !strcmp(getenv("VALGRIND"), "1"))
  2955.     EnterFloatSymbol(&TmpComp, DBL_MAX, True);
  2956.   else
  2957. #endif
  2958.     EnterFloatSymbol(&TmpComp, AS_FLOAT_MAX, True);
  2959.  
  2960.   strmaxcpy(TmpCompStr, VerName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, VerNo, SegNone, True);
  2961.   as_snprintf(ArchVal, sizeof(ArchVal), "%s-%s", ARCHPRNAME, ARCHSYSNAME);
  2962.   strmaxcpy(TmpCompStr, ArchName, sizeof(TmpCompStr)); EnterStringSymbol(&TmpComp, ArchVal, True);
  2963.   strmaxcpy(TmpCompStr, Has64Name, sizeof(TmpCompStr));
  2964. #ifdef HAS64
  2965.   EnterIntSymbol(&TmpComp, 1, SegNone, True);
  2966. #else
  2967.   EnterIntSymbol(&TmpComp, 0, SegNone, True);
  2968. #endif
  2969.   strmaxcpy(TmpCompStr, CaseSensName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, Ord(CaseSensitive), SegNone, True);
  2970.   if (PassNo == 0)
  2971.   {
  2972.     NLS_CurrDateString(DateS, sizeof(DateS));
  2973.     NLS_CurrTimeString(False, TimeS, sizeof(TimeS));
  2974.   }
  2975.   if (!FindDefSymbol(DateName))
  2976.   {
  2977.     strmaxcpy(TmpCompStr, DateName, sizeof(TmpCompStr));
  2978.     EnterStringSymbol(&TmpComp, DateS, True);
  2979.   }
  2980.   if (!FindDefSymbol(TimeName))
  2981.   {
  2982.     strmaxcpy(TmpCompStr, TimeName, sizeof(TmpCompStr));
  2983.     EnterStringSymbol(&TmpComp, TimeS, True);
  2984.   }
  2985.  
  2986.   if (*DefCPU == '\0')
  2987.     SetCPUByType(0, NULL);
  2988.   else
  2989.   {
  2990.     tStrComp TmpComp2;
  2991.  
  2992.     StrCompMkTemp(&TmpComp2, DefCPU, sizeof(DefCPU));
  2993.     if (!SetCPUByName(&TmpComp2))
  2994.       SetCPUByType(0, NULL);
  2995.   }
  2996.  
  2997.   strmaxcpy(TmpCompStr, ListOnName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, ListOn = 1, SegNone, True);
  2998.   SetLstMacroExp(eLstMacroExpAll);
  2999.   InitLstMacroExpMod(&LstMacroExpModOverride);
  3000.   InitLstMacroExpMod(&LstMacroExpModDefault);
  3001.   SetFlag(&RelaxedMode, RelaxedName, DefRelaxedMode);
  3002.   SetIntConstRelaxedMode(DefRelaxedMode);
  3003.   if (def_int_syntax.p_str && *def_int_syntax.p_str)
  3004.   {
  3005.     tStrComp int_comp;
  3006.  
  3007.     LineCompReset(&int_comp.Pos);
  3008.     as_dynstr_ini_clone(&int_comp.str, &def_int_syntax);
  3009.     split_arguments(&int_comp, ",");
  3010.     CodeINTSYNTAX(0);
  3011.     as_dynstr_free(&int_comp.str);
  3012.   }
  3013.   strmaxcpy(TmpCompStr, NestMaxName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, NestMax = DEF_NESTMAX, SegNone, True);
  3014.   CopyDefSymbols();
  3015.  
  3016.   /* initialize counter for temp symbols here after implicit symbols
  3017.      have been defined, so counter starts at a value as low as possible */
  3018.  
  3019.   InitTmpSymbols();
  3020.  
  3021.   ResetPageCounter();
  3022.  
  3023.   StartAdrPresent = False;
  3024.  
  3025.   AfterBSRAddr = 0;
  3026.  
  3027.   Repass = False;
  3028.   PassNo++;
  3029.  
  3030. #ifdef PROFILE_MEMO
  3031.   NumMemoSum = 0;
  3032.   NumMemoCnt = 0;
  3033. #endif
  3034.  
  3035.   dbgexit("AssembleFile_InitPass");
  3036. }
  3037.  
  3038. static void AssembleFile_ExitPass(void)
  3039. {
  3040.   tSavePhase *pSavePhase;
  3041.   int z;
  3042.  
  3043. #if 0
  3044.   if CurrIncludeLevel)
  3045.     WrXError(ErrNum_InternalError, "open include");
  3046. #endif
  3047.  
  3048.   UnsetCPU();
  3049.   ClearLocStack();
  3050.   ClearStacks();
  3051.   AsmErrPassExit();
  3052.   for (z = 0; z < SegCount; z++)
  3053.     while (pPhaseStacks[z])
  3054.     {
  3055.       pSavePhase = pPhaseStacks[z];
  3056.       pPhaseStacks[z] = pSavePhase->pNext;
  3057.       free(pSavePhase);
  3058.     }
  3059.   if (FirstIfSave)
  3060.     WrError(ErrNum_MissEndif);
  3061.   if (FirstSaveState)
  3062.     WrError(ErrNum_NoRestoreFrame);
  3063.   if (SectionStack)
  3064.     WrError(ErrNum_MissingEndSect);
  3065.   if (StructStack)
  3066.     WrXError(ErrNum_OpenStruct, StructStack->Name);
  3067. }
  3068.  
  3069. static void AssembleFile_WrSummary(const char *pStr)
  3070. {
  3071.   if (msg_level >= e_msg_level_normal)
  3072.     WrConsoleLine(pStr, True);
  3073.   if (ListMode == 2)
  3074.     WrLstLine(pStr);
  3075. }
  3076.  
  3077. static void AssembleFile(char *Name)
  3078. {
  3079.   char *p_out_name;
  3080.   String s, Tmp;
  3081.  
  3082.   dbgentry("AssembleFile");
  3083.  
  3084.   strmaxcpy(SourceFile, Name, STRINGSIZE);
  3085.   if (MakeDebug)
  3086.     fprintf(Debug, "File %s\n", SourceFile);
  3087.  
  3088.   /* Untermodule initialisieren */
  3089.  
  3090.   AsmDefInit();
  3091.   AsmParsInit();
  3092.   AsmIFInit();
  3093.   InitFileList();
  3094.   ResetStack();
  3095.  
  3096.   /* Kommandozeilenoptionen verarbeiten */
  3097.  
  3098.   p_out_name = MoveFromOutListFirst();
  3099.   strmaxcpy(OutName, p_out_name ? p_out_name : "", STRINGSIZE);
  3100.   free(p_out_name);
  3101.   if (OutName[0] == '\0')
  3102.   {
  3103.     strmaxcpy(OutName, SourceFile, STRINGSIZE);
  3104.     KillSuffix(OutName);
  3105.     AddSuffix(OutName, PrgSuffix);
  3106.   }
  3107.  
  3108.   if (*ErrorPath == '\0')
  3109.   {
  3110.     strmaxcpy(ErrorName, SourceFile, STRINGSIZE);
  3111.     KillSuffix(ErrorName);
  3112.     AddSuffix(ErrorName, LogSuffix);
  3113.     unlink(ErrorName);
  3114.   }
  3115.  
  3116.   switch (ListMode)
  3117.   {
  3118.     case 0:
  3119.       strmaxcpy(LstName, NULLDEV, STRINGSIZE);
  3120.       break;
  3121.     case 1:
  3122.       strmaxcpy(LstName, "!1", STRINGSIZE);
  3123.       break;
  3124.     case 2:
  3125.     {
  3126.       char *p_lst_name = MoveFromListOutListFirst();
  3127.  
  3128.       strmaxcpy(LstName, p_lst_name ? p_lst_name : "", STRINGSIZE);
  3129.       if (p_lst_name) free(p_lst_name);
  3130.       if (*LstName == '\0')
  3131.       {
  3132.         strmaxcpy(LstName, SourceFile, STRINGSIZE);
  3133.         KillSuffix(LstName);
  3134.         AddSuffix(LstName, LstSuffix);
  3135.       }
  3136.       break;
  3137.     }
  3138.   }
  3139.   ListToStdout = !strcmp(LstName, "!1");
  3140.   ListToNull = !strcmp(LstName, NULLDEV);
  3141.  
  3142.   if (ShareMode != 0)
  3143.   {
  3144.     char *p_share_name = MoveFromShareOutListFirst();
  3145.  
  3146.     strmaxcpy(ShareName, p_share_name ? p_share_name : "", STRINGSIZE);
  3147.     if (p_share_name)
  3148.       free(p_share_name);
  3149.     if (*ShareName == '\0')
  3150.     {
  3151.       strmaxcpy(ShareName, SourceFile, STRINGSIZE);
  3152.       KillSuffix(ShareName);
  3153.       switch (ShareMode)
  3154.       {
  3155.         case 1:
  3156.           AddSuffix(ShareName, ".inc");
  3157.           break;
  3158.         case 2:
  3159.           AddSuffix(ShareName, ".h");
  3160.           break;
  3161.         case 3:
  3162.           AddSuffix(ShareName, IncSuffix);
  3163.           break;
  3164.       }
  3165.     }
  3166.   }
  3167.  
  3168.   if (MacProOutput)
  3169.   {
  3170.     strmaxcpy(MacProName, SourceFile, STRINGSIZE);
  3171.     KillSuffix(MacProName);
  3172.     AddSuffix(MacProName, PreSuffix);
  3173.   }
  3174.  
  3175.   if (MacroOutput)
  3176.   {
  3177.     strmaxcpy(MacroName, SourceFile, STRINGSIZE);
  3178.     KillSuffix(MacroName);
  3179.     AddSuffix(MacroName, MacSuffix);
  3180.   }
  3181.  
  3182.   ClearIncludeList();
  3183.   CurrIncludeLevel = 0;
  3184.  
  3185.   if (DebugMode != DebugNone)
  3186.     InitLineInfo();
  3187.  
  3188.   /* Variablen initialisieren */
  3189.  
  3190.   StartTime = GTime();
  3191.  
  3192.   PassNo = 0;
  3193.  
  3194.   /* Listdatei eroeffnen */
  3195.  
  3196.   if (msg_level >= e_msg_level_normal)
  3197.     printf("%s%s\n", getmessage(Num_InfoMessAssembling), SourceFile);
  3198.  
  3199.   /* Maximum include level survives re-passing, so it can be
  3200.      used for the listing to format to the right max. depth from
  3201.      the beginning: */
  3202.  
  3203.   MaxIncDepth = 0;
  3204.  
  3205.   do
  3206.   {
  3207.     /* Durchlauf initialisieren */
  3208.  
  3209.     AssembleFile_InitPass();
  3210.     AsmSubPassInit();
  3211.     AsmErrPassInit();
  3212.     if (msg_level >= e_msg_level_normal)
  3213.     {
  3214.       as_snprintf(Tmp, sizeof(Tmp), "%s", getmessage(Num_InfoMessPass));
  3215.       as_snprcatf(Tmp, sizeof(Tmp), IntegerFormat, PassNo);
  3216.       WrConsoleLine(Tmp, True);
  3217.     }
  3218.  
  3219.     /* Dateien oeffnen */
  3220.  
  3221.     if (CodeOutput)
  3222.       OpenFile();
  3223.  
  3224.     if (ShareMode != 0)
  3225.     {
  3226.       ShareFile = fopen(ShareName, "w");
  3227.       if (!ShareFile)
  3228.         ChkXIO(ErrNum_OpeningFile, ShareName);
  3229.       errno = 0;
  3230.       switch (ShareMode)
  3231.       {
  3232.         case 1:
  3233.           fprintf(ShareFile, "(* %s-Include File for CONST Section *)\n", SourceFile);
  3234.           break;
  3235.         case 2:
  3236.           fprintf(ShareFile, "/* %s-Include File for C Program */\n", SourceFile);
  3237.           break;
  3238.         case 3:
  3239.           fprintf(ShareFile, "; %s-Include File for Assembler Program\n", SourceFile);
  3240.           break;
  3241.       }
  3242.       ChkIO(ErrNum_ListWrError);
  3243.     }
  3244.  
  3245.     if (MacProOutput)
  3246.     {
  3247.       MacProFile = fopen(MacProName, "w");
  3248.       if (!MacProFile)
  3249.         ChkXIO(ErrNum_OpeningFile, MacProName);
  3250.     }
  3251.  
  3252.     if ((MacroOutput) && (PassNo == 1))
  3253.     {
  3254.       MacroFile = fopen(MacroName, "w");
  3255.       if (!MacroFile)
  3256.         ChkXIO(ErrNum_OpeningFile, MacroName);
  3257.     }
  3258.  
  3259.     /* Listdatei oeffnen */
  3260.  
  3261.     OpenWithStandard(&LstFile, LstName);
  3262.     if (!LstFile)
  3263.       ChkXIO(ErrNum_OpeningFile, LstName);
  3264.     if (!ListToNull)
  3265.     {
  3266.       errno = 0;
  3267.       fprintf(LstFile, "%s", PrtInitString);
  3268.       ChkIO(ErrNum_ListWrError);
  3269.     }
  3270.     if ((ListMask & 1) != 0)
  3271.       NewPage(0, False);
  3272.  
  3273.     /* assemblieren */
  3274.  
  3275.     ProcessFile(SourceFile);
  3276.     AssembleFile_ExitPass();
  3277.  
  3278.     /* Dateien schliessen */
  3279.  
  3280.     if (CodeOutput)
  3281.       CloseFile();
  3282.  
  3283.     if (ShareMode != 0)
  3284.     {
  3285.       errno = 0;
  3286.       switch (ShareMode)
  3287.       {
  3288.         case 1:
  3289.           fprintf(ShareFile, "(* Ende Include File for CONST Section *)\n");
  3290.           break;
  3291.         case 2:
  3292.           fprintf(ShareFile, "/* Ende Include File for C Program */\n");
  3293.           break;
  3294.         case 3:
  3295.           fprintf(ShareFile, "; Ende Include File for Assembler Program\n");
  3296.           break;
  3297.       }
  3298.       ChkIO(ErrNum_ListWrError);
  3299.       CloseIfOpen(&ShareFile);
  3300.     }
  3301.  
  3302.     if (MacProOutput)
  3303.       CloseIfOpen(&MacProFile);
  3304.     if (MacroOutput && (PassNo == 1))
  3305.       CloseIfOpen(&MacroFile);
  3306.  
  3307.     /* evtl. fuer naechsten Durchlauf aufraeumen */
  3308.  
  3309.     if ((ErrorCount == 0) && (Repass))
  3310.     {
  3311.       CloseIfOpen(&LstFile);
  3312.       if (CodeOutput)
  3313.         unlink(OutName);
  3314.       ClearCodepages();
  3315.       if (MakeUseList)
  3316.         ClearUseList();
  3317.       if (MakeCrossList)
  3318.         ClearCrossList();
  3319.       ClearDefineList();
  3320.       if (DebugMode != DebugNone)
  3321.         ClearLineInfo();
  3322.       ClearIncludeList();
  3323.       if (DebugMode != DebugNone)
  3324.       {
  3325.         ResetAddressRanges();
  3326.         ClearSectionUsage();
  3327.       }
  3328.     }
  3329.   }
  3330.   while ((ErrorCount == 0) && (Repass));
  3331.  
  3332.   /* bei Fehlern loeschen */
  3333.  
  3334.   if (ErrorCount != 0)
  3335.   {
  3336.     if (CodeOutput)
  3337.       unlink(OutName);
  3338.     if (MacProOutput)
  3339.       unlink(MacProName);
  3340.     if ((MacroOutput) && (PassNo == 1))
  3341.       unlink(MacroName);
  3342.     if (ShareMode != 0)
  3343.       unlink(ShareName);
  3344.     GlobErrFlag = True;
  3345.   }
  3346.  
  3347.   /* Debug-Ausgabe muss VOR die Symbollistenausgabe, weil letztere die
  3348.      Symbolliste loescht */
  3349.  
  3350.   if (DebugMode != DebugNone)
  3351.   {
  3352.     if (ErrorCount == 0)
  3353.       DumpDebugInfo();
  3354.     ClearLineInfo();
  3355.   }
  3356.  
  3357.   /* Listdatei abschliessen */
  3358.  
  3359.   if  (strcmp(LstName, NULLDEV))
  3360.   {
  3361.     if (ListMask & 2)
  3362.       PrintSymbolList();
  3363.  
  3364.     if (ListMask & 64)
  3365.       PrintRegDefs();
  3366.  
  3367.     if (ListMask & 4)
  3368.       PrintMacroList();
  3369.  
  3370.     if (ListMask & 256)
  3371.       PrintStructList();
  3372.  
  3373.     if (ListMask & 8)
  3374.       PrintFunctionList();
  3375.  
  3376.     if (ListMask & 32)
  3377.       PrintDefineList();
  3378.  
  3379.     if (ListMask & 128)
  3380.       PrintCodepages();
  3381.  
  3382.     if (MakeUseList)
  3383.     {
  3384.       NewPage(ChapDepth, True);
  3385.       PrintUseList();
  3386.     }
  3387.  
  3388.     if (MakeCrossList)
  3389.     {
  3390.       NewPage(ChapDepth, True);
  3391.       PrintCrossList();
  3392.     }
  3393.  
  3394.     if (MakeSectionList)
  3395.       PrintSectionList();
  3396.  
  3397.     if (MakeIncludeList)
  3398.       PrintIncludeList();
  3399.  
  3400.     if (!ListToNull)
  3401.     {
  3402.       errno = 0;
  3403.       fprintf(LstFile, "%s", PrtExitString);
  3404.       ChkIO(ErrNum_ListWrError);
  3405.     }
  3406.   }
  3407.  
  3408.   if (MakeUseList)
  3409.     ClearUseList();
  3410.  
  3411.   if (MakeCrossList)
  3412.     ClearCrossList();
  3413.  
  3414.   ClearSectionList();
  3415.  
  3416.   ClearIncludeList();
  3417.  
  3418.   if (!*ErrorPath)
  3419.     CloseIfOpen(&ErrorFile);
  3420.  
  3421.   ClearUp();
  3422.  
  3423.   /* Statistik ausgeben */
  3424.  
  3425.   StopTime = GTime();
  3426.   TWrite(DTime(StartTime, StopTime), s, sizeof(s));
  3427.   strmaxcat(s, getmessage(Num_InfoMessAssTime), STRINGSIZE);
  3428.   if (msg_level >= e_msg_level_normal)
  3429.   {
  3430.     WrConsoleLine("", True);
  3431.     WrConsoleLine(s, True);
  3432.     WrConsoleLine("", True);
  3433.   }
  3434.   if (ListMode == 2)
  3435.   {
  3436.     WrLstLine("");
  3437.     WrLstLine(s);
  3438.     WrLstLine("");
  3439.   }
  3440.  
  3441.   as_snprintf(s, sizeof(s), "%7" PRILongInt "%s", LineSum,
  3442.               getmessage((LineSum == 1) ? Num_InfoMessAssLine : Num_InfoMessAssLines), STRINGSIZE);
  3443.   AssembleFile_WrSummary(s);
  3444.  
  3445.   if (LineSum != MacLineSum)
  3446.   {
  3447.     as_snprintf(s, sizeof(s), "%7" PRILongInt "%s", MacLineSum,
  3448.                 getmessage((MacLineSum == 1) ? Num_InfoMessMacAssLine : Num_InfoMessMacAssLines), STRINGSIZE);
  3449.     AssembleFile_WrSummary(s);
  3450.   }
  3451.  
  3452.   as_snprintf(s, sizeof(s), "%7d%s", (int)PassNo,
  3453.               getmessage((PassNo == 1) ? Num_InfoMessPassCnt : Num_InfoMessPPassCnt), STRINGSIZE);
  3454.   AssembleFile_WrSummary(s);
  3455.  
  3456.   if ((ErrorCount > 0) && Repass)
  3457.     AssembleFile_WrSummary(getmessage(Num_InfoMessNoPass));
  3458.  
  3459. #ifdef __TURBOC__
  3460.   as_snprintf(s, sizeof(s), "%7lu%s", coreleft() >> 10,
  3461.               getmessage(Num_InfoMessRemainMem));
  3462.   AssembleFile_WrSummary(s);
  3463.  
  3464.   as_snprintf(s, sizeof(s), "%7lu%s", (unsigned long)StackRes(),
  3465.               getmessage(Num_InfoMessRemainStack));
  3466.   AssembleFile_WrSummary(s);
  3467. #endif
  3468.  
  3469.   as_snprintf(s, sizeof(s), "%7u%s%s", (unsigned)ErrorCount,
  3470.               getmessage(Num_InfoMessErrCnt),
  3471.               (ErrorCount == 1) ? "" : getmessage(Num_InfoMessErrPCnt));
  3472.   AssembleFile_WrSummary(s);
  3473.  
  3474.   as_snprintf(s, sizeof(s), "%7u%s%s", (unsigned)WarnCount,
  3475.               getmessage(Num_InfoMessWarnCnt),
  3476.               (WarnCount == 1) ? "" : getmessage(Num_InfoMessWarnPCnt));
  3477.   AssembleFile_WrSummary(s);
  3478.  
  3479. #ifdef PROFILE_MEMO
  3480.   {
  3481.     unsigned long Sum = (NumMemoSum * 100) / NumMemoCnt;
  3482.  
  3483.     as_snprintf(s, sizeof(s), "%4lu.%02lu%s", Sum / 100, Sum % 100, " Oppart Compares");
  3484.     if (msg_level >= e_msg_level_normal)
  3485.       WrConsoleLine(s, True);
  3486.     if (ListMode == 2)
  3487.       WrLstLine(s);
  3488.   }
  3489. #endif
  3490.  
  3491.   CloseIfOpen(&LstFile);
  3492.  
  3493.   /* verstecktes */
  3494.  
  3495.   if (MakeDebug)
  3496.     PrintSymbolDepth();
  3497.  
  3498.   /* Speicher freigeben */
  3499.  
  3500.   ClearSymbolList();
  3501.   ClearCodepages();
  3502.   ClearMacroList();
  3503.   ClearFunctionList();
  3504.   ClearDefineList();
  3505.   ClearFileList();
  3506.   ClearStructList();
  3507.  
  3508.   dbgentry("AssembleFile");
  3509. }
  3510.  
  3511. static void AssembleGroup(const char *pFileMask)
  3512. {
  3513.   String FileMask;
  3514.  
  3515.   strmaxcpy(FileMask, pFileMask, sizeof(FileMask));
  3516.   AddSuffix(FileMask, SrcSuffix);
  3517.   if (!DirScan(FileMask, AssembleFile))
  3518.     fprintf(stderr, "%s%s\n", FileMask, getmessage(Num_InfoMessNFilesFound));
  3519. }
  3520.  
  3521. /*-------------------------------------------------------------------------*/
  3522.  
  3523. static int LineZ, screen_height = 0;
  3524. static Boolean write_cpu_list_exit;
  3525.  
  3526. static void write_console_next(const char *p_line)
  3527. {
  3528.   WrConsoleLine(p_line, True);
  3529.   if (screen_height && (++LineZ >= screen_height))
  3530.   {
  3531.     LineZ = 0;
  3532.     WrConsoleLine(getmessage(Num_KeyWaitMsg), False);
  3533.     fflush(stdout);
  3534.     while (getchar() != '\n');
  3535.     printf("%s", CursUp);
  3536.   }
  3537. }
  3538.  
  3539. static as_cmd_result_t CMD_SharePascal(Boolean Negate, const char *Arg)
  3540. {
  3541.   UNUSED(Arg);
  3542.  
  3543.   if (!Negate)
  3544.     ShareMode = 1;
  3545.   else if (ShareMode == 1)
  3546.     ShareMode = 0;
  3547.   return e_cmd_ok;
  3548. }
  3549.  
  3550. static as_cmd_result_t CMD_ShareC(Boolean Negate, const char *Arg)
  3551. {
  3552.   UNUSED(Arg);
  3553.  
  3554.   if (!Negate)
  3555.     ShareMode = 2;
  3556.   else if (ShareMode == 2)
  3557.     ShareMode = 0;
  3558.   return e_cmd_ok;
  3559. }
  3560.  
  3561. static as_cmd_result_t CMD_ShareAssembler(Boolean Negate, const char *Arg)
  3562. {
  3563.   UNUSED(Arg);
  3564.  
  3565.   if (!Negate)
  3566.     ShareMode = 3;
  3567.   else if (ShareMode == 3)
  3568.     ShareMode = 0;
  3569.   return e_cmd_ok;
  3570. }
  3571.  
  3572. static as_cmd_result_t CMD_DebugMode(Boolean Negate, const char *pArg)
  3573. {
  3574.   String Arg;
  3575.  
  3576.   strmaxcpy(Arg, pArg, STRINGSIZE);
  3577.   UpString(Arg);
  3578.  
  3579.   if (Negate)
  3580.   {
  3581.     if (Arg[0] != '\0')
  3582.       return e_cmd_err;
  3583.     else
  3584.     {
  3585.       DebugMode = DebugNone;
  3586.       return e_cmd_ok;
  3587.     }
  3588.   }
  3589.   else if (!strcmp(Arg, ""))
  3590.   {
  3591.     DebugMode = DebugMAP;
  3592.     return e_cmd_ok;
  3593.   }
  3594.   else if (!strcmp(Arg, "ATMEL"))
  3595.   {
  3596.     DebugMode = DebugAtmel;
  3597.     return e_cmd_arg;
  3598.   }
  3599.   else if (!strcmp(Arg, "MAP"))
  3600.   {
  3601.     DebugMode = DebugMAP;
  3602.     return e_cmd_arg;
  3603.   }
  3604.   else if (!strcmp(Arg, "NOICE"))
  3605.   {
  3606.     DebugMode = DebugNoICE;
  3607.     return e_cmd_arg;
  3608.   }
  3609. #if 0
  3610.   else if (!strcmp(Arg, "A.OUT"))
  3611.   {
  3612.     DebugMode = DebugAOUT;
  3613.     return e_cmd_arg;
  3614.   }
  3615.   else if (!strcmp(Arg, "COFF"))
  3616.   {
  3617.     DebugMode = DebugCOFF;
  3618.     return e_cmd_arg;
  3619.   }
  3620.   else if (!strcmp(Arg, "ELF"))
  3621.   {
  3622.     DebugMode = DebugELF;
  3623.     return e_cmd_arg;
  3624.   }
  3625. #endif
  3626.   else
  3627.     return e_cmd_err;
  3628.  
  3629. #if 0
  3630.   if (Negate)
  3631.     DebugMode = DebugNone;
  3632.   else
  3633.     DebugMode = DebugMAP;
  3634.   return e_cmd_ok;
  3635. #endif
  3636. }
  3637.  
  3638. static as_cmd_result_t CMD_ListConsole(Boolean Negate, const char *Arg)
  3639. {
  3640.   UNUSED(Arg);
  3641.  
  3642.   if (!Negate)
  3643.     ListMode = 1;
  3644.   else if (ListMode == 1)
  3645.     ListMode = 0;
  3646.   return e_cmd_ok;
  3647. }
  3648.  
  3649. static as_cmd_result_t CMD_ListRadix(Boolean Negate, const char *Arg)
  3650. {
  3651.   Boolean OK, new_zero_pad = False;
  3652.   LargeWord NewListRadixBase;
  3653.  
  3654.   if (Negate)
  3655.   {
  3656.     ListRadixBase = 16;
  3657.     ListPCZeroPad = False;
  3658.     return e_cmd_ok;
  3659.   }
  3660.  
  3661.   if (*Arg == '0')
  3662.   {
  3663.     new_zero_pad = True;
  3664.     Arg++;
  3665.   }
  3666.   NewListRadixBase = ConstLongInt(Arg, &OK, 10);
  3667.   if (!OK || (NewListRadixBase < 2) || (NewListRadixBase > 36))
  3668.     return e_cmd_err;
  3669.   ListRadixBase = NewListRadixBase;
  3670.   ListPCZeroPad = new_zero_pad;
  3671.   return e_cmd_arg;
  3672. }
  3673.  
  3674. static as_cmd_result_t CMD_screen_height(Boolean negate, const char *p_arg)
  3675. {
  3676.   Boolean ok;
  3677.   int new_screen_height;
  3678.  
  3679.   if (negate)
  3680.   {
  3681.     screen_height = 0;
  3682.     return e_cmd_ok;
  3683.   }
  3684.   new_screen_height = ConstLongInt(p_arg, &ok, 10);
  3685.   if (!ok)
  3686.     return e_cmd_err;
  3687.   screen_height = new_screen_height;
  3688.   return e_cmd_arg;
  3689. }
  3690.  
  3691. static as_cmd_result_t CMD_ListFile(Boolean Negate, const char *Arg)
  3692. {
  3693.   UNUSED(Arg);
  3694.  
  3695.   if (!Negate)
  3696.     ListMode = 2;
  3697.   else if (ListMode == 2)
  3698.     ListMode = 0;
  3699.   return e_cmd_ok;
  3700. }
  3701.  
  3702. static as_cmd_result_t CMD_SuppWarns(Boolean Negate, const char *Arg)
  3703. {
  3704.   UNUSED(Arg);
  3705.  
  3706.   SuppWarns = !Negate;
  3707.   return e_cmd_ok;
  3708. }
  3709.  
  3710. static as_cmd_result_t CMD_UseList(Boolean Negate, const char *Arg)
  3711. {
  3712.   UNUSED(Arg);
  3713.  
  3714.   MakeUseList = !Negate;
  3715.   return e_cmd_ok;
  3716. }
  3717.  
  3718. static as_cmd_result_t CMD_CrossList(Boolean Negate, const char *Arg)
  3719. {
  3720.   UNUSED(Arg);
  3721.  
  3722.   MakeCrossList = !Negate;
  3723.   return e_cmd_ok;
  3724. }
  3725.  
  3726. static as_cmd_result_t CMD_SectionList(Boolean Negate, const char *Arg)
  3727. {
  3728.   UNUSED(Arg);
  3729.  
  3730.   MakeSectionList = !Negate;
  3731.   return e_cmd_ok;
  3732. }
  3733.  
  3734. static as_cmd_result_t CMD_BalanceTree(Boolean Negate, const char *Arg)
  3735. {
  3736.   UNUSED(Arg);
  3737.  
  3738.   BalanceTrees = !Negate;
  3739.   return e_cmd_ok;
  3740. }
  3741.  
  3742. static as_cmd_result_t CMD_MakeDebug(Boolean Negate, const char *Arg)
  3743. {
  3744.   UNUSED(Arg);
  3745.  
  3746.   if (!Negate)
  3747.   {
  3748.     MakeDebug = True;
  3749.     errno = 0;
  3750.     Debug = fopen("as.deb", "w");
  3751.     if (!Debug)
  3752.       ChkIO(ErrNum_ListWrError);
  3753.   }
  3754.   else if (MakeDebug)
  3755.   {
  3756.     MakeDebug = False;
  3757.     CloseIfOpen(&Debug);
  3758.   }
  3759.   return e_cmd_ok;
  3760. }
  3761.  
  3762. static as_cmd_result_t CMD_MacProOutput(Boolean Negate, const char *Arg)
  3763. {
  3764.   UNUSED(Arg);
  3765.  
  3766.   MacProOutput = !Negate;
  3767.   return e_cmd_ok;
  3768. }
  3769.  
  3770. static as_cmd_result_t CMD_MacroOutput(Boolean Negate, const char *Arg)
  3771. {
  3772.   UNUSED(Arg);
  3773.  
  3774.   MacroOutput = !Negate;
  3775.   return e_cmd_ok;
  3776. }
  3777.  
  3778. static as_cmd_result_t CMD_MakeIncludeList(Boolean Negate, const char *Arg)
  3779. {
  3780.   UNUSED(Arg);
  3781.  
  3782.   MakeIncludeList = !Negate;
  3783.   return e_cmd_ok;
  3784. }
  3785.  
  3786. static as_cmd_result_t CMD_CodeOutput(Boolean Negate, const char *Arg)
  3787. {
  3788.   UNUSED(Arg);
  3789.  
  3790.   CodeOutput = !Negate;
  3791.   return e_cmd_ok;
  3792. }
  3793.  
  3794. static as_cmd_result_t CMD_MsgIfRepass(Boolean Negate, const char *Arg)
  3795. {
  3796.   Boolean OK;
  3797.   UNUSED(Arg);
  3798.  
  3799.   MsgIfRepass = !Negate;
  3800.   if (MsgIfRepass)
  3801.   {
  3802.     if (Arg[0] == '\0')
  3803.     {
  3804.       PassNoForMessage = 1;
  3805.       return e_cmd_ok;
  3806.     }
  3807.     else
  3808.     {
  3809.       PassNoForMessage = ConstLongInt(Arg, &OK, 10);
  3810.       if (!OK)
  3811.       {
  3812.         PassNoForMessage = 1;
  3813.         return e_cmd_ok;
  3814.       }
  3815.       else if (PassNoForMessage < 1)
  3816.         return e_cmd_err;
  3817.       else
  3818.         return e_cmd_arg;
  3819.     }
  3820.   }
  3821.   else
  3822.     return e_cmd_ok;
  3823. }
  3824.  
  3825. static as_cmd_result_t CMD_Relaxed(Boolean Negate, const char *pArg)
  3826. {
  3827.   UNUSED(pArg);
  3828.  
  3829.   DefRelaxedMode = !Negate;
  3830.   return e_cmd_ok;
  3831. }
  3832.  
  3833. static as_cmd_result_t cmd_int_syntax(Boolean negate, const char *p_arg)
  3834. {
  3835.   if (negate)
  3836.   {
  3837.     as_dynstr_ini_c_str(&def_int_syntax, "");
  3838.     return e_cmd_ok;
  3839.   }
  3840.   else
  3841.   {
  3842.     as_sdprcatf(&def_int_syntax, "%s%s",
  3843.                 "," + !(def_int_syntax.p_str && *def_int_syntax.p_str),
  3844.                 p_arg);
  3845.     return e_cmd_arg;
  3846.   }
  3847. }
  3848.  
  3849. static as_cmd_result_t CMD_ExtendErrors(Boolean Negate, const char *Arg)
  3850. {
  3851.   UNUSED(Arg);
  3852.  
  3853.   if ((Negate) && (ExtendErrors > 0))
  3854.     ExtendErrors--;
  3855.   else if ((!Negate) && (ExtendErrors < 2))
  3856.     ExtendErrors++;
  3857.  
  3858.   return e_cmd_ok;
  3859. }
  3860.  
  3861. static as_cmd_result_t CMD_NumericErrors(Boolean Negate, const char *Arg)
  3862. {
  3863.   UNUSED(Arg);
  3864.  
  3865.   NumericErrors = !Negate;
  3866.   return e_cmd_ok;
  3867. }
  3868.  
  3869. static as_cmd_result_t CMD_HexLowerCase(Boolean Negate, const char *Arg)
  3870. {
  3871.   UNUSED(Arg);
  3872.  
  3873.   HexStartCharacter = Negate ? 'A' : 'a';
  3874.   return e_cmd_ok;
  3875. }
  3876.  
  3877. static as_cmd_result_t CMD_SplitByte(Boolean Negate, const char *Arg)
  3878. {
  3879.   UNUSED(Arg);
  3880.  
  3881.   if (Negate)
  3882.   {
  3883.     SplitByteCharacter = '\0';
  3884.     return e_cmd_ok;
  3885.   }
  3886.   else if (*Arg)
  3887.   {
  3888.     if (strlen(Arg) != 1)
  3889.       return e_cmd_err;
  3890.     SplitByteCharacter = *Arg;
  3891.     return e_cmd_arg;
  3892.   }
  3893.   else
  3894.   {
  3895.     SplitByteCharacter = '.';
  3896.     return e_cmd_ok;
  3897.   }
  3898. }
  3899.  
  3900. static as_cmd_result_t CMD_ThrowErrors(Boolean Negate, const char *Arg)
  3901. {
  3902.   UNUSED(Arg);
  3903.  
  3904.   ThrowErrors = !Negate;
  3905.   return e_cmd_ok;
  3906. }
  3907.  
  3908. static as_cmd_result_t CMD_CaseSensitive(Boolean Negate, const char *Arg)
  3909. {
  3910.   UNUSED(Arg);
  3911.  
  3912.   CaseSensitive = !Negate;
  3913.   return e_cmd_ok;
  3914. }
  3915.  
  3916. static as_cmd_result_t CMD_GNUErrors(Boolean Negate, const char *Arg)
  3917. {
  3918.   UNUSED(Arg);
  3919.  
  3920.   GNUErrors  = !Negate;
  3921.   return e_cmd_ok;
  3922. }
  3923.  
  3924. static as_cmd_result_t CMD_ListMacroHandles(Boolean negate, const char *p_arg)
  3925. {
  3926.   UNUSED(p_arg);
  3927.   list_macro_handles = !negate;
  3928.   return e_cmd_ok;
  3929. }
  3930.  
  3931. static as_cmd_result_t CMD_IncludeList(Boolean Negate, const char *Arg)
  3932. {
  3933.   char *p;
  3934.   String Copy, part;
  3935.  
  3936.   if (*Arg == '\0') return e_cmd_err;
  3937.   else
  3938.   {
  3939.     strmaxcpy(Copy, Arg, STRINGSIZE);
  3940.     do
  3941.     {
  3942.       p = strrchr(Copy, DIRSEP);
  3943.       if (!p)
  3944.       {
  3945.         strmaxcpy(part, Copy, STRINGSIZE);
  3946.         *Copy = '\0';
  3947.       }
  3948.       else
  3949.       {
  3950.         *p = '\0';
  3951.         strmaxcpy(part, p + 1, STRINGSIZE);
  3952.       }
  3953.       if (Negate)
  3954.         RemoveIncludeList(part);
  3955.       else
  3956.         AddIncludeList(part);
  3957.     }
  3958.     while (Copy[0] != '\0');
  3959.     return e_cmd_arg;
  3960.   }
  3961. }
  3962.  
  3963. static as_cmd_result_t CMD_ListMask(Boolean Negate, const char *Arg)
  3964. {
  3965.   Word erg;
  3966.   Boolean OK;
  3967.  
  3968.   if (Arg[0] == '\0')
  3969.     return e_cmd_err;
  3970.   else
  3971.   {
  3972.     erg = ConstLongInt(Arg, &OK, 10);
  3973.     if ((!OK) || (erg > 511))
  3974.       return e_cmd_err;
  3975.     else
  3976.     {
  3977.       ListMask = Negate ? (ListMask & ~erg) : (ListMask | erg);
  3978.       return e_cmd_arg;
  3979.     }
  3980.   }
  3981. }
  3982.  
  3983. static as_cmd_result_t CMD_DefSymbol(Boolean Negate, const char *Arg)
  3984. {
  3985.   String Copy, Part, Name;
  3986.   char *p;
  3987.   as_cmd_result_t Result = e_cmd_err;
  3988.  
  3989.   TempResult t;
  3990.   as_tempres_ini(&t);
  3991.  
  3992.   if (Arg[0] == '\0')
  3993.     LEAVE;
  3994.  
  3995.   strmaxcpy(Copy, Arg, STRINGSIZE);
  3996.   do
  3997.   {
  3998.     p = QuotPos(Copy, ',');
  3999.     if (!p)
  4000.     {
  4001.       strmaxcpy(Part, Copy, STRINGSIZE);
  4002.       Copy[0] = '\0';
  4003.     }
  4004.     else
  4005.     {
  4006.       *p = '\0';
  4007.       strmaxcpy(Part, Copy, STRINGSIZE);
  4008.       strmov(Copy, p + 1);
  4009.     }
  4010.    if (!CaseSensitive)
  4011.      UpString(Part);
  4012.    p = QuotPos(Part, '=');
  4013.    if (!p)
  4014.    {
  4015.      strmaxcpy(Name, Part, STRINGSIZE);
  4016.      Part[0] = '\0';
  4017.    }
  4018.    else
  4019.    {
  4020.      *p = '\0';
  4021.      strmaxcpy(Name, Part, STRINGSIZE);
  4022.      strmov(Part, p + 1);
  4023.    }
  4024.    if (!ChkSymbName(Name))
  4025.      LEAVE;
  4026.    if (Negate)
  4027.      RemoveDefSymbol(Name);
  4028.    else
  4029.    {
  4030.      AsmParsInit();
  4031.      if (Part[0] != '\0')
  4032.      {
  4033.        EvalExpression(Part, &t);
  4034.        if ((t.Typ == TempNone) || mFirstPassUnknown(t.Flags))
  4035.          return e_cmd_err;
  4036.      }
  4037.      else
  4038.        as_tempres_set_int(&t, 1);
  4039.      AddDefSymbol(Name, &t);
  4040.    }
  4041.   }
  4042.   while (Copy[0] != '\0');
  4043.  
  4044.   Result = e_cmd_arg;
  4045. func_exit:
  4046.   as_tempres_free(&t);
  4047.   return Result;
  4048. }
  4049.  
  4050. static as_cmd_result_t CMD_ErrorPath(Boolean Negate, const char *Arg)
  4051. {
  4052.   if (Negate)
  4053.     return e_cmd_err;
  4054.   else if (Arg[0] == '\0')
  4055.   {
  4056.     ErrorPath[0] = '\0';
  4057.     return e_cmd_ok;
  4058.   }
  4059.   else
  4060.   {
  4061.     strmaxcpy(ErrorPath, Arg, STRINGSIZE);
  4062.     return e_cmd_arg;
  4063.   }
  4064. }
  4065.  
  4066. static as_cmd_result_t CMD_HardRanges(Boolean Negate, const char *Arg)
  4067. {
  4068.   UNUSED(Arg);
  4069.  
  4070.   HardRanges = Negate;
  4071.   return e_cmd_ok;
  4072. }
  4073.  
  4074. static as_cmd_result_t CMD_OutFile(Boolean Negate, const char *Arg)
  4075. {
  4076.   if (Arg[0] == '\0')
  4077.   {
  4078.     if (Negate)
  4079.     {
  4080.       ClearOutList();
  4081.       return e_cmd_ok;
  4082.     }
  4083.     else
  4084.       return e_cmd_err;
  4085.   }
  4086.   else
  4087.   {
  4088.     if (Negate)
  4089.       RemoveFromOutList(Arg);
  4090.     else
  4091.       AddToOutList(Arg);
  4092.     return e_cmd_arg;
  4093.   }
  4094. }
  4095.  
  4096. static as_cmd_result_t CMD_ShareOutFile(Boolean Negate, const char *Arg)
  4097. {
  4098.   if (Arg[0] == '\0')
  4099.   {
  4100.     if (Negate)
  4101.     {
  4102.       ClearShareOutList();
  4103.       return e_cmd_ok;
  4104.     }
  4105.     else
  4106.       return e_cmd_err;
  4107.   }
  4108.   else
  4109.   {
  4110.     if (Negate)
  4111.       RemoveFromShareOutList(Arg);
  4112.     else
  4113.       AddToShareOutList(Arg);
  4114.     return e_cmd_arg;
  4115.   }
  4116. }
  4117.  
  4118. static as_cmd_result_t CMD_ListOutFile(Boolean Negate, const char *Arg)
  4119. {
  4120.   if (Arg[0] == '\0')
  4121.   {
  4122.     if (Negate)
  4123.     {
  4124.       ClearListOutList();
  4125.       return e_cmd_ok;
  4126.     }
  4127.     else
  4128.       return e_cmd_err;
  4129.   }
  4130.   else
  4131.   {
  4132.     if (Negate)
  4133.       RemoveFromListOutList(Arg);
  4134.     else
  4135.       AddToListOutList(Arg);
  4136.     return e_cmd_arg;
  4137.   }
  4138. }
  4139.  
  4140. static Boolean CMD_CPUAlias_ChkCPUName(char *s)
  4141. {
  4142.   int z;
  4143.  
  4144.   for (z = 0; z < (int)strlen(s); z++)
  4145.     if (!isalnum((unsigned int) s[z]))
  4146.       return False;
  4147.   return True;
  4148. }
  4149.  
  4150. static as_cmd_result_t CMD_CPUAlias(Boolean Negate, const char *Arg)
  4151. {
  4152.   const char *p;
  4153.   String s1, s2;
  4154.  
  4155.   if (Negate)
  4156.     return e_cmd_err;
  4157.   else if (Arg[0] == '\0')
  4158.     return e_cmd_err;
  4159.   else
  4160.   {
  4161.     p = strchr(Arg, '=');
  4162.     if (!p)
  4163.       return e_cmd_err;
  4164.     else
  4165.     {
  4166.       strmemcpy(s1, STRINGSIZE, Arg, p - Arg);
  4167.       UpString(s1);
  4168.       strmaxcpy(s2, p + 1, STRINGSIZE);
  4169.       UpString(s2);
  4170.       if (!(CMD_CPUAlias_ChkCPUName(s1) && CMD_CPUAlias_ChkCPUName(s2)))
  4171.         return e_cmd_err;
  4172.       else if (!AddCPUAlias(s2, s1))
  4173.         return e_cmd_err;
  4174.       else
  4175.         return e_cmd_arg;
  4176.     }
  4177.   }
  4178. }
  4179.  
  4180. static as_cmd_result_t CMD_SetCPU(Boolean Negate, const char *Arg)
  4181. {
  4182.   if (Negate)
  4183.   {
  4184.     *DefCPU = '\0';
  4185.     return e_cmd_ok;
  4186.   }
  4187.   else
  4188.   {
  4189.     if (*Arg == '\0')
  4190.       return e_cmd_err;
  4191.  
  4192.     if (!as_strcasecmp(Arg, "?") || !as_strcasecmp(Arg, "LIST"))
  4193.     {
  4194.       write_cpu_list_exit = True;
  4195.       return e_cmd_arg;
  4196.     }
  4197.  
  4198.     strmaxcpy(DefCPU, Arg, sizeof(DefCPU) - 1);
  4199.     NLS_UpString(DefCPU);
  4200.  
  4201.     if (!LookupCPUDefByName(DefCPU))
  4202.     {
  4203.       *DefCPU = '\0';
  4204.       return e_cmd_err;
  4205.     }
  4206.     return e_cmd_arg;
  4207.   }
  4208. }
  4209.  
  4210. static as_cmd_result_t CMD_NoICEMask(Boolean Negate, const char *Arg)
  4211. {
  4212.   Word erg;
  4213.   Boolean OK;
  4214.  
  4215.   if (Negate)
  4216.   {
  4217.     NoICEMask = 1 << SegCode;
  4218.     return e_cmd_ok;
  4219.   }
  4220.   else if (Arg[0] == '\0')
  4221.     return e_cmd_err;
  4222.   else
  4223.   {
  4224.     erg = ConstLongInt(Arg, &OK, 10);
  4225.     if (!OK || (erg >= (1 << SegCount)))
  4226.       return e_cmd_err;
  4227.     else
  4228.     {
  4229.       NoICEMask = erg;
  4230.       return e_cmd_arg;
  4231.     }
  4232.   }
  4233. }
  4234.  
  4235. static as_cmd_result_t CMD_MaxErrors(Boolean Negate, const char *Arg)
  4236. {
  4237.   if (Negate)
  4238.   {
  4239.     MaxErrors = 0;
  4240.     return e_cmd_ok;
  4241.   }
  4242.   else if (Arg[0] == '\0')
  4243.     return e_cmd_err;
  4244.   else
  4245.   {
  4246.     Boolean OK;
  4247.     LongWord NewMaxErrors = ConstLongInt(Arg, &OK, 10);
  4248.  
  4249.     if (!OK)
  4250.       return e_cmd_err;
  4251.     MaxErrors = NewMaxErrors;
  4252.     return e_cmd_arg;
  4253.   }
  4254. }
  4255.  
  4256. /*!------------------------------------------------------------------------
  4257.  * \fn     CMD_MaxIncludeLevel(Boolean Negate, const char *pArg)
  4258.  * \brief  set maximum include nesting level
  4259.  * \param  Negate back to default?
  4260.  * \param  pArg numeric argument
  4261.  * \return exec result
  4262.  * ------------------------------------------------------------------------ */
  4263.  
  4264. #define DEFAULT_MAXINCLUDELEVEL 200
  4265.  
  4266. static as_cmd_result_t CMD_MaxIncludeLevel(Boolean Negate, const char *pArg)
  4267. {
  4268.   if (Negate)
  4269.   {
  4270.     MaxErrors = DEFAULT_MAXINCLUDELEVEL;
  4271.     return e_cmd_ok;
  4272.   }
  4273.   else if (pArg[0] == '\0')
  4274.     return e_cmd_err;
  4275.   else
  4276.   {
  4277.     Boolean OK;
  4278.     Integer NewMaxIncludeLevel = ConstLongInt(pArg, &OK, 10);
  4279.  
  4280.     if (!OK)
  4281.       return e_cmd_err;
  4282.     MaxIncludeLevel = NewMaxIncludeLevel;
  4283.     return e_cmd_arg;
  4284.   }
  4285. }
  4286.  
  4287. static const as_cmd_rec_t ASParams[] =
  4288. {
  4289.   { "A"             , CMD_BalanceTree     },
  4290.   { "alias"         , CMD_CPUAlias        },
  4291.   { "a"             , CMD_ShareAssembler  },
  4292.   { "C"             , CMD_CrossList       },
  4293.   { "c"             , CMD_ShareC          },
  4294.   { "CPU"           , CMD_SetCPU          },
  4295.   { "D"             , CMD_DefSymbol       },
  4296.   { "E"             , CMD_ErrorPath       },
  4297.   { "g"             , CMD_DebugMode       },
  4298.   { "G"             , CMD_CodeOutput      },
  4299.   { "gnuerrors"     , CMD_GNUErrors       },
  4300.   { "h"             , CMD_HexLowerCase    },
  4301.   { "i"             , CMD_IncludeList     },
  4302.   { "I"             , CMD_MakeIncludeList },
  4303.   { "intsyntax"     , cmd_int_syntax      },
  4304.   { "L"             , CMD_ListFile        },
  4305.   { "l"             , CMD_ListConsole     },
  4306.   { "listradix"     , CMD_ListRadix       },
  4307.   { "splitbyte"     , CMD_SplitByte       },
  4308.   { "M"             , CMD_MacroOutput     },
  4309.   { "maxerrors"     , CMD_MaxErrors       },
  4310.   { "maxinclevel"   , CMD_MaxIncludeLevel },
  4311.   { "n"             , CMD_NumericErrors   },
  4312.   { "noicemask"     , CMD_NoICEMask       },
  4313.   { "o"             , CMD_OutFile         },
  4314.   { "P"             , CMD_MacProOutput    },
  4315.   { "p"             , CMD_SharePascal     },
  4316.   { "r"             , CMD_MsgIfRepass     },
  4317.   { RelaxedName     , CMD_Relaxed         },
  4318.   { "s"             , CMD_SectionList     },
  4319.   { "screenheight"  , CMD_screen_height   },
  4320.   { "shareout"      , CMD_ShareOutFile    },
  4321.   { "olist"         , CMD_ListOutFile     },
  4322.   { "list-macro-handles", CMD_ListMacroHandles },
  4323.   { "t"             , CMD_ListMask        },
  4324.   { "u"             , CMD_UseList         },
  4325.   { "U"             , CMD_CaseSensitive   },
  4326.   { "w"             , CMD_SuppWarns       },
  4327.   { "warnranges"    , CMD_HardRanges      },
  4328.   { "x"             , CMD_ExtendErrors    },
  4329.   { "X"             , CMD_MakeDebug       },
  4330.   { "Y"             , CMD_ThrowErrors     }
  4331. };
  4332.  
  4333. /*--------------------------------------------------------------------------*/
  4334.  
  4335. #ifdef __sunos__
  4336.  
  4337. extern void on_exit(void (*procp)(int status, caddr_t arg),caddr_t arg);
  4338.  
  4339. static void GlobExitProc(int status, caddr_t arg)
  4340. {
  4341.   if (MakeDebug)
  4342.     CloseIfOpen(&Debug);
  4343. }
  4344.  
  4345. #else
  4346.  
  4347. /* Might no longer need this with newer TCC versions: */
  4348.  
  4349. #ifdef __TINYC__
  4350. void * __dso_handle __attribute((visibility("hidden"))) = &__dso_handle;
  4351. #endif
  4352.  
  4353. static void GlobExitProc(void)
  4354. {
  4355.   if (MakeDebug)
  4356.     CloseIfOpen(&Debug);
  4357. }
  4358.  
  4359. #endif
  4360.  
  4361. int main(int argc, char **argv)
  4362. {
  4363.   char *Env;
  4364.   String Dummy;
  4365.   static Boolean First = TRUE;
  4366.   as_cmd_results_t cmd_results;
  4367.  
  4368.   if (First)
  4369.   {
  4370.     be_le_init();
  4371.     nls_init();
  4372.     bpemu_init();
  4373.     stdhandl_init();
  4374.     strutil_init();
  4375.     chunks_init();
  4376.     if (!NLS_Initialize(&argc, argv))
  4377.       exit(4);
  4378.  
  4379. #ifdef _USE_MSH
  4380.     nlmessages_init_buffer(as_msh_data, sizeof(as_msh_data), MsgId1, MsgId2);
  4381. #else
  4382.     nlmessages_init_file("as.msg", *argv, MsgId1, MsgId2);
  4383. #endif
  4384.     ioerrs_init(*argv);
  4385.     as_cmdarg_init(*argv);
  4386.     msg_level_init();
  4387.     as_cmd_register(ASParams, as_array_size(ASParams));
  4388.  
  4389.     asmfnums_init();
  4390.     asminclist_init();
  4391.     asmitree_init();
  4392.  
  4393.     asmdef_init();
  4394.     cpulist_init();
  4395.     asmsub_init();
  4396.     asmpars_init();
  4397.     intformat_init();
  4398.  
  4399.     asmmac_init();
  4400.     asmstruct_init();
  4401.     asmif_init();
  4402.     asmerr_init();
  4403.     asmcode_init();
  4404.     asmlabel_init();
  4405.     asmdebug_init();
  4406.     asmlist_init();
  4407.  
  4408.     codeallg_init();
  4409.     onoff_common_init();
  4410.     literals_init();
  4411.  
  4412. #if 1
  4413.     codenone_init();
  4414. #endif
  4415.     code68k_init();
  4416.     code56k_init();
  4417.     code601_init();
  4418.     codepalm_init();
  4419.     codemcore_init();
  4420.     codexgate_init();
  4421.     code68_init();
  4422.     code6805_init();
  4423.     code6809_init();
  4424.     code6812_init();
  4425.     codes12z_init();
  4426.     code6816_init();
  4427.     code68rs08_init();
  4428.     codeh8_3_init();
  4429.     codeh8_5_init();
  4430.     code7000_init();
  4431.     codeko09_init();
  4432.     code65_init();
  4433.     codepps4_init();
  4434.     codeh16_init();
  4435.     code7700_init();
  4436.     codehmcs400_init();
  4437.     code4500_init();
  4438.     codem16_init();
  4439.     codem16c_init();
  4440.     codepdp11_init();
  4441.     codevax_init();
  4442.     code4004_init();
  4443.     code8008_init();
  4444.     code48_init();
  4445.     code51_init();
  4446.     code96_init();
  4447.     code85_init();
  4448.     code86_init();
  4449.     code960_init();
  4450.     code8x30x_init();
  4451.     code2650_init();
  4452.     codexa_init();
  4453.     codeavr_init();
  4454.     code29k_init();
  4455.     code166_init();
  4456.     codez80_init();
  4457.     codez8_init();
  4458.     codez8000_init();
  4459.     codekcpsm_init();
  4460.     codekcpsm3_init();
  4461.     codemico8_init();
  4462.     code96c141_init();
  4463.     code90c141_init();
  4464.     code87c800_init();
  4465.     code870c_init();
  4466.     code47c00_init();
  4467.     code97c241_init();
  4468.     code9331_init();
  4469.     code16c5x_init();
  4470.     code16c8x_init();
  4471.     code17c4x_init();
  4472.     codesx20_init();
  4473.     codepdk_init();
  4474.     codest6_init();
  4475.     codest7_init();
  4476.     codest9_init();
  4477.     code6804_init();
  4478.     code3201x_init();
  4479.     code3202x_init();
  4480.     code3203x_init();
  4481.     code3205x_init();
  4482.     code32054x_init();
  4483.     code3206x_init();
  4484.     code9900_init();
  4485.     codetms7_init();
  4486.     code370_init();
  4487.     codemsp_init();
  4488.     codetms1_init();
  4489.     code78c10_init();
  4490.     code75xx_init();
  4491.     code75k0_init();
  4492.     code78k0_init();
  4493.     code78k2_init();
  4494.     code78k3_init();
  4495.     code78k4_init();
  4496.     code7720_init();
  4497.     code77230_init();
  4498.     codev60_init();
  4499.     codeuc43_init();
  4500.     codescmp_init();
  4501.     codeimp16_init();
  4502.     code807x_init();
  4503.     codecop4_init();
  4504.     codecop8_init();
  4505.     codesc14xxx_init();
  4506.     codens32k_init();
  4507.     codeace_init();
  4508.     codecp3f_init();
  4509.     codef8_init();
  4510.     code53c8xx_init();
  4511.     codef2mc8_init();
  4512.     codef2mc16_init();
  4513.     codemn1610_init();
  4514.     codemn2610_init();
  4515.     codeolms40_init();
  4516.     codeolms50_init();
  4517.     code1802_init();
  4518.     codevector_init();
  4519.     codexcore_init();
  4520.     code1750_init();
  4521.     codekenbak_init();
  4522.     codecp1600_init();
  4523.     codenano_init();
  4524.     code6100_init();
  4525.     coderx_init();
  4526.     code61860_init();
  4527.     code62015_init();
  4528.     First = FALSE;
  4529.   }
  4530.  
  4531. #ifdef __sunos__
  4532.   on_exit(GlobExitProc, (caddr_t) NULL);
  4533. #else
  4534. # ifndef __MUNIX__
  4535.   atexit(GlobExitProc);
  4536. # endif
  4537. #endif
  4538.  
  4539.   *CursUp = '\0';
  4540.   switch (Redirected)
  4541.   {
  4542.     case NoRedir:
  4543.       Env = getenv("USEANSI");
  4544.       strmaxcpy(Dummy, Env ? Env : "Y", STRINGSIZE);
  4545.       if (as_toupper(Dummy[0]) == 'N')
  4546.       {
  4547.       }
  4548.       else
  4549.       {
  4550.         strcpy(CursUp, " [A"); CursUp[0] = Char_ESC;
  4551.       }
  4552.       break;
  4553.     case RedirToDevice:
  4554.       break;
  4555.     case RedirToFile:
  4556.       break;
  4557.   }
  4558.  
  4559.   ShareMode = 0;
  4560.   ListMode = 0;
  4561.   IncludeList[0] = '\0';
  4562.   SuppWarns = False;
  4563.   MakeUseList = False;
  4564.   MakeCrossList = False;
  4565.   MakeSectionList = False;
  4566.   MakeIncludeList = False;
  4567.   ListMask = 0x1ff;
  4568.   list_macro_handles = False;
  4569.   MakeDebug = False;
  4570.   ExtendErrors = 0;
  4571.   DefRelaxedMode = False;
  4572.   as_dynstr_ini_c_str(&def_int_syntax, "");
  4573.   MacroOutput = False;
  4574.   MacProOutput = False;
  4575.   CodeOutput = True;
  4576.   strcpy(ErrorPath,  "!2");
  4577.   MsgIfRepass = False;
  4578.   NumericErrors = False;
  4579.   DebugMode = DebugNone;
  4580.   CaseSensitive = False;
  4581.   ThrowErrors = False;
  4582.   HardRanges = True;
  4583.   NoICEMask = 1 << SegCode;
  4584.   GNUErrors = False;
  4585.   MaxErrors = 0;
  4586.   ListRadixBase = 16;
  4587.   ListPCZeroPad = False;
  4588.   MaxIncludeLevel = DEFAULT_MAXINCLUDELEVEL;
  4589.   write_cpu_list_exit = False;
  4590.  
  4591.   LineZ = 0;
  4592.   screen_height = 0;
  4593.  
  4594. #if defined(INCDIR)
  4595.   CMD_IncludeList(False, INCDIR);
  4596. #endif
  4597.   if (e_cmd_err == as_cmd_process(argc, argv, EnvName, &cmd_results))
  4598.   {
  4599.     printf("%s%s\n", getmessage(cmd_results.error_arg_in_env ? Num_ErrMsgInvEnvParam : Num_ErrMsgInvParam), cmd_results.error_arg);
  4600.     exit(4);
  4601.   }
  4602.  
  4603.   if ((msg_level >= e_msg_level_verbose) || cmd_results.write_version_exit)
  4604.   {
  4605.     String Tmp;
  4606.  
  4607.     as_snprintf(Tmp, sizeof(Tmp), "%s%s", getmessage(Num_InfoMessMacroAss), Version);
  4608.     write_console_next(Tmp);
  4609.     as_snprintf(Tmp, sizeof(Tmp), "(%s-%s)", ARCHPRNAME, ARCHSYSNAME);
  4610.     write_console_next(Tmp);
  4611.     write_console_next(InfoMessCopyright);
  4612.     WriteCopyrights(write_console_next);
  4613.     write_console_next("");
  4614.   }
  4615.  
  4616.   if (cmd_results.write_help_exit)
  4617.   {
  4618.     char *ph1, *ph2;
  4619.     String tmp;
  4620.     as_snprintf(tmp, sizeof(tmp), "%s%s%s", getmessage(Num_InfoMessHead1), as_cmdarg_get_executable_name(), getmessage(Num_InfoMessHead2));
  4621.     write_console_next(tmp);
  4622.     for (ph1 = getmessage(Num_InfoMessHelp), ph2 = strchr(ph1, '\n'); ph2; ph1 = ph2 + 1, ph2 = strchr(ph1, '\n'))
  4623.     {
  4624.       *ph2 = '\0';
  4625.       write_console_next(ph1);
  4626.       *ph2 = '\n';
  4627.     }
  4628.   }
  4629.  
  4630.   if (write_cpu_list_exit)
  4631.   {
  4632.     write_console_next(getmessage(Num_InfoMessCPUList));
  4633.     PrintCPUList(write_console_next);
  4634.     ClearCPUList();
  4635.   }
  4636.  
  4637.   if (cmd_results.write_version_exit || write_cpu_list_exit || cmd_results.write_help_exit)
  4638.     exit(0);
  4639.  
  4640.   /* ListRadixBase must have been set */
  4641.  
  4642.   asmlist_setup();
  4643.  
  4644.   GlobErrFlag = False;
  4645.   if (ErrorPath[0] != '\0')
  4646.   {
  4647.     strcpy(ErrorName, ErrorPath);
  4648.     unlink(ErrorName);
  4649.   }
  4650.  
  4651.   if (StringListEmpty(cmd_results.file_arg_list))
  4652.   {
  4653.     fprintf(stderr, "%s: %s\n", as_cmdarg_get_executable_name(), getmessage(Num_ErrMessNoInputFiles));
  4654.     exit(1);
  4655.   }
  4656.   else
  4657.   {
  4658.     char *pFile;
  4659.  
  4660.     while (True)
  4661.     {
  4662.       pFile = MoveAndCutStringListFirst(&cmd_results.file_arg_list);
  4663.       if (!pFile)
  4664.         break;
  4665.       if (*pFile)
  4666.         AssembleGroup(pFile);
  4667.       free(pFile);
  4668.     }
  4669.   }
  4670.  
  4671.   if (*ErrorPath)
  4672.     CloseIfOpen(&ErrorFile);
  4673.  
  4674.   ClearCPUList();
  4675.  
  4676.   return GlobErrFlag ? 2 : 0;
  4677. }
  4678.