Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

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