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