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(¯o_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(¯o_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 | } |