Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

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