/* as.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Hauptmodul */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <assert.h>
#include "version.h"
#include "be_le.h"
#include "bpemu.h"
#include "stdhandl.h"
#include "nls.h"
#include "nlmessages.h"
#include "as.rsc"
#ifdef _USE_MSH
# include "as.msh"
#endif
#include "ioerrs.h"
#include "strutil.h"
#include "stringlists.h"
#include "cmdarg.h"
#include "msg_level.h"
#include "asmitree.h"
#include "trees.h"
#include "chunks.h"
#include "console.h"
#include "asminclist.h"
#include "asmfnums.h"
#include "asmdef.h"
#include "cpulist.h"
#include "asmerr.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmmac.h"
#include "asmstructs.h"
#include "asmif.h"
#include "asmcode.h"
#include "asmlist.h"
#include "asmlabel.h"
#include "asmdebug.h"
#include "asmrelocs.h"
#include "literals.h"
#include "asmallg.h"
#include "onoff_common.h"
#include "codepseudo.h"
#include "as.h"
#include "codenone.h"
#include "code68k.h"
#include "code56k.h"
#include "code601.h"
#include "codepalm.h"
#include "codemcore.h"
#include "codexgate.h"
#include "code68.h"
#include "code6805.h"
#include "code6809.h"
#include "code6812.h"
#include "codes12z.h"
#include "code6816.h"
#include "code68rs08.h"
#include "codeh8_3.h"
#include "codeh8_5.h"
#include "code7000.h"
#include "codeko09.h"
#include "code65.h"
#include "codepps4.h"
#include "codeh16.h"
#include "code7700.h"
#include "codehmcs400.h"
#include "code4500.h"
#include "codem16.h"
#include "codem16c.h"
#include "codepdp11.h"
#include "codevax.h"
#include "code4004.h"
#include "code8008.h"
#include "code48.h"
#include "code51.h"
#include "code96.h"
#include "code85.h"
#include "code86.h"
#include "code960.h"
#include "code8x30x.h"
#include "code2650.h"
#include "codexa.h"
#include "codeavr.h"
#include "code29k.h"
#include "code166.h"
#include "codez80.h"
#include "codez8.h"
#include "codez8000.h"
#include "codekcpsm.h"
#include "codekcp3.h"
#include "codemic8.h"
#include "code96c141.h"
#include "code90c141.h"
#include "code87c800.h"
#include "code870c.h"
#include "code47c00.h"
#include "code97c241.h"
#include "code9331.h"
#include "code16c5x.h"
#include "code16c8x.h"
#include "code17c4x.h"
#include "codesx20.h"
#include "codepdk.h"
#include "codest6.h"
#include "codest7.h"
#include "codest9.h"
#include "code6804.h"
#include "code3201x.h"
#include "code3202x.h"
#include "code3203x.h"
#include "code3205x.h"
#include "code3254x.h"
#include "code3206x.h"
#include "code9900.h"
#include "codetms7.h"
#include "code370.h"
#include "codemsp.h"
#include "codetms1.h"
#include "codescmp.h"
#include "codeimp16.h"
#include "code807x.h"
#include "codecop4.h"
#include "codecop8.h"
#include "codesc14xxx.h"
#include "codens32k.h"
#include "codeace.h"
#include "codecp3f.h"
#include "codef8.h"
#include "code78c10.h"
#include "code75xx.h"
#include "code75k0.h"
#include "code78k0.h"
#include "code78k2.h"
#include "code78k3.h"
#include "code78k4.h"
#include "code7720.h"
#include "code77230.h"
#include "codev60.h"
#include "code53c8xx.h"
#include "codefmc8.h"
#include "codefmc16.h"
#include "codemn1610.h"
#include "codemn2610.h"
#include "codeol40.h"
#include "codeol50.h"
#include "code1802.h"
#include "codevector.h"
#include "codexcore.h"
#include "code1750.h"
#include "codekenbak.h"
#include "codecp1600.h"
#include "codenano.h"
#include "code6100.h"
#include "coderx.h"
#include "code61860.h"
#include "code62015.h"
/** Code21xx};**/
static long StartTime, StopTime;
static Boolean GlobErrFlag;
static unsigned MacroNestLevel = 0;
/*=== Zeilen einlesen ======================================================*/
#if 0
# define dbgentry(str) printf("***enter %s\n", str);
# define dbgexit(str) printf("***exit %s\n", str);
#else
# define dbgentry(str) {}
# define dbgexit(str) {}
#endif
#define LEAVE goto func_exit
static void NULL_Restorer(PInputTag PInp)
{
UNUSED(PInp);
}
static Boolean NULL_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
{
UNUSED(PInp);
UNUSED(ActGNUErrors);
if (DestSize)
*dest = '\0';
return False;
}
static Boolean INCLUDE_Processor(PInputTag PInp, as_dynstr_t *p_dest);
static PInputTag GenerateProcessor(void)
{
PInputTag PInp
= (PInputTag
)malloc(sizeof(TInputTag
));
PInp->IsMacro = False;
PInp->Next = NULL;
PInp->First = True;
PInp->OrigDoLst = DoLst;
PInp->StartLine = CurrLine;
PInp->ParCnt = 0; PInp->ParZ = 0;
InitStringList(&(PInp->Params));
PInp->LineCnt = PInp->ContLineCnt = 0; PInp->LineZ = 1;
PInp->Lines = PInp->LineRun = NULL;
StrCompMkTemp(&PInp->SpecName, PInp->SpecNameStr, sizeof(PInp->SpecNameStr));
StrCompReset(&PInp->SpecName);
PInp->AllArgs[0] = '\0';
PInp->NumArgs[0] = '\0';
PInp->IsEmpty = False;
PInp->Buffer = NULL;
PInp->Datei = NULL;
PInp->IfLevel = SaveIFs();
PInp->IncludeLevel = CurrIncludeLevel;
PInp->Restorer = NULL_Restorer;
PInp->GetPos = NULL_GetPos;
PInp->Macro = NULL;
PInp->SaveAttr[0] = '\0';
PInp->SaveLabel[0] = '\0';
PInp->GlobalSymbols = False;
PInp->UsesNumArgs =
PInp->UsesAllArgs = False;
/* in case the input tag chain is empty, this must be the master file */
PInp->FromFile = !FirstInputTag || (FirstInputTag->Processor == INCLUDE_Processor);
return PInp;
}
static POutputTag GenerateOUTProcessor(SimpProc Processor, tErrorNum OpenErrMsg)
{
POutputTag POut;
POut
= (POutputTag
) malloc(sizeof(TOutputTag
));
POut->Processor = Processor;
POut->NestLevel = 0;
POut->Tag = NULL;
POut->Mac = NULL;
POut->ParamNames = NULL;
POut->ParamDefVals = NULL;
POut->PubSect = 0;
POut->GlobSect = 0;
POut->DoExport = False;
POut->DoGlobCopy= False;
POut->UsesNumArgs =
POut->UsesAllArgs = False;
*POut->GName = '\0';
POut->OpenErrMsg = OpenErrMsg;
return POut;
}
/*=========================================================================*/
/* Makroprozessor */
/*-------------------------------------------------------------------------*/
/* allgemein gebrauchte Subfunktionen */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* werden gebraucht, um festzustellen, ob innerhalb eines Makrorumpfes weitere
Makroschachtelungen auftreten */
static Boolean MacroStart(void)
{
return ((Memo("MACRO")) || (Memo("IRP")) || (Memo("IRPC")) || (Memo("REPT")) || (Memo("WHILE")));
}
static Boolean MacroEnd(void)
{
if (Memo("ENDM"))
{
WasMACRO = True;
return True;
}
else
return False;
}
typedef void (*tMacroArgCallback)(Boolean CtrlArg, const tStrComp *pArg, void *pUser);
static void ProcessMacroArgs(tMacroArgCallback Callback, void *pUser)
{
tStrComp *pArg;
int l;
for (pArg = ArgStr + 1; pArg <= ArgStr + ArgCnt; pArg++)
{
if ((l >= 2) && (pArg->str.p_str[0] == '{') && (pArg->str.p_str[l - 1] == '}'))
{
tStrComp Arg;
StrCompRefRight(&Arg, pArg, 1);
StrCompShorten(&Arg, 1);
Callback(TRUE, &Arg, pUser);
}
else
{
Callback(FALSE, pArg, pUser);
}
}
}
/*-------------------------------------------------------------------------*/
/* Dieser Einleseprozessor dient nur dazu, eine fehlerhafte Makrodefinition
bis zum Ende zu ueberlesen */
static void WaitENDM_Processor(void)
{
POutputTag Tmp;
if (MacroStart())
FirstOutputTag->NestLevel++;
else if (MacroEnd())
FirstOutputTag->NestLevel--;
if (FirstOutputTag->NestLevel <= -1)
{
Tmp = FirstOutputTag;
FirstOutputTag = Tmp->Next;
}
}
static void AddWaitENDM_Processor(void)
{
POutputTag Neu;
Neu = GenerateOUTProcessor(WaitENDM_Processor, ErrNum_OpenMacro);
Neu->Next = FirstOutputTag;
FirstOutputTag = Neu;
}
/*-------------------------------------------------------------------------*/
/* normale Makros */
static void ComputeMacroStrings(PInputTag Tag)
{
StringRecPtr Lauf;
/* recompute # of params */
if (Tag->UsesNumArgs)
as_snprintf(Tag->NumArgs, sizeof(Tag->NumArgs), Integ32Format, Tag->ParCnt);
/* recompute 'all string' parameter */
if (Tag->UsesAllArgs)
{
Tag->AllArgs[0] = '\0';
Lauf = Tag->Params;
while (Lauf)
{
if (Tag->AllArgs[0] != '\0')
strmaxcat(Tag->AllArgs, ",", STRINGSIZE);
strmaxcat(Tag->AllArgs, Lauf->Content, STRINGSIZE);
Lauf = Lauf->Next;
}
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Diese Routine leitet die Quellcodezeilen bei der Makrodefinition in den
Makro-Record um */
static void MACRO_OutProcessor(void)
{
POutputTag Tmp;
int z;
StringRecPtr l;
PMacroRec GMacro;
WasMACRO = True;
/* write preprocessed output to file ? */
if ((MacroOutput) && (FirstOutputTag->DoExport))
{
errno = 0;
fprintf(MacroFile
, "%s\n", OneLine.
p_str);
ChkIO(ErrNum_FileWriteError);
}
/* check for additional nested macros resp. end of definition */
if (MacroStart())
FirstOutputTag->NestLevel++;
else if (MacroEnd())
FirstOutputTag->NestLevel--;
/* still lines to put into the macro body ? */
if (FirstOutputTag->NestLevel != -1)
{
as_dynstr_t s;
as_dynstr_ini_clone(&s, &OneLine);
KillCtrl(s.p_str);
/* compress into tokens */
l = FirstOutputTag->ParamNames;
for (z = 1; z <= FirstOutputTag->Mac->ParamCount; z++)
{
const char *p_param_name = GetStringListNext(&l);
CompressLine(p_param_name ? p_param_name : "", z, &s, CaseSensitive);
}
/* reserved argument names are never case-sensitive */
if (HasAttrs)
CompressLine(AttrName, ArgCntMax + 1, &s, FALSE);
if (CompressLine(ArgCName, ArgCntMax + 2, &s, FALSE) > 0)
FirstOutputTag->UsesNumArgs = TRUE;
if (CompressLine(AllArgName, ArgCntMax + 3, &s, FALSE) > 0)
FirstOutputTag->UsesAllArgs = TRUE;
if (FirstOutputTag->Mac->LocIntLabel)
CompressLine(LabelName, ArgCntMax + 4, &s, FALSE);
AddStringListLast(&(FirstOutputTag->Mac->FirstLine), s.p_str);
as_dynstr_free(&s);
}
/* otherwise, finish definition */
if (FirstOutputTag->NestLevel == -1)
{
if (IfAsm)
{
FirstOutputTag->Mac->UsesNumArgs = FirstOutputTag->UsesNumArgs;
FirstOutputTag->Mac->UsesAllArgs = FirstOutputTag->UsesAllArgs;
FirstOutputTag->Mac->ParamNames = FirstOutputTag->ParamNames;
FirstOutputTag->ParamNames = NULL;
FirstOutputTag->Mac->ParamDefVals = FirstOutputTag->ParamDefVals;
FirstOutputTag->ParamDefVals = NULL;
AddMacro(FirstOutputTag->Mac, FirstOutputTag->PubSect, True);
if ((FirstOutputTag->DoGlobCopy) && (SectionStack))
{
GMacro
= (PMacroRec
) malloc(sizeof(MacroRec
));
GMacro->Name = as_strdup(FirstOutputTag->GName);
GMacro->ParamCount = FirstOutputTag->Mac->ParamCount;
GMacro->FirstLine = DuplicateStringList(FirstOutputTag->Mac->FirstLine);
GMacro->ParamNames = DuplicateStringList(FirstOutputTag->Mac->ParamNames);
GMacro->ParamDefVals = DuplicateStringList(FirstOutputTag->Mac->ParamDefVals);
GMacro->UsesNumArgs = FirstOutputTag->Mac->UsesNumArgs;
GMacro->UsesAllArgs = FirstOutputTag->Mac->UsesAllArgs;
AddMacro(GMacro, FirstOutputTag->GlobSect, False);
}
}
else
{
ClearMacroRec(&(FirstOutputTag->Mac), TRUE);
}
Tmp = FirstOutputTag;
FirstOutputTag = Tmp->Next;
ClearStringList(&(Tmp->ParamNames));
ClearStringList(&(Tmp->ParamDefVals));
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Von hier her kommen bei einem Makroaufruf die expandierten Zeilen */
Boolean MACRO_Processor(PInputTag PInp, as_dynstr_t *p_dest)
{
StringRecPtr Lauf;
int z;
Boolean Result;
Result = True;
/* run to current line */
Lauf = PInp->Lines;
for (z = 1; z <= PInp->LineZ - 1; z++)
Lauf = Lauf->Next;
as_dynstr_copy_c_str(p_dest, Lauf->Content);
/* process parameters */
Lauf = PInp->Params;
for (z = 1; z <= PInp->ParCnt; z++)
{
ExpandLine(Lauf->Content, z, p_dest);
Lauf = Lauf->Next;
}
/* process special parameters */
if (HasAttrs)
ExpandLine(PInp->SaveAttr, ArgCntMax + 1, p_dest);
if (PInp->UsesNumArgs)
ExpandLine(PInp->NumArgs, ArgCntMax + 2, p_dest);
if (PInp->UsesAllArgs)
ExpandLine(PInp->AllArgs, ArgCntMax + 3, p_dest);
if (PInp->Macro->LocIntLabel)
ExpandLine(PInp->SaveLabel, ArgCntMax + 4, p_dest);
CurrLine = PInp->StartLine;
InMacroFlag = True;
/* before the first line, start a new local symbol space */
if ((PInp->LineZ == 1) && (!PInp->GlobalSymbols))
PushLocHandle(GetLocHandle());
/* signal the end of the macro */
if (++(PInp->LineZ) > PInp->LineCnt)
Result = False;
return Result;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Initialisierung des Makro-Einleseprozesses */
static Boolean ReadMacro_SearchArg(const char *pTest, const char *pComp, Boolean *pErg)
{
if (!as_strcasecmp(pTest, pComp))
{
*pErg = True;
return True;
}
else if ((strlen(pTest
) > 2) && (!as_strncasecmp
(pTest
, "NO", 2)) && (!as_strcasecmp
(pTest
+ 2, pComp
)))
{
*pErg = False;
return True;
}
else
return False;
}
static Boolean ReadMacro_SearchSect(char *Test_O, const char *Comp, Boolean *Erg, LongInt *Section)
{
char *p;
String Test, Sect;
strmaxcpy(Test, Test_O, STRINGSIZE); KillBlanks(Test);
if (!p)
*Sect = '\0';
else
{
strmaxcpy(Sect, p + 1, STRINGSIZE);
*p = '\0';
}
if ((strlen(Test
) > 2) && (!as_strncasecmp
(Test
, "NO", 2)) && (!as_strcasecmp
(Test
+ 2, Comp
)))
{
*Erg = False;
return True;
}
else if (!as_strcasecmp(Test, Comp))
{
tStrComp TmpComp;
*Erg = True;
StrCompMkTemp(&TmpComp, Sect, sizeof(Sect));
return (IdentifySection(&TmpComp, Section));
}
else
return False;
}
typedef struct
{
String PList;
POutputTag pOutputTag;
tLstMacroExpMod LstMacroExpMod;
Boolean DoPublic, DoIntLabel, GlobalSymbols;
Boolean ErrFlag;
int ParamCount;
} tReadMacroContext;
static void ExpandPList(String PList, const char *pArg, Boolean CtrlArg)
{
if (!*PList)
strmaxcat(PList, ",", STRINGSIZE);
if (CtrlArg)
strmaxcat(PList, "{", STRINGSIZE);
strmaxcat(PList, pArg, STRINGSIZE);
if (CtrlArg)
strmaxcat(PList, "}", STRINGSIZE);
}
static void ProcessMACROArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
{
tReadMacroContext *pContext = (tReadMacroContext*)pUser;
if (CtrlArg)
{
Boolean DoMacExp;
if (ReadMacro_SearchArg(pArg->str.p_str, "EXPORT", &(pContext->pOutputTag->DoExport)));
else if (ReadMacro_SearchArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
else if (ReadMacro_SearchArg(pArg->str.p_str, "EXPAND", &DoMacExp))
{
if (!AddLstMacroExpMod(&pContext->LstMacroExpMod, DoMacExp, eLstMacroExpAll))
WrStrErrorPos(ErrNum_TooManyMacExpMod, pArg);
ExpandPList(pContext->PList, pArg->str.p_str, CtrlArg);
}
else if (ReadMacro_SearchArg(pArg->str.p_str, "EXPIF", &DoMacExp))
{
if (!AddLstMacroExpMod(&pContext->LstMacroExpMod, DoMacExp, eLstMacroExpIf))
WrStrErrorPos(ErrNum_TooManyMacExpMod, pArg);
ExpandPList(pContext->PList, pArg->str.p_str, CtrlArg);
}
else if (ReadMacro_SearchArg(pArg->str.p_str, "EXPMACRO", &DoMacExp))
{
if (!AddLstMacroExpMod(&pContext->LstMacroExpMod, DoMacExp, eLstMacroExpMacro))
WrStrErrorPos(ErrNum_TooManyMacExpMod, pArg);
ExpandPList(pContext->PList, pArg->str.p_str, CtrlArg);
}
else if (ReadMacro_SearchArg(pArg->str.p_str, "EXPREST", &DoMacExp))
{
if (!AddLstMacroExpMod(&pContext->LstMacroExpMod, DoMacExp, eLstMacroExpRest))
WrStrErrorPos(ErrNum_TooManyMacExpMod, pArg);
ExpandPList(pContext->PList, pArg->str.p_str, CtrlArg);
}
else if (ReadMacro_SearchArg(pArg->str.p_str, "INTLABEL", &pContext->DoIntLabel))
{
ExpandPList(pContext->PList, pArg->str.p_str, CtrlArg);
}
else if (ReadMacro_SearchSect(pArg->str.p_str, "GLOBAL", &(pContext->pOutputTag->DoGlobCopy), &(pContext->pOutputTag->GlobSect)));
else if (ReadMacro_SearchSect(pArg->str.p_str, "PUBLIC", &pContext->DoPublic, &(pContext->pOutputTag->PubSect)));
else
{
WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
pContext->ErrFlag = True;
}
}
else
{
char *pDefault;
tStrComp Arg;
StrCompRefRight(&Arg, pArg, 0);
ExpandPList(pContext->PList, Arg.str.p_str, CtrlArg);
pDefault = QuotPos(Arg.str.p_str, '=');
if (pDefault)
{
Arg.Pos.Len = pDefault - Arg.str.p_str;
*pDefault++ = '\0';
KillPostBlanksStrComp(&Arg);
KillPrefBlanksStrComp(&Arg);
}
if (!ChkMacSymbName(Arg.str.p_str))
{
WrStrErrorPos(ErrNum_InvSymName, &Arg);
pContext->ErrFlag = True;
}
if (!CaseSensitive)
UpString(Arg.str.p_str);
AddStringListLast(&(pContext->pOutputTag->ParamNames), Arg.str.p_str);
AddStringListLast(&(pContext->pOutputTag->ParamDefVals), pDefault ? pDefault : "");
pContext->ParamCount++;
}
}
static void ReadMacro(void)
{
PSaveSection RunSection;
PMacroRec OneMacro;
tReadMacroContext Context;
LongInt HSect;
String macro_name_buf;
tStrComp macro_name;
const tStrComp *p_macro_name;
WasMACRO = True;
CodeLen = 0;
Context.ErrFlag = False;
/* Makronamen pruefen */
/* Definition nur im ersten Pass */
StrCompMkTemp(¯o_name, macro_name_buf, sizeof(macro_name_buf));
if (PassNo != 1)
{
Context.ErrFlag = True;
p_macro_name = &LabPart;
}
else
{
p_macro_name = ExpandStrSymbol(¯o_name, &LabPart, False);
if (!p_macro_name)
{
Context.ErrFlag = True;
p_macro_name = &LabPart;
}
else if (!ChkSymbName(p_macro_name->str.p_str))
{
WrStrErrorPos(ErrNum_InvSymName, &LabPart);
Context.ErrFlag = True;
}
}
/* create tag */
Context.pOutputTag = GenerateOUTProcessor(MACRO_OutProcessor, ErrNum_OpenMacro);
Context.pOutputTag->Next = FirstOutputTag;
/* check arguments, sort out control directives */
Context.LstMacroExpMod = LstMacroExpModDefault;
Context.DoPublic = False;
Context.DoIntLabel = False;
Context.GlobalSymbols = False;
*Context.PList = '\0';
Context.ParamCount = 0;
ProcessMacroArgs(ProcessMACROArgs, &Context);
/* contradicting macro expansion? */
if (!ChkLstMacroExpMod(&Context.LstMacroExpMod))
{
WrError(ErrNum_ConflictingMacExpMod);
Context.ErrFlag = True;
}
/* Abbruch bei Fehler */
if (Context.ErrFlag)
{
ClearStringList(&(Context.pOutputTag->ParamNames));
ClearStringList(&(Context.pOutputTag->ParamDefVals));
free(Context.
pOutputTag);
AddWaitENDM_Processor();
return;
}
/* Bei Globalisierung Namen des Extramakros ermitteln */
if (Context.pOutputTag->DoGlobCopy)
{
strmaxcpy(Context.pOutputTag->GName, MacroName, STRINGSIZE);
RunSection = SectionStack;
HSect = MomSectionHandle;
while ((HSect != Context.pOutputTag->GlobSect) && (RunSection != NULL))
{
strmaxprep(Context.pOutputTag->GName, "_", STRINGSIZE);
strmaxprep(Context.pOutputTag->GName, GetSectionName(HSect), STRINGSIZE);
HSect = RunSection->Handle;
RunSection = RunSection->Next;
}
}
if (!Context.DoPublic)
Context.pOutputTag->PubSect = MomSectionHandle;
/* chain in */
OneMacro
= (PMacroRec
) calloc(1, sizeof(MacroRec
));
OneMacro->FirstLine =
OneMacro->ParamNames =
OneMacro->ParamDefVals = NULL;
Context.pOutputTag->Mac = OneMacro;
if ((MacroOutput) && (Context.pOutputTag->DoExport))
{
errno = 0;
fprintf(MacroFile
, "%s MACRO %s\n",
Context.pOutputTag->DoGlobCopy ? Context.pOutputTag->GName : MacroName,
Context.PList);
ChkIO(ErrNum_FileWriteError);
}
OneMacro->UseCounter = 0;
OneMacro->Name = as_strdup(p_macro_name->str.p_str);
OneMacro->ParamCount = Context.ParamCount;
OneMacro->FirstLine = NULL;
OneMacro->LstMacroExpMod = Context.LstMacroExpMod;
OneMacro->LocIntLabel = Context.DoIntLabel;
OneMacro->GlobalSymbols = Context.GlobalSymbols;
FirstOutputTag = Context.pOutputTag;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Beendigung der Expansion eines Makros */
static void MACRO_Cleanup(PInputTag PInp)
{
ClearStringList(&(PInp->Params));
}
static Boolean MACRO_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
{
UNUSED(ActGNUErrors);
as_snprintf(dest, DestSize, "%s(%lu) ", PInp->SpecName.str.p_str, (unsigned long)(PInp->LineZ - 1));
return False;
}
static void MACRO_Restorer(PInputTag PInp)
{
/* discard the local symbol space */
if (!PInp->GlobalSymbols)
PopLocHandle();
/* undo the recursion counter by one */
if ((PInp->Macro) && (PInp->Macro->UseCounter > 0))
PInp->Macro->UseCounter--;
/* restore list flag */
DoLst = PInp->OrigDoLst;
/* decrement macro nesting counter only if this actually was a macro */
if (PInp->Processor == MACRO_Processor)
MacroNestLevel--;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Dies initialisiert eine Makroexpansion */
static void ExpandMacro(PMacroRec OneMacro)
{
int z1, z2;
StringRecPtr Lauf, pDefault, pParamName, pArg;
PInputTag Tag = NULL;
Boolean NamedArgs;
char *p;
CodeLen = 0;
if ((NestMax > 0) && (OneMacro->UseCounter > NestMax)) WrError(ErrNum_RekMacro);
else
{
OneMacro->UseCounter++;
/* 1. Tag erzeugen */
Tag = GenerateProcessor();
Tag->Processor = MACRO_Processor;
Tag->Restorer = MACRO_Restorer;
Tag->Cleanup = MACRO_Cleanup;
Tag->GetPos = MACRO_GetPos;
Tag->Macro = OneMacro;
Tag->GlobalSymbols = OneMacro->GlobalSymbols;
Tag->UsesNumArgs = OneMacro->UsesNumArgs;
Tag->UsesAllArgs = OneMacro->UsesAllArgs;
strmaxcpy(Tag->SpecName.str.p_str, OneMacro->Name, STRINGSIZE);
strmaxcpy(Tag->SaveAttr, AttrPart.str.p_str, STRINGSIZE);
if (OneMacro->LocIntLabel)
strmaxcpy(Tag->SaveLabel, LabPart.str.p_str, STRINGSIZE);
Tag->IsMacro = True;
/* 2. Store special parameters - in the original form.
Omit this if they aren't used at all in the macro's body. */
Tag->NumArgs[0] = '\0';
if (Tag->UsesNumArgs)
as_snprintf(Tag->NumArgs, sizeof(Tag->NumArgs), "%d", ArgCnt);
Tag->AllArgs[0] = '\0';
if (Tag->UsesAllArgs)
{
for (z1 = 1; z1 <= ArgCnt; z1++)
{
if (z1 != 1) strmaxcat(Tag->AllArgs, ",", STRINGSIZE);
strmaxcat(Tag->AllArgs, ArgStr[z1].str.p_str, STRINGSIZE);
}
}
Tag->ParCnt = OneMacro->ParamCount;
/* 3. generate argument list */
/* 3a. initialize with empty defaults - order is irrelevant at this point: */
for (z1 = OneMacro->ParamCount; z1 >= 1; z1--)
AddStringListFirst(&(Tag->Params), NULL);
/* 3b. walk over given arguments */
NamedArgs = False;
for (z1 = 1; z1 <= ArgCnt; z1++)
{
if (!CaseSensitive) UpString(ArgStr[z1].str.p_str);
/* explicit name given? */
p = QuotPos(ArgStr[z1].str.p_str, '=');
/* if parameter name given... */
if (p)
{
/* split it off */
*p++ = '\0';
KillPostBlanksStrComp(&ArgStr[z1]);
KillPrefBlanks(p);
/* search parameter by name */
for (pParamName = OneMacro->ParamNames, pArg = Tag->Params;
pParamName; pParamName = pParamName->Next, pArg = pArg->Next)
if (!strcmp(ArgStr
[z1
].
str.
p_str, pParamName
->Content
))
{
if (pArg->Content)
{
WrXError(ErrNum_MacArgRedef, pParamName->Content);
}
pArg->Content = as_strdup(p);
break;
}
if (!pParamName)
WrStrErrorPos(ErrNum_UndefKeyArg, &ArgStr[z1]);
/* set flag that no unnamed args are any longer allowed */
NamedArgs = True;
}
/* do not mix unnamed with named arguments: */
else if (NamedArgs)
WrError(ErrNum_NoPosArg);
/* empty positional parameters mean using defaults - insert non-empty args here: */
else if ((z1
<= OneMacro
->ParamCount
) && (strlen(ArgStr
[z1
].
str.
p_str) > 0))
{
pArg = Tag->Params;
pParamName = OneMacro->ParamNames;
for (z2 = 0; z2 < z1 - 1; z2++)
{
pParamName = pParamName->Next;
pArg = pArg->Next;
}
if (pArg->Content)
{
WrXError(ErrNum_MacArgRedef, pParamName->Content);
}
pArg->Content = as_strdup(ArgStr[z1].str.p_str);
}
/* excess unnamed arguments: append at end of list */
else if (z1 > OneMacro->ParamCount)
AddStringListLast(&(Tag->Params), ArgStr[z1].str.p_str);
}
/* 3c. fill in defaults */
for (pParamName = OneMacro->ParamNames, pArg = Tag->Params, pDefault = OneMacro->ParamDefVals;
pParamName; pParamName = pParamName->Next, pArg = pArg->Next, pDefault = pDefault->Next)
if (!pArg->Content)
pArg->Content = as_strdup(pDefault->Content);
/* 4. Zeilenliste anhaengen */
Tag->Lines = OneMacro->FirstLine;
Tag->IsEmpty = !OneMacro->FirstLine;
Lauf = OneMacro->FirstLine;
while (Lauf)
{
Tag->LineCnt++;
Lauf = Lauf->Next;
}
}
/* 5. anhaengen */
if (Tag)
{
if (IfAsm)
{
/* override has higher prio, so apply as second */
NextDoLst = ApplyLstMacroExpMod(DoLst, &OneMacro->LstMacroExpMod);
NextDoLst = ApplyLstMacroExpMod(NextDoLst, &LstMacroExpModOverride);
Tag->Next = FirstInputTag;
FirstInputTag = Tag;
MacroNestLevel++;
}
else
{
ClearStringList
(&(Tag
->Params
)); free(Tag
);
}
}
}
/*-------------------------------------------------------------------------*/
/* vorzeitiger Abbruch eines Makros */
static void ExpandEXITM(void)
{
WasMACRO = True;
if (!ChkArgCnt(0, 0));
else if (!FirstInputTag) WrError(ErrNum_EXITMOutsideMacro);
else if (!FirstInputTag->IsMacro) WrError(ErrNum_EXITMOutsideMacro);
else if (IfAsm)
{
FirstInputTag->Cleanup(FirstInputTag);
RestoreIFs(FirstInputTag->IfLevel);
FirstInputTag->IsEmpty = True;
}
}
/*-------------------------------------------------------------------------*/
/* discard first argument */
static void ExpandSHIFT(void)
{
PInputTag RunTag;
WasMACRO = True;
if (!ChkArgCnt(0, 0));
else if (!FirstInputTag) WrError(ErrNum_EXITMOutsideMacro);
else if (!FirstInputTag->IsMacro) WrError(ErrNum_EXITMOutsideMacro);
else if (IfAsm)
{
for (RunTag = FirstInputTag; RunTag; RunTag = RunTag->Next)
if (RunTag->Processor == MACRO_Processor)
break;
if (RunTag && RunTag->Params)
{
char *p_arg = MoveAndCutStringListFirst(&RunTag->Params);
if (p_arg)
RunTag->ParCnt--;
ComputeMacroStrings(RunTag);
}
}
}
/*-------------------------------------------------------------------------*/
/*--- IRP (was das bei MASM auch immer heissen mag...)
Ach ja: Individual Repeat! Danke Bernhard, jetzt hab'
ich's gerafft! -----------------------*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Diese Routine liefert bei der Expansion eines IRP-Statements die expan-
dierten Zeilen */
Boolean IRP_Processor(PInputTag PInp, as_dynstr_t *p_dest)
{
StringRecPtr Lauf;
int z;
Boolean Result;
Result = True;
/* increment line counter only if contents came from a true file */
CurrLine = PInp->StartLine;
if (PInp->FromFile)
CurrLine += PInp->LineZ;
/* first line? Then open new symbol space and reset line pointer */
if (PInp->LineZ == 1)
{
if (!PInp->GlobalSymbols)
{
if (!PInp->First) PopLocHandle();
PushLocHandle(GetLocHandle());
}
PInp->First = False;
PInp->LineRun = PInp->Lines;
}
/* extract line */
as_dynstr_copy_c_str(p_dest, PInp->LineRun->Content);
PInp->LineRun = PInp->LineRun->Next;
/* expand iteration parameter */
Lauf = PInp->Params; for (z = 1; z <= PInp->ParZ - 1; z++)
Lauf = Lauf->Next;
ExpandLine(Lauf->Content, 1, p_dest);
/* end of body? then reset to line 1 and exit if this was the last iteration */
if (++(PInp->LineZ) > PInp->LineCnt)
{
PInp->LineZ = 1;
if (++(PInp->ParZ) > PInp->ParCnt)
Result = False;
}
return Result;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Aufraeumroutine IRP/IRPC */
static void IRP_Cleanup(PInputTag PInp)
{
StringRecPtr Lauf;
/* letzten Parameter sichern, wird evtl. noch fuer GetPos gebraucht!
... SaveAttr ist aber frei */
if (PInp->Processor == IRP_Processor)
{
for (Lauf = PInp->Params; Lauf->Next; Lauf = Lauf->Next);
strmaxcpy(PInp->SaveAttr, Lauf->Content, STRINGSIZE);
}
ClearStringList(&(PInp->Lines));
ClearStringList(&(PInp->Params));
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Posisionsangabe im IRP(C) fuer Fehlermeldungen */
static Boolean IRP_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
{
int z, ParZ = PInp->ParZ, LineZ = PInp->LineZ;
const char *IRPType;
char *IRPVal, tmp[20];
UNUSED(ActGNUErrors);
/* LineZ/ParZ already hopped to next line - step one back: */
if (--LineZ <= 0)
{
LineZ = PInp->LineCnt;
ParZ--;
}
if (PInp->Processor == IRP_Processor)
{
IRPType = "IRP";
if (*PInp->SaveAttr != '\0')
IRPVal = PInp->SaveAttr;
else
{
StringRecPtr Lauf = PInp->Params;
for (z = 1; z <= ParZ - 1; z++)
Lauf = Lauf->Next;
IRPVal = Lauf->Content;
}
}
else
{
IRPType = "IRPC";
as_snprintf(tmp, sizeof(tmp), "'%c'", PInp->SpecName.str.p_str[ParZ - 1]);
IRPVal = tmp;
}
as_snprintf(dest, DestSize, "%s:%s(%lu) ", IRPType, IRPVal, (unsigned long)LineZ);
return False;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Diese Routine sammelt waehrend der Definition eines IRP(C)-Statements die
Quellzeilen ein */
static void IRP_OutProcessor(void)
{
POutputTag Tmp;
WasMACRO = True;
/* Schachtelungen mitzaehlen */
if (MacroStart())
FirstOutputTag->NestLevel++;
else if (MacroEnd())
FirstOutputTag->NestLevel--;
/* falls noch nicht zuende, weiterzaehlen */
if (FirstOutputTag->NestLevel > -1)
{
as_dynstr_t s;
StringRecPtr Dummy;
const char *p_first_param = GetStringListFirst(FirstOutputTag->ParamNames, &Dummy);
as_dynstr_ini_clone(&s, &OneLine); KillCtrl(s.p_str);
CompressLine(p_first_param ? p_first_param : "", 1, &s, CaseSensitive);
AddStringListLast(&(FirstOutputTag->Tag->Lines), s.p_str);
as_dynstr_free(&s);
FirstOutputTag->Tag->LineCnt++;
}
/* alles zusammen? Dann umhaengen */
if (FirstOutputTag->NestLevel == -1)
{
Tmp = FirstOutputTag;
FirstOutputTag = FirstOutputTag->Next;
Tmp->Tag->IsEmpty = !Tmp->Tag->Lines;
if (IfAsm)
{
NextDoLst = ApplyLstMacroExpMod(DoLst, &LstMacroExpModDefault);
NextDoLst = ApplyLstMacroExpMod(NextDoLst, &LstMacroExpModOverride);
Tmp->Tag->Next = FirstInputTag;
FirstInputTag = Tmp->Tag;
}
else
{
ClearStringList(&(Tmp->Tag->Lines));
ClearStringList(&(Tmp->Tag->Params));
}
ClearStringList(&(Tmp->ParamNames));
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Initialisierung der IRP-Bearbeitung */
typedef struct
{
Boolean ErrFlag;
Boolean GlobalSymbols;
int ArgCnt;
POutputTag pOutputTag;
StringList Params;
} tExpandIRPContext;
static void ProcessIRPArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
{
tExpandIRPContext *pContext = (tExpandIRPContext*)pUser;
if (CtrlArg)
{
if (ReadMacro_SearchArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
else
{
WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
pContext->ErrFlag = True;
}
}
else
{
/* differentiate placeholder & arguments */
if (0 == pContext->ArgCnt)
{
if (!ChkMacSymbName(pArg->str.p_str))
{
WrStrErrorPos(ErrNum_InvSymName, pArg);
pContext->ErrFlag = True;
}
else
AddStringListFirst(&(pContext->pOutputTag->ParamNames), pArg->str.p_str);
}
else
{
if (!CaseSensitive)
UpString(pArg->str.p_str);
AddStringListLast(&(pContext->Params), pArg->str.p_str);
}
pContext->ArgCnt++;
}
}
static Boolean ExpandIRP(void)
{
PInputTag Tag;
tExpandIRPContext Context;
WasMACRO = True;
/* 0. terminate if conditional assembly bites */
if (!IfAsm)
{
AddWaitENDM_Processor();
return True;
}
/* 1. Parameter pruefen */
Context.ErrFlag = False;
Context.GlobalSymbols = False;
Context.ArgCnt = 0;
Context.Params = NULL;
Context.pOutputTag = GenerateOUTProcessor(IRP_OutProcessor, ErrNum_OpenIRP);
Context.pOutputTag->Next = FirstOutputTag;
ProcessMacroArgs(ProcessIRPArgs, &Context);
/* at least parameter & one arg */
if (!ChkArgCntExt(Context.ArgCnt, 2, ArgCntMax))
Context.ErrFlag = True;
if (Context.ErrFlag)
{
ClearStringList(&(Context.pOutputTag->ParamNames));
ClearStringList(&(Context.pOutputTag->ParamDefVals));
ClearStringList(&(Context.Params));
free(Context.
pOutputTag);
AddWaitENDM_Processor();
return False;
}
/* 2. Tag erzeugen */
Tag = GenerateProcessor();
Tag->ParCnt = Context.ArgCnt - 1;
Tag->Params = Context.Params;
Tag->Processor = IRP_Processor;
Tag->Restorer = MACRO_Restorer;
Tag->Cleanup = IRP_Cleanup;
Tag->GetPos = IRP_GetPos;
Tag->GlobalSymbols = Context.GlobalSymbols;
Tag->ParZ = 1;
Tag->IsMacro = True;
*Tag->SaveAttr = '\0';
Context.pOutputTag->Tag = Tag;
/* 4. einbetten */
FirstOutputTag = Context.pOutputTag;
return True;
}
/*--- IRPC: dito fuer Zeichen eines Strings ---------------------------------*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Diese Routine liefert bei der Expansion eines IRPC-Statements die expan-
dierten Zeilen */
Boolean IRPC_Processor(PInputTag PInp, as_dynstr_t *p_dest)
{
Boolean Result;
char tmp[5];
Result = True;
/* increment line counter only if contents came from a true file */
CurrLine = PInp->StartLine;
if (PInp->FromFile)
CurrLine += PInp->LineZ;
/* first line? Then open new symbol space and reset line pointer */
if (PInp->LineZ == 1)
{
if (!PInp->GlobalSymbols)
{
if (!PInp->First) PopLocHandle();
PushLocHandle(GetLocHandle());
}
PInp->First = False;
PInp->LineRun = PInp->Lines;
}
/* extract line */
as_dynstr_copy_c_str(p_dest, PInp->LineRun->Content);
PInp->LineRun = PInp->LineRun->Next;
/* extract iteration parameter */
*tmp = PInp->SpecName.str.p_str[PInp->ParZ - 1];
tmp[1] = '\0';
ExpandLine(tmp, 1, p_dest);
/* end of body? then reset to line 1 and exit if this was the last iteration */
if (++(PInp->LineZ) > PInp->LineCnt)
{
PInp->LineZ = 1;
if (++(PInp->ParZ) > PInp->ParCnt)
Result = False;
}
return Result;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Initialisierung der IRPC-Bearbeitung */
typedef struct
{
Boolean ErrFlag;
Boolean GlobalSymbols;
int ArgCnt;
POutputTag pOutputTag;
String ParameterStr;
tStrComp Parameter;
} tExpandIRPCContext;
static void ProcessIRPCArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
{
tExpandIRPCContext *pContext = (tExpandIRPCContext*)pUser;
if (CtrlArg)
{
if (ReadMacro_SearchArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
else
{
WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
pContext->ErrFlag = True;
}
}
else
{
if (0 == pContext->ArgCnt)
{
if (!ChkMacSymbName(pArg->str.p_str))
{
WrStrErrorPos(ErrNum_InvSymName, pArg);
pContext->ErrFlag = True;
}
else
AddStringListFirst(&(pContext->pOutputTag->ParamNames), pArg->str.p_str);
}
else
{
Boolean OK;
EvalStrStringExpression(pArg, &OK, pContext->Parameter.str.p_str);
pContext->Parameter.Pos = pArg->Pos;
if (!OK)
pContext->ErrFlag = True;
}
pContext->ArgCnt++;
}
}
static Boolean ExpandIRPC(void)
{
PInputTag Tag;
tExpandIRPCContext Context;
WasMACRO = True;
/* 0. terminate if conditinal assembly bites */
if (!IfAsm)
{
AddWaitENDM_Processor();
return True;
}
/* 1.Parameter pruefen */
Context.ErrFlag = False;
Context.GlobalSymbols = False;
Context.ArgCnt = 0;
StrCompMkTemp(&Context.Parameter, Context.ParameterStr, sizeof(Context.ParameterStr));
StrCompReset(&Context.Parameter);
Context.pOutputTag = GenerateOUTProcessor(IRP_OutProcessor, ErrNum_OpenIRPC);
Context.pOutputTag->Next = FirstOutputTag;
ProcessMacroArgs(ProcessIRPCArgs, &Context);
/* parameter & string */
if (!ChkArgCntExt(Context.ArgCnt, 2, ArgCntMax))
Context.ErrFlag = True;
if (Context.ErrFlag)
{
ClearStringList(&(Context.pOutputTag->ParamNames));
AddWaitENDM_Processor();
return False;
}
/* 2. Tag erzeugen */
Tag = GenerateProcessor();
Tag
->ParCnt
= strlen(Context.
Parameter.
str.
p_str);
Tag->Processor = IRPC_Processor;
Tag->Restorer = MACRO_Restorer;
Tag->Cleanup = IRP_Cleanup;
Tag->GetPos = IRP_GetPos;
Tag->GlobalSymbols = Context.GlobalSymbols;
Tag->ParZ = 1;
Tag->IsMacro = True;
*Tag->SaveAttr = '\0';
StrCompCopy(&Tag->SpecName, &Context.Parameter);
/* 4. einbetten */
Context.pOutputTag->Tag = Tag;
FirstOutputTag = Context.pOutputTag;
return True;
}
/*--- Repetition -----------------------------------------------------------*/
static void REPT_Cleanup(PInputTag PInp)
{
ClearStringList(&(PInp->Lines));
}
static Boolean REPT_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
{
int z1 = PInp->ParZ, z2 = PInp->LineZ;
UNUSED(ActGNUErrors);
if (--z2 <= 0)
{
z2 = PInp->LineCnt;
z1--;
}
as_snprintf(dest, DestSize, "REPT %lu(%lu)", (unsigned long)z1, (unsigned long)z2);
return False;
}
Boolean REPT_Processor(PInputTag PInp, as_dynstr_t *p_dest)
{
Boolean Result;
Result = True;
/* increment line counter only if contents came from a true file */
CurrLine = PInp->StartLine;
if (PInp->FromFile)
CurrLine += PInp->LineZ;
/* first line? Then open new symbol space and reset line pointer */
if (PInp->LineZ == 1)
{
if (!PInp->GlobalSymbols)
{
if (!PInp->First) PopLocHandle();
PushLocHandle(GetLocHandle());
}
PInp->First = False;
PInp->LineRun = PInp->Lines;
}
/* extract line */
as_dynstr_copy_c_str(p_dest, PInp->LineRun->Content);
PInp->LineRun = PInp->LineRun->Next;
/* last line of body? Then increment count and stop if last iteration */
if ((++PInp->LineZ) > PInp->LineCnt)
{
PInp->LineZ = 1;
if ((++PInp->ParZ) > PInp->ParCnt)
Result = False;
}
return Result;
}
static void REPT_OutProcessor(void)
{
POutputTag Tmp;
WasMACRO = True;
/* Schachtelungen mitzaehlen */
if (MacroStart())
FirstOutputTag->NestLevel++;
else if (MacroEnd())
FirstOutputTag->NestLevel--;
/* falls noch nicht zuende, weiterzaehlen */
if (FirstOutputTag->NestLevel > -1)
{
AddStringListLast(&(FirstOutputTag->Tag->Lines), OneLine.p_str);
FirstOutputTag->Tag->LineCnt++;
}
/* alles zusammen? Dann umhaengen */
if (FirstOutputTag->NestLevel == -1)
{
Tmp = FirstOutputTag;
FirstOutputTag = FirstOutputTag->Next;
Tmp->Tag->IsEmpty = !Tmp->Tag->Lines;
if ((IfAsm) && (Tmp->Tag->ParCnt > 0))
{
NextDoLst = ApplyLstMacroExpMod(DoLst, &LstMacroExpModDefault);
NextDoLst = ApplyLstMacroExpMod(NextDoLst, &LstMacroExpModOverride);
Tmp->Tag->Next = FirstInputTag;
FirstInputTag = Tmp->Tag;
}
else
{
ClearStringList(&(Tmp->Tag->Lines));
}
}
}
typedef struct
{
Boolean ErrFlag;
Boolean GlobalSymbols;
int ArgCnt;
LongInt ReptCount;
} tExpandREPTContext;
static void ProcessREPTArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
{
tExpandREPTContext *pContext = (tExpandREPTContext*)pUser;
if (CtrlArg)
{
if (ReadMacro_SearchArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
else
{
WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
pContext->ErrFlag = True;
}
}
else
{
Boolean ValOK;
tSymbolFlags SymbolFlags;
pContext->ReptCount = EvalStrIntExpressionWithFlags(pArg, Int32, &ValOK, &SymbolFlags);
if (mFirstPassUnknown(SymbolFlags))
WrStrErrorPos(ErrNum_FirstPassCalc, pArg);
if (!ValOK || mFirstPassUnknown(SymbolFlags))
pContext->ErrFlag = True;
pContext->ArgCnt++;
}
}
static Boolean ExpandREPT(void)
{
PInputTag Tag;
POutputTag Neu;
tExpandREPTContext Context;
WasMACRO = True;
/* 0. skip everything when conditional assembly is off */
if (!IfAsm)
{
AddWaitENDM_Processor();
return True;
}
/* 1. Repetitionszahl ermitteln */
Context.GlobalSymbols = False;
Context.ReptCount = 0;
Context.ErrFlag = False;
Context.ArgCnt = 0;
ProcessMacroArgs(ProcessREPTArgs, &Context);
/* rept count must be present only once */
if (!ChkArgCntExt(Context.ArgCnt, 1, 1))
Context.ErrFlag = True;
if (Context.ErrFlag)
{
AddWaitENDM_Processor();
return False;
}
/* 2. Tag erzeugen */
Tag = GenerateProcessor();
Tag->ParCnt = Context.ReptCount;
Tag->Processor = REPT_Processor;
Tag->Restorer = MACRO_Restorer;
Tag->Cleanup = REPT_Cleanup;
Tag->GetPos = REPT_GetPos;
Tag->GlobalSymbols = Context.GlobalSymbols;
Tag->IsMacro = True;
Tag->ParZ = 1;
/* 3. einbetten */
Neu = GenerateOUTProcessor(REPT_OutProcessor, ErrNum_OpenREPT);
Neu->Next = FirstOutputTag;
Neu->Tag = Tag;
FirstOutputTag = Neu;
return True;
}
/*- bedingte Wiederholung -------------------------------------------------------*/
static void WHILE_Cleanup(PInputTag PInp)
{
ClearStringList(&(PInp->Lines));
}
static Boolean WHILE_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
{
int z1 = PInp->ParZ, z2 = PInp->LineZ;
UNUSED(ActGNUErrors);
if (--z2 <= 0)
{
z2 = PInp->LineCnt;
z1--;
}
as_snprintf(dest, DestSize, "WHILE %lu/%lu", (unsigned long)z1, (unsigned long)z2);
return False;
}
Boolean WHILE_Processor(PInputTag PInp, as_dynstr_t *p_dest)
{
int z;
Boolean OK, Result;
/* increment line counter only if this came from a true file */
CurrLine = PInp->StartLine;
if (PInp->FromFile)
CurrLine += PInp->LineZ;
/* if this is the first line of the loop body, open a new handle
for macro-local symbols and drop the old one if this was not the
first pass through the body. */
if (PInp->LineZ == 1)
{
if (!PInp->GlobalSymbols)
{
if (!PInp->First)
PopLocHandle();
PushLocHandle(GetLocHandle());
}
PInp->First = False;
PInp->LineRun = PInp->Lines;
}
/* evaluate condition before first line */
if (PInp->LineZ == 1)
{
z = EvalStrIntExpression(&PInp->SpecName, Int32, &OK);
Result = (OK && (z != 0));
}
else
Result = True;
if (Result)
{
/* get line of body */
as_dynstr_copy_c_str(p_dest, PInp->LineRun->Content);
PInp->LineRun = PInp->LineRun->Next;
/* in case this is the last line of the body, reset counters */
if ((++PInp->LineZ) > PInp->LineCnt)
{
PInp->LineZ = 1;
PInp->ParZ++;
}
}
/* nasty last line... */
else
*p_dest->p_str = '\0';
return Result;
}
static void WHILE_OutProcessor(void)
{
POutputTag Tmp;
Boolean OK;
tSymbolFlags SymbolFlags;
LongInt Erg;
WasMACRO = True;
/* Schachtelungen mitzaehlen */
if (MacroStart())
FirstOutputTag->NestLevel++;
else if (MacroEnd())
FirstOutputTag->NestLevel--;
/* falls noch nicht zuende, weiterzaehlen */
if (FirstOutputTag->NestLevel > -1)
{
AddStringListLast(&(FirstOutputTag->Tag->Lines), OneLine.p_str);
FirstOutputTag->Tag->LineCnt++;
}
/* alles zusammen? Dann umhaengen */
if (FirstOutputTag->NestLevel == -1)
{
Tmp = FirstOutputTag;
FirstOutputTag = FirstOutputTag->Next;
Tmp->Tag->IsEmpty = !Tmp->Tag->Lines;
Erg = EvalStrIntExpressionWithFlags(&Tmp->Tag->SpecName, Int32, &OK, &SymbolFlags);
if (mFirstPassUnknown(SymbolFlags))
{
WrError(ErrNum_FirstPassCalc);
OK = False;
}
OK = (OK && (Erg != 0));
if (IfAsm && OK)
{
NextDoLst = ApplyLstMacroExpMod(DoLst, &LstMacroExpModDefault);
NextDoLst = ApplyLstMacroExpMod(NextDoLst, &LstMacroExpModOverride);
Tmp->Tag->Next = FirstInputTag;
FirstInputTag = Tmp->Tag;
}
else
{
ClearStringList(&(Tmp->Tag->Lines));
}
}
}
typedef struct
{
Boolean ErrFlag;
Boolean GlobalSymbols;
int ArgCnt;
String SpecNameStr;
tStrComp SpecName;
} tExpandWHILEContext;
static void ProcessWHILEArgs(Boolean CtrlArg, const tStrComp *pArg, void *pUser)
{
tExpandWHILEContext *pContext = (tExpandWHILEContext*)pUser;
if (CtrlArg)
{
if (ReadMacro_SearchArg(pArg->str.p_str, "GLOBALSYMBOLS", &pContext->GlobalSymbols));
else
{
WrStrErrorPos(ErrNum_UnknownMacArg, pArg);
pContext->ErrFlag = True;
}
}
else
{
StrCompCopy(&pContext->SpecName, pArg);
pContext->ArgCnt++;
}
}
static Boolean ExpandWHILE(void)
{
PInputTag Tag;
POutputTag Neu;
tExpandWHILEContext Context;
WasMACRO = True;
/* 0. turned off ? */
if (!IfAsm)
{
AddWaitENDM_Processor();
return True;
}
/* 1. Bedingung ermitteln */
Context.GlobalSymbols = False;
Context.ErrFlag = False;
Context.ArgCnt = 0;
StrCompMkTemp(&Context.SpecName, Context.SpecNameStr, sizeof(Context.SpecNameStr));
StrCompReset(&Context.SpecName);
ProcessMacroArgs(ProcessWHILEArgs, &Context);
/* condition must be present only once */
if (!ChkArgCntExt(Context.ArgCnt, 1, 1))
Context.ErrFlag = True;
if (Context.ErrFlag)
{
AddWaitENDM_Processor();
return False;
}
/* 2. Tag erzeugen */
Tag = GenerateProcessor();
Tag->Processor = WHILE_Processor;
Tag->Restorer = MACRO_Restorer;
Tag->Cleanup = WHILE_Cleanup;
Tag->GetPos = WHILE_GetPos;
Tag->GlobalSymbols = Context.GlobalSymbols;
Tag->IsMacro = True;
Tag->ParZ = 1;
StrCompCopy(&Tag->SpecName, &Context.SpecName);
/* 3. einbetten */
Neu = GenerateOUTProcessor(WHILE_OutProcessor, ErrNum_OpenWHILE);
Neu->Next = FirstOutputTag;
Neu->Tag = Tag;
FirstOutputTag = Neu;
return True;
}
/*--------------------------------------------------------------------------*/
/* Einziehen von Include-Files */
static void INCLUDE_Cleanup(PInputTag PInp)
{
/* if last line in file was continued, do not forget to add up
continuation lines: */
LineSum += PInp->LineZ + PInp->ContLineCnt;
if ((*LstName != '\0') && (msg_level >= e_msg_level_normal))
{
String Tmp;
as_snprintf(Tmp, sizeof(Tmp), "%s(%lu)", NamePart(CurrFileName), (unsigned long)CurrLine);
WrConsoleLine(Tmp, True);
}
if (MakeIncludeList)
PopInclude();
CurrIncludeLevel = PInp->IncludeLevel;
}
static Boolean INCLUDE_GetPos(PInputTag PInp, char *dest, size_t DestSize, Boolean ActGNUErrors)
{
UNUSED(PInp);
as_snprintf(dest, DestSize, ActGNUErrors ? "%s:%lu" : "%s(%lu) ", NamePart(PInp->SpecName.str.p_str), (unsigned long)PInp->LineZ);
return !GNUErrors;
}
Boolean INCLUDE_Processor(PInputTag PInp, as_dynstr_t *p_dest)
{
Boolean Result;
int Count = 1;
/* add up # of continuation lines from previous source line */
if (PInp->ContLineCnt)
{
CurrLine = (PInp->LineZ += PInp->ContLineCnt);
PInp->ContLineCnt = 0;
}
Result = True;
*p_dest->p_str = '\0';
else
{
Count = ReadLnCont(PInp->Datei, p_dest);
/**ChkIO(ErrNum_FileReadError);**/
}
/* Even if we had continuation lines, only increment line counter
by one at this place so the first line's # is the number of the
concatenated line: */
if (Count > 0)
{
PInp->LineZ++;
CurrLine = PInp->LineZ;
PInp->ContLineCnt = Count - 1;
}
Result = False;
return Result;
}
static void INCLUDE_Restorer(PInputTag PInp)
{
CurrLine = PInp->StartLine;
strmaxcpy(CurrFileName, PInp->SaveAttr, STRINGSIZE);
IncDepth--;
}
/*!------------------------------------------------------------------------
* \fn ExpandINCLUDE_Core(const tStrComp *pArg, Boolean SearchPath)
* \brief The actual core code to open a source file for assembly
* \param pArg file's name to open
* \param SearchPath searhc file in include path?
* ------------------------------------------------------------------------ */
static void ExpandINCLUDE_Core(const tStrComp *pArg, Boolean SearchPath)
{
tStrComp FNameArg;
String FNameArgStr;
PInputTag Tag;
StrCompMkTemp(&FNameArg, FNameArgStr, sizeof(FNameArgStr));
INCLUDE_SearchCore(&FNameArg, pArg, SearchPath);
/* Tag erzeugen */
Tag = GenerateProcessor();
Tag->Processor = INCLUDE_Processor;
Tag->Restorer = INCLUDE_Restorer;
Tag->Cleanup = INCLUDE_Cleanup;
Tag->GetPos = INCLUDE_GetPos;
Tag
->Buffer
= (void *) malloc(BufferArraySize
);
/* Sicherung alter Daten */
Tag->StartLine = CurrLine;
strmaxcpy(Tag->SpecName.str.p_str, FNameArg.str.p_str, STRINGSIZE);
LineCompReset(&Tag->SpecName.Pos);
strmaxcpy(Tag->SaveAttr, CurrFileName, STRINGSIZE);
/* Datei oeffnen */
#ifdef __CYGWIN32__
DeCygwinPath(FNameArg.str.p_str);
#endif
Tag
->Datei
= fopen(FNameArg.
str.
p_str, "r");
if (!Tag->Datei) ChkStrIO(ErrNum_OpeningFile, pArg);
setvbuf(Tag
->Datei
, (char*)Tag
->Buffer
, _IOFBF
, BufferArraySize
);
/* neu besetzen */
strmaxcpy(CurrFileName, FNameArg.str.p_str, STRINGSIZE);
Tag->LineZ = 0;
AddFile(FNameArg.str.p_str);
PushInclude(FNameArg.str.p_str);
if (++CurrIncludeLevel > MaxIncludeLevel)
WrStrErrorPos(ErrNum_MaxIncLevelExceeded, pArg);
/* einhaengen */
Tag->Next = FirstInputTag; FirstInputTag = Tag;
}
/*!------------------------------------------------------------------------
* \fn ExpandINCLUDE(void)
* \brief Handle INCLUDE statement
* ------------------------------------------------------------------------ */
static void ExpandINCLUDE(void)
{
if (!IfAsm)
return;
if (!ChkArgCnt(1, 1))
return;
ExpandINCLUDE_Core(&ArgStr[1], True);
NextIncDepth++;
}
/*=========================================================================*/
/* Einlieferung von Zeilen */
static void GetNextLine(as_dynstr_t *pLine)
{
PInputTag HTag;
InMacroFlag = False;
while (FirstInputTag && FirstInputTag->IsEmpty)
{
FirstInputTag->Cleanup(FirstInputTag);
FirstInputTag->Restorer(FirstInputTag);
HTag = FirstInputTag;
FirstInputTag = HTag->Next;
}
if (!FirstInputTag)
{
*pLine->p_str = '\0';
return;
}
if (!FirstInputTag->Processor(FirstInputTag, pLine))
{
FirstInputTag->IsEmpty = True;
}
MacLineSum++;
}
typedef struct
{
char *pStr;
size_t AllocLen;
} tAllocStr;
static void InitStr(tAllocStr *pStr)
{
pStr->pStr = NULL;
pStr->AllocLen = 0;
}
static void ReallocStr(tAllocStr *pStr, unsigned NewAllocLen)
{
if (NewAllocLen > pStr->AllocLen)
{
char *pNewStr;
/* round up, and implicitly avoid allocating 4/8 bytes (sizeof pointer)
so size check in as_vsnprcatf() does not generate false positive: */
NewAllocLen = (NewAllocLen + 15) &~15;
pNewStr = pStr->AllocLen
? (char*)realloc(pStr
->pStr
, NewAllocLen
)
if (pNewStr)
{
pStr->pStr = pNewStr;
pStr->pStr[pStr->AllocLen] = '\0';
pStr->AllocLen = NewAllocLen;
}
}
}
char *GetErrorPos(void)
{
String ActPos;
PInputTag RunTag;
tAllocStr Str;
int CurrStrLen, NewLen;
Boolean Last;
InitStr(&Str);
CurrStrLen = 0;
/* no file has yet been opened: */
if (!FirstInputTag)
{
const char FixedName[] = "INTERNAL";
ReallocStr
(&Str
, strlen(FixedName
) + 1);
strmaxcat(Str.pStr, FixedName, Str.AllocLen);
}
/* for GNU error message style: */
else if (GNUErrors)
{
PInputTag pInnerTag = NULL;
const char *pMsg;
/* we only honor the include positions. First, print the upper include layers... */
for (RunTag = FirstInputTag; RunTag; RunTag = RunTag->Next)
if (RunTag->GetPos == INCLUDE_GetPos)
{
if (!pInnerTag)
pInnerTag = RunTag;
else
{
Last = RunTag->GetPos(RunTag, ActPos, sizeof(ActPos), GNUErrors);
if (!Str.AllocLen)
{
pMsg = getmessage(Num_GNUErrorMsg1);
ReallocStr(&Str, NewLen);
as_snprintf(Str.pStr, Str.AllocLen, "%s %s", pMsg, ActPos);
CurrStrLen = NewLen;
}
else
{
pMsg = getmessage(Num_GNUErrorMsgN);
NewLen
= CurrStrLen
+ 2 + strlen(pMsg
) + 1 + strlen(ActPos
) + 1;
ReallocStr(&Str, NewLen);
as_snprcatf(Str.pStr, Str.AllocLen, ",\n%s %s", pMsg, ActPos);
CurrStrLen = NewLen;
}
}
}
/* ...append something... */
if (CurrStrLen > 0)
{
NewLen = CurrStrLen + 3;
ReallocStr(&Str, NewLen);
as_snprcatf(Str.pStr, Str.AllocLen, ":\n");
CurrStrLen = NewLen;
}
/* ...then the innermost one */
if (pInnerTag)
{
pInnerTag->GetPos(pInnerTag, ActPos, sizeof(ActPos), GNUErrors);
NewLen
= CurrStrLen
+ strlen(ActPos
) + 1;
ReallocStr(&Str, NewLen);
as_snprcatf(Str.pStr, Str.AllocLen, "%s", ActPos);
CurrStrLen = NewLen;
}
}
/* otherwise the standard AS position generator: */
else
{
int ThisLen;
for (RunTag = FirstInputTag; RunTag; RunTag = RunTag->Next)
{
Last = RunTag->GetPos(RunTag, ActPos, sizeof(ActPos), GNUErrors);
ReallocStr(&Str, NewLen = CurrStrLen + ThisLen + 1);
strmaxprep(Str.pStr, ActPos, Str.AllocLen);
CurrStrLen = NewLen;
if (Last)
break;
}
}
return Str.pStr;
}
static Boolean InputEnd(void)
{
PInputTag Lauf;
Lauf = FirstInputTag;
while (Lauf)
{
if (!Lauf->IsEmpty)
return False;
Lauf = Lauf->Next;
}
return True;
}
/*=== Eine Quelldatei ( Haupt-oder Includedatei ) bearbeiten ===============*/
/*--- aus der zerlegten Zeile Code erzeugen --------------------------------*/
void WriteCode(void)
{
unsigned z;
for (z = 0; z < StopfZahl; z++)
{
switch (ActListGran)
{
case 4:
DAsmCode[CodeLen >> 2] = NOPCode;
break;
case 2:
WAsmCode[CodeLen >> 1] = NOPCode;
break;
case 1:
BAsmCode[CodeLen] = NOPCode;
break;
}
CodeLen += ActListGran/Granularity();
}
if ((ActPC != StructSeg) && (!ChkPC(PCs[ActPC] + CodeLen - 1)) && (CodeLen != 0))
{
WrError(ErrNum_AdrOverflow);
CodeLen = 0;
}
else
{
LargeWord NewPC = PCs[ActPC] + CodeLen;
if ((!DontPrint) && (ActPC != StructSeg) && (CodeLen > 0))
BookKeeping();
if (ActPC == StructSeg)
{
if ((CodeLen != 0) && (!DontPrint)) WrError(ErrNum_NotInStruct);
if (StructStack->StructRec->IsUnion)
{
BumpStructLength(StructStack->StructRec, CodeLen);
CodeLen = 0;
NewPC = 0;
}
}
else if (CodeOutput)
{
PCsUsed[ActPC] = True;
if (DontPrint)
NewRecord(PCs[ActPC] + CodeLen);
else
WriteBytes();
}
PCs[ActPC] = NewPC;
}
}
static void Produce_Code(void)
{
PMacroRec OneMacro;
PStructRec OneStruct;
Boolean SearchMacros, Found, IsMacro = False, IsStruct = False, ResetLastLabel = True;
tStrComp non_upper_case_op_part;
String non_upper_case_op_part_buf;
const tStrComp *p_search_op_part;
ActListGran = ListGran();
WasIF = WasMACRO = False;
/* Makrosuche unterdruecken ? */
/* We need the OpPart also in a variant not converted to all-uppercase,
since structure and macro names may be case sensitive: */
StrCompMkTemp(&non_upper_case_op_part, non_upper_case_op_part_buf, sizeof(non_upper_case_op_part_buf));
if (*OpPart.str.p_str == '!')
{
SearchMacros = False;
StrCompCutLeft(&OpPart, 1);
StrCompCopy(&non_upper_case_op_part, &OpPart);
}
else
{
const tStrComp *p_lop_part;
SearchMacros = True;
p_lop_part = ExpandStrSymbol(&non_upper_case_op_part, &OpPart, False);
if (p_lop_part && (p_lop_part != &OpPart))
as_dynstr_copy(&OpPart.str, &p_lop_part->str);
}
NLS_UpString(OpPart.str.p_str);
p_search_op_part = CaseSensitive ? &non_upper_case_op_part : &OpPart;
/* Prozessor eingehaengt ? */
if (FirstOutputTag)
{
FirstOutputTag->Processor();
return;
}
/* otherwise generate code: check for macro/structs here */
IsMacro = (SearchMacros) && (FoundMacro(&OneMacro, p_search_op_part));
if (IsMacro)
WasMACRO = True;
if (!IsMacro)
IsStruct = FoundStruct(&OneStruct, p_search_op_part->str.p_str);
/* no longer at an address right after a BSR? */
if (EProgCounter() != AfterBSRAddr)
AfterBSRAddr = 0;
/* evtl. voranstehendes Label ablegen */
if (IfAsm && (!IsMacro || !OneMacro->LocIntLabel))
{
if (LabelPresent())
LabelHandle(&LabPart, EProgCounter(), False);
}
Found = False;
switch (*OpPart.str.p_str)
{
case 'I':
/* Makroliste ? */
Found = True;
if (Memo("IRP")) ResetLastLabel = !ExpandIRP();
else if (Memo("IRPC")) ResetLastLabel = !ExpandIRPC();
else Found = False;
break;
case 'R':
/* Repetition ? */
Found = True;
if (Memo("REPT")) ResetLastLabel = !ExpandREPT();
else Found = False;
break;
case 'W':
/* bedingte Repetition ? */
Found = True;
if (Memo("WHILE")) ResetLastLabel = !ExpandWHILE();
else Found = False;
break;
}
/* bedingte Assemblierung ? */
if (!Found)
WasIF = Found = CodeIFs();
if (!Found)
switch (*OpPart.str.p_str)
{
case 'M':
/* Makrodefinition ? */
Found = True;
if (Memo("MACRO")) ReadMacro();
else Found = False;
break;
case 'E':
/* Abbruch Makroexpansion ? */
Found = True;
if (Memo("EXITM")) ExpandEXITM();
else Found = False;
break;
case 'S':
/* shift macro arguments ? */
Found = True;
if (memo_shift_pseudo() || (ShiftIsOccupied && Memo("SHFT"))) ExpandSHIFT();
else Found = False;
break;
case 'I':
/* Includefile? */
Found = True;
if (Memo("INCLUDE"))
ExpandINCLUDE();
else
Found = False;
break;
}
if (Found);
/* Makroaufruf ? */
else if (IsMacro)
{
ResetLastLabel = False;
if (IfAsm)
{
ExpandMacro(OneMacro);
if ((MacroNestLevel > 1) && (MacroNestLevel < 100))
as_snprintf(ListLine, STRINGSIZE, "%*s(MACRO-%u)", MacroNestLevel - 1, "", MacroNestLevel);
else
strmaxcpy(ListLine, "(MACRO)", STRINGSIZE);
/* Macro call itself must not appear in expanded output. However, a label
in the same line that is not consumed by the macro must. In this case,
dump the source line with the OpPart (macro's name) muted out. */
if (MacProOutput && (LabPart.Pos.StartCol >= 0) && !OneMacro->LocIntLabel)
PrintOneLineMuted(MacProFile, OneLine.p_str, &OpPart.Pos, &ArgPart.Pos);
}
}
else
{
StopfZahl = 0;
CodeLen = 0;
DontPrint = False;
#ifdef PROFILE_MEMO
NumMemo = 0;
#endif
if (IfAsm)
{
/* structure declaration ? */
if (IsStruct)
{
ExpandStruct(OneStruct, p_search_op_part->str.p_str);
strmaxcpy(ListLine, OneStruct->IsUnion ? "(UNION)" : "(STRUCT)", STRINGSIZE);
}
else
{
AttrPartOpSize[0] = AttrPartOpSize[1] = eSymbolSizeUnknown;
if (DecodeAttrPart ? DecodeAttrPart() : True)
{
if (!CodeGlobalPseudo())
MakeCode();
}
}
if (MacProOutput && ((*OpPart.str.p_str != '\0') || (*LabPart.str.p_str != '\0') || (*CommPart.str.p_str != '\0')))
{
errno = 0;
fprintf(MacProFile
, "%s\n", OneLine.
p_str);
ChkIO(ErrNum_ListWrError);
}
}
#ifdef PROFILE_MEMO
NumMemoSum += NumMemo;
NumMemoCnt++;
#endif
WriteCode();
}
/* reset memory about previous label if it is a non-empty instruction */
if (*OpPart.str.p_str && ResetLastLabel)
LabelReset();
/* dies ueberprueft implizit, ob von der letzten Eval...-Operation noch
externe Referenzen liegengeblieben sind. */
SetRelocs(NULL);
}
/*--- Zeile in Listing zerteilen -------------------------------------------*/
static void adjust_copy_comp(tStrComp *p_comp, const char *p_src, size_t newsz)
{
if (newsz + 1 > p_comp->str.capacity)
as_dynstr_realloc(&p_comp->str, as_dynstr_roundup_len(newsz));
p_comp->Pos.Len = strmemcpy(p_comp->str.p_str, p_comp->str.capacity, p_src, newsz);
}
static void SplitLine(void)
{
const char *pRun, *pEnd, *pPos;
Retracted = False;
/* run preprocessor */
ExpandDefines(OneLine.p_str);
pRun = OneLine.p_str;
/* If comment is present, ignore everything after it: */
pPos = QuotSMultPosQualify(pRun, pCommentLeadIn, QualifyQuote);
if (pPos)
{
adjust_copy_comp(&CommPart, pPos, pEnd - pPos);
CommPart.Pos.StartCol = pPos - OneLine.p_str;
pEnd = pPos;
}
else
StrCompReset(&CommPart);
/* Non-blank character in first column is always label: */
if ((pRun < pEnd) && *pRun && !as_isspace(*pRun))
{
for (pPos = pRun; pPos < pEnd; pPos++)
if (as_isspace(*pPos) || (*pPos == ':'))
break;
LabPart.Pos.StartCol = pRun - OneLine.p_str;
if (pPos >= pEnd)
{
LabPart.Pos.Len = strmemcpy(LabPart.str.p_str, STRINGSIZE, pRun, pEnd - pRun);
pRun = pEnd;
}
else
{
LabPart.Pos.Len = strmemcpy(LabPart.str.p_str, STRINGSIZE, pRun, pPos - pRun);
pRun = pPos + 1;
}
if ((LabPart.Pos.Len > 0) && (LabPart.str.p_str[LabPart.Pos.Len - 1] == ':')) /* needed? */
LabPart.str.p_str[--LabPart.Pos.Len] = '\0';
}
else
StrCompReset(&LabPart);
/* Opcode & Argument trennen */
while (True)
{
for (; (pRun < pEnd) && as_isspace(*pRun); pRun++);
for (pPos = pRun; (pPos < pEnd) && !as_isspace(*pPos); pPos++);
/* If potential OpPart starts with argument divider,
OpPart is empty and rest of line is all-arguments: */
if (strchr(DivideChars
, *pRun
))
{
StrCompReset(&OpPart);
adjust_copy_comp(&ArgPart, pRun, pEnd - pRun);
ArgPart.Pos.StartCol = pRun - OneLine.p_str;
}
else
{
/* copy out OpPart */
OpPart.Pos.StartCol = pRun - OneLine.p_str;
OpPart.Pos.Len = strmemcpy(OpPart.str.p_str, OpPart.str.capacity, pRun, pPos - pRun);
/* continue after OpPart separator */
pRun = (pPos < pEnd) ? pPos + 1 : pEnd;
/* Falls noch kein Label da war, kann es auch ein Label sein */
if ((*LabPart.str.p_str == '\0') && OpPart.Pos.Len && (OpPart.str.p_str[OpPart.Pos.Len - 1] == ':'))
{
OpPart.str.p_str[--OpPart.Pos.Len] = '\0';
StrCompCopy(&LabPart, &OpPart);
continue; /* -> retry finding opcode */
}
/* save remainder to ArgPart */
adjust_copy_comp(&ArgPart, pRun, pEnd - pRun);
ArgPart.Pos.StartCol = pRun - OneLine.p_str;
}
break;
}
ArgCnt = 0;
/* trailing separator on OpPart means we have to push in another empty argument */
if (OpPart.
Pos.
Len && strchr(DivideChars
, OpPart.
str.
p_str[OpPart.
Pos.
Len - 1]))
{
const char EmptyArg[] = "";
OpPart.str.p_str[--OpPart.Pos.Len] = '\0';
strcpy(ArgStr
[ArgCnt
].
str.
p_str, EmptyArg
);
ArgStr[ArgCnt].Pos = ArgPart.Pos;
}
/* Attribut abspalten */
oppart_leading_dot = False;
if (HasAttrs)
{
const char *pActAttrChar;
char *pAttrPos, *pActAttrPos;
int Tries = 0;
again:
pAttrPos = NULL; AttrSplit = ' ';
for (pActAttrChar = AttrChars; *pActAttrChar; pActAttrChar++)
{
pActAttrPos
= strchr(OpPart.
str.
p_str, *pActAttrChar
);
if (pActAttrPos && ((!pAttrPos) || (pActAttrPos < pAttrPos)))
pAttrPos = pActAttrPos;
}
if (pAttrPos)
{
AttrSplit = (*pAttrPos);
AttrPart.Pos.StartCol = OpPart.Pos.StartCol + (pAttrPos + 1 - OpPart.str.p_str);
AttrPart.
Pos.
Len = strmemcpy
(AttrPart.
str.
p_str, STRINGSIZE
, pAttrPos
+ 1, strlen(pAttrPos
+ 1));
*pAttrPos = '\0';
OpPart.Pos.Len = pAttrPos - OpPart.str.p_str;
/* The dot-prefixed OpPart may itself contain an attribute (.instr.attr). So reiterate
splitting off attribute, but only once ;-) */
if ((*OpPart.str.p_str == '\0') && (*AttrPart.str.p_str != '\0'))
{
StrCompCopy(&OpPart, &AttrPart);
StrCompReset(&AttrPart);
if (!Tries && (AttrSplit == '.'))
oppart_leading_dot = True;
if (++Tries < 2)
goto again;
}
}
else
StrCompReset(&AttrPart);
}
else
StrCompReset(&AttrPart);
KillPostBlanksStrComp(&ArgPart);
/* Argumente zerteilen: */
if (*ArgPart.str.p_str)
{
const char *pDivPos, *pActDiv, *pActDivPos;
pRun = ArgPart.str.p_str;
pActDivPos = NULL;
/* A separator found in the previous iteration forces another argument,
even if it will be empty because the separator is right at the end: */
while ((pRun < pEnd) || pActDivPos)
{
while (*pRun && as_isspace(*pRun))
pRun++;
#if 0 /* TODO: should work, but doesn't yet */
pDivPos = QuotMultPosFixup(pRun, DivideChars, NULL);
if (!pDivPos)
pDivPos = pEnd;
#endif
pDivPos = pEnd;
for (pActDiv = DivideChars; *pActDiv; pActDiv++)
{
pActDivPos = QuotPosQualify(pRun, *pActDiv, QualifyQuote);
if (pActDivPos && (pActDivPos < pDivPos))
pDivPos = pActDivPos;
}
if (ArgCnt >= ArgCntMax)
{
WrError(ErrNum_TooManyArgs);
break;
}
AppendArg(pDivPos - pRun);
adjust_copy_comp(&ArgStr[ArgCnt], pRun, pDivPos - pRun);
ArgStr[ArgCnt].Pos.StartCol = ArgPart.Pos.StartCol + (pRun - ArgPart.str.p_str);
KillPostBlanksStrComp(&ArgStr[ArgCnt]);
pRun = (pDivPos < pEnd) ? pDivPos + 1 : pEnd;
}
}
}
/*------------------------------------------------------------------------*/
static void ProcessFile(char *pFileName)
{
long NxtTime, ListTime;
char *Run;
tStrComp FileArg;
dbgentry("ProcessFile");
*OneLine.p_str = *CurrFileName = '\0';
StrCompMkTemp(&FileArg, pFileName, 0);
ExpandINCLUDE_Core(&FileArg, False);
ListTime = GTime();
while (!InputEnd() && !ENDOccured)
{
/* Zeile lesen */
GetNextLine(&OneLine);
/* Ergebnisfelder vorinitialisieren */
DontPrint = False;
CodeLen = 0;
*ListLine = '\0';
NextDoLst = DoLst;
NextIncDepth = IncDepth;
for (Run = OneLine.p_str; *Run != '\0'; Run++)
if (!as_isspace(*Run))
break;
if (*Run == '#')
Preprocess();
else
{
SplitLine();
Produce_Code();
}
MakeList(OneLine.p_str);
DoLst = NextDoLst;
IncDepth = NextIncDepth;
if (MaxIncDepth < IncDepth)
MaxIncDepth = IncDepth;
/* Zeilenzaehler */
if (msg_level >= e_msg_level_normal)
{
NxtTime = GTime();
if (((!ListToStdout) || ((ListMask&1) == 0)) && (DTime(ListTime, NxtTime) > 50))
{
String Num;
PInputTag p_input_tag;
/* search innermost file currently being read, and request its position */
for (p_input_tag = FirstInputTag; p_input_tag; p_input_tag = p_input_tag->Next)
if (p_input_tag->Processor == INCLUDE_Processor)
break;
p_input_tag->GetPos(p_input_tag, Num, sizeof(Num), False);
WrConsoleLine(Num, False);
ListTime = NxtTime;
}
}
/* bei Ende Makroprozessor ausraeumen
OK - das ist eine Hauruckmethode... */
if (ENDOccured)
while (FirstInputTag)
GetNextLine(&OneLine);
}
while (FirstInputTag)
GetNextLine(&OneLine);
/* irgendeine Makrodefinition nicht abgeschlossen ? */
if (FirstOutputTag)
{
WrError(FirstOutputTag->OpenErrMsg);
}
dbgexit("ProcessFile");
}
/****************************************************************************/
static const char *TWrite_Plur(int n)
{
return (n != 1) ? getmessage(Num_ListPlurName) : "";
}
static void TWrite(long DTime, char *dest, size_t DestSize)
{
int h;
*dest = '\0';
h = DTime / 360000;
DTime %= 360000;
if (h > 0)
as_snprcatf(dest, DestSize, "%d%s%s, ", h, getmessage(Num_ListHourName), TWrite_Plur(h));
h = DTime / 6000;
DTime %= 6000;
if (h > 0)
as_snprcatf(dest, DestSize, "%d%s%s, ", h, getmessage(Num_ListMinuName), TWrite_Plur(h));
h = DTime / 100;
DTime %= 100;
as_snprcatf(dest, DestSize, "%d.%02d%s%s", h, (int)DTime, getmessage(Num_ListSecoName), TWrite_Plur(h));
}
/*--------------------------------------------------------------------------*/
static void AssembleFile_InitPass(void)
{
static char DateS[31], TimeS[31];
int z;
String ArchVal;
String TmpCompStr;
tStrComp TmpComp;
StrCompMkTemp(&TmpComp, TmpCompStr, sizeof(TmpCompStr));
dbgentry("AssembleFile_InitPass");
FirstInputTag = NULL;
FirstOutputTag = NULL;
MomLocHandle = -1;
LocHandleCnt = 0;
SectSymbolCounter = 0;
SectionStack = NULL;
FirstIfSave = NULL;
FirstSaveState = NULL;
StructStack =
pInnermostNamedStruct = NULL;
for (z = 0; z < SegCount; z++)
pPhaseStacks[z] = NULL;
InitPass();
AsmLabelPassInit();
ActPC = SegCode;
PCs[ActPC] = 0;
RelSegs = False;
ENDOccured = False;
ErrorCount = 0;
WarnCount = 0;
LineSum = 0;
MacLineSum = 0;
for (z = 1; z <= StructSeg; z++)
{
PCsUsed[z] = FALSE;
Phases[z] = 0;
InitChunk(SegChunks + z);
}
TransTables =
CurrTransTable
= (PTransTable
) malloc(sizeof(TTransTable
));
CurrTransTable->Next = NULL;
CurrTransTable->Name = as_strdup("STANDARD");
CurrTransTable->p_table = as_chartrans_table_new();
EnumSegment = SegNone;
EnumIncrement = 1;
EnumCurrentValue = 0;
strmaxcpy(CurrFileName, "INTERNAL", STRINGSIZE);
AddFile(CurrFileName);
CurrLine = 0;
IncDepth = 0;
DoLst = eLstMacroExpAll;
/* Pseudovariablen initialisieren */
ResetSymbolDefines();
ResetMacroDefines();
ResetStructDefines();
strmaxcpy(TmpCompStr, FlagTrueName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, 1, SegNone, True);
strmaxcpy(TmpCompStr, FlagFalseName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, 0, SegNone, True);
strmaxcpy
(TmpCompStr
, PiName
, sizeof(TmpCompStr
)); EnterFloatSymbol
(&TmpComp
, 4.0 * atan(1.0), True
);
strmaxcpy(TmpCompStr, VerName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, VerNo, SegNone, True);
as_snprintf(ArchVal, sizeof(ArchVal), "%s-%s", ARCHPRNAME, ARCHSYSNAME);
strmaxcpy(TmpCompStr, ArchName, sizeof(TmpCompStr)); EnterStringSymbol(&TmpComp, ArchVal, True);
strmaxcpy(TmpCompStr, Has64Name, sizeof(TmpCompStr));
#ifdef HAS64
EnterIntSymbol(&TmpComp, 1, SegNone, True);
#else
EnterIntSymbol(&TmpComp, 0, SegNone, True);
#endif
strmaxcpy(TmpCompStr, CaseSensName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, Ord(CaseSensitive), SegNone, True);
if (PassNo == 0)
{
NLS_CurrDateString(DateS, sizeof(DateS));
NLS_CurrTimeString(False, TimeS, sizeof(TimeS));
}
if (!FindDefSymbol(DateName))
{
strmaxcpy(TmpCompStr, DateName, sizeof(TmpCompStr));
EnterStringSymbol(&TmpComp, DateS, True);
}
if (!FindDefSymbol(TimeName))
{
strmaxcpy(TmpCompStr, TimeName, sizeof(TmpCompStr));
EnterStringSymbol(&TmpComp, TimeS, True);
}
if (*DefCPU == '\0')
SetCPUByType(0, NULL);
else
{
tStrComp TmpComp2;
StrCompMkTemp(&TmpComp2, DefCPU, sizeof(DefCPU));
if (!SetCPUByName(&TmpComp2))
SetCPUByType(0, NULL);
}
strmaxcpy(TmpCompStr, ListOnName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, ListOn = 1, SegNone, True);
SetLstMacroExp(eLstMacroExpAll);
InitLstMacroExpMod(&LstMacroExpModOverride);
InitLstMacroExpMod(&LstMacroExpModDefault);
SetFlag(&RelaxedMode, RelaxedName, DefRelaxedMode);
SetIntConstRelaxedMode(DefRelaxedMode);
strmaxcpy(TmpCompStr, NestMaxName, sizeof(TmpCompStr)); EnterIntSymbol(&TmpComp, NestMax = DEF_NESTMAX, SegNone, True);
CopyDefSymbols();
/* initialize counter for temp symbols here after implicit symbols
have been defined, so counter starts at a value as low as possible */
InitTmpSymbols();
ResetPageCounter();
StartAdrPresent = False;
AfterBSRAddr = 0;
Repass = False;
PassNo++;
#ifdef PROFILE_MEMO
NumMemoSum = 0;
NumMemoCnt = 0;
#endif
dbgexit("AssembleFile_InitPass");
}
static void AssembleFile_ExitPass(void)
{
tSavePhase *pSavePhase;
int z;
#if 0
if CurrIncludeLevel)
WrXError(ErrNum_InternalError, "open include");
#endif
UnsetCPU();
ClearLocStack();
ClearStacks();
AsmErrPassExit();
for (z = 0; z < SegCount; z++)
while (pPhaseStacks[z])
{
pSavePhase = pPhaseStacks[z];
pPhaseStacks[z] = pSavePhase->pNext;
}
if (FirstIfSave)
WrError(ErrNum_MissEndif);
if (FirstSaveState)
WrError(ErrNum_NoRestoreFrame);
if (SectionStack)
WrError(ErrNum_MissingEndSect);
if (StructStack)
WrXError(ErrNum_OpenStruct, StructStack->Name);
}
static void AssembleFile_WrSummary(const char *pStr)
{
if (msg_level >= e_msg_level_normal)
WrConsoleLine(pStr, True);
if (ListMode == 2)
WrLstLine(pStr);
}
static void AssembleFile(char *Name)
{
char *p_out_name;
String s, Tmp;
dbgentry("AssembleFile");
strmaxcpy(SourceFile, Name, STRINGSIZE);
if (MakeDebug)
fprintf(Debug
, "File %s\n", SourceFile
);
/* Untermodule initialisieren */
AsmDefInit();
AsmParsInit();
AsmIFInit();
InitFileList();
ResetStack();
/* Kommandozeilenoptionen verarbeiten */
p_out_name = MoveFromOutListFirst();
strmaxcpy(OutName, p_out_name ? p_out_name : "", STRINGSIZE);
if (OutName[0] == '\0')
{
strmaxcpy(OutName, SourceFile, STRINGSIZE);
KillSuffix(OutName);
AddSuffix(OutName, PrgSuffix);
}
if (*ErrorPath == '\0')
{
strmaxcpy(ErrorName, SourceFile, STRINGSIZE);
KillSuffix(ErrorName);
AddSuffix(ErrorName, LogSuffix);
unlink(ErrorName);
}
switch (ListMode)
{
case 0:
strmaxcpy(LstName, NULLDEV, STRINGSIZE);
break;
case 1:
strmaxcpy(LstName, "!1", STRINGSIZE);
break;
case 2:
{
char *p_lst_name = MoveFromListOutListFirst();
strmaxcpy(LstName, p_lst_name ? p_lst_name : "", STRINGSIZE);
if (p_lst_name
) free(p_lst_name
);
if (*LstName == '\0')
{
strmaxcpy(LstName, SourceFile, STRINGSIZE);
KillSuffix(LstName);
AddSuffix(LstName, LstSuffix);
}
break;
}
}
ListToStdout
= !strcmp(LstName
, "!1");
ListToNull
= !strcmp(LstName
, NULLDEV
);
if (ShareMode != 0)
{
char *p_share_name = MoveFromShareOutListFirst();
strmaxcpy(ShareName, p_share_name ? p_share_name : "", STRINGSIZE);
if (p_share_name)
if (*ShareName == '\0')
{
strmaxcpy(ShareName, SourceFile, STRINGSIZE);
KillSuffix(ShareName);
switch (ShareMode)
{
case 1:
AddSuffix(ShareName, ".inc");
break;
case 2:
AddSuffix(ShareName, ".h");
break;
case 3:
AddSuffix(ShareName, IncSuffix);
break;
}
}
}
if (MacProOutput)
{
strmaxcpy(MacProName, SourceFile, STRINGSIZE);
KillSuffix(MacProName);
AddSuffix(MacProName, PreSuffix);
}
if (MacroOutput)
{
strmaxcpy(MacroName, SourceFile, STRINGSIZE);
KillSuffix(MacroName);
AddSuffix(MacroName, MacSuffix);
}
ClearIncludeList();
CurrIncludeLevel = 0;
if (DebugMode != DebugNone)
InitLineInfo();
/* Variablen initialisieren */
StartTime = GTime();
PassNo = 0;
/* Listdatei eroeffnen */
if (msg_level >= e_msg_level_normal)
printf("%s%s\n", getmessage
(Num_InfoMessAssembling
), SourceFile
);
/* Maximum include level survives re-passing, so it can be
used for the listing to format to the right max. depth from
the beginning: */
MaxIncDepth = 0;
do
{
/* Durchlauf initialisieren */
AssembleFile_InitPass();
AsmSubPassInit();
AsmErrPassInit();
if (msg_level >= e_msg_level_normal)
{
as_snprintf(Tmp, sizeof(Tmp), "%s", getmessage(Num_InfoMessPass));
as_snprcatf(Tmp, sizeof(Tmp), IntegerFormat, PassNo);
WrConsoleLine(Tmp, True);
}
/* Dateien oeffnen */
if (CodeOutput)
OpenFile();
if (ShareMode != 0)
{
ShareFile
= fopen(ShareName
, "w");
if (!ShareFile)
ChkXIO(ErrNum_OpeningFile, ShareName);
errno = 0;
switch (ShareMode)
{
case 1:
fprintf(ShareFile
, "(* %s-Include File for CONST Section *)\n", SourceFile
);
break;
case 2:
fprintf(ShareFile
, "/* %s-Include File for C Program */\n", SourceFile
);
break;
case 3:
fprintf(ShareFile
, "; %s-Include File for Assembler Program\n", SourceFile
);
break;
}
ChkIO(ErrNum_ListWrError);
}
if (MacProOutput)
{
MacProFile
= fopen(MacProName
, "w");
if (!MacProFile)
ChkXIO(ErrNum_OpeningFile, MacProName);
}
if ((MacroOutput) && (PassNo == 1))
{
MacroFile
= fopen(MacroName
, "w");
if (!MacroFile)
ChkXIO(ErrNum_OpeningFile, MacroName);
}
/* Listdatei oeffnen */
OpenWithStandard(&LstFile, LstName);
if (!LstFile)
ChkXIO(ErrNum_OpeningFile, LstName);
if (!ListToNull)
{
errno = 0;
fprintf(LstFile
, "%s", PrtInitString
);
ChkIO(ErrNum_ListWrError);
}
if ((ListMask & 1) != 0)
NewPage(0, False);
/* assemblieren */
ProcessFile(SourceFile);
AssembleFile_ExitPass();
/* Dateien schliessen */
if (CodeOutput)
CloseFile();
if (ShareMode != 0)
{
errno = 0;
switch (ShareMode)
{
case 1:
fprintf(ShareFile
, "(* Ende Include File for CONST Section *)\n");
break;
case 2:
fprintf(ShareFile
, "/* Ende Include File for C Program */\n");
break;
case 3:
fprintf(ShareFile
, "; Ende Include File for Assembler Program\n");
break;
}
ChkIO(ErrNum_ListWrError);
CloseIfOpen(&ShareFile);
}
if (MacProOutput)
CloseIfOpen(&MacProFile);
if (MacroOutput && (PassNo == 1))
CloseIfOpen(&MacroFile);
/* evtl. fuer naechsten Durchlauf aufraeumen */
if ((ErrorCount == 0) && (Repass))
{
CloseIfOpen(&LstFile);
if (CodeOutput)
unlink(OutName);
ClearCodepages();
if (MakeUseList)
ClearUseList();
if (MakeCrossList)
ClearCrossList();
ClearDefineList();
if (DebugMode != DebugNone)
ClearLineInfo();
ClearIncludeList();
if (DebugMode != DebugNone)
{
ResetAddressRanges();
ClearSectionUsage();
}
}
}
while ((ErrorCount == 0) && (Repass));
/* bei Fehlern loeschen */
if (ErrorCount != 0)
{
if (CodeOutput)
unlink(OutName);
if (MacProOutput)
unlink(MacProName);
if ((MacroOutput) && (PassNo == 1))
unlink(MacroName);
if (ShareMode != 0)
unlink(ShareName);
GlobErrFlag = True;
}
/* Debug-Ausgabe muss VOR die Symbollistenausgabe, weil letztere die
Symbolliste loescht */
if (DebugMode != DebugNone)
{
if (ErrorCount == 0)
DumpDebugInfo();
ClearLineInfo();
}
/* Listdatei abschliessen */
{
if (ListMask & 2)
PrintSymbolList();
if (ListMask & 64)
PrintRegDefs();
if (ListMask & 4)
PrintMacroList();
if (ListMask & 256)
PrintStructList();
if (ListMask & 8)
PrintFunctionList();
if (ListMask & 32)
PrintDefineList();
if (ListMask & 128)
PrintCodepages();
if (MakeUseList)
{
NewPage(ChapDepth, True);
PrintUseList();
}
if (MakeCrossList)
{
NewPage(ChapDepth, True);
PrintCrossList();
}
if (MakeSectionList)
PrintSectionList();
if (MakeIncludeList)
PrintIncludeList();
if (!ListToNull)
{
errno = 0;
fprintf(LstFile
, "%s", PrtExitString
);
ChkIO(ErrNum_ListWrError);
}
}
if (MakeUseList)
ClearUseList();
if (MakeCrossList)
ClearCrossList();
ClearSectionList();
ClearIncludeList();
if (!*ErrorPath)
CloseIfOpen(&ErrorFile);
ClearUp();
/* Statistik ausgeben */
StopTime = GTime();
TWrite(DTime(StartTime, StopTime), s, sizeof(s));
strmaxcat(s, getmessage(Num_InfoMessAssTime), STRINGSIZE);
if (msg_level >= e_msg_level_normal)
{
WrConsoleLine("", True);
WrConsoleLine(s, True);
WrConsoleLine("", True);
}
if (ListMode == 2)
{
WrLstLine("");
WrLstLine(s);
WrLstLine("");
}
as_snprintf(s, sizeof(s), "%7" PRILongInt "%s", LineSum,
getmessage((LineSum == 1) ? Num_InfoMessAssLine : Num_InfoMessAssLines), STRINGSIZE);
AssembleFile_WrSummary(s);
if (LineSum != MacLineSum)
{
as_snprintf(s, sizeof(s), "%7" PRILongInt "%s", MacLineSum,
getmessage((MacLineSum == 1) ? Num_InfoMessMacAssLine : Num_InfoMessMacAssLines), STRINGSIZE);
AssembleFile_WrSummary(s);
}
as_snprintf(s, sizeof(s), "%7d%s", (int)PassNo,
getmessage((PassNo == 1) ? Num_InfoMessPassCnt : Num_InfoMessPPassCnt), STRINGSIZE);
AssembleFile_WrSummary(s);
if ((ErrorCount > 0) && (Repass) && (ListMode != 0))
WrLstLine(getmessage(Num_InfoMessNoPass));
#ifdef __TURBOC__
as_snprintf(s, sizeof(s), "%7lu%s", coreleft() >> 10,
getmessage(Num_InfoMessRemainMem));
AssembleFile_WrSummary(s);
as_snprintf(s, sizeof(s), "%7lu%s", (unsigned long)StackRes(),
getmessage(Num_InfoMessRemainStack));
AssembleFile_WrSummary(s);
#endif
as_snprintf(s, sizeof(s), "%7u%s%s", (unsigned)ErrorCount,
getmessage(Num_InfoMessErrCnt),
(ErrorCount == 1) ? "" : getmessage(Num_InfoMessErrPCnt));
AssembleFile_WrSummary(s);
as_snprintf(s, sizeof(s), "%7u%s%s", (unsigned)WarnCount,
getmessage(Num_InfoMessWarnCnt),
(WarnCount == 1) ? "" : getmessage(Num_InfoMessWarnPCnt));
AssembleFile_WrSummary(s);
#ifdef PROFILE_MEMO
{
unsigned long Sum = (NumMemoSum * 100) / NumMemoCnt;
as_snprintf(s, sizeof(s), "%4lu.%02lu%s", Sum / 100, Sum % 100, " Oppart Compares");
if (msg_level >= e_msg_level_normal)
WrConsoleLine(s, True);
if (ListMode == 2)
WrLstLine(s);
}
#endif
CloseIfOpen(&LstFile);
/* verstecktes */
if (MakeDebug)
PrintSymbolDepth();
/* Speicher freigeben */
ClearSymbolList();
ClearCodepages();
ClearMacroList();
ClearFunctionList();
ClearDefineList();
ClearFileList();
ClearStructList();
dbgentry("AssembleFile");
}
static void AssembleGroup(const char *pFileMask)
{
String FileMask;
strmaxcpy(FileMask, pFileMask, sizeof(FileMask));
AddSuffix(FileMask, SrcSuffix);
if (!DirScan(FileMask, AssembleFile))
fprintf(stderr
, "%s%s\n", FileMask
, getmessage
(Num_InfoMessNFilesFound
));
}
/*-------------------------------------------------------------------------*/
static int LineZ, screen_height = 0;
static Boolean write_cpu_list_exit;
static void write_console_next(const char *p_line)
{
WrConsoleLine(p_line, True);
if (screen_height && (++LineZ >= screen_height))
{
LineZ = 0;
WrConsoleLine(getmessage(Num_KeyWaitMsg), False);
}
}
static as_cmd_result_t CMD_SharePascal(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
if (!Negate)
ShareMode = 1;
else if (ShareMode == 1)
ShareMode = 0;
return e_cmd_ok;
}
static as_cmd_result_t CMD_ShareC(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
if (!Negate)
ShareMode = 2;
else if (ShareMode == 2)
ShareMode = 0;
return e_cmd_ok;
}
static as_cmd_result_t CMD_ShareAssembler(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
if (!Negate)
ShareMode = 3;
else if (ShareMode == 3)
ShareMode = 0;
return e_cmd_ok;
}
static as_cmd_result_t CMD_DebugMode(Boolean Negate, const char *pArg)
{
String Arg;
strmaxcpy(Arg, pArg, STRINGSIZE);
UpString(Arg);
if (Negate)
{
if (Arg[0] != '\0')
return e_cmd_err;
else
{
DebugMode = DebugNone;
return e_cmd_ok;
}
}
{
DebugMode = DebugMAP;
return e_cmd_ok;
}
else if (!strcmp(Arg
, "ATMEL"))
{
DebugMode = DebugAtmel;
return e_cmd_arg;
}
{
DebugMode = DebugMAP;
return e_cmd_arg;
}
else if (!strcmp(Arg
, "NOICE"))
{
DebugMode = DebugNoICE;
return e_cmd_arg;
}
#if 0
else if (!strcmp(Arg
, "A.OUT"))
{
DebugMode = DebugAOUT;
return e_cmd_arg;
}
else if (!strcmp(Arg
, "COFF"))
{
DebugMode = DebugCOFF;
return e_cmd_arg;
}
{
DebugMode = DebugELF;
return e_cmd_arg;
}
#endif
else
return e_cmd_err;
#if 0
if (Negate)
DebugMode = DebugNone;
else
DebugMode = DebugMAP;
return e_cmd_ok;
#endif
}
static as_cmd_result_t CMD_ListConsole(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
if (!Negate)
ListMode = 1;
else if (ListMode == 1)
ListMode = 0;
return e_cmd_ok;
}
static as_cmd_result_t CMD_ListRadix(Boolean Negate, const char *Arg)
{
Boolean OK, new_zero_pad = False;
LargeWord NewListRadixBase;
if (Negate)
{
ListRadixBase = 16;
ListPCZeroPad = False;
return e_cmd_ok;
}
if (*Arg == '0')
{
new_zero_pad = True;
Arg++;
}
NewListRadixBase = ConstLongInt(Arg, &OK, 10);
if (!OK || (NewListRadixBase < 2) || (NewListRadixBase > 36))
return e_cmd_err;
ListRadixBase = NewListRadixBase;
ListPCZeroPad = new_zero_pad;
return e_cmd_arg;
}
static as_cmd_result_t CMD_screen_height(Boolean negate, const char *p_arg)
{
Boolean ok;
int new_screen_height;
if (negate)
{
screen_height = 0;
return e_cmd_ok;
}
new_screen_height = ConstLongInt(p_arg, &ok, 10);
if (!ok)
return e_cmd_err;
screen_height = new_screen_height;
return e_cmd_arg;
}
static as_cmd_result_t CMD_ListFile(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
if (!Negate)
ListMode = 2;
else if (ListMode == 2)
ListMode = 0;
return e_cmd_ok;
}
static as_cmd_result_t CMD_SuppWarns(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
SuppWarns = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_UseList(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
MakeUseList = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_CrossList(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
MakeCrossList = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_SectionList(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
MakeSectionList = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_BalanceTree(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
BalanceTrees = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_MakeDebug(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
if (!Negate)
{
MakeDebug = True;
errno = 0;
Debug
= fopen("as.deb", "w");
if (!Debug)
ChkIO(ErrNum_ListWrError);
}
else if (MakeDebug)
{
MakeDebug = False;
CloseIfOpen(&Debug);
}
return e_cmd_ok;
}
static as_cmd_result_t CMD_MacProOutput(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
MacProOutput = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_MacroOutput(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
MacroOutput = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_MakeIncludeList(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
MakeIncludeList = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_CodeOutput(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
CodeOutput = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_MsgIfRepass(Boolean Negate, const char *Arg)
{
Boolean OK;
UNUSED(Arg);
MsgIfRepass = !Negate;
if (MsgIfRepass)
{
if (Arg[0] == '\0')
{
PassNoForMessage = 1;
return e_cmd_ok;
}
else
{
PassNoForMessage = ConstLongInt(Arg, &OK, 10);
if (!OK)
{
PassNoForMessage = 1;
return e_cmd_ok;
}
else if (PassNoForMessage < 1)
return e_cmd_err;
else
return e_cmd_arg;
}
}
else
return e_cmd_ok;
}
static as_cmd_result_t CMD_Relaxed(Boolean Negate, const char *pArg)
{
UNUSED(pArg);
DefRelaxedMode = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_ExtendErrors(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
if ((Negate) && (ExtendErrors > 0))
ExtendErrors--;
else if ((!Negate) && (ExtendErrors < 2))
ExtendErrors++;
return e_cmd_ok;
}
static as_cmd_result_t CMD_NumericErrors(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
NumericErrors = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_HexLowerCase(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
HexStartCharacter = Negate ? 'A' : 'a';
return e_cmd_ok;
}
static as_cmd_result_t CMD_SplitByte(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
if (Negate)
{
SplitByteCharacter = '\0';
return e_cmd_ok;
}
else if (*Arg)
{
return e_cmd_err;
SplitByteCharacter = *Arg;
return e_cmd_arg;
}
else
{
SplitByteCharacter = '.';
return e_cmd_ok;
}
}
static as_cmd_result_t CMD_ThrowErrors(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
ThrowErrors = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_CaseSensitive(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
CaseSensitive = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_GNUErrors(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
GNUErrors = !Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_IncludeList(Boolean Negate, const char *Arg)
{
char *p;
String Copy, part;
if (*Arg == '\0') return e_cmd_err;
else
{
strmaxcpy(Copy, Arg, STRINGSIZE);
do
{
if (!p)
{
strmaxcpy(part, Copy, STRINGSIZE);
*Copy = '\0';
}
else
{
*p = '\0';
strmaxcpy(part, p + 1, STRINGSIZE);
}
if (Negate)
RemoveIncludeList(part);
else
AddIncludeList(part);
}
while (Copy[0] != '\0');
return e_cmd_arg;
}
}
static as_cmd_result_t CMD_ListMask(Boolean Negate, const char *Arg)
{
Word erg;
Boolean OK;
if (Arg[0] == '\0')
return e_cmd_err;
else
{
erg = ConstLongInt(Arg, &OK, 10);
if ((!OK) || (erg > 511))
return e_cmd_err;
else
{
ListMask = Negate ? (ListMask & ~erg) : (ListMask | erg);
return e_cmd_arg;
}
}
}
static as_cmd_result_t CMD_DefSymbol(Boolean Negate, const char *Arg)
{
String Copy, Part, Name;
char *p;
as_cmd_result_t Result = e_cmd_err;
TempResult t;
as_tempres_ini(&t);
if (Arg[0] == '\0')
LEAVE;
strmaxcpy(Copy, Arg, STRINGSIZE);
do
{
p = QuotPos(Copy, ',');
if (!p)
{
strmaxcpy(Part, Copy, STRINGSIZE);
Copy[0] = '\0';
}
else
{
*p = '\0';
strmaxcpy(Part, Copy, STRINGSIZE);
strmov(Copy, p + 1);
}
if (!CaseSensitive)
UpString(Part);
p = QuotPos(Part, '=');
if (!p)
{
strmaxcpy(Name, Part, STRINGSIZE);
Part[0] = '\0';
}
else
{
*p = '\0';
strmaxcpy(Name, Part, STRINGSIZE);
strmov(Part, p + 1);
}
if (!ChkSymbName(Name))
LEAVE;
if (Negate)
RemoveDefSymbol(Name);
else
{
AsmParsInit();
if (Part[0] != '\0')
{
EvalExpression(Part, &t);
if ((t.Typ == TempNone) || mFirstPassUnknown(t.Flags))
return e_cmd_err;
}
else
as_tempres_set_int(&t, 1);
AddDefSymbol(Name, &t);
}
}
while (Copy[0] != '\0');
Result = e_cmd_arg;
func_exit:
as_tempres_free(&t);
return Result;
}
static as_cmd_result_t CMD_ErrorPath(Boolean Negate, const char *Arg)
{
if (Negate)
return e_cmd_err;
else if (Arg[0] == '\0')
{
ErrorPath[0] = '\0';
return e_cmd_ok;
}
else
{
strmaxcpy(ErrorPath, Arg, STRINGSIZE);
return e_cmd_arg;
}
}
static as_cmd_result_t CMD_HardRanges(Boolean Negate, const char *Arg)
{
UNUSED(Arg);
HardRanges = Negate;
return e_cmd_ok;
}
static as_cmd_result_t CMD_OutFile(Boolean Negate, const char *Arg)
{
if (Arg[0] == '\0')
{
if (Negate)
{
ClearOutList();
return e_cmd_ok;
}
else
return e_cmd_err;
}
else
{
if (Negate)
RemoveFromOutList(Arg);
else
AddToOutList(Arg);
return e_cmd_arg;
}
}
static as_cmd_result_t CMD_ShareOutFile(Boolean Negate, const char *Arg)
{
if (Arg[0] == '\0')
{
if (Negate)
{
ClearShareOutList();
return e_cmd_ok;
}
else
return e_cmd_err;
}
else
{
if (Negate)
RemoveFromShareOutList(Arg);
else
AddToShareOutList(Arg);
return e_cmd_arg;
}
}
static as_cmd_result_t CMD_ListOutFile(Boolean Negate, const char *Arg)
{
if (Arg[0] == '\0')
{
if (Negate)
{
ClearListOutList();
return e_cmd_ok;
}
else
return e_cmd_err;
}
else
{
if (Negate)
RemoveFromListOutList(Arg);
else
AddToListOutList(Arg);
return e_cmd_arg;
}
}
static Boolean CMD_CPUAlias_ChkCPUName(char *s)
{
int z;
for (z
= 0; z
< (int)strlen(s
); z
++)
return False;
return True;
}
static as_cmd_result_t CMD_CPUAlias(Boolean Negate, const char *Arg)
{
const char *p;
String s1, s2;
if (Negate)
return e_cmd_err;
else if (Arg[0] == '\0')
return e_cmd_err;
else
{
if (!p)
return e_cmd_err;
else
{
strmemcpy(s1, STRINGSIZE, Arg, p - Arg);
UpString(s1);
strmaxcpy(s2, p + 1, STRINGSIZE);
UpString(s2);
if (!(CMD_CPUAlias_ChkCPUName(s1) && CMD_CPUAlias_ChkCPUName(s2)))
return e_cmd_err;
else if (!AddCPUAlias(s2, s1))
return e_cmd_err;
else
return e_cmd_arg;
}
}
}
static as_cmd_result_t CMD_SetCPU(Boolean Negate, const char *Arg)
{
if (Negate)
{
*DefCPU = '\0';
return e_cmd_ok;
}
else
{
if (*Arg == '\0')
return e_cmd_err;
if (!as_strcasecmp(Arg, "?") || !as_strcasecmp(Arg, "LIST"))
{
write_cpu_list_exit = True;
return e_cmd_arg;
}
strmaxcpy(DefCPU, Arg, sizeof(DefCPU) - 1);
NLS_UpString(DefCPU);
if (!LookupCPUDefByName(DefCPU))
{
*DefCPU = '\0';
return e_cmd_err;
}
return e_cmd_arg;
}
}
static as_cmd_result_t CMD_NoICEMask(Boolean Negate, const char *Arg)
{
Word erg;
Boolean OK;
if (Negate)
{
NoICEMask = 1 << SegCode;
return e_cmd_ok;
}
else if (Arg[0] == '\0')
return e_cmd_err;
else
{
erg = ConstLongInt(Arg, &OK, 10);
if (!OK || (erg >= (1 << SegCount)))
return e_cmd_err;
else
{
NoICEMask = erg;
return e_cmd_arg;
}
}
}
static as_cmd_result_t CMD_MaxErrors(Boolean Negate, const char *Arg)
{
if (Negate)
{
MaxErrors = 0;
return e_cmd_ok;
}
else if (Arg[0] == '\0')
return e_cmd_err;
else
{
Boolean OK;
LongWord NewMaxErrors = ConstLongInt(Arg, &OK, 10);
if (!OK)
return e_cmd_err;
MaxErrors = NewMaxErrors;
return e_cmd_arg;
}
}
/*!------------------------------------------------------------------------
* \fn CMD_MaxIncludeLevel(Boolean Negate, const char *pArg)
* \brief set maximum include nesting level
* \param Negate back to default?
* \param pArg numeric argument
* \return exec result
* ------------------------------------------------------------------------ */
#define DEFAULT_MAXINCLUDELEVEL 200
static as_cmd_result_t CMD_MaxIncludeLevel(Boolean Negate, const char *pArg)
{
if (Negate)
{
MaxErrors = DEFAULT_MAXINCLUDELEVEL;
return e_cmd_ok;
}
else if (pArg[0] == '\0')
return e_cmd_err;
else
{
Boolean OK;
Integer NewMaxIncludeLevel = ConstLongInt(pArg, &OK, 10);
if (!OK)
return e_cmd_err;
MaxIncludeLevel = NewMaxIncludeLevel;
return e_cmd_arg;
}
}
static const as_cmd_rec_t ASParams[] =
{
{ "A" , CMD_BalanceTree },
{ "alias" , CMD_CPUAlias },
{ "a" , CMD_ShareAssembler },
{ "C" , CMD_CrossList },
{ "c" , CMD_ShareC },
{ "CPU" , CMD_SetCPU },
{ "D" , CMD_DefSymbol },
{ "E" , CMD_ErrorPath },
{ "g" , CMD_DebugMode },
{ "G" , CMD_CodeOutput },
{ "gnuerrors" , CMD_GNUErrors },
{ "h" , CMD_HexLowerCase },
{ "i" , CMD_IncludeList },
{ "I" , CMD_MakeIncludeList },
{ "L" , CMD_ListFile },
{ "l" , CMD_ListConsole },
{ "listradix" , CMD_ListRadix },
{ "splitbyte" , CMD_SplitByte },
{ "M" , CMD_MacroOutput },
{ "maxerrors" , CMD_MaxErrors },
{ "maxinclevel" , CMD_MaxIncludeLevel },
{ "n" , CMD_NumericErrors },
{ "noicemask" , CMD_NoICEMask },
{ "o" , CMD_OutFile },
{ "P" , CMD_MacProOutput },
{ "p" , CMD_SharePascal },
{ "r" , CMD_MsgIfRepass },
{ RelaxedName , CMD_Relaxed },
{ "s" , CMD_SectionList },
{ "screenheight" , CMD_screen_height },
{ "shareout" , CMD_ShareOutFile },
{ "olist" , CMD_ListOutFile },
{ "t" , CMD_ListMask },
{ "u" , CMD_UseList },
{ "U" , CMD_CaseSensitive },
{ "w" , CMD_SuppWarns },
{ "warnranges" , CMD_HardRanges },
{ "x" , CMD_ExtendErrors },
{ "X" , CMD_MakeDebug },
{ "Y" , CMD_ThrowErrors }
};
/*--------------------------------------------------------------------------*/
#ifdef __sunos__
extern void on_exit(void (*procp)(int status, caddr_t arg),caddr_t arg);
static void GlobExitProc(int status, caddr_t arg)
{
if (MakeDebug)
CloseIfOpen(&Debug);
}
#else
/* Might no longer need this with newer TCC versions: */
#ifdef __TINYC__
void * __dso_handle __attribute((visibility("hidden"))) = &__dso_handle;
#endif
static void GlobExitProc(void)
{
if (MakeDebug)
CloseIfOpen(&Debug);
}
#endif
int main(int argc, char **argv)
{
char *Env;
String Dummy;
static Boolean First = TRUE;
as_cmd_results_t cmd_results;
if (First)
{
be_le_init();
nls_init();
bpemu_init();
stdhandl_init();
strutil_init();
chunks_init();
if (!NLS_Initialize(&argc, argv))
#ifdef _USE_MSH
nlmessages_init_buffer(as_msh_data, sizeof(as_msh_data), MsgId1, MsgId2);
#else
nlmessages_init_file("as.msg", *argv, MsgId1, MsgId2);
#endif
ioerrs_init(*argv);
as_cmdarg_init(*argv);
msg_level_init();
as_cmd_register(ASParams, as_array_size(ASParams));
asmfnums_init();
asminclist_init();
asmitree_init();
asmdef_init();
cpulist_init();
asmsub_init();
asmpars_init();
intformat_init();
asmmac_init();
asmstruct_init();
asmif_init();
asmerr_init();
asmcode_init();
asmlabel_init();
asmdebug_init();
codeallg_init();
onoff_common_init();
literals_init();
#if 1
codenone_init();
#endif
code68k_init();
code56k_init();
code601_init();
codepalm_init();
codemcore_init();
codexgate_init();
code68_init();
code6805_init();
code6809_init();
code6812_init();
codes12z_init();
code6816_init();
code68rs08_init();
codeh8_3_init();
codeh8_5_init();
code7000_init();
codeko09_init();
code65_init();
codepps4_init();
codeh16_init();
code7700_init();
codehmcs400_init();
code4500_init();
codem16_init();
codem16c_init();
codepdp11_init();
codevax_init();
code4004_init();
code8008_init();
code48_init();
code51_init();
code96_init();
code85_init();
code86_init();
code960_init();
code8x30x_init();
code2650_init();
codexa_init();
codeavr_init();
code29k_init();
code166_init();
codez80_init();
codez8_init();
codez8000_init();
codekcpsm_init();
codekcpsm3_init();
codemico8_init();
code96c141_init();
code90c141_init();
code87c800_init();
code870c_init();
code47c00_init();
code97c241_init();
code9331_init();
code16c5x_init();
code16c8x_init();
code17c4x_init();
codesx20_init();
codepdk_init();
codest6_init();
codest7_init();
codest9_init();
code6804_init();
code3201x_init();
code3202x_init();
code3203x_init();
code3205x_init();
code32054x_init();
code3206x_init();
code9900_init();
codetms7_init();
code370_init();
codemsp_init();
codetms1_init();
code78c10_init();
code75xx_init();
code75k0_init();
code78k0_init();
code78k2_init();
code78k3_init();
code78k4_init();
code7720_init();
code77230_init();
codev60_init();
codescmp_init();
codeimp16_init();
code807x_init();
codecop4_init();
codecop8_init();
codesc14xxx_init();
codens32k_init();
codeace_init();
codecp3f_init();
codef8_init();
code53c8xx_init();
codef2mc8_init();
codef2mc16_init();
codemn1610_init();
codemn2610_init();
codeolms40_init();
codeolms50_init();
code1802_init();
codevector_init();
codexcore_init();
code1750_init();
codekenbak_init();
codecp1600_init();
codenano_init();
code6100_init();
coderx_init();
code61860_init();
code62015_init();
First = FALSE;
}
#ifdef __sunos__
on_exit(GlobExitProc, (caddr_t) NULL);
#else
# ifndef __MUNIX__
# endif
#endif
*CursUp = '\0';
switch (Redirected)
{
case NoRedir:
strmaxcpy(Dummy, Env ? Env : "Y", STRINGSIZE);
if (as_toupper(Dummy[0]) == 'N')
{
}
else
{
strcpy(CursUp
, " [A"); CursUp
[0] = Char_ESC
;
}
break;
case RedirToDevice:
break;
case RedirToFile:
break;
}
ShareMode = 0;
ListMode = 0;
IncludeList[0] = '\0';
SuppWarns = False;
MakeUseList = False;
MakeCrossList = False;
MakeSectionList = False;
MakeIncludeList = False;
ListMask = 0x1ff;
MakeDebug = False;
ExtendErrors = 0;
DefRelaxedMode = False;
MacroOutput = False;
MacProOutput = False;
CodeOutput = True;
MsgIfRepass = False;
NumericErrors = False;
DebugMode = DebugNone;
CaseSensitive = False;
ThrowErrors = False;
HardRanges = True;
NoICEMask = 1 << SegCode;
GNUErrors = False;
MaxErrors = 0;
ListRadixBase = 16;
ListPCZeroPad = False;
MaxIncludeLevel = DEFAULT_MAXINCLUDELEVEL;
write_cpu_list_exit = False;
LineZ = 0;
screen_height = 0;
#if defined(INCDIR)
CMD_IncludeList(False, INCDIR);
#endif
if (e_cmd_err == as_cmd_process(argc, argv, EnvName, &cmd_results))
{
printf("%s%s\n", getmessage
(cmd_results.
error_arg_in_env ? Num_ErrMsgInvEnvParam
: Num_ErrMsgInvParam
), cmd_results.
error_arg);
}
if ((msg_level >= e_msg_level_verbose) || cmd_results.write_version_exit)
{
String Tmp;
as_snprintf(Tmp, sizeof(Tmp), "%s%s", getmessage(Num_InfoMessMacroAss), Version);
write_console_next(Tmp);
as_snprintf(Tmp, sizeof(Tmp), "(%s-%s)", ARCHPRNAME, ARCHSYSNAME);
write_console_next(Tmp);
write_console_next(InfoMessCopyright);
WriteCopyrights(write_console_next);
write_console_next("");
}
if (cmd_results.write_help_exit)
{
char *ph1, *ph2;
String tmp;
as_snprintf(tmp, sizeof(tmp), "%s%s%s", getmessage(Num_InfoMessHead1), as_cmdarg_get_executable_name(), getmessage(Num_InfoMessHead2));
write_console_next(tmp);
for (ph1
= getmessage
(Num_InfoMessHelp
), ph2
= strchr(ph1
, '\n'); ph2
; ph1
= ph2
+ 1, ph2
= strchr(ph1
, '\n'))
{
*ph2 = '\0';
write_console_next(ph1);
*ph2 = '\n';
}
}
if (write_cpu_list_exit)
{
write_console_next(getmessage(Num_InfoMessCPUList));
PrintCPUList(write_console_next);
ClearCPUList();
}
if (cmd_results.write_version_exit || write_cpu_list_exit || cmd_results.write_help_exit)
/* ListRadixBase must have been set */
asmlist_init();
GlobErrFlag = False;
if (ErrorPath[0] != '\0')
{
unlink(ErrorName);
}
if (StringListEmpty(cmd_results.file_arg_list))
{
fprintf(stderr
, "%s: %s\n", as_cmdarg_get_executable_name
(), getmessage
(Num_ErrMessNoInputFiles
));
}
else
{
char *pFile;
while (True)
{
pFile = MoveAndCutStringListFirst(&cmd_results.file_arg_list);
if (!pFile)
break;
if (*pFile)
AssembleGroup(pFile);
}
}
if (*ErrorPath)
CloseIfOpen(&ErrorFile);
ClearCPUList();
return GlobErrFlag ? 2 : 0;
}