1 /* asmsub.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
4 /* */
5 /* AS-Portierung */
6 /* */
7 /* Unterfunktionen, vermischtes */
8 /* */
9 /*****************************************************************************/
10
11
12 #include "stdinc.h"
13 #include <string.h>
14 #include <ctype.h>
15 #include <stdarg.h>
16
17 #include "version.h"
18 #include "endian.h"
19 #include "stdhandl.h"
20 #include "console.h"
21 #include "nls.h"
22 #include "nlmessages.h"
23 #include "as.rsc"
24 #include "strutil.h"
25 #include "stringlists.h"
26 #include "chunks.h"
27 #include "ioerrs.h"
28 #include "errmsg.h"
29 #include "asmdef.h"
30 #include "asmpars.h"
31 #include "asmdebug.h"
32 #include "as.h"
33
34 #include "asmsub.h"
35
36
37 #ifdef __TURBOC__
38 #ifdef __DPMI16__
39 #define STKSIZE 36864
40 #else
41 #define STKSIZE 49152
42 #endif
43 #endif
44
45 #define VALID_S1 1
46 #define VALID_SN 2
47 #define VALID_M1 4
48 #define VALID_MN 8
49
50 static StringList CopyrightList, OutList, ShareOutList, ListOutList;
51
52 static LongWord StartStack, MinStack, LowStack;
53
54 static unsigned ValidSymCharLen;
55 static Byte *ValidSymChar;
56
57 /****************************************************************************/
58 /* Modulinitialisierung */
59
AsmSubPassInit(void)60 void AsmSubPassInit(void)
61 {
62 PageLength = 60;
63 PageWidth = 0;
64 }
65
66 /****************************************************************************/
67 /* Copyrightlistenverwaltung */
68
AddCopyright(const char * NewLine)69 void AddCopyright(const char *NewLine)
70 {
71 AddStringListLast(&CopyrightList, NewLine);
72 }
73
WriteCopyrights(TSwitchProc NxtProc)74 void WriteCopyrights(TSwitchProc NxtProc)
75 {
76 StringRecPtr Lauf;
77
78 if (!StringListEmpty(CopyrightList))
79 {
80 WrConsoleLine(GetStringListFirst(CopyrightList, &Lauf), True);
81 NxtProc();
82 while (Lauf)
83 {
84 WrConsoleLine(GetStringListNext(&Lauf), True);
85 NxtProc();
86 }
87 }
88 }
89
90 /*--------------------------------------------------------------------------*/
91 /* ermittelt das erste/letzte Auftauchen eines Zeichens ausserhalb */
92 /* "geschuetzten" Bereichen */
93
QuotMultPosQualify(const char * s,const char * pSearch,tQualifyQuoteFnc QualifyQuoteFnc)94 char *QuotMultPosQualify(const char *s, const char *pSearch, tQualifyQuoteFnc QualifyQuoteFnc)
95 {
96 register ShortInt Brack = 0, AngBrack = 0;
97 register const char *i;
98 Boolean InSglQuot = False, InDblQuot = False, ThisEscaped = False, NextEscaped = False;
99
100 for (i = s; *i; i++, ThisEscaped = NextEscaped)
101 {
102 NextEscaped = False;
103 if (strchr(pSearch, *i))
104 {
105 if (!AngBrack && !Brack && !InSglQuot && !InDblQuot)
106 return (char*)i;
107 }
108 switch (*i)
109 {
110 case '"':
111 if (!InSglQuot && !ThisEscaped)
112 InDblQuot = !InDblQuot;
113 break;
114 case '\'':
115 if (!InDblQuot && !ThisEscaped)
116 {
117 if (InSglQuot || !QualifyQuoteFnc || QualifyQuoteFnc(s, i))
118 InSglQuot = !InSglQuot;
119 }
120 break;
121 case '\\':
122 if ((InSglQuot || InDblQuot) && !ThisEscaped)
123 NextEscaped = True;
124 break;
125 case '(':
126 if (!AngBrack && !InDblQuot && !InSglQuot)
127 Brack++;
128 break;
129 case ')':
130 if (!AngBrack && !InDblQuot && !InSglQuot)
131 Brack--;
132 break;
133 case '[':
134 if (!Brack && !InDblQuot && !InSglQuot)
135 AngBrack++;
136 break;
137 case ']':
138 if (!Brack && !InDblQuot && !InSglQuot)
139 AngBrack--;
140 break;
141 }
142 }
143
144 return NULL;
145 }
146
QuotPosQualify(const char * s,char Zeichen,tQualifyQuoteFnc QualifyQuoteFnc)147 char *QuotPosQualify(const char *s, char Zeichen, tQualifyQuoteFnc QualifyQuoteFnc)
148 {
149 char Tmp[2];
150
151 Tmp[0] = Zeichen;
152 Tmp[1] = '\0';
153 return QuotMultPosQualify(s, Tmp, QualifyQuoteFnc);
154 }
155
RQuotPos(char * s,char Zeichen)156 char *RQuotPos(char *s, char Zeichen)
157 {
158 ShortInt Brack = 0, AngBrack = 0;
159 char *i;
160 Boolean Quot = False, Paren = False;
161
162 for (i = s + strlen(s) - 1; i >= s; i--)
163 if (*i == Zeichen)
164 {
165 if ((!AngBrack) && (!Brack) && (!Paren) && (!Quot))
166 return i;
167 }
168 else switch (*i)
169 {
170 case '"':
171 if ((!Brack) && (!AngBrack) && (!Quot))
172 Paren = !Paren;
173 break;
174 case '\'':
175 if ((!Brack) && (!AngBrack) && (!Paren))
176 Quot = !Quot;
177 break;
178 case ')':
179 if ((!AngBrack) && (!Paren) && (!Quot))
180 Brack++;
181 break;
182 case '(':
183 if ((!AngBrack) && (!Paren) && (!Quot))
184 Brack--;
185 break;
186 case ']':
187 if ((!Brack) && (!Paren) && (!Quot))
188 AngBrack++;
189 break;
190 case '[':
191 if ((!Brack) && (!Paren) && (!Quot))
192 AngBrack--;
193 break;
194 }
195
196 return NULL;
197 }
198
199 /*--------------------------------------------------------------------------*/
200 /* ermittelt das erste (nicht-) Leerzeichen in einem String */
201
FirstBlank(const char * s)202 char *FirstBlank(const char *s)
203 {
204 const char *h, *Min = NULL;
205
206 h = strchr(s, ' ');
207 if (h)
208 if ((!Min) || (h < Min))
209 Min = h;
210 h = strchr(s, Char_HT);
211 if (h)
212 if ((!Min) || (h < Min))
213 Min = h;
214 return (char*)Min;
215 }
216
217 /*--------------------------------------------------------------------------*/
218 /* einen String in zwei Teile zerlegen */
219
SplitString(char * Source,char * Left,char * Right,char * Trenner)220 void SplitString(char *Source, char *Left, char *Right, char *Trenner)
221 {
222 char Save;
223 LongInt slen = strlen(Source);
224
225 if ((!Trenner) || (Trenner >= Source + slen))
226 Trenner = Source + slen;
227 Save = (*Trenner);
228 *Trenner = '\0';
229 strmov(Left, Source);
230 *Trenner = Save;
231 if (Trenner >= Source + slen)
232 *Right = '\0';
233 else
234 strmov(Right, Trenner + 1);
235 }
236
237 /*--------------------------------------------------------------------------*/
238 /* verbesserte Grossbuchstabenfunktion */
239
240 /* einen String in Grossbuchstaben umwandeln. Dabei Stringkonstanten in Ruhe */
241 /* lassen */
242
UpString(char * s)243 void UpString(char *s)
244 {
245 char *z;
246 int hypquot = 0;
247 Boolean LastBk = FALSE, ThisBk;
248
249 for (z = s; *z != '\0'; z++)
250 {
251 ThisBk = FALSE;
252 switch (*z)
253 {
254 case '\\':
255 ThisBk = TRUE;
256 break;
257 case '\'':
258 if ((!(hypquot & 2)) && (!LastBk))
259 hypquot ^= 1;
260 break;
261 case '"':
262 if ((!(hypquot & 1)) && (!LastBk))
263 hypquot ^= 2;
264 break;
265 default:
266 if (!hypquot)
267 *z = UpCaseTable[(int)*z];
268 }
269 LastBk = ThisBk;
270 }
271 }
272
273 /****************************************************************************/
274
TranslateString(char * s,int Length)275 void TranslateString(char *s, int Length)
276 {
277 char *pRun, *pEnd;
278
279 if (Length < 0)
280 Length = strlen(s);
281 for (pRun = s, pEnd = pRun + Length; pRun < pEnd; pRun++)
282 *pRun = CharTransTable[((usint)(*pRun)) & 0xff];
283 }
284
StrCaseCmp(const char * s1,const char * s2,LongInt Hand1,LongInt Hand2)285 ShortInt StrCaseCmp(const char *s1, const char *s2, LongInt Hand1, LongInt Hand2)
286 {
287 int tmp;
288
289 tmp = as_toupper(*s1) - as_toupper(*s2);
290 if (!tmp)
291 tmp = as_strcasecmp(s1, s2);
292 if (!tmp)
293 tmp = Hand1 - Hand2;
294 if (tmp < 0)
295 return -1;
296 if (tmp > 0)
297 return 1;
298 return 0;
299 }
300
301 /****************************************************************************/
302 /* an einen Dateinamen eine Endung anhaengen */
303
AddSuffix(char * s,const char * Suff)304 void AddSuffix(char *s, const char *Suff)
305 {
306 char *p, *z, *Part;
307
308 p = NULL;
309 for (z = s; *z != '\0'; z++)
310 if (*z == '\\')
311 p = z;
312 Part = p ? p : s;
313 if (!strchr(Part, '.'))
314 strmaxcat(s, Suff, STRINGSIZE);
315 }
316
317
318 /*--------------------------------------------------------------------------*/
319 /* von einem Dateinamen die Endung loeschen */
320
KillSuffix(char * s)321 void KillSuffix(char *s)
322 {
323 char *p, *z, *Part;
324
325 p = NULL;
326 for (z = s; *z != '\0'; z++)
327 if (*z == '\\')
328 p = z;
329 Part = p ? p : s;
330 Part = strchr(Part, '.');
331 if (Part)
332 *Part = '\0';
333 }
334
335 /*--------------------------------------------------------------------------*/
336 /* Pfadanteil (Laufwerk+Verzeichnis) von einem Dateinamen abspalten */
337
PathPart(char * Name)338 char *PathPart(char *Name)
339 {
340 static String s;
341 char *p;
342
343 strmaxcpy(s, Name, STRINGSIZE);
344
345 p = strrchr(Name, PATHSEP);
346 #ifdef DRSEP
347 if (!p)
348 p = strrchr(Name, DRSEP);
349 #endif
350
351 if (!p)
352 *s = '\0';
353 else
354 s[1] = '\0';
355
356 return s;
357 }
358
359 /*--------------------------------------------------------------------------*/
360 /* Namensanteil von einem Dateinamen abspalten */
361
NamePart(const char * Name)362 const char *NamePart(const char *Name)
363 {
364 const char *p = strrchr(Name, PATHSEP);
365
366 #ifdef DRSEP
367 if (!p)
368 p = strrchr(Name, DRSEP);
369 #endif
370
371 return p ? p + 1 : Name;
372 }
373
374 /****************************************************************************/
375 /* eine Gleitkommazahl in einen String umwandeln */
376
FloatString(char * pDest,size_t DestSize,Double f)377 void FloatString(char *pDest, size_t DestSize, Double f)
378 {
379 #define MaxLen 18
380 char *p, *d, ExpChar = HexStartCharacter + ('E' - 'A');
381 sint n, ExpVal, nzeroes;
382 Boolean WithE, OK;
383
384 /* 1. mit Maximallaenge wandeln, fuehrendes Vorzeichen weg */
385
386 (void)DestSize;
387 as_snprintf(pDest, DestSize, "%27.15e", f);
388 for (p = pDest; (*p == ' ') || (*p == '+'); p++);
389 if (p != pDest)
390 strmov(pDest, p);
391
392 /* 2. Exponenten soweit als moeglich kuerzen, evtl. ganz streichen */
393
394 p = strchr(pDest, ExpChar);
395 if (!p)
396 return;
397 switch (*(++p))
398 {
399 case '+':
400 strmov(p, p + 1);
401 break;
402 case '-':
403 p++;
404 break;
405 }
406
407 while (*p == '0')
408 strmov(p, p + 1);
409 WithE = (*p != '\0');
410 if (!WithE)
411 pDest[strlen(pDest) - 1] = '\0';
412
413 /* 3. Nullen am Ende der Mantisse entfernen, Komma bleibt noch */
414
415 p = WithE ? strchr(pDest, ExpChar) : pDest + strlen(pDest);
416 p--;
417 while (*p == '0')
418 {
419 strmov(p, p + 1);
420 p--;
421 }
422
423 /* 4. auf die gewuenschte Maximalstellenzahl begrenzen */
424
425 p = WithE ? strchr(pDest, ExpChar) : pDest + strlen(pDest);
426 d = strchr(pDest, '.');
427 n = p - d - 1;
428
429 /* 5. Maximallaenge ueberschritten ? */
430
431 if (strlen(pDest) > MaxLen)
432 strmov(d + (n - (strlen(pDest) - MaxLen)), d + n);
433
434 /* 6. Exponentenwert berechnen */
435
436 if (WithE)
437 {
438 p = strchr(pDest, ExpChar);
439 ExpVal = ConstLongInt(p + 1, &OK, 10);
440 }
441 else
442 {
443 p = pDest + strlen(pDest);
444 ExpVal = 0;
445 }
446
447 /* 7. soviel Platz, dass wir den Exponenten weglassen und evtl. Nullen
448 anhaengen koennen ? */
449
450 if (ExpVal > 0)
451 {
452 nzeroes = ExpVal - (p - strchr(pDest, '.') - 1); /* = Zahl von Nullen, die anzuhaengen waere */
453
454 /* 7a. nur Kommaverschiebung erforderlich. Exponenten loeschen und
455 evtl. auch Komma */
456
457 if (nzeroes <= 0)
458 {
459 *p = '\0';
460 d = strchr(pDest, '.');
461 strmov(d, d + 1);
462 if (nzeroes != 0)
463 {
464 memmove(pDest + strlen(pDest) + nzeroes + 1, pDest + strlen(pDest) + nzeroes, -nzeroes);
465 pDest[strlen(pDest) - 1 + nzeroes] = '.';
466 }
467 }
468
469 /* 7b. Es muessen Nullen angehaengt werden. Schauen, ob nach Loeschen von
470 Punkt und E-Teil genuegend Platz ist */
471
472 else
473 {
474 n = strlen(p) + 1 + (MaxLen - strlen(pDest)); /* = Anzahl freizubekommender Zeichen+Gutschrift */
475 if (n >= nzeroes)
476 {
477 *p = '\0';
478 d = strchr(pDest, '.');
479 strmov(d, d + 1);
480 d = pDest + strlen(pDest);
481 for (n = 0; n < nzeroes; n++)
482 *(d++) = '0';
483 *d = '\0';
484 }
485 }
486 }
487
488 /* 8. soviel Platz, dass Exponent wegkann und die Zahl mit vielen Nullen
489 vorne geschrieben werden kann ? */
490
491 else if (ExpVal < 0)
492 {
493 n = (-ExpVal) - (strlen(p)); /* = Verlaengerung nach Operation */
494 if (strlen(pDest) + n <= MaxLen)
495 {
496 *p = '\0';
497 d = strchr(pDest, '.');
498 strmov(d, d + 1);
499 d = (pDest[0] == '-') ? pDest + 1 : pDest;
500 memmove(d - ExpVal + 1, d, strlen(pDest) + 1);
501 *(d++) = '0';
502 *(d++) = '.';
503 for (n = 0; n < -ExpVal - 1; n++)
504 *(d++) = '0';
505 }
506 }
507
508
509 /* 9. Ueberfluessiges Komma entfernen */
510
511 if (WithE)
512 p = strchr(pDest, ExpChar);
513 else
514 p = pDest + strlen(pDest);
515 if (p && (*(p - 1) == '.'))
516 strmov(p - 1, p);
517 }
518
519 /****************************************************************************/
520 /* Symbol in String wandeln */
521
StrSym(TempResult * t,Boolean WithSystem,char * Dest,size_t DestLen,unsigned Radix)522 void StrSym(TempResult *t, Boolean WithSystem, char *Dest, size_t DestLen, unsigned Radix)
523 {
524 LargeInt IntVal;
525
526 switch (t->Typ)
527 {
528 case TempInt:
529 IntVal = t->Contents.Int;
530 IsInt:
531 SysString(Dest, DestLen - 3, IntVal, Radix,
532 1, (16 == Radix) && (ConstMode == ConstModeIntel), HexStartCharacter);
533 if (WithSystem)
534 switch (ConstMode)
535 {
536 case ConstModeIntel:
537 switch (Radix)
538 {
539 case 16:
540 case 8:
541 case 2:
542 as_snprcatf(Dest, DestLen, GetIntelSuffix(Radix));
543 break;
544 }
545 break;
546 case ConstModeMoto:
547 switch (Radix)
548 {
549 case 16:
550 strprep(Dest, "$");
551 break;
552 case 8:
553 strprep(Dest, "@");
554 break;
555 case 2:
556 strprep(Dest, "%");
557 break;
558 }
559 break;
560 case ConstModeC:
561 switch (Radix)
562 {
563 case 16:
564 strprep(Dest, "0x");
565 break;
566 case 8:
567 strprep(Dest, "0");
568 break;
569 }
570 break;
571 case ConstModeWeird :
572 switch (Radix)
573 {
574 case 16:
575 strprep(Dest, "x'");
576 strcat(Dest, "'");
577 break;
578 }
579 break;
580 }
581 break;
582 case TempFloat:
583 FloatString(Dest, DestLen, t->Contents.Float);
584 break;
585 case TempString:
586 TempResultToPlainString(Dest, t, DestLen);
587 break;
588 case TempReg:
589 if (t->Contents.RegDescr.Dissect)
590 t->Contents.RegDescr.Dissect(Dest, DestLen, t->Contents.RegDescr.Reg, t->DataSize);
591 else
592 {
593 IntVal = t->Contents.RegDescr.Reg;
594 goto IsInt;
595 }
596 break;
597 default:
598 strmaxcpy(Dest, "???", DestLen);
599 }
600 }
601
602 /****************************************************************************/
603 /* Listingzaehler zuruecksetzen */
604
ResetPageCounter(void)605 void ResetPageCounter(void)
606 {
607 int z;
608
609 for (z = 0; z <= ChapMax; z++)
610 PageCounter[z] = 0;
611 LstCounter = 0;
612 ChapDepth = 0;
613 }
614
615 /*--------------------------------------------------------------------------*/
616 /* eine neue Seite im Listing beginnen */
617
NewPage(ShortInt Level,Boolean WithFF)618 void NewPage(ShortInt Level, Boolean WithFF)
619 {
620 ShortInt z;
621 String Header, s;
622 char Save;
623
624 if (ListOn == 0)
625 return;
626
627 LstCounter = 0;
628
629 if (ChapDepth < (Byte) Level)
630 {
631 memmove(PageCounter + (Level - ChapDepth), PageCounter, (ChapDepth + 1) * sizeof(Word));
632 for (z = 0; z <= Level - ChapDepth; PageCounter[z++] = 1);
633 ChapDepth = Level;
634 }
635 for (z = 0; z <= Level - 1; PageCounter[z++] = 1);
636 PageCounter[Level]++;
637
638 if ((WithFF) && (!ListToNull))
639 {
640 errno = 0;
641 fprintf(LstFile, "%c", Char_FF);
642 ChkIO(ErrNum_ListWrError);
643 }
644
645 as_snprintf(Header, sizeof(Header), " AS V%s%s%s",
646 Version,
647 getmessage(Num_HeadingFileNameLab),
648 NamePart(SourceFile));
649 if ((strcmp(CurrFileName, "INTERNAL"))
650 && (strcmp(NamePart(CurrFileName), NamePart(SourceFile))))
651 {
652 strmaxcat(Header, "(", STRINGSIZE);
653 strmaxcat(Header, NamePart(CurrFileName), STRINGSIZE);
654 strmaxcat(Header, ")", STRINGSIZE);
655 }
656 strmaxcat(Header, getmessage(Num_HeadingPageLab), STRINGSIZE);
657
658 for (z = ChapDepth; z >= 0; z--)
659 {
660 as_snprintf(s, sizeof(s), IntegerFormat, PageCounter[z]);
661 strmaxcat(Header, s, STRINGSIZE);
662 if (z != 0)
663 strmaxcat(Header, ".", STRINGSIZE);
664 }
665
666 strmaxcat(Header, " - ", STRINGSIZE);
667 NLS_CurrDateString(s, sizeof(s));
668 strmaxcat(Header, s, STRINGSIZE);
669 strmaxcat(Header, " ", STRINGSIZE);
670 NLS_CurrTimeString(False, s, sizeof(s));
671 strmaxcat(Header, s, STRINGSIZE);
672
673 if (PageWidth != 0)
674 while (strlen(Header) > PageWidth)
675 {
676 Save = Header[PageWidth];
677 Header[PageWidth] = '\0';
678 if (!ListToNull)
679 {
680 errno = 0;
681 fprintf(LstFile, "%s\n", Header);
682 ChkIO(ErrNum_ListWrError);
683 }
684 Header[PageWidth] = Save;
685 strmov(Header, Header + PageWidth);
686 }
687
688 if (!ListToNull)
689 {
690 errno = 0;
691 fprintf(LstFile, "%s\n", Header);
692 ChkIO(ErrNum_ListWrError);
693
694 if (PrtTitleString[0])
695 {
696 errno = 0;
697 fprintf(LstFile, "%s\n", PrtTitleString);
698 ChkIO(ErrNum_ListWrError);
699 }
700
701 errno = 0;
702 fprintf(LstFile, "\n\n");
703 ChkIO(ErrNum_ListWrError);
704 }
705 }
706
707 /*--------------------------------------------------------------------------*/
708 /* eine Zeile ins Listing schieben */
709
WrLstLine(const char * Line)710 void WrLstLine(const char *Line)
711 {
712 int LLength;
713 char bbuf[2500];
714 String LLine;
715 int blen = 0, hlen, z, Start;
716
717 if ((ListOn == 0) || (ListToNull))
718 return;
719
720 if (PageLength == 0)
721 {
722 errno = 0;
723 fprintf(LstFile, "%s\n", Line);
724 ChkIO(ErrNum_ListWrError);
725 }
726 else
727 {
728 if ((PageWidth == 0) || ((strlen(Line) << 3) < PageWidth))
729 LLength = 1;
730 else
731 {
732 blen = 0;
733 for (z = 0; z < (int)strlen(Line); z++)
734 if (Line[z] == Char_HT)
735 {
736 memset(bbuf + blen, ' ', 8 - (blen & 7));
737 blen += 8 - (blen&7);
738 }
739 else
740 bbuf[blen++] = Line[z];
741 LLength = blen / PageWidth;
742 if (blen % PageWidth)
743 LLength++;
744 }
745 if (LLength == 1)
746 {
747 errno = 0;
748 fprintf(LstFile, "%s\n", Line);
749 ChkIO(ErrNum_ListWrError);
750 if ((++LstCounter) == PageLength)
751 NewPage(0, True);
752 }
753 else
754 {
755 Start = 0;
756 for (z = 1; z <= LLength; z++)
757 {
758 hlen = PageWidth;
759 if (blen - Start < hlen)
760 hlen = blen - Start;
761 memcpy(LLine, bbuf + Start, hlen);
762 LLine[hlen] = '\0';
763 errno = 0;
764 fprintf(LstFile, "%s\n", LLine);
765 if ((++LstCounter) == PageLength)
766 NewPage(0, True);
767 Start += hlen;
768 }
769 }
770 }
771 }
772
773 /*****************************************************************************/
774 /* Ausdruck in Spalte vor Listing */
775
SetListLineVal(TempResult * t)776 void SetListLineVal(TempResult *t)
777 {
778 *ListLine = '=';
779 StrSym(t, True, ListLine + 1, STRINGSIZE - 1, ListRadixBase);
780 LimitListLine();
781 }
782
LimitListLine(void)783 void LimitListLine(void)
784 {
785 if (strlen(ListLine) + 1 > LISTLINESPACE)
786 {
787 ListLine[LISTLINESPACE - 4] = '\0';
788 strmaxcat(ListLine, "..", STRINGSIZE);
789 }
790 }
791
792 /*!------------------------------------------------------------------------
793 * \fn PrintOneLineMuted(FILE *pFile, const char *pLine,
794 const struct sLineComp *pMuteComponent,
795 const struct sLineComp *pMuteComponent2)
796 * \brief print a line, with a certain component muted out (i.e. replaced by spaces)
797 * \param pFile where to write
798 * \param pLine line to print
799 * \param pMuteComponent component to mute in printout
800 * ------------------------------------------------------------------------ */
801
CompMatch(int Col,const struct sLineComp * pComp)802 static Boolean CompMatch(int Col, const struct sLineComp *pComp)
803 {
804 return (pComp
805 && (pComp->StartCol >= 0)
806 && (Col >= pComp->StartCol)
807 && (Col < pComp->StartCol + (int)pComp->Len));
808 }
809
PrintOneLineMuted(FILE * pFile,const char * pLine,const struct sLineComp * pMuteComponent,const struct sLineComp * pMuteComponent2)810 void PrintOneLineMuted(FILE *pFile, const char *pLine,
811 const struct sLineComp *pMuteComponent,
812 const struct sLineComp *pMuteComponent2)
813 {
814 int z, Len = strlen(pLine);
815 Boolean Match;
816
817 errno = 0;
818 for (z = 0; z < Len; z++)
819 {
820 Match = CompMatch(z, pMuteComponent) || CompMatch(z, pMuteComponent2);
821 fputc(Match ? ' ' : pLine[z], pFile);
822 }
823 fputc('\n', pFile);
824 ChkIO(ErrNum_ListWrError);
825 }
826
827 /*!------------------------------------------------------------------------
828 * \fn PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer,
829 char Marker, const struct sLineComp *pLineComp)
830 * \brief print a line, optionally with a marking of a component below
831 * \param pFile where to write
832 * \param pLine line to print/underline
833 * \param pPrefix what to print before (under)line
834 * \param pTrailer what to print after (under)line
835 * \param Marker character to use for marking
836 * \param pLineComp position and length of optional marker
837 * ------------------------------------------------------------------------ */
838
PrLineMarker(FILE * pFile,const char * pLine,const char * pPrefix,const char * pTrailer,char Marker,const struct sLineComp * pLineComp)839 void PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer,
840 char Marker, const struct sLineComp *pLineComp)
841 {
842 const char *pRun;
843 int z;
844
845 fputs(pPrefix, pFile);
846 for (pRun = pLine; *pRun; pRun++)
847 fputc(TabCompressed(*pRun), pFile);
848 fprintf(pFile, "%s\n", pTrailer);
849
850 if (pLineComp && (pLineComp->StartCol >= 0) && (pLineComp->Len > 0))
851 {
852 fputs(pPrefix, pFile);
853 if (pLineComp->StartCol > 0)
854 fprintf(pFile, "%*s", pLineComp->StartCol, "");
855 for (z = 0; z < (int)pLineComp->Len; z++)
856 fputc(Marker, pFile);
857 fprintf(pFile, "%s\n", pTrailer);
858 }
859 }
860
861 /****************************************************************************/
862 /* einen Symbolnamen auf Gueltigkeit ueberpruefen */
863
GetValidSymChar(unsigned Ch)864 static Byte GetValidSymChar(unsigned Ch)
865 {
866 return (Ch < ValidSymCharLen) ? ValidSymChar[Ch] : 0;
867 }
868
ChkNameUpTo(const char * pSym,const char * pUpTo,Byte _Mask)869 static char *ChkNameUpTo(const char *pSym, const char *pUpTo, Byte _Mask)
870 {
871 Byte Mask = _Mask;
872 unsigned Ch;
873 const char *pPrev;
874
875 if (!*pSym)
876 return (char*)pSym;
877
878 while (*pSym && (pSym != pUpTo))
879 {
880 pPrev = pSym;
881 if (ValidSymCharLen > 256)
882 Ch = UTF8ToUnicode(&pSym);
883 else
884 Ch = ((unsigned int)*pSym++) & 0xff;
885
886 if (!(GetValidSymChar(Ch) & Mask))
887 return (char*)pPrev;
888 Mask = _Mask << 1;
889 }
890 return (char*)pSym;
891 }
892
ChkSymbNameUpTo(const char * pSym,const char * pUpTo)893 char *ChkSymbNameUpTo(const char *pSym, const char *pUpTo)
894 {
895 char *pResult = ChkNameUpTo(pSym, pUpTo, VALID_S1);
896
897 /* If NULL as UpTo was given, and all is fine up to end of string,
898 also return NULL as result. So Equation 'Result==UpTo' is fulfilled: */
899
900 if (!pUpTo && !*pResult)
901 pResult= NULL;
902 return pResult;
903 }
904
ChkSymbName(const char * pSym)905 Boolean ChkSymbName(const char *pSym)
906 {
907 const char *pEnd = ChkSymbNameUpTo(pSym, NULL);
908 return *pSym && !pEnd;
909 }
910
ChkMacSymbNameUpTo(const char * pSym,const char * pUpTo)911 char *ChkMacSymbNameUpTo(const char *pSym, const char *pUpTo)
912 {
913 char *pResult = ChkNameUpTo(pSym, pUpTo, VALID_M1);
914
915 /* If NULL as UpTo was given, and all is fine up to end of string,
916 also return NULL as result. So Equation 'Result==UpTo' is fulfilled: */
917
918 if (!pUpTo && !*pResult)
919 pResult= NULL;
920 return pResult;
921 }
922
ChkMacSymbName(const char * pSym)923 Boolean ChkMacSymbName(const char *pSym)
924 {
925 const char *pEnd = ChkMacSymbNameUpTo(pSym, NULL);
926 return *pSym && !pEnd;
927 }
928
929 /*!------------------------------------------------------------------------
930 * \fn visible_strlen(const char *pSym)
931 * \brief retrieve 'visible' length of string, regarding multi-by sequences for UTF-8
932 * \param pSym symbol name
933 * \return visible length in characters
934 * ------------------------------------------------------------------------ */
935
visible_strlen(const char * pSym)936 unsigned visible_strlen(const char *pSym)
937 {
938 if (ValidSymCharLen > 256)
939 {
940 unsigned Result = 0;
941
942 while (*pSym)
943 {
944 (void)UTF8ToUnicode(&pSym);
945 Result++;
946 }
947 return Result;
948 }
949 else
950 return strlen(pSym);
951 }
952
953 /****************************************************************************/
954
ProgCounter(void)955 LargeWord ProgCounter(void)
956 {
957 return PCs[ActPC];
958 }
959
960 /*--------------------------------------------------------------------------*/
961 /* aktuellen Programmzaehler mit Phasenverschiebung holen */
962
EProgCounter(void)963 LargeWord EProgCounter(void)
964 {
965 return PCs[ActPC] + Phases[ActPC];
966 }
967
968 /*--------------------------------------------------------------------------*/
969 /* Granularitaet des aktuellen Segments holen */
970
Granularity(void)971 Word Granularity(void)
972 {
973 return Grans[ActPC];
974 }
975
976 /*--------------------------------------------------------------------------*/
977 /* Linstingbreite des aktuellen Segments holen */
978
ListGran(void)979 Word ListGran(void)
980 {
981 return ListGrans[ActPC];
982 }
983
984 /*--------------------------------------------------------------------------*/
985 /* pruefen, ob alle Symbole einer Formel im korrekten Adressraum lagen */
986
ChkSpace(Byte AddrSpace,unsigned AddrSpaceMask)987 void ChkSpace(Byte AddrSpace, unsigned AddrSpaceMask)
988 {
989 AddrSpaceMask &= ~(1 << AddrSpace);
990
991 if (AddrSpaceMask) WrError(ErrNum_WrongSegment);
992 }
993
994 /****************************************************************************/
995 /* eine Chunkliste im Listing ausgeben & Speicher loeschen */
996
PrintChunk(ChunkList * NChunk,DissectBitProc Dissect,int ItemsPerLine)997 void PrintChunk(ChunkList *NChunk, DissectBitProc Dissect, int ItemsPerLine)
998 {
999 LargeWord NewMin, FMin;
1000 Boolean Found;
1001 Word p = 0, z;
1002 int BufferZ;
1003 String BufferS;
1004 int MaxItemLen = 79 / ItemsPerLine;
1005
1006 NewMin = 0;
1007 BufferZ = 0;
1008 *BufferS = '\0';
1009
1010 do
1011 {
1012 /* niedrigsten Start finden, der ueberhalb des letzten Endes liegt */
1013
1014 Found = False;
1015 FMin = IntTypeDefs[LargeWordType].Max;
1016 for (z = 0; z < NChunk->RealLen; z++)
1017 if (NChunk->Chunks[z].Start >= NewMin)
1018 if (FMin > NChunk->Chunks[z].Start)
1019 {
1020 Found = True;
1021 FMin = NChunk->Chunks[z].Start;
1022 p = z;
1023 }
1024
1025 if (Found)
1026 {
1027 char Num[30];
1028
1029 Dissect(Num, sizeof(Num), NChunk->Chunks[p].Start);
1030 strmaxcat(BufferS, Num, STRINGSIZE);
1031 if (NChunk->Chunks[p].Length != 1)
1032 {
1033 strmaxcat(BufferS, "-", STRINGSIZE);
1034 Dissect(Num, sizeof(Num), NChunk->Chunks[p].Start + NChunk->Chunks[p].Length - 1);
1035 strmaxcat(BufferS, Num, STRINGSIZE);
1036 }
1037 strmaxcat(BufferS, Blanks(MaxItemLen - strlen(BufferS) % MaxItemLen), STRINGSIZE);
1038 if (++BufferZ == ItemsPerLine)
1039 {
1040 WrLstLine(BufferS);
1041 *BufferS = '\0';
1042 BufferZ = 0;
1043 }
1044 NewMin = NChunk->Chunks[p].Start + NChunk->Chunks[p].Length;
1045 }
1046 }
1047 while (Found);
1048
1049 if (BufferZ != 0)
1050 WrLstLine(BufferS);
1051 }
1052
1053 /*--------------------------------------------------------------------------*/
1054 /* Listen ausgeben */
1055
PrintUseList(void)1056 void PrintUseList(void)
1057 {
1058 int z, z2, l;
1059 String s;
1060
1061 for (z = 1; z <= PCMax; z++)
1062 if (SegChunks[z].Chunks)
1063 {
1064 as_snprintf(s, sizeof(s), " %s%s%s",
1065 getmessage(Num_ListSegListHead1), SegNames[z],
1066 getmessage(Num_ListSegListHead2));
1067 WrLstLine(s);
1068 strcpy(s, " ");
1069 l = strlen(SegNames[z]) + strlen(getmessage(Num_ListSegListHead1)) + strlen(getmessage(Num_ListSegListHead2));
1070 for (z2 = 0; z2 < l; z2++)
1071 strmaxcat(s, "-", STRINGSIZE);
1072 WrLstLine(s);
1073 WrLstLine("");
1074 PrintChunk(SegChunks + z,
1075 (z == SegBData) ? DissectBit : Default_DissectBit,
1076 (z == SegBData) ? 3 : 4);
1077 WrLstLine("");
1078 }
1079 }
1080
ClearUseList(void)1081 void ClearUseList(void)
1082 {
1083 int z;
1084
1085 for (z = 1; z <= PCMax; z++)
1086 ClearChunk(SegChunks + z);
1087 }
1088
1089 /****************************************************************************/
1090 /* Include-Pfadlistenverarbeitung */
1091
GetPath(char * Acc)1092 static char *GetPath(char *Acc)
1093 {
1094 char *p;
1095 static String tmp;
1096
1097 p = strchr(Acc, DIRSEP);
1098 if (!p)
1099 {
1100 strmaxcpy(tmp, Acc, STRINGSIZE);
1101 Acc[0] = '\0';
1102 }
1103 else
1104 {
1105 *p = '\0';
1106 strmaxcpy(tmp, Acc, STRINGSIZE);
1107 strmov(Acc, p + 1);
1108 }
1109 return tmp;
1110 }
1111
AddIncludeList(char * NewPath)1112 void AddIncludeList(char *NewPath)
1113 {
1114 String Test;
1115
1116 strmaxcpy(Test, IncludeList, STRINGSIZE);
1117 while (*Test != '\0')
1118 if (!strcmp(GetPath(Test), NewPath))
1119 return;
1120 if (*IncludeList != '\0')
1121 strmaxprep(IncludeList, SDIRSEP, STRINGSIZE);
1122 strmaxprep(IncludeList, NewPath, STRINGSIZE);
1123 }
1124
1125
RemoveIncludeList(char * RemPath)1126 void RemoveIncludeList(char *RemPath)
1127 {
1128 String Save;
1129 char *Part;
1130
1131 strmaxcpy(IncludeList, Save, STRINGSIZE);
1132 IncludeList[0] = '\0';
1133 while (Save[0] != '\0')
1134 {
1135 Part = GetPath(Save);
1136 if (strcmp(Part, RemPath))
1137 {
1138 if (IncludeList[0] != '\0')
1139 strmaxcat(IncludeList, SDIRSEP, STRINGSIZE);
1140 strmaxcat(IncludeList, Part, STRINGSIZE);
1141 }
1142 }
1143 }
1144
1145 /****************************************************************************/
1146 /* Listen mit Ausgabedateien */
1147
ClearOutList(void)1148 void ClearOutList(void)
1149 {
1150 ClearStringList(&OutList);
1151 }
1152
AddToOutList(const char * NewName)1153 void AddToOutList(const char *NewName)
1154 {
1155 AddStringListLast(&OutList, NewName);
1156 }
1157
RemoveFromOutList(const char * OldName)1158 void RemoveFromOutList(const char *OldName)
1159 {
1160 RemoveStringList(&OutList, OldName);
1161 }
1162
GetFromOutList(void)1163 char *GetFromOutList(void)
1164 {
1165 return GetAndCutStringList(&OutList);
1166 }
1167
ClearShareOutList(void)1168 void ClearShareOutList(void)
1169 {
1170 ClearStringList(&ShareOutList);
1171 }
1172
AddToShareOutList(const char * NewName)1173 void AddToShareOutList(const char *NewName)
1174 {
1175 AddStringListLast(&ShareOutList, NewName);
1176 }
1177
RemoveFromShareOutList(const char * OldName)1178 void RemoveFromShareOutList(const char *OldName)
1179 {
1180 RemoveStringList(&ShareOutList, OldName);
1181 }
1182
GetFromShareOutList(void)1183 char *GetFromShareOutList(void)
1184 {
1185 return GetAndCutStringList(&ShareOutList);
1186 }
1187
ClearListOutList(void)1188 void ClearListOutList(void)
1189 {
1190 ClearStringList(&ListOutList);
1191 }
1192
AddToListOutList(const char * NewName)1193 void AddToListOutList(const char *NewName)
1194 {
1195 AddStringListLast(&ListOutList, NewName);
1196 }
1197
RemoveFromListOutList(const char * OldName)1198 void RemoveFromListOutList(const char *OldName)
1199 {
1200 RemoveStringList(&ListOutList, OldName);
1201 }
1202
GetFromListOutList(void)1203 char *GetFromListOutList(void)
1204 {
1205 return GetAndCutStringList(&ListOutList);
1206 }
1207
1208 /****************************************************************************/
1209 /* Tokenverarbeitung */
1210
CompressLine_NErl(char ch)1211 static Boolean CompressLine_NErl(char ch)
1212 {
1213 return (((ch >= 'A') && (ch <= 'Z'))
1214 || ((ch >= 'a') && (ch <= 'z'))
1215 || ((ch >= '0') && (ch <= '9')));
1216 }
1217
1218 static char Token[3] = { 0x01, 0x00, 0x00 };
1219 typedef int (*tCompareFnc)(const char *s1, const char *s2, size_t n);
1220
ReplaceLine(char * pStr,unsigned StrSize,const char * pSearch,const char * pReplace,Boolean CaseSensitive)1221 int ReplaceLine(char *pStr, unsigned StrSize, const char *pSearch, const char *pReplace, Boolean CaseSensitive)
1222 {
1223 int SearchLen = strlen(pSearch), ReplaceLen = strlen(pReplace), StrLen = strlen(pStr), DeltaLen = ReplaceLen - SearchLen;
1224 int NumReplace = 0, Pos, End, CmpRes, Avail, nCopy, nMove;
1225 tCompareFnc Compare = CaseSensitive ? strncmp : as_strncasecmp;
1226
1227 Pos = 0;
1228 while (Pos <= StrLen - SearchLen)
1229 {
1230 End = Pos + SearchLen;
1231 CmpRes = Compare(&pStr[Pos], pSearch, SearchLen);
1232 if ((!CmpRes)
1233 && ((Pos == 0) || (!CompressLine_NErl(pStr[Pos - 1])))
1234 && ((End >= StrLen) || (!CompressLine_NErl(pStr[End]))))
1235 {
1236 Avail = StrSize - 1 - Pos;
1237 nCopy = ReplaceLen; if (nCopy > Avail) nCopy = Avail;
1238 Avail -= nCopy;
1239 nMove = StrLen - (Pos + SearchLen); if (nMove > Avail) nMove = Avail;
1240 memmove(&pStr[Pos + nCopy], &pStr[Pos + SearchLen], nMove);
1241 memcpy(&pStr[Pos], pReplace, nCopy);
1242 pStr[Pos + nCopy + nMove] = '\0';
1243 Pos += nCopy;
1244 StrLen += DeltaLen;
1245 NumReplace++;
1246 }
1247 else
1248 Pos++;
1249 }
1250 return NumReplace;
1251 }
1252
SetToken(unsigned TokenNum)1253 static void SetToken(unsigned TokenNum)
1254 {
1255 Token[0] = (TokenNum >> 4) + 1;
1256 Token[1] = (TokenNum & 15) + 1;
1257 }
1258
CompressLine(const char * TokNam,unsigned TokenNum,char * Line,unsigned LineSize,Boolean ThisCaseSensitive)1259 int CompressLine(const char *TokNam, unsigned TokenNum, char *Line, unsigned LineSize, Boolean ThisCaseSensitive)
1260 {
1261 SetToken(TokenNum);
1262 return ReplaceLine(Line, LineSize, TokNam, Token, ThisCaseSensitive);
1263 }
1264
ExpandLine(const char * TokNam,unsigned TokenNum,char * Line,unsigned LineSize)1265 void ExpandLine(const char *TokNam, unsigned TokenNum, char *Line, unsigned LineSize)
1266 {
1267 SetToken(TokenNum);
1268 (void)ReplaceLine(Line, LineSize, Token, TokNam, True);
1269 }
1270
KillCtrl(char * Line)1271 void KillCtrl(char *Line)
1272 {
1273 char *z;
1274
1275 if (*(z = Line) == '\0')
1276 return;
1277 do
1278 {
1279 if (*z == '\0');
1280 else if (*z == Char_HT)
1281 {
1282 strmov(z, z + 1);
1283 strprep(z, Blanks(8 - ((z - Line) % 8)));
1284 }
1285 else if ((*z & 0xe0) == 0)
1286 *z = ' ';
1287 z++;
1288 }
1289 while (*z != '\0');
1290 }
1291
1292 /****************************************************************************/
1293 /* Buchhaltung */
1294
BookKeeping(void)1295 void BookKeeping(void)
1296 {
1297 if (MakeUseList)
1298 if (AddChunk(SegChunks + ActPC, ProgCounter(), CodeLen, ActPC == SegCode))
1299 WrError(ErrNum_Overlap);
1300 if (DebugMode != DebugNone)
1301 {
1302 AddSectionUsage(ProgCounter(), CodeLen);
1303 AddLineInfo(InMacroFlag, CurrLine, CurrFileName, ActPC, PCs[ActPC], CodeLen);
1304 }
1305 }
1306
1307 /****************************************************************************/
1308 /* Differenz zwischen zwei Zeiten mit Tagesueberlauf berechnen */
1309
DTime(long t1,long t2)1310 long DTime(long t1, long t2)
1311 {
1312 LongInt d;
1313
1314 d = t2 - t1;
1315 if (d < 0) d += (24*360000);
1316 return (d > 0) ? d : -d;
1317 }
1318
1319 /*--------------------------------------------------------------------------*/
1320 /* Init/Deinit passes */
1321
1322 typedef struct sProcStore
1323 {
1324 struct sProcStore *pNext;
1325 SimpProc Proc;
1326 } tProcStore;
1327
1328 static tProcStore *pInitPassProcStore = NULL,
1329 *pClearUpProcStore = NULL;
1330
InitPass(void)1331 void InitPass(void)
1332 {
1333 tProcStore *pStore;
1334
1335 for (pStore = pInitPassProcStore; pStore; pStore = pStore->pNext)
1336 pStore->Proc();
1337 }
1338
ClearUp(void)1339 void ClearUp(void)
1340 {
1341 tProcStore *pStore;
1342
1343 for (pStore = pClearUpProcStore; pStore; pStore = pStore->pNext)
1344 pStore->Proc();
1345 }
1346
AddInitPassProc(SimpProc NewProc)1347 void AddInitPassProc(SimpProc NewProc)
1348 {
1349 tProcStore *pNewStore = (tProcStore*)calloc(1, sizeof(*pNewStore));
1350
1351 pNewStore->pNext = pInitPassProcStore;
1352 pNewStore->Proc = NewProc;
1353 pInitPassProcStore = pNewStore;
1354 }
1355
AddClearUpProc(SimpProc NewProc)1356 void AddClearUpProc(SimpProc NewProc)
1357 {
1358 tProcStore *pNewStore = (tProcStore*)calloc(1, sizeof(*pNewStore));
1359
1360 pNewStore->pNext = pClearUpProcStore;
1361 pNewStore->Proc = NewProc;
1362 pClearUpProcStore = pNewStore;
1363 }
1364
1365 /*--------------------------------------------------------------------------*/
1366 /* Zeit holen */
1367
1368 #ifdef __MSDOS__
1369
1370 #include <dos.h>
1371
GTime(void)1372 long GTime(void)
1373 {
1374 struct time tbuf;
1375 long result;
1376
1377 gettime(&tbuf);
1378 result = tbuf.ti_hour;
1379 result = (result * 60) + tbuf.ti_min;
1380 result = (result * 60) + tbuf.ti_sec;
1381 result = (result * 100) + tbuf.ti_hund;
1382 return result;
1383 }
1384
1385 #elif __IBMC__
1386
1387 #include <time.h>
1388 #define INCL_DOSDATETIME
1389 #include <os2.h>
1390
GTime(void)1391 long GTime(void)
1392 {
1393 DATETIME dt;
1394 struct tm ts;
1395 DosGetDateTime(&dt);
1396 memset(&ts, 0, sizeof(ts));
1397 ts.tm_year = dt.year - 1900;
1398 ts.tm_mon = dt.month - 1;
1399 ts.tm_mday = dt.day;
1400 ts.tm_hour = dt.hours;
1401 ts.tm_min = dt.minutes;
1402 ts.tm_sec = dt.seconds;
1403 return (mktime(&ts) * 100) + (dt.hundredths);
1404 }
1405
1406 #elif __MINGW32__
1407
1408 /* distribution by Gunnar Wallmann */
1409
1410 #include <sys/time.h>
1411 #include "math64.h"
1412
1413 /*time from 1 Jan 1601 to 1 Jan 1970 in 100ns units */
1414
1415 typedef struct _FILETIME
1416 {
1417 unsigned long dwLowDateTime;
1418 unsigned long dwHighDateTime;
1419 } FILETIME;
1420
1421 void __stdcall GetSystemTimeAsFileTime(FILETIME*);
1422
GTime(void)1423 long GTime(void)
1424 {
1425 union
1426 {
1427 #ifndef NOLONGLONG
1428 long long ns100; /*time since 1 Jan 1601 in 100ns units */
1429 #endif
1430 FILETIME ft;
1431 } _now;
1432
1433 GetSystemTimeAsFileTime(&(_now.ft));
1434 #ifdef NOLONGLONG
1435 {
1436 static const t64 offs = { 0xd53e8000, 0x019db1de },
1437 div = { 100000, 0 };
1438 t64 acc;
1439
1440 acc.low = _now.ft.dwLowDateTime;
1441 acc.high = _now.ft.dwHighDateTime;
1442 sub64(&acc, &acc, &offs);
1443 div64(&acc, &acc, &div);
1444 return acc.low;
1445 }
1446 #else
1447 # define _W32_FT_OFFSET (116444736000000000LL)
1448 return (_now.ns100 - _W32_FT_OFFSET) / 100000LL;
1449 #endif
1450 }
1451
1452 #else
1453
1454 #include <sys/time.h>
1455
GTime(void)1456 long GTime(void)
1457 {
1458 struct timeval tv;
1459
1460 gettimeofday(&tv, NULL);
1461 return (tv.tv_sec*100) + (tv.tv_usec/10000);
1462 }
1463
1464 #endif
1465
1466 /*-------------------------------------------------------------------------*/
1467 /* Stackfehler abfangen - bis auf DOS nur Dummies */
1468
1469 #ifdef __TURBOC__
1470
1471 #ifdef __DPMI16__
1472 #else
1473 unsigned _stklen = STKSIZE;
1474 unsigned _ovrbuffer = 64*48;
1475 #endif
1476 #include <malloc.h>
1477
ChkStack(void)1478 void ChkStack(void)
1479 {
1480 LongWord avail = stackavail();
1481 if (avail < MinStack)
1482 WrError(ErrNum_StackOvfl);
1483 if (avail < LowStack)
1484 LowStack = avail;
1485 }
1486
ResetStack(void)1487 void ResetStack(void)
1488 {
1489 LowStack = stackavail();
1490 }
1491
StackRes(void)1492 LongWord StackRes(void)
1493 {
1494 return LowStack - MinStack;
1495 }
1496 #endif /* __TURBOC__ */
1497
1498 #ifdef CKMALLOC
1499 #undef malloc
1500 #undef realloc
1501
ckmalloc(size_t s)1502 void *ckmalloc(size_t s)
1503 {
1504 void *tmp;
1505
1506 #ifdef __TURBOC__
1507 if (coreleft() < HEAPRESERVE + s)
1508 WrError(ErrNum_HeapOvfl);
1509 #endif
1510
1511 tmp = malloc(s);
1512 if (!tmp && (s > 0))
1513 WrError(ErrNum_HeapOvfl);
1514 return tmp;
1515 }
1516
ckrealloc(void * p,size_t s)1517 void *ckrealloc(void *p, size_t s)
1518 {
1519 void *tmp;
1520
1521 #ifdef __TURBOC__
1522 if (coreleft() < HEAPRESERVE + s)
1523 WrError(ErrNum_HeapOvfl);
1524 #endif
1525
1526 tmp = realloc(p, s);
1527 if (!tmp)
1528 WrError(ErrNum_HeapOvfl);
1529 return tmp;
1530 }
1531 #endif
1532
SetValidSymChar(unsigned Ch,Byte Value)1533 static void SetValidSymChar(unsigned Ch, Byte Value)
1534 {
1535 ValidSymChar[Ch] = Value;
1536 }
1537
SetValidSymChars(unsigned Start,unsigned Stop,Byte Value)1538 static void SetValidSymChars(unsigned Start, unsigned Stop, Byte Value)
1539 {
1540 for (; Start <= Stop; Start++)
1541 SetValidSymChar(Start, Value);
1542 }
1543
asmsub_init(void)1544 void asmsub_init(void)
1545 {
1546 #ifdef __TURBOC__
1547 #ifdef __MSDOS__
1548 #ifdef __DPMI16__
1549 char *MemFlag, *p;
1550 String MemVal, TempName;
1551 unsigned long FileLen;
1552 #else
1553 char *envval;
1554 int ovrerg;
1555 #endif
1556 #endif
1557 #endif
1558
1559 InitStringList(&CopyrightList);
1560 InitStringList(&OutList);
1561 InitStringList(&ShareOutList);
1562 InitStringList(&ListOutList);
1563
1564 #ifdef __TURBOC__
1565 #ifdef __MSDOS__
1566 #ifdef __DPMI16__
1567 /* Fuer DPMI evtl. Swapfile anlegen */
1568
1569 MemFlag = getenv("ASXSWAP");
1570 if (MemFlag)
1571 {
1572 strmaxcpy(MemVal, MemFlag, STRINGSIZE);
1573 p = strchr(MemVal, ',');
1574 if (!p)
1575 strcpy(TempName, "ASX.TMP");
1576 else
1577 {
1578 *p = NULL;
1579 strcpy(TempName, MemVal);
1580 strmov(MemVal, p + 1);
1581 };
1582 KillBlanks(TempName);
1583 KillBlanks(MemVal);
1584 FileLen = strtol(MemFlag, &p, 0);
1585 if (*p != '\0')
1586 {
1587 fputs(getmessage(Num_ErrMsgInvSwapSize), stderr);
1588 exit(4);
1589 }
1590 if (MEMinitSwapFile(TempName, FileLen << 20) != RTM_OK)
1591 {
1592 fputs(getmessage(Num_ErrMsgSwapTooBig), stderr);
1593 exit(4);
1594 }
1595 }
1596 #else
1597 /* Bei DOS Auslagerung Overlays in XMS/EMS versuchen */
1598
1599 envval = getenv("USEXMS");
1600 if ((envval) && (as_toupper(*envval) == 'N'))
1601 ovrerg = -1;
1602 else
1603 ovrerg = _OvrInitExt(0, 0);
1604 if (ovrerg != 0)
1605 {
1606 envval = getenv("USEEMS");
1607 if ((!envval) || (as_toupper(*envval) != 'N'))
1608 _OvrInitEms(0, 0, 0);
1609 }
1610 #endif
1611 #endif
1612 #endif
1613
1614 #ifdef __TURBOC__
1615 StartStack = stackavail();
1616 LowStack = stackavail();
1617 MinStack = StartStack - STKSIZE + 0x800;
1618 #else
1619 StartStack = LowStack = MinStack = 0;
1620 #endif
1621
1622 /* initialize array of valid characters */
1623
1624 ValidSymCharLen = (NLS_GetCodepage() == eCodepageUTF8) ? 1280 : 256;
1625 ValidSymChar = (Byte*) calloc(ValidSymCharLen, sizeof(Byte));
1626
1627 /* The basic ASCII stuff: letters, dot and underbar are allowed
1628 anwhere, numbers not at beginning: */
1629
1630 SetValidSymChars('a', 'z', VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1631 SetValidSymChars('A', 'Z', VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1632 SetValidSymChars('0', '9', VALID_SN | VALID_MN);
1633 SetValidSymChar ('.' , VALID_S1 | VALID_SN );
1634 SetValidSymChar ('_' , VALID_S1 | VALID_SN );
1635
1636 /* Extensions, depending on character set: */
1637
1638 switch (NLS_GetCodepage())
1639 {
1640 case eCodepage1251:
1641 SetValidSymChar (0xa3 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1642 SetValidSymChar (0xb3 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1643 SetValidSymChar (0xa8 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1644 SetValidSymChar (0xb8 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1645 SetValidSymChar (0xaa , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1646 SetValidSymChar (0xba , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1647 SetValidSymChar (0xaf , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1648 SetValidSymChar (0xbf , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1649 SetValidSymChar (0xbd , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1650 SetValidSymChar (0xbe , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1651 goto iso8859_1;
1652 case eCodepage1252:
1653 SetValidSymChar (0x8a , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1654 SetValidSymChar (0x9a , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1655 SetValidSymChar (0x8c , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1656 SetValidSymChar (0x9c , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1657 SetValidSymChar (0x8e , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1658 SetValidSymChar (0x9e , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1659 SetValidSymChar (0x9f , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1660 goto iso8859_1;
1661 case eCodepage850:
1662 SetValidSymChars(0xb5, 0xb7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1663 SetValidSymChars(0xc6, 0xc7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1664 SetValidSymChars(0xd0, 0xd9, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1665 SetValidSymChar (0xde , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1666 SetValidSymChars(0xe0, 0xed, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1667 /* fall-through */
1668 case eCodepage437:
1669 SetValidSymChars(128, 165, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1670 SetValidSymChar (225 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1671 break;
1672 case eCodepage866:
1673 SetValidSymChars(0x80, 0xaf, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1674 SetValidSymChars(0xe0, 0xf7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1675 break;
1676 case eCodepageISO8859_15:
1677 SetValidSymChar (0xa6 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1678 SetValidSymChar (0xa8 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1679 SetValidSymChar (0xb4 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1680 SetValidSymChar (0xb8 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1681 SetValidSymChar (0xbc , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1682 SetValidSymChar (0xbd , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1683 SetValidSymChar (0xbe , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1684 /* fall-through */
1685 case eCodepageISO8859_1:
1686 iso8859_1:
1687 SetValidSymChar (0xa1 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1688 SetValidSymChar (0xa2 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1689 SetValidSymChars(0xc0, 0xff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1690 break;
1691 case eCodepageKOI8_R:
1692 SetValidSymChar (0xa3 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1693 SetValidSymChar (0xb3 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1694 SetValidSymChars(0xc0, 0xff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1695 break;
1696 case eCodepageUTF8:
1697 {
1698 const tNLSCharacterTab *pTab = GetCharacterTab(eCodepageUTF8);
1699 tNLSCharacter ch;
1700 unsigned Unicode;
1701 const char *pCh;
1702
1703 for (ch = (tNLSCharacter)0; ch < eCH_cnt; ch++)
1704 {
1705 if ((ch == eCH_e2) || (ch == eCH_mu) || (ch == eCH_iquest) || (ch == eCH_iexcl))
1706 continue;
1707 pCh = &((*pTab)[ch][0]);
1708 Unicode = UTF8ToUnicode(&pCh);
1709 if (Unicode < ValidSymCharLen)
1710 SetValidSymChar (Unicode, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1711 }
1712
1713 /* Greek */
1714
1715 SetValidSymChar ( 895 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1716 SetValidSymChar ( 902 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1717 SetValidSymChar (1011 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1718 SetValidSymChar (1016 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1719 SetValidSymChar (1018 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1720 SetValidSymChar (1019 , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1721 SetValidSymChars( 904, 974, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1722 SetValidSymChars( 984, 1007, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1723
1724 /* Cyrillic */
1725
1726 SetValidSymChars(0x400, 0x481, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1727 SetValidSymChars(0x48a, 0x4ff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
1728 }
1729 default:
1730 break;
1731 }
1732
1733 #if 0
1734 for (z = 0; z < ValidSymCharLen; z++)
1735 {
1736 if (!(z & 15))
1737 fprintf(stderr, "%02x:", z);
1738 fprintf(stderr, " %x", ValidSymChar[z]);
1739 if ((z & 15) == 15)
1740 fprintf(stderr, "\n");
1741 }
1742 #endif
1743
1744 version_init();
1745 }
1746