Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  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. #include "stdinc.h"
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <stdarg.h>
  15. #include <float.h>
  16.  
  17. #include "version.h"
  18. #include "be_le.h"
  19. #include "stdhandl.h"
  20. #include "console.h"
  21. #include "nls.h"
  22. #include "chardefs.h"
  23. #include "nlmessages.h"
  24. #include "cmdarg.h"
  25. #include "as.rsc"
  26. #include "strutil.h"
  27. #include "stringlists.h"
  28. #include "chunks.h"
  29. #include "ioerrs.h"
  30. #include "intformat.h"
  31. #include "errmsg.h"
  32. #include "asmdef.h"
  33. #include "asmpars.h"
  34. #include "asmdebug.h"
  35. #include "asmlist.h"
  36. #include "as.h"
  37.  
  38. #include "asmsub.h"
  39.  
  40.  
  41. #ifdef __TURBOC__
  42. #ifdef __DPMI16__
  43. #define STKSIZE 32768
  44. #else
  45. #define STKSIZE 49152
  46. #endif
  47. #endif
  48.  
  49. #define VALID_S1 1
  50. #define VALID_SN 2
  51. #define VALID_M1 4
  52. #define VALID_MN 8
  53.  
  54. static StringList CopyrightList, OutList, ShareOutList, ListOutList;
  55.  
  56. static LongWord StartStack, MinStack, LowStack;
  57.  
  58. static unsigned ValidSymCharLen;
  59. static Byte *ValidSymChar;
  60.  
  61. /****************************************************************************/
  62. /* Modulinitialisierung */
  63.  
  64. void AsmSubPassInit(void)
  65. {
  66.   PageLength = 60;
  67.   PageWidth = 0;
  68. }
  69.  
  70. /****************************************************************************/
  71. /* Copyrightlistenverwaltung */
  72.  
  73. void AddCopyright(const char *NewLine)
  74. {
  75.   AddStringListLast(&CopyrightList, NewLine);
  76. }
  77.  
  78. void WriteCopyrights(void(*PrintProc)(const char *))
  79. {
  80.   StringRecPtr Lauf;
  81.   const char *p_line;
  82.  
  83.   for (p_line = GetStringListFirst(CopyrightList, &Lauf);
  84.        p_line; p_line = GetStringListNext(&Lauf))
  85.     PrintProc(p_line);
  86. }
  87.  
  88. /*!------------------------------------------------------------------------
  89.  * \fn     QuotMultPosQualify(const char *s, const char *pSearch, as_qualify_quote_fnc_t QualifyQuoteFnc)
  90.  * \brief  find first occurence in non-quoted areas of string
  91.  * \param  s string to search in
  92.  * \param  pSearch search test function (returns 0 for match)
  93.  * \param  QualifyQuoteFnc checks whether single quote actually begins quoted area
  94.  * \return first occurence or NULL if not found
  95.  * ------------------------------------------------------------------------ */
  96.  
  97. typedef struct
  98. {
  99.   as_quoted_iterator_cb_data_t data;
  100.   ShortInt brack, ang_brack;
  101.   const char *p_result;
  102.   int (*search_fnc)(const char*, const char*);
  103.   const char *p_search;
  104. } quot_search_cb_data;
  105.  
  106. static int quot_search_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
  107. {
  108.   quot_search_cb_data *p_data = (quot_search_cb_data*)p_cb_data;
  109.  
  110.   if (!p_data->brack && !p_data->ang_brack && !p_data->search_fnc(p_pos, p_data->p_search))
  111.   {
  112.     p_data->p_result = p_pos;
  113.     return -1;
  114.   }
  115.  
  116.   switch (*p_pos)
  117.   {
  118.     case '(':
  119.       if (!p_data->ang_brack)
  120.         p_data->brack++;
  121.       break;
  122.     case ')':
  123.       if (!p_data->ang_brack)
  124.         p_data->brack--;
  125.       break;
  126.     case '[':
  127.       if (!p_data->brack)
  128.         p_data->ang_brack++;
  129.       break;
  130.     case ']':
  131.       if (!p_data->brack)
  132.         p_data->ang_brack--;
  133.       break;
  134.   }
  135.  
  136.   return 0;
  137. }
  138.  
  139. static char *QuotPosCore(const char *s, int (*SearchFnc)(const char*, const char*), const char *pSearch, as_qualify_quote_fnc_t QualifyQuoteFnc)
  140. {
  141.   quot_search_cb_data data;
  142.  
  143.   data.data.qualify_quote = QualifyQuoteFnc;
  144.   data.data.callback_before = True;
  145.   data.brack = data.ang_brack = 0;
  146.   data.p_result = NULL;
  147.   data.search_fnc = SearchFnc;
  148.   data.p_search = pSearch;
  149.  
  150.   as_iterate_str_quoted(s, quot_search_cb, &data.data);
  151.   return (char*)data.p_result;
  152. }
  153.  
  154. /*!------------------------------------------------------------------------
  155.  * \fn     QuotMultPosQualify(const char *s, char Zeichen, as_qualify_quote_fnc_t QualifyQuoteFnc)
  156.  * \brief  find first occurence of characters in non-quoted areas of string
  157.  * \param  s string to search in
  158.  * \param  Zeichen characters to search for
  159.  * \param  QualifyQuoteFnc checks whether single quote actually begins quoted area
  160.  * \return first occurence or NULL if not found
  161.  * ------------------------------------------------------------------------ */
  162.  
  163. static int SearchMultChar(const char *pPos, const char *pSearch)
  164. {
  165.   return !strchr(pSearch, *pPos);
  166. }
  167.  
  168. char *QuotMultPosQualify(const char *s, const char *pSearch, as_qualify_quote_fnc_t QualifyQuoteFnc)
  169. {
  170.   return QuotPosCore(s, SearchMultChar, pSearch, QualifyQuoteFnc);
  171. }
  172.  
  173. /*!------------------------------------------------------------------------
  174.  * \fn     QuotPosQualify(const char *s, char Zeichen, as_qualify_quote_fnc_t QualifyQuoteFnc)
  175.  * \brief  find first occurence of character in non-quoted areas of string
  176.  * \param  s string to search in
  177.  * \param  Zeichen character to search for
  178.  * \param  QualifyQuoteFnc checks whether single quote actually begins quoted area
  179.  * \return first occurence or NULL if not found
  180.  * ------------------------------------------------------------------------ */
  181.  
  182. static int SearchSingleChar(const char *pPos, const char *pSearch)
  183. {
  184.   return ((int)*pSearch) - ((int)*pPos);
  185. }
  186.  
  187. char *QuotPosQualify(const char *s, char Zeichen, as_qualify_quote_fnc_t QualifyQuoteFnc)
  188. {
  189.   return QuotPosCore(s, SearchSingleChar, &Zeichen, QualifyQuoteFnc);
  190. }
  191.  
  192. /*!------------------------------------------------------------------------
  193.  * \fn     QuotSMultPosQualify(const char *s, const char *pStrs, as_qualify_quote_fnc_t QualifyQuoteFnc)
  194.  * \brief  find first occurence of strings in non-quoted areas of string
  195.  * \param  s string to search in
  196.  * \param  pStrs strings to search for (continuous list, terminated by empty string)
  197.  * \param  QualifyQuoteFnc checks whether single quote actually begins quoted area
  198.  * \return first occurence or NULL if not found
  199.  * ------------------------------------------------------------------------ */
  200.  
  201. static int SearchMultString(const char *pPos, const char *pSearch)
  202. {
  203.   int len;
  204.  
  205.   while (True)
  206.   {
  207.     if (!(len = strlen(pSearch)))
  208.       return 1;
  209.     if (!strncmp(pPos, pSearch, len))
  210.       return 0;
  211.     pSearch += len + 1;
  212.   }
  213. }
  214.  
  215. char *QuotSMultPosQualify(const char *s, const char *pStrs, as_qualify_quote_fnc_t QualifyQuoteFnc)
  216. {
  217.   return QuotPosCore(s, SearchMultString, pStrs, QualifyQuoteFnc);
  218. }
  219.  
  220. /*!------------------------------------------------------------------------
  221.  * \fn     RQuotPos(char *s, char Zeichen)
  222.  * \brief  find last occurence of character, skipping quoted/parenthized parts
  223.  * \param  s string to search
  224.  * \param  Zeichen character to search for
  225.  * \return last occurence or NULL if not found at all
  226.  * ------------------------------------------------------------------------ */
  227.  
  228. /* NOTE: Though we search for the last occurence, it is not wise to search
  229.    the string in backward direction.  Character escaping can only be tracked
  230.    correctly and unambiguously if we traverse the string in forward order.
  231.    So when we found an occurence, continue to search for a later one: */
  232.  
  233. typedef struct
  234. {
  235.   as_quoted_iterator_cb_data_t data;
  236.   ShortInt brack, ang_brack;
  237.   const char *p_result;
  238.   char search;
  239. } rquot_search_cb_data;
  240.  
  241. static int rquot_search_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
  242. {
  243.   rquot_search_cb_data *p_data = (rquot_search_cb_data*)p_cb_data;
  244.  
  245.   if (!p_data->brack && !p_data->ang_brack && (*p_pos == p_data->search))
  246.     p_data->p_result = p_pos;
  247.  
  248.   else switch (*p_pos)
  249.   {
  250.     case '(':
  251.       if (!p_data->ang_brack)
  252.         p_data->brack++;
  253.       break;
  254.     case ')':
  255.       if (!p_data->ang_brack)
  256.         p_data->brack--;
  257.       break;
  258.     case '[':
  259.       if (!p_data->brack)
  260.         p_data->ang_brack++;
  261.       break;
  262.     case ']':
  263.       if (!p_data->brack)
  264.         p_data->ang_brack--;
  265.       break;
  266.   }
  267.  
  268.   return 0;
  269. }
  270.  
  271. char *RQuotPos(char *s, char Zeichen)
  272. {
  273.   rquot_search_cb_data data;
  274.  
  275.   data.data.qualify_quote = QualifyQuote;
  276.   data.data.callback_before = True;
  277.   data.brack = data.ang_brack = 0;
  278.   data.p_result = NULL;
  279.   data.search = Zeichen;
  280.  
  281.   as_iterate_str_quoted(s, rquot_search_cb, &data.data);
  282.   return (char*)data.p_result;
  283. }
  284.  
  285. /*!------------------------------------------------------------------------
  286.  * \fn     CopyNoBlanks(char *pDest, const char *pSrc, size_t MaxLen)
  287.  * \brief  copy string, excluding spaces in non-quoted areas
  288.  * \param  pDest destination buffer
  289.  * \param  pSrc copy source
  290.  * \param  MaxLen capacity of dest buffer
  291.  * \return # of copied characters, excluding NUL
  292.  * ------------------------------------------------------------------------ */
  293.  
  294. typedef struct
  295. {
  296.   as_quoted_iterator_cb_data_t data;
  297.   char *p_dest;
  298.   size_t rem_cap, cnt;
  299. } copy_cb_data_t;
  300.  
  301. static int copy_no_blanks_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
  302. {
  303.   copy_cb_data_t *p_data = (copy_cb_data_t*)p_cb_data;
  304.  
  305.   /* leave space for NUL */
  306.  
  307.   if ((p_cb_data->in_single_quote || p_cb_data->in_double_quote || !as_isspace(*p_pos)) && (p_data->rem_cap > 1))
  308.   {
  309.     *(p_data->p_dest++) = *p_pos;
  310.     p_data->rem_cap--;
  311.     p_data->cnt++;
  312.   }
  313.   return 0;
  314. }
  315.  
  316. int CopyNoBlanks(char *pDest, const char *pSrc, size_t MaxLen)
  317. {
  318.   copy_cb_data_t data;
  319.  
  320.   data.data.qualify_quote = NULL;
  321.   data.data.callback_before = True;
  322.   data.p_dest = pDest;
  323.   data.rem_cap = MaxLen;
  324.   data.cnt = 0;
  325.  
  326.   as_iterate_str(pSrc, copy_no_blanks_cb, &data.data);
  327.   if (data.rem_cap)
  328.     *(data.p_dest) = '\0';
  329.  
  330.   return data.cnt;
  331. }
  332.  
  333. /*!------------------------------------------------------------------------
  334.  * \fn     KillBlanks(char *s)
  335.  * \brief  Delete all spaces in non-quoted areas from string
  336.  * \param  s string to process
  337.  * ------------------------------------------------------------------------ */
  338.  
  339. void KillBlanks(char *s)
  340. {
  341.   CopyNoBlanks(s, s, 65535); /* SIZE_MAX */
  342. }
  343.  
  344. /*--------------------------------------------------------------------------*/
  345. /* ermittelt das erste (nicht-) Leerzeichen in einem String */
  346.  
  347. char *FirstBlank(const char *s)
  348. {
  349.   const char *h, *Min = NULL;
  350.  
  351.   h = strchr(s, ' ');
  352.   if (h)
  353.     if ((!Min) || (h < Min))
  354.       Min = h;
  355.   h = strchr(s, Char_HT);
  356.   if (h)
  357.     if ((!Min) || (h < Min))
  358.       Min = h;
  359.   return (char*)Min;
  360. }
  361.  
  362. /*--------------------------------------------------------------------------*/
  363. /* einen String in zwei Teile zerlegen */
  364.  
  365. void SplitString(char *Source, char *Left, char *Right, char *Trenner)
  366. {
  367.   char Save;
  368.   LongInt slen = strlen(Source);
  369.  
  370.   if ((!Trenner) || (Trenner >= Source + slen))
  371.     Trenner = Source + slen;
  372.   Save = (*Trenner);
  373.   *Trenner = '\0';
  374.   strmov(Left, Source);
  375.   *Trenner = Save;
  376.   if (Trenner >= Source + slen)
  377.     *Right = '\0';
  378.   else
  379.     strmov(Right, Trenner + 1);
  380. }
  381.  
  382. /*!------------------------------------------------------------------------
  383.  * \fn     UpString(char *s)
  384.  * \brief  convert string to upper case, excluding quoted areas
  385.  * \param  s string to convert
  386.  * ------------------------------------------------------------------------ */
  387.  
  388. static int upstring_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
  389. {
  390.   UNUSED(p_cb_data);
  391.   *((char*)p_pos) = UpCaseTable[(int)*p_pos];
  392.   return 0;
  393. }
  394.  
  395. void UpString(char *s)
  396. {
  397.   as_quoted_iterator_cb_data_t data;
  398.  
  399.   data.qualify_quote = QualifyQuote;
  400.   data.callback_before = False;
  401.  
  402.   as_iterate_str_quoted(s, upstring_cb, &data);
  403. }
  404.  
  405. /*!------------------------------------------------------------------------
  406.  * \fn     MatchChars(const char *pStr, const char *pPattern, ...)
  407.  * \brief  see if beginning of string matches given pattern
  408.  * \param  pStr string to check
  409.  * \param  pPattern expected pattern
  410.  * \return * to character following match or NULL if no match
  411.  * ------------------------------------------------------------------------ */
  412.  
  413. char *MatchChars(const char *pStr, const char *pPattern, ...)
  414. {
  415.   va_list ap;
  416.   char *pResult = NULL;
  417.  
  418.   va_start(ap, pPattern);
  419.   for (; *pPattern; pPattern++)
  420.     switch (*pPattern)
  421.     {
  422.       /* single space in pattern matches arbitrary # of spaces in string */
  423.       case ' ':
  424.         for (; as_isspace(*pStr); pStr++);
  425.         break;
  426.       case '?':
  427.       {
  428.         const char *pPatternStr = va_arg(ap, const char*);
  429.         char *pSave = va_arg(ap, char*);
  430.  
  431.         if (!strchr(pPatternStr, as_toupper(*pStr)))
  432.           goto func_exit;
  433.         if (pSave)
  434.           *pSave = *pStr;
  435.         pStr++;
  436.         break;
  437.       }
  438.       default:
  439.         if (as_toupper(*pStr) != as_toupper(*pPattern))
  440.           goto func_exit;
  441.         pStr++;
  442.     }
  443.   pResult = (char*)pStr;
  444. func_exit:
  445.   va_end(ap);
  446.   return pResult;
  447. }
  448.  
  449. /*!------------------------------------------------------------------------
  450.  * \fn     MatchCharsRev(const char *pStr, const char *pPattern, ...)
  451.  * \brief  see if end of string matches given pattern
  452.  * \param  pStr string to check
  453.  * \param  pPattern expected pattern
  454.  * \return * to trailing string matching pattern or NULL if no match
  455.  * ------------------------------------------------------------------------ */
  456.  
  457. char *MatchCharsRev(const char *pStr, const char *pPattern, ...)
  458. {
  459.   va_list ap;
  460.   char *pResult = NULL;
  461.   const char *pPatternRun = pPattern + strlen(pPattern) - 1,
  462.              *pStrRun = pStr + strlen(pStr) - 1;
  463.  
  464.   va_start(ap, pPattern);
  465.   for (; pPatternRun >= pPattern; pPatternRun--)
  466.     switch (*pPatternRun)
  467.     {
  468.       /* single space in pattern matches arbitrary # of spaces in string */
  469.       case ' ':
  470.         for (; (pStrRun >= pStr) && as_isspace(*pStrRun); pStrRun--);
  471.         break;
  472.       case '?':
  473.       {
  474.         const char *pPatternStr = va_arg(ap, const char*);
  475.         char *pSave = va_arg(ap, char*);
  476.  
  477.         if (!strchr(pPatternStr, as_toupper(*pStrRun)))
  478.           goto func_exit;
  479.         if (pSave)
  480.           *pSave = *pStrRun;
  481.         pStrRun--;
  482.         break;
  483.       }
  484.       default:
  485.         if ((pStrRun < pStr) || (as_toupper(*pStrRun) != as_toupper(*pPatternRun)))
  486.           goto func_exit;
  487.         pStrRun--;
  488.     }
  489.   pResult = (char*)(pStrRun + 1);
  490. func_exit:
  491.   va_end(ap);
  492.   return pResult;
  493. }
  494.  
  495. /*!------------------------------------------------------------------------
  496.  * \fn     FindClosingParenthese(const char *pStr)
  497.  * \brief  find matching closing parenthese
  498.  * \param  pStr * to string right after opening parenthese
  499.  * \return * to closing parenthese or NULL
  500.  * ------------------------------------------------------------------------ */
  501.  
  502. typedef struct
  503. {
  504.   as_quoted_iterator_cb_data_t data;
  505.   int nest;
  506.   const char *p_ret;
  507. } close_par_cb_data_t;
  508.  
  509. static int close_par_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
  510. {
  511.   close_par_cb_data_t *p_data = (close_par_cb_data_t*)p_cb_data;
  512.  
  513.   switch(*p_pos)
  514.   {
  515.     case '(':
  516.       p_data->nest++;
  517.       break;
  518.     case ')':
  519.       if (!--p_data->nest)
  520.       {
  521.         p_data->p_ret = p_pos;
  522.         return -1;
  523.       }
  524.       break;
  525.   }
  526.   return 0;
  527. }
  528.  
  529. char *FindClosingParenthese(const char *pStr)
  530. {
  531.   close_par_cb_data_t data;
  532.  
  533.   data.data.callback_before = False;
  534.   data.data.qualify_quote = QualifyQuote;
  535.   data.nest = 1;
  536.   data.p_ret = NULL;
  537.  
  538.   as_iterate_str_quoted(pStr, close_par_cb, &data.data);
  539.  
  540.   return (char*)data.p_ret;
  541. }
  542.  
  543. /*!------------------------------------------------------------------------
  544.  * \fn     FindOpeningParenthese(const char *pStrBegin, const char *pStrEnd, const char Bracks[2])
  545.  * \brief  find matching opening parenthese in string
  546.  * \param  pStrBegin start of string
  547.  * \param  pStrEnd end of string, preceding closing parenthese in question
  548.  * \param  Bracks opening & closing parenthese
  549.  * \return * to opening parenthese or NULL if not found
  550.  * ------------------------------------------------------------------------ */
  551.  
  552. typedef struct
  553. {
  554.   as_quoted_iterator_cb_data_t data;
  555.   int nest;
  556.   const char *p_str_end;
  557.   const char *p_ret;
  558.   const char *p_bracks;
  559. } open_par_cb_data_t;
  560.  
  561. static int open_par_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
  562. {
  563.   open_par_cb_data_t *p_data = (open_par_cb_data_t*)p_cb_data;
  564.  
  565.   if (*p_pos == p_data->p_bracks[0])
  566.   {
  567.     if (!p_data->nest)
  568.       p_data->p_ret = p_pos;
  569.     p_data->nest++;
  570.   }
  571.   else if (*p_pos == p_data->p_bracks[1])
  572.     p_data->nest--;
  573.  
  574.   /* We are interested in the opening parenthese that is nearest to the closing
  575.      one and on same level, so continue searching: */
  576.  
  577.   return ((p_pos + 1) < p_data->p_str_end) ? 0 : -1;
  578. }
  579.  
  580. char *FindOpeningParenthese(const char *pStrBegin, const char *pStrEnd, const char Bracks[2])
  581. {
  582.   open_par_cb_data_t data;
  583.  
  584.   data.data.callback_before = False;
  585.   data.data.qualify_quote = QualifyQuote;
  586.   data.nest = 0;
  587.   data.p_ret = NULL;
  588.   data.p_bracks = Bracks;
  589.   data.p_str_end = pStrEnd;
  590.  
  591.   as_iterate_str_quoted(pStrBegin, open_par_cb, &data.data);
  592.  
  593.   return (char*)data.p_ret;
  594. }
  595.  
  596. /****************************************************************************/
  597.  
  598. ShortInt StrCaseCmp(const char *s1, const char *s2, LongInt Hand1, LongInt Hand2)
  599. {
  600.   int tmp;
  601.  
  602.   tmp = as_toupper(*s1) - as_toupper(*s2);
  603.   if (!tmp)
  604.     tmp = as_strcasecmp(s1, s2);
  605.   if (!tmp)
  606.     tmp = Hand1 - Hand2;
  607.   if (tmp < 0)
  608.     return -1;
  609.   if (tmp > 0)
  610.     return 1;
  611.   return 0;
  612. }
  613.  
  614. /****************************************************************************/
  615. /* an einen Dateinamen eine Endung anhaengen */
  616.  
  617. Boolean AddSuffix(char *s, const char *Suff)
  618. {
  619.   char *p, *z, *Part;
  620.  
  621.   p = NULL;
  622.   for (z = s; *z != '\0'; z++)
  623.     if (*z == PATHSEP)
  624.       p = z;
  625.   Part = p ? p : s;
  626.   if (!strchr(Part, '.'))
  627.   {
  628.     strmaxcat(s, Suff, STRINGSIZE);
  629.     return True;
  630.   }
  631.   else
  632.     return False;
  633. }
  634.  
  635.  
  636. /*--------------------------------------------------------------------------*/
  637. /* von einem Dateinamen die Endung loeschen */
  638.  
  639. void KillSuffix(char *s)
  640. {
  641.   char *p, *z, *Part;
  642.  
  643.   p = NULL;
  644.   for (z = s; *z != '\0'; z++)
  645.     if (*z == PATHSEP)
  646.       p = z;
  647.   Part = p ? p : s;
  648.   Part = strchr(Part, '.');
  649.   if (Part)
  650.     *Part = '\0';
  651. }
  652.  
  653. /*--------------------------------------------------------------------------*/
  654. /* Pfadanteil (Laufwerk+Verzeichnis) von einem Dateinamen abspalten */
  655.  
  656. char *PathPart(char *Name)
  657. {
  658.   static String s;
  659.   char *p;
  660.  
  661.   strmaxcpy(s, Name, STRINGSIZE);
  662.  
  663.   p = strrchr(Name, PATHSEP);
  664. #ifdef DRSEP
  665.   if (!p)
  666.     p = strrchr(Name, DRSEP);
  667. #endif
  668.  
  669.   if (!p)
  670.     *s = '\0';
  671.   else
  672.     s[1] = '\0';
  673.  
  674.   return s;
  675. }
  676.  
  677. /*--------------------------------------------------------------------------*/
  678. /* Namensanteil von einem Dateinamen abspalten */
  679.  
  680. const char *NamePart(const char *Name)
  681. {
  682.   const char *p = strrchr(Name, PATHSEP);
  683.  
  684. #ifdef DRSEP
  685.   if (!p)
  686.     p = strrchr(Name, DRSEP);
  687. #endif
  688.  
  689.   return p ? p + 1 : Name;
  690. }
  691.  
  692. /****************************************************************************/
  693. /* eine Gleitkommazahl in einen String umwandeln */
  694.  
  695. void FloatString(char *pDest, size_t DestSize, as_float_t f)
  696. {
  697. #define MaxLen (3 + AS_FLOAT_DIG)
  698.   char *p, *d, ExpChar = HexStartCharacter + ('E' - 'A');
  699.   sint n, ExpVal, nzeroes;
  700.   Boolean WithE, OK;
  701.  
  702.   /* 1. mit Maximallaenge wandeln, fuehrendes Vorzeichen weg */
  703.  
  704.   (void)DestSize;
  705.   as_snprintf(pDest, DestSize, "%*.*llle", 12 + AS_FLOAT_DIG, AS_FLOAT_DIG, f);
  706.   for (p = pDest; (*p == ' ') || (*p == '+'); p++);
  707.   if (p != pDest)
  708.     strmov(pDest, p);
  709.  
  710.   /* 2. Exponenten soweit als moeglich kuerzen, evtl. ganz streichen */
  711.  
  712.   p = strchr(pDest, ExpChar);
  713.   if (!p)
  714.     return;
  715.   switch (*(++p))
  716.   {
  717.     case '+':
  718.       strmov(p, p + 1);
  719.       break;
  720.     case '-':
  721.       p++;
  722.       break;
  723.   }
  724.  
  725.   while (*p == '0')
  726.     strmov(p, p + 1);
  727.   WithE = (*p != '\0');
  728.   if (!WithE)
  729.     pDest[strlen(pDest) - 1] = '\0';
  730.  
  731.   /* 3. Nullen am Ende der Mantisse entfernen, Komma bleibt noch */
  732.  
  733.   p = WithE ? strchr(pDest, ExpChar) : pDest + strlen(pDest);
  734.   p--;
  735.   while (*p == '0')
  736.   {
  737.     strmov(p, p + 1);
  738.     p--;
  739.   }
  740.  
  741.   /* 4. auf die gewuenschte Maximalstellenzahl begrenzen */
  742.  
  743.   p = WithE ? strchr(pDest, ExpChar) : pDest + strlen(pDest);
  744.   d = strchr(pDest, '.');
  745.   n = p - d - 1;
  746.  
  747.   /* 5. Maximallaenge ueberschritten ? */
  748.  
  749.   if (strlen(pDest) > MaxLen)
  750.     strmov(d + (n - (strlen(pDest) - MaxLen)), d + n);
  751.  
  752.   /* 6. Exponentenwert berechnen */
  753.  
  754.   if (WithE)
  755.   {
  756.     p = strchr(pDest, ExpChar);
  757.     ExpVal = ConstLongInt(p + 1, &OK, 10);
  758.   }
  759.   else
  760.   {
  761.     p = pDest + strlen(pDest);
  762.     ExpVal = 0;
  763.   }
  764.  
  765.   /* 7. soviel Platz, dass wir den Exponenten weglassen und evtl. Nullen
  766.        anhaengen koennen ? */
  767.  
  768.   if (ExpVal > 0)
  769.   {
  770.     nzeroes = ExpVal - (p - strchr(pDest, '.') - 1); /* = Zahl von Nullen, die anzuhaengen waere */
  771.  
  772.     /* 7a. nur Kommaverschiebung erforderlich. Exponenten loeschen und
  773.           evtl. auch Komma */
  774.  
  775.     if (nzeroes <= 0)
  776.     {
  777.       *p = '\0';
  778.       d = strchr(pDest, '.');
  779.       strmov(d, d + 1);
  780.       if (nzeroes != 0)
  781.       {
  782.         memmove(pDest + strlen(pDest) + nzeroes + 1, pDest + strlen(pDest) + nzeroes, -nzeroes);
  783.         pDest[strlen(pDest) - 1 + nzeroes] = '.';
  784.       }
  785.     }
  786.  
  787.     /* 7b. Es muessen Nullen angehaengt werden. Schauen, ob nach Loeschen von
  788.           Punkt und E-Teil genuegend Platz ist */
  789.  
  790.     else
  791.     {
  792.       n = strlen(p) + 1 + (MaxLen - strlen(pDest)); /* = Anzahl freizubekommender Zeichen+Gutschrift */
  793.       if (n >= nzeroes)
  794.       {
  795.         *p = '\0';
  796.         d = strchr(pDest, '.');
  797.         strmov(d, d + 1);
  798.         d = pDest + strlen(pDest);
  799.         for (n = 0; n < nzeroes; n++)
  800.           *(d++) = '0';
  801.         *d = '\0';
  802.       }
  803.     }
  804.   }
  805.  
  806.   /* 8. soviel Platz, dass Exponent wegkann und die Zahl mit vielen Nullen
  807.        vorne geschrieben werden kann ? */
  808.  
  809.   else if (ExpVal < 0)
  810.   {
  811.     n = (-ExpVal) - (strlen(p)); /* = Verlaengerung nach Operation */
  812.     if (strlen(pDest) + n <= MaxLen)
  813.     {
  814.       *p = '\0';
  815.       d = strchr(pDest, '.');
  816.       strmov(d, d + 1);
  817.       d = (pDest[0] == '-') ? pDest + 1 : pDest;
  818.       memmove(d - ExpVal + 1, d, strlen(pDest) + 1);
  819.       *(d++) = '0';
  820.       *(d++) = '.';
  821.       for (n = 0; n < -ExpVal - 1; n++)
  822.         *(d++) = '0';
  823.     }
  824.   }
  825.  
  826.  
  827.   /* 9. Ueberfluessiges Komma entfernen */
  828.  
  829.   if (WithE)
  830.     p = strchr(pDest, ExpChar);
  831.   else
  832.     p = pDest + strlen(pDest);
  833.   if (p && (*(p - 1) == '.'))
  834.     strmov(p - 1, p);
  835. }
  836.  
  837. /****************************************************************************/
  838. /* Symbol in String wandeln */
  839.  
  840. void StrSym(const TempResult *t, Boolean WithSystem, as_dynstr_t *p_dest, unsigned Radix)
  841. {
  842.   LargeInt IntVal;
  843.  
  844.   if (p_dest->capacity)
  845.     p_dest->p_str[0] = '\0';
  846.   switch (t->Typ)
  847.   {
  848.     case TempInt:
  849.       IntVal = t->Contents.Int;
  850.     IsInt:
  851.     {
  852.       String Buf;
  853.  
  854.       if (WithSystem)
  855.       {
  856.         switch (IntConstMode)
  857.         {
  858.           case eIntConstModeMoto:
  859.             as_sdprcatf(p_dest, "%s", GetIntConstMotoPrefix(Radix));
  860.             break;
  861.           case eIntConstModeC:
  862.             as_sdprcatf(p_dest, "%s", GetIntConstCPrefix(Radix));
  863.             break;
  864.           case eIntConstModeIBM:
  865.             as_sdprcatf(p_dest, "%s", GetIntConstIBMPrefix(Radix));
  866.             break;
  867.           default:
  868.             break;
  869.         }
  870.       }
  871.       SysString(Buf, sizeof(Buf), IntVal, Radix,
  872.                 1, (16 == Radix) && (IntConstMode == eIntConstModeIntel),
  873.                 HexStartCharacter, SplitByteCharacter);
  874.       as_sdprcatf(p_dest, "%s", Buf);
  875.       if (WithSystem)
  876.       {
  877.         switch (IntConstMode)
  878.         {
  879.           case eIntConstModeIntel:
  880.             as_sdprcatf(p_dest, GetIntConstIntelSuffix(Radix));
  881.             break;
  882.           case eIntConstModeIBM:
  883.             as_sdprcatf(p_dest, GetIntConstIBMSuffix(Radix));
  884.             break;
  885.           default:
  886.             break;
  887.         }
  888.       }
  889.       break;
  890.     }
  891.     case TempFloat:
  892.       FloatString(p_dest->p_str, p_dest->capacity, t->Contents.Float);
  893.       break;
  894.     case TempString:
  895.       as_tempres_append_dynstr(p_dest, t, 10);
  896.       break;
  897.     case TempReg:
  898.       if (t->Contents.RegDescr.Dissect)
  899.         t->Contents.RegDescr.Dissect(p_dest->p_str, p_dest->capacity, t->Contents.RegDescr.Reg, t->DataSize);
  900.       else
  901.       {
  902.         IntVal = t->Contents.RegDescr.Reg;
  903.         goto IsInt;
  904.       }
  905.       break;
  906.     default:
  907.       as_sdprintf(p_dest, "???");
  908.   }
  909. }
  910.  
  911. /****************************************************************************/
  912. /* Listingzaehler zuruecksetzen */
  913.  
  914. void ResetPageCounter(void)
  915. {
  916.   int z;
  917.  
  918.   for (z = 0; z <= ChapMax; z++)
  919.     PageCounter[z] = 0;
  920.   LstCounter = 0;
  921.   ChapDepth = 0;
  922. }
  923.  
  924. /*--------------------------------------------------------------------------*/
  925. /* eine neue Seite im Listing beginnen */
  926.  
  927. void NewPage(ShortInt Level, Boolean WithFF)
  928. {
  929.   ShortInt z;
  930.   String Header, s;
  931.   char Save;
  932.  
  933.   if (ListOn == 0)
  934.     return;
  935.  
  936.   LstCounter = 0;
  937.  
  938.   if (ChapDepth < (Byte) Level)
  939.   {
  940.     memmove(PageCounter + (Level - ChapDepth), PageCounter, (ChapDepth + 1) * sizeof(Word));
  941.     for (z = 0; z <= Level - ChapDepth; PageCounter[z++] = 1);
  942.     ChapDepth = Level;
  943.   }
  944.   for (z = 0; z <= Level - 1; PageCounter[z++] = 1);
  945.   PageCounter[Level]++;
  946.  
  947.   if ((WithFF) && (!ListToNull))
  948.   {
  949.     errno = 0;
  950.     fprintf(LstFile, "%c", Char_FF);
  951.     ChkIO(ErrNum_ListWrError);
  952.   }
  953.  
  954.   as_snprintf(Header, sizeof(Header), " AS V%s%s%s",
  955.               Version,
  956.               getmessage(Num_HeadingFileNameLab),
  957.               NamePart(SourceFile));
  958.   if (strcmp(CurrFileName, "INTERNAL")
  959.    && *CurrFileName
  960.    && strcmp(NamePart(CurrFileName), NamePart(SourceFile)))
  961.   {
  962.     strmaxcat(Header, "(", STRINGSIZE);
  963.     strmaxcat(Header, NamePart(CurrFileName), STRINGSIZE);
  964.     strmaxcat(Header, ")", STRINGSIZE);
  965.   }
  966.   strmaxcat(Header, getmessage(Num_HeadingPageLab), STRINGSIZE);
  967.  
  968.   for (z = ChapDepth; z >= 0; z--)
  969.   {
  970.     as_snprintf(s, sizeof(s), IntegerFormat, PageCounter[z]);
  971.     strmaxcat(Header, s, STRINGSIZE);
  972.     if (z != 0)
  973.       strmaxcat(Header, ".", STRINGSIZE);
  974.   }
  975.  
  976.   strmaxcat(Header, " - ", STRINGSIZE);
  977.   NLS_CurrDateString(s, sizeof(s));
  978.   strmaxcat(Header, s, STRINGSIZE);
  979.   strmaxcat(Header, " ", STRINGSIZE);
  980.   NLS_CurrTimeString(False, s, sizeof(s));
  981.   strmaxcat(Header, s, STRINGSIZE);
  982.  
  983.   if (PageWidth != 0)
  984.     while (strlen(Header) > PageWidth)
  985.     {
  986.       Save = Header[PageWidth];
  987.       Header[PageWidth] = '\0';
  988.       if (!ListToNull)
  989.       {
  990.         errno = 0;
  991.         fprintf(LstFile, "%s\n", Header);
  992.         ChkIO(ErrNum_ListWrError);
  993.       }
  994.       Header[PageWidth] = Save;
  995.       strmov(Header, Header + PageWidth);
  996.     }
  997.  
  998.   if (!ListToNull)
  999.   {
  1000.     errno = 0;
  1001.     fprintf(LstFile, "%s\n", Header);
  1002.     ChkIO(ErrNum_ListWrError);
  1003.  
  1004.     if (PrtTitleString[0])
  1005.     {
  1006.       errno = 0;
  1007.       fprintf(LstFile, "%s\n", PrtTitleString);
  1008.       ChkIO(ErrNum_ListWrError);
  1009.     }
  1010.  
  1011.     errno = 0;
  1012.     fprintf(LstFile, "\n\n");
  1013.     ChkIO(ErrNum_ListWrError);
  1014.   }
  1015. }
  1016.  
  1017. /*--------------------------------------------------------------------------*/
  1018. /* eine Zeile ins Listing schieben */
  1019.  
  1020. void WrLstLine(const char *Line)
  1021. {
  1022.   int LLength;
  1023.   char bbuf[2500];
  1024.   String LLine;
  1025.   int blen = 0, hlen, z, Start;
  1026.  
  1027.   if ((ListOn == 0) || (ListToNull))
  1028.     return;
  1029.  
  1030.   if (PageLength == 0)
  1031.   {
  1032.     errno = 0;
  1033.     fprintf(LstFile, "%s\n", Line);
  1034.     ChkIO(ErrNum_ListWrError);
  1035.   }
  1036.   else
  1037.   {
  1038.     if ((PageWidth == 0) || ((strlen(Line) << 3) < PageWidth))
  1039.       LLength = 1;
  1040.     else
  1041.     {
  1042.       blen = 0;
  1043.       for (z = 0; z < (int)strlen(Line);  z++)
  1044.         if (Line[z] == Char_HT)
  1045.         {
  1046.           memset(bbuf + blen, ' ', 8 - (blen & 7));
  1047.           blen += 8 - (blen&7);
  1048.         }
  1049.         else
  1050.           bbuf[blen++] = Line[z];
  1051.       LLength = blen / PageWidth;
  1052.       if (blen % PageWidth)
  1053.         LLength++;
  1054.     }
  1055.     if (LLength == 1)
  1056.     {
  1057.       errno = 0;
  1058.       fprintf(LstFile, "%s\n", Line);
  1059.       ChkIO(ErrNum_ListWrError);
  1060.       if ((++LstCounter) == PageLength)
  1061.         NewPage(0, True);
  1062.     }
  1063.     else
  1064.     {
  1065.       Start = 0;
  1066.       for (z = 1; z <= LLength; z++)
  1067.       {
  1068.         hlen = PageWidth;
  1069.         if (blen - Start < hlen)
  1070.           hlen = blen - Start;
  1071.         memcpy(LLine, bbuf + Start, hlen);
  1072.         LLine[hlen] = '\0';
  1073.         errno = 0;
  1074.         fprintf(LstFile, "%s\n", LLine);
  1075.         if ((++LstCounter) == PageLength)
  1076.           NewPage(0, True);
  1077.         Start += hlen;
  1078.       }
  1079.     }
  1080.   }
  1081. }
  1082.  
  1083. /*****************************************************************************/
  1084. /* Ausdruck in Spalte vor Listing */
  1085.  
  1086. void SetListLineVal(TempResult *t)
  1087. {
  1088.   as_dynstr_t str;
  1089.  
  1090.   as_dynstr_ini(&str, STRINGSIZE);
  1091.   StrSym(t, True, &str, ListRadixBase);
  1092.   as_snprintf(ListLine, STRINGSIZE, "=%s", str.p_str);
  1093.   as_dynstr_free(&str);
  1094. }
  1095.  
  1096. /*!------------------------------------------------------------------------
  1097.  * \fn     PrintOneLineMuted(FILE *pFile, const char *pLine,
  1098.                              const struct sLineComp *pMuteComponent,
  1099.                              const struct sLineComp *pMuteComponent2)
  1100.  * \brief  print a line, with a certain component muted out (i.e. replaced by spaces)
  1101.  * \param  pFile where to write
  1102.  * \param  pLine line to print
  1103.  * \param  pMuteComponent component to mute in printout
  1104.  * ------------------------------------------------------------------------ */
  1105.  
  1106. static Boolean CompMatch(int Col, const struct sLineComp *pComp)
  1107. {
  1108.   return (pComp
  1109.        && (pComp->StartCol >= 0)
  1110.        && (Col >= pComp->StartCol)
  1111.        && (Col < pComp->StartCol + (int)pComp->Len));
  1112. }
  1113.  
  1114. void PrintOneLineMuted(FILE *pFile, const char *pLine,
  1115.                        const struct sLineComp *pMuteComponent,
  1116.                        const struct sLineComp *pMuteComponent2)
  1117. {
  1118.   int z, Len = strlen(pLine);
  1119.   Boolean Match;
  1120.  
  1121.   errno = 0;
  1122.   for (z = 0; z < Len; z++)
  1123.   {
  1124.     Match = CompMatch(z, pMuteComponent) || CompMatch(z, pMuteComponent2);
  1125.     fputc(Match ? ' ' : pLine[z], pFile);
  1126.   }
  1127.   fputc('\n', pFile);
  1128.   ChkIO(ErrNum_ListWrError);
  1129. }
  1130.  
  1131. /*!------------------------------------------------------------------------
  1132.  * \fn     PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer,
  1133.                         char Marker, const struct sLineComp *pLineComp)
  1134.  * \brief  print a line, optionally with a marking of a component below
  1135.  * \param  pFile where to write
  1136.  * \param  pLine line to print/underline
  1137.  * \param  pPrefix what to print before (under)line
  1138.  * \param  pTrailer what to print after (under)line
  1139.  * \param  Marker character to use for marking
  1140.  * \param  pLineComp position and length of optional marker
  1141.  * ------------------------------------------------------------------------ */
  1142.  
  1143. void PrLineMarker(FILE *pFile, const char *pLine, const char *pPrefix, const char *pTrailer,
  1144.                   char Marker, const struct sLineComp *pLineComp)
  1145. {
  1146.   const char *pRun;
  1147.   int z;
  1148.  
  1149.   fputs(pPrefix, pFile);
  1150.   for (pRun = pLine; *pRun; pRun++)
  1151.     fputc(TabCompressed(*pRun), pFile);
  1152.   fprintf(pFile, "%s\n", pTrailer);
  1153.  
  1154.   if (pLineComp && (pLineComp->StartCol >= 0) && (pLineComp->Len > 0))
  1155.   {
  1156.     fputs(pPrefix, pFile);
  1157.     if (pLineComp->StartCol > 0)
  1158.       fprintf(pFile, "%*s", pLineComp->StartCol, "");
  1159.     for (z = 0; z < (int)pLineComp->Len; z++)
  1160.       fputc(Marker, pFile);
  1161.     fprintf(pFile, "%s\n", pTrailer);
  1162.   }
  1163. }
  1164.  
  1165. /****************************************************************************/
  1166. /* einen Symbolnamen auf Gueltigkeit ueberpruefen */
  1167.  
  1168. static Byte GetValidSymChar(unsigned Ch)
  1169. {
  1170.   return (Ch < ValidSymCharLen) ? ValidSymChar[Ch] : 0;
  1171. }
  1172.  
  1173. static char *ChkNameUpTo(const char *pSym, const char *pUpTo, Byte _Mask)
  1174. {
  1175.   Byte Mask = _Mask;
  1176.   unsigned Ch;
  1177.   const char *pPrev;
  1178.  
  1179.   if (!*pSym)
  1180.     return (char*)pSym;
  1181.  
  1182.   while (*pSym && (pSym != pUpTo))
  1183.   {
  1184.     pPrev = pSym;
  1185.     if (ValidSymCharLen > 256)
  1186.       Ch = UTF8ToUnicode(&pSym);
  1187.     else
  1188.       Ch = ((unsigned int)*pSym++) & 0xff;
  1189.  
  1190.     if (!(GetValidSymChar(Ch) & Mask))
  1191.       return (char*)pPrev;
  1192.     Mask = _Mask << 1;
  1193.   }
  1194.   return (char*)pSym;
  1195. }
  1196.  
  1197. char *ChkSymbNameUpTo(const char *pSym, const char *pUpTo)
  1198. {
  1199.   char *pResult = ChkNameUpTo(pSym, pUpTo, VALID_S1);
  1200.  
  1201.   /* If NULL as UpTo was given, and all is fine up to end of string,
  1202.      also return NULL as result.  So Equation 'Result==UpTo' is fulfilled: */
  1203.  
  1204.   if (!pUpTo && !*pResult)
  1205.      pResult= NULL;
  1206.   return pResult;
  1207. }
  1208.  
  1209. Boolean ChkSymbName(const char *pSym)
  1210. {
  1211.   const char *pEnd = ChkSymbNameUpTo(pSym, NULL);
  1212.   return *pSym && !pEnd;
  1213. }
  1214.  
  1215. char *ChkMacSymbNameUpTo(const char *pSym, const char *pUpTo)
  1216. {
  1217.   char *pResult = ChkNameUpTo(pSym, pUpTo, VALID_M1);
  1218.  
  1219.   /* If NULL as UpTo was given, and all is fine up to end of string,
  1220.      also return NULL as result.  So Equation 'Result==UpTo' is fulfilled: */
  1221.  
  1222.   if (!pUpTo && !*pResult)
  1223.      pResult= NULL;
  1224.   return pResult;
  1225. }
  1226.  
  1227. Boolean ChkMacSymbName(const char *pSym)
  1228. {
  1229.   const char *pEnd = ChkMacSymbNameUpTo(pSym, NULL);
  1230.   return *pSym && !pEnd;
  1231. }
  1232.  
  1233. Boolean ChkMacSymbChar(char ch)
  1234. {
  1235.   return !!(GetValidSymChar(ch) & (VALID_M1 | VALID_MN));
  1236. }
  1237.  
  1238. /*!------------------------------------------------------------------------
  1239.  * \fn     visible_strlen(const char *pSym)
  1240.  * \brief  retrieve 'visible' length of string, regarding multi-byte
  1241.            sequences for UTF-8
  1242.  * \param  pSym symbol name
  1243.  * \return visible length in characters
  1244.  * ------------------------------------------------------------------------ */
  1245.  
  1246. unsigned visible_strlen(const char *pSym)
  1247. {
  1248.   if (ValidSymCharLen > 256)
  1249.   {
  1250.     unsigned Result = 0;
  1251.  
  1252.     while (*pSym)
  1253.       Result += as_wcwidth(UTF8ToUnicode(&pSym));
  1254.     return Result;
  1255.   }
  1256.   else
  1257.     return strlen(pSym);
  1258. }
  1259.  
  1260. /****************************************************************************/
  1261.  
  1262. LargeWord ProgCounter(void)
  1263. {
  1264.   return PCs[ActPC];
  1265. }
  1266.  
  1267. /*--------------------------------------------------------------------------*/
  1268. /* aktuellen Programmzaehler mit Phasenverschiebung holen */
  1269.  
  1270. LargeWord EProgCounter(void)
  1271. {
  1272.   return PCs[ActPC] + Phases[ActPC];
  1273. }
  1274.  
  1275. /*--------------------------------------------------------------------------*/
  1276. /* Granularitaet des aktuellen Segments holen */
  1277.  
  1278. Word Granularity(void)
  1279. {
  1280.   return Grans[ActPC];
  1281. }
  1282.  
  1283. /*--------------------------------------------------------------------------*/
  1284. /* Linstingbreite des aktuellen Segments holen */
  1285.  
  1286. Word ListGran(void)
  1287. {
  1288.   return ListGrans[ActPC];
  1289. }
  1290.  
  1291. /*--------------------------------------------------------------------------*/
  1292. /* pruefen, ob alle Symbole einer Formel im korrekten Adressraum lagen */
  1293.  
  1294. void ChkSpace(Byte AddrSpace, unsigned AddrSpaceMask)
  1295. {
  1296.   AddrSpaceMask &= ~(1 << AddrSpace);
  1297.  
  1298.   if (AddrSpaceMask) WrError(ErrNum_WrongSegment);
  1299. }
  1300.  
  1301. /****************************************************************************/
  1302. /* eine Chunkliste im Listing ausgeben & Speicher loeschen */
  1303.  
  1304. void PrintChunk(ChunkList *NChunk, DissectBitProc Dissect, int ItemsPerLine)
  1305. {
  1306.   LargeWord NewMin, FMin;
  1307.   Boolean Found;
  1308.   Word p = 0, z;
  1309.   int BufferZ;
  1310.   String BufferS;
  1311.   int MaxItemLen = 79 / ItemsPerLine;
  1312.  
  1313.   NewMin = 0;
  1314.   BufferZ = 0;
  1315.   *BufferS = '\0';
  1316.  
  1317.   do
  1318.   {
  1319.     /* niedrigsten Start finden, der ueberhalb des letzten Endes liegt */
  1320.  
  1321.     Found = False;
  1322.     FMin = IntTypeDefs[LargeUIntType].Max;
  1323.     for (z = 0; z < NChunk->RealLen; z++)
  1324.       if (NChunk->Chunks[z].Start >= NewMin)
  1325.         if (FMin > NChunk->Chunks[z].Start)
  1326.         {
  1327.           Found = True;
  1328.           FMin = NChunk->Chunks[z].Start;
  1329.           p = z;
  1330.         }
  1331.  
  1332.     if (Found)
  1333.     {
  1334.       char Num[30];
  1335.  
  1336.       Dissect(Num, sizeof(Num), NChunk->Chunks[p].Start);
  1337.       strmaxcat(BufferS, Num, STRINGSIZE);
  1338.       if (NChunk->Chunks[p].Length != 1)
  1339.       {
  1340.         strmaxcat(BufferS, "-", STRINGSIZE);
  1341.         Dissect(Num, sizeof(Num), NChunk->Chunks[p].Start + NChunk->Chunks[p].Length - 1);
  1342.         strmaxcat(BufferS, Num, STRINGSIZE);
  1343.       }
  1344.       strmaxcat(BufferS, Blanks(MaxItemLen - strlen(BufferS) % MaxItemLen), STRINGSIZE);
  1345.       if (++BufferZ == ItemsPerLine)
  1346.       {
  1347.         WrLstLine(BufferS);
  1348.         *BufferS = '\0';
  1349.         BufferZ = 0;
  1350.       }
  1351.       NewMin = NChunk->Chunks[p].Start + NChunk->Chunks[p].Length;
  1352.     }
  1353.   }
  1354.   while (Found);
  1355.  
  1356.   if (BufferZ != 0)
  1357.     WrLstLine(BufferS);
  1358. }
  1359.  
  1360. /*--------------------------------------------------------------------------*/
  1361. /* Listen ausgeben */
  1362.  
  1363. void PrintUseList(void)
  1364. {
  1365.   int z, z2, l;
  1366.   String s;
  1367.  
  1368.   for (z = 1; z < SegCount; z++)
  1369.     if (SegChunks[z].Chunks)
  1370.     {
  1371.       as_snprintf(s, sizeof(s), "  %s%s%s",
  1372.                   getmessage(Num_ListSegListHead1), SegNames[z],
  1373.                   getmessage(Num_ListSegListHead2));
  1374.       WrLstLine(s);
  1375.       strcpy(s, "  ");
  1376.       l = strlen(SegNames[z]) + strlen(getmessage(Num_ListSegListHead1)) + strlen(getmessage(Num_ListSegListHead2));
  1377.       for (z2 = 0; z2 < l; z2++)
  1378.         strmaxcat(s, "-", STRINGSIZE);
  1379.       WrLstLine(s);
  1380.       WrLstLine("");
  1381.       PrintChunk(SegChunks + z,
  1382.                  (z == SegBData) ? DissectBit : Default_DissectBit,
  1383.                  (z == SegBData) ? 3 : 4);
  1384.       WrLstLine("");
  1385.     }
  1386. }
  1387.  
  1388. void ClearUseList(void)
  1389. {
  1390.   int z;
  1391.  
  1392.   for (z = 1; z < SegCount; z++)
  1393.     ClearChunk(SegChunks + z);
  1394. }
  1395.  
  1396. /****************************************************************************/
  1397. /* Include-Pfadlistenverarbeitung */
  1398.  
  1399. /*!------------------------------------------------------------------------
  1400.  * \fn     get_first_path_from_list(const char *p_path_list, char *p_first_path, size_t first_path_size)
  1401.  * \brief  extract first path from list of paths
  1402.  * \param  p_path_list path list
  1403.  * \param  p_first_path where to put component
  1404.  * \param  first_path_size buffer size
  1405.  * \return p_path_list for next call of get_first_path_from_list()
  1406.  * ------------------------------------------------------------------------ */
  1407.  
  1408. static const char *get_first_path_from_list(const char *p_path_list, char *p_first_path, size_t first_path_size)
  1409. {
  1410.   const char *p;
  1411.  
  1412.   p = strchr(p_path_list, DIRSEP);
  1413.   if (!p)
  1414.   {
  1415.     strmaxcpy(p_first_path, p_path_list, first_path_size);
  1416.     return "";
  1417.   }
  1418.   else
  1419.   {
  1420.     strmemcpy(p_first_path, first_path_size, p_path_list, p - p_path_list);
  1421.     return p + 1;
  1422.   }
  1423. }
  1424.  
  1425. /*!------------------------------------------------------------------------
  1426.  * \fn     AddIncludeList(const char *p_new_path)
  1427.  * \brief  add path to include list
  1428.  * \param  p_new_path path to add
  1429.  * ------------------------------------------------------------------------ */
  1430.  
  1431. void AddIncludeList(const char *p_new_path)
  1432. {
  1433.   const char *p_list_run = IncludeList;
  1434.   String one_path;
  1435.  
  1436.   /* path already present in list? */
  1437.  
  1438.   while (*p_list_run)
  1439.   {
  1440.     p_list_run = get_first_path_from_list(p_list_run, one_path, sizeof(one_path));
  1441.     if (!strcmp(one_path, p_new_path))
  1442.       return;
  1443.   }
  1444.  
  1445.   /* no -> prepend */
  1446.  
  1447.   if (*IncludeList != '\0')
  1448.     strmaxprep(IncludeList, SDIRSEP, STRINGSIZE);
  1449.   strmaxprep(IncludeList, p_new_path, STRINGSIZE);
  1450. }
  1451.  
  1452. /*!------------------------------------------------------------------------
  1453.  * \fn     RemoveIncludeList(const char *p_rem_path)
  1454.  * \brief  remove one path from include list
  1455.  * \param  p_rem_path path to remove
  1456.  * ------------------------------------------------------------------------ */
  1457.  
  1458. void RemoveIncludeList(const char *p_rem_path)
  1459. {
  1460.   String one_path;
  1461.   const char *p_list_run, *p_list_next;
  1462.  
  1463.   p_list_run = IncludeList;
  1464.   while (*p_list_run)
  1465.   {
  1466.     p_list_next = get_first_path_from_list(p_list_run, one_path, sizeof(one_path));
  1467.     if (!strcmp(one_path, p_rem_path))
  1468.       strmov((char*)p_list_run, p_list_next);
  1469.     else
  1470.       p_list_run = p_list_next;
  1471.   }
  1472. }
  1473.  
  1474. /****************************************************************************/
  1475. /* Listen mit Ausgabedateien */
  1476.  
  1477. void ClearOutList(void)
  1478. {
  1479.   ClearStringList(&OutList);
  1480. }
  1481.  
  1482. void AddToOutList(const char *NewName)
  1483. {
  1484.   AddStringListLast(&OutList, NewName);
  1485. }
  1486.  
  1487. void RemoveFromOutList(const char *OldName)
  1488. {
  1489.   RemoveStringList(&OutList, OldName);
  1490. }
  1491.  
  1492. char *MoveFromOutListFirst(void)
  1493. {
  1494.   return MoveAndCutStringListFirst(&OutList);
  1495. }
  1496.  
  1497. void ClearShareOutList(void)
  1498. {
  1499.   ClearStringList(&ShareOutList);
  1500. }
  1501.  
  1502. void AddToShareOutList(const char *NewName)
  1503. {
  1504.   AddStringListLast(&ShareOutList, NewName);
  1505. }
  1506.  
  1507. void RemoveFromShareOutList(const char *OldName)
  1508. {
  1509.   RemoveStringList(&ShareOutList, OldName);
  1510. }
  1511.  
  1512. char *MoveFromShareOutListFirst(void)
  1513. {
  1514.   return MoveAndCutStringListFirst(&ShareOutList);
  1515. }
  1516.  
  1517. void ClearListOutList(void)
  1518. {
  1519.   ClearStringList(&ListOutList);
  1520. }
  1521.  
  1522. void AddToListOutList(const char *NewName)
  1523. {
  1524.   AddStringListLast(&ListOutList, NewName);
  1525. }
  1526.  
  1527. void RemoveFromListOutList(const char *OldName)
  1528. {
  1529.   RemoveStringList(&ListOutList, OldName);
  1530. }
  1531.  
  1532. char *MoveFromListOutListFirst(void)
  1533. {
  1534.   return MoveAndCutStringListFirst(&ListOutList);
  1535. }
  1536.  
  1537. /****************************************************************************/
  1538. /* Tokenverarbeitung */
  1539.  
  1540. typedef int (*tCompareFnc)(const char *s1, const char *s2, size_t n);
  1541.  
  1542. int ReplaceLine(as_dynstr_t *p_str, const char *pSearch, const char *pReplace, Boolean CaseSensitive)
  1543. {
  1544.   int SearchLen = strlen(pSearch), ReplaceLen = strlen(pReplace), StrLen = strlen(p_str->p_str), DeltaLen = ReplaceLen - SearchLen;
  1545.   int NumReplace = 0, Pos, End, CmpRes, Avail, nCopy, nMove;
  1546.   tCompareFnc Compare = CaseSensitive ? strncmp : as_strncasecmp;
  1547.  
  1548.   Pos = 0;
  1549.   while (Pos <= StrLen - SearchLen)
  1550.   {
  1551.     End = Pos + SearchLen;
  1552.     CmpRes = Compare(&p_str->p_str[Pos], pSearch, SearchLen);
  1553.     if ((!CmpRes)
  1554.      && ((Pos == 0) || !ChkMacSymbChar(p_str->p_str[Pos - 1]))
  1555.      && ((End >= StrLen) || !ChkMacSymbChar(p_str->p_str[End])))
  1556.     {
  1557.       if (StrLen + DeltaLen + 1 > (int)p_str->capacity)
  1558.         as_dynstr_realloc(p_str, as_dynstr_roundup_len(p_str->capacity + DeltaLen));
  1559.       Avail = p_str->capacity - 1 - Pos;
  1560.       nCopy = ReplaceLen; if (nCopy > Avail) nCopy = Avail;
  1561.       Avail -= nCopy;
  1562.       nMove = StrLen - (Pos + SearchLen); if (nMove > Avail) nMove = Avail;
  1563.       memmove(&p_str->p_str[Pos + nCopy], &p_str->p_str[Pos + SearchLen], nMove);
  1564.       memcpy(&p_str->p_str[Pos], pReplace, nCopy);
  1565.       p_str->p_str[Pos + nCopy + nMove] = '\0';
  1566.       Pos += nCopy;
  1567.       StrLen += DeltaLen;
  1568.       NumReplace++;
  1569.     }
  1570.     else
  1571.       Pos++;
  1572.   }
  1573.   return NumReplace;
  1574. }
  1575.  
  1576. static void SetToken(char *Token, unsigned TokenNum)
  1577. {
  1578.   Token[0] = (TokenNum >> 4) + 1;
  1579.   Token[1] = (TokenNum & 15) + 1;
  1580.   Token[2] = 0;
  1581. }
  1582.  
  1583. /*!------------------------------------------------------------------------
  1584.  * \fn     CompressLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str, Boolean ThisCaseSensitive)
  1585.  * \brief  compress tokens in line
  1586.  * \param  TokNam name to compress into token
  1587.  * \param  TokenNum token #
  1588.  * \param  p_str string to work on
  1589.  * \param  ThisCaseSensitive operate case sensitive?
  1590.  * ------------------------------------------------------------------------ */
  1591.  
  1592. int CompressLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str, Boolean ThisCaseSensitive)
  1593. {
  1594.   char Token[3];
  1595.   SetToken(Token, TokenNum);
  1596.   return ReplaceLine(p_str, TokNam, Token, ThisCaseSensitive);
  1597. }
  1598.  
  1599. /*!------------------------------------------------------------------------
  1600.  * \fn     ExpandLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str)
  1601.  * \brief  expand tokens in line
  1602.  * \param  TokNam name to expand token to
  1603.  * \param  TokenNum token #
  1604.  * \param  p_str string to work on
  1605.  * ------------------------------------------------------------------------ */
  1606.  
  1607. void ExpandLine(const char *TokNam, unsigned TokenNum, as_dynstr_t *p_str)
  1608. {
  1609.   char Token[3];
  1610.   SetToken(Token, TokenNum);
  1611.   (void)ReplaceLine(p_str, Token, TokNam, True);
  1612. }
  1613.  
  1614. void KillCtrl(char *Line)
  1615. {
  1616.   char *z;
  1617.  
  1618.   if (*(z = Line) == '\0')
  1619.     return;
  1620.   do
  1621.   {
  1622.     if (*z == '\0');
  1623.     else if (*z == Char_HT)
  1624.     {
  1625.       strmov(z, z + 1);
  1626.       strprep(z, Blanks(8 - ((z - Line) % 8)));
  1627.     }
  1628.     else if ((*z & 0xe0) == 0)
  1629.       *z = ' ';
  1630.     z++;
  1631.   }
  1632.   while (*z != '\0');
  1633. }
  1634.  
  1635. /****************************************************************************/
  1636. /* Buchhaltung */
  1637.  
  1638. void BookKeeping(void)
  1639. {
  1640.   if (MakeUseList)
  1641.     if (AddChunk(SegChunks + ActPC, ProgCounter(), CodeLen, ActPC == SegCode))
  1642.       WrError(ErrNum_Overlap);
  1643.   if (DebugMode != DebugNone)
  1644.   {
  1645.     AddSectionUsage(ProgCounter(), CodeLen);
  1646.     AddLineInfo(InMacroFlag, CurrLine, CurrFileName, ActPC, PCs[ActPC], CodeLen);
  1647.   }
  1648. }
  1649.  
  1650. /****************************************************************************/
  1651. /* Differenz zwischen zwei Zeiten mit Tagesueberlauf berechnen */
  1652.  
  1653. long DTime(long t1, long t2)
  1654. {
  1655.   LongInt d;
  1656.  
  1657.   d = t2 - t1;
  1658.   if (d < 0) d += (24*360000);
  1659.   return (d > 0) ? d : -d;
  1660. }
  1661.  
  1662. /*--------------------------------------------------------------------------*/
  1663. /* Init/Deinit passes */
  1664.  
  1665. typedef struct sProcStore
  1666. {
  1667.   struct sProcStore *pNext;
  1668.   SimpProc Proc;
  1669. } tProcStore;
  1670.  
  1671. static tProcStore *pInitPassProcStore = NULL,
  1672.                   *pClearUpProcStore = NULL;
  1673.  
  1674. void InitPass(void)
  1675. {
  1676.   tProcStore *pStore;
  1677.  
  1678.   for (pStore = pInitPassProcStore; pStore; pStore = pStore->pNext)
  1679.     pStore->Proc();
  1680. }
  1681.  
  1682. void ClearUp(void)
  1683. {
  1684.   tProcStore *pStore;
  1685.  
  1686.   for (pStore = pClearUpProcStore; pStore; pStore = pStore->pNext)
  1687.     pStore->Proc();
  1688. }
  1689.  
  1690. void AddInitPassProc(SimpProc NewProc)
  1691. {
  1692.   tProcStore *pNewStore = (tProcStore*)calloc(1, sizeof(*pNewStore));
  1693.  
  1694.   pNewStore->pNext = pInitPassProcStore;
  1695.   pNewStore->Proc = NewProc;
  1696.   pInitPassProcStore = pNewStore;
  1697. }
  1698.  
  1699. void AddClearUpProc(SimpProc NewProc)
  1700. {
  1701.   tProcStore *pNewStore = (tProcStore*)calloc(1, sizeof(*pNewStore));
  1702.  
  1703.   pNewStore->pNext = pClearUpProcStore;
  1704.   pNewStore->Proc = NewProc;
  1705.   pClearUpProcStore = pNewStore;
  1706. }
  1707.  
  1708. /*!------------------------------------------------------------------------
  1709.  * \fn     GTime(void)
  1710.  * \brief  fetch time of day in units of 10 ms
  1711.  * \return time of day
  1712.  * ------------------------------------------------------------------------ */
  1713.  
  1714. #ifdef __MSDOS__
  1715.  
  1716. #include <dos.h>
  1717.  
  1718. long GTime(void)
  1719. {
  1720.   struct time tbuf;
  1721.   long result;
  1722.  
  1723.   gettime(&tbuf);
  1724.   result = tbuf.ti_hour;
  1725.   result = (result * 60) + tbuf.ti_min;
  1726.   result = (result * 60) + tbuf.ti_sec;
  1727.   result = (result * 100) + tbuf.ti_hund;
  1728.   return result;
  1729. }
  1730.  
  1731. # define GTIME_DEFINED
  1732. #endif /* __MSDOS__ */
  1733.  
  1734. #ifdef __IBMC__
  1735.  
  1736. #include <time.h>
  1737. #define INCL_DOSDATETIME
  1738. #include <os2.h>
  1739.  
  1740. long GTime(void)
  1741. {
  1742.   DATETIME dt;
  1743.   struct tm ts;
  1744.   DosGetDateTime(&dt);
  1745.   memset(&ts, 0, sizeof(ts));
  1746.   ts.tm_year = dt.year - 1900;
  1747.   ts.tm_mon  = dt.month - 1;
  1748.   ts.tm_mday = dt.day;
  1749.   ts.tm_hour = dt.hours;
  1750.   ts.tm_min  = dt.minutes;
  1751.   ts.tm_sec  = dt.seconds;
  1752.   return (mktime(&ts) * 100) + (dt.hundredths);
  1753. }
  1754.  
  1755. # define GTIME_DEFINED
  1756. #endif /* __IBMC__ */
  1757.  
  1758. #ifdef _WIN32
  1759.  
  1760. # include <windows.h>
  1761.  
  1762. # if !AS_HAS_LONGLONG
  1763. #  include "math64.h"
  1764. # endif
  1765.  
  1766. long GTime(void)
  1767. {
  1768.   FILETIME ft;
  1769.  
  1770.   GetSystemTimeAsFileTime(&ft);
  1771. # if !AS_HAS_LONGLONG
  1772.   {
  1773.     static const t64 offs = { 0xd53e8000, 0x019db1de },
  1774.                      div = { 100000, 0 },
  1775.                      mod = { 8640000, 0 };
  1776.     t64 acc;
  1777.  
  1778.     /* time since 1 Jan 1601 in 100ns units */
  1779.     acc.low = ft.dwLowDateTime;
  1780.     acc.high = ft.dwHighDateTime;
  1781.     /* -> time since 1 Jan 1970 in 100ns units */
  1782.     sub64(&acc, &acc, &offs);
  1783.     /* -> time since 1 Jan 1970 in 10ms units */
  1784.     div64(&acc, &acc, &div);
  1785.     /* -> time since 0:00:00.0 in 10ms units */
  1786.     mod64(&acc, &acc, &mod);
  1787.     return acc.low;
  1788.   }
  1789. # else /* AS_HAS_LONGLONG */
  1790. #  define _W32_FT_OFFSET (116444736000000000ULL)
  1791.   unsigned long long time_tot;
  1792.   /* time since 1 Jan 1601 in 100ns units */
  1793.   time_tot =  ((unsigned long long)ft.dwLowDateTime )      ;
  1794.   time_tot += ((unsigned long long)ft.dwHighDateTime) << 32;
  1795.  
  1796.   /* -> time since 1 Jan 1970 in 100ns units */
  1797.   time_tot -= _W32_FT_OFFSET;
  1798.   /* -> time since 1 Jan 1970 in 10ms units */
  1799.   time_tot /= 100000ULL;
  1800.   /* -> time since 0:00:00.0 in 10ms units */
  1801.   time_tot %= 8640000ULL;
  1802.   return time_tot;
  1803. # endif /* !AS_HAS_LONGLONG */
  1804. }
  1805.  
  1806. # define GTIME_DEFINED
  1807. #endif /* _WIN32 */
  1808.  
  1809. #ifndef GTIME_DEFINED
  1810.  
  1811. #include <sys/time.h>
  1812.  
  1813. #ifdef NEED_GETTIMEOFDAY
  1814. # include <portability.h>
  1815. #endif
  1816.  
  1817. long GTime(void)
  1818. {
  1819.   struct timeval tv;
  1820.  
  1821.   gettimeofday(&tv, NULL);
  1822.   tv.tv_sec %= 86400;
  1823.   return (tv.tv_sec * 100) + (tv.tv_usec/10000);
  1824. }
  1825.  
  1826. #endif /* GTIME_DEFINED */
  1827.  
  1828. /*-------------------------------------------------------------------------*/
  1829. /* Stackfehler abfangen - bis auf DOS nur Dummies */
  1830.  
  1831. #ifdef __TURBOC__
  1832.  
  1833. #ifdef __DPMI16__
  1834. #else
  1835. unsigned _stklen = STKSIZE;
  1836. unsigned _ovrbuffer = 64*48;
  1837. #endif
  1838. #include <malloc.h>
  1839.  
  1840. void ChkStack(void)
  1841. {
  1842.   LongWord avail = stackavail();
  1843.   if (avail < MinStack)
  1844.     WrError(ErrNum_StackOvfl);
  1845.   if (avail < LowStack)
  1846.     LowStack = avail;
  1847. }
  1848.  
  1849. void ResetStack(void)
  1850. {
  1851.   LowStack = stackavail();
  1852. }
  1853.  
  1854. LongWord StackRes(void)
  1855. {
  1856.   return LowStack - MinStack;
  1857. }
  1858. #endif /* __TURBOC__ */
  1859.  
  1860. #ifdef CKMALLOC
  1861. #undef malloc
  1862. #undef realloc
  1863.  
  1864. void *ckmalloc(size_t s)
  1865. {
  1866.   void *tmp;
  1867.  
  1868. #ifdef __TURBOC__
  1869.   if (coreleft() < HEAPRESERVE + s)
  1870.     WrError(ErrNum_HeapOvfl);
  1871. #endif
  1872.  
  1873.   tmp = malloc(s);
  1874.   if (!tmp && (s > 0))
  1875.     WrError(ErrNum_HeapOvfl);
  1876.   return tmp;
  1877. }
  1878.  
  1879. void *ckrealloc(void *p, size_t s)
  1880. {
  1881.   void *tmp;
  1882.  
  1883. #ifdef __TURBOC__
  1884.   if (coreleft() < HEAPRESERVE + s)
  1885.     WrError(ErrNum_HeapOvfl);
  1886. #endif
  1887.  
  1888.   tmp = realloc(p, s);
  1889.   if (!tmp)
  1890.     WrError(ErrNum_HeapOvfl);
  1891.   return tmp;
  1892. }
  1893. #endif
  1894.  
  1895. static void SetValidSymChar(unsigned Ch, Byte Value)
  1896. {
  1897.   ValidSymChar[Ch] = Value;
  1898. }
  1899.  
  1900. static void SetValidSymChars(unsigned Start, unsigned Stop, Byte Value)
  1901. {
  1902.   for (; Start <= Stop; Start++)
  1903.     SetValidSymChar(Start, Value);
  1904. }
  1905.  
  1906. static as_cmd_result_t cmd_underscore_macroargs(Boolean negate, const char *p_arg)
  1907. {
  1908.   unsigned ch = (unsigned)'_';
  1909.  
  1910.   UNUSED(p_arg);
  1911.   if (negate)
  1912.     ValidSymChar[ch] &= ~(VALID_M1 | VALID_MN);
  1913.   else
  1914.     ValidSymChar[ch] |= (VALID_M1 | VALID_MN);
  1915.   return e_cmd_ok;
  1916. }
  1917.  
  1918. static const as_cmd_rec_t cmd_params[] =
  1919. {
  1920.   { "underscore-macroargs", cmd_underscore_macroargs }
  1921. };
  1922.  
  1923. void asmsub_init(void)
  1924. {
  1925. #ifdef __TURBOC__
  1926. #ifdef __MSDOS__
  1927. #ifdef __DPMI16__
  1928.   char *MemFlag, *p;
  1929.   String MemVal, TempName;
  1930.   unsigned long FileLen;
  1931. #else
  1932.   char *envval;
  1933.   int ovrerg;
  1934. #endif
  1935. #endif
  1936. #endif
  1937.  
  1938.   InitStringList(&CopyrightList);
  1939.   InitStringList(&OutList);
  1940.   InitStringList(&ShareOutList);
  1941.   InitStringList(&ListOutList);
  1942.  
  1943. #ifdef __TURBOC__
  1944. #ifdef __MSDOS__
  1945. #ifdef __DPMI16__
  1946.   /* Fuer DPMI evtl. Swapfile anlegen */
  1947.  
  1948.   MemFlag = getenv("ASXSWAP");
  1949.   if (MemFlag)
  1950.   {
  1951.     strmaxcpy(MemVal, MemFlag, STRINGSIZE);
  1952.     p = strchr(MemVal, ',');
  1953.     if (!p)
  1954.       strcpy(TempName, "ASX.TMP");
  1955.     else
  1956.     {
  1957.       *p = NULL;
  1958.       strcpy(TempName, MemVal);
  1959.       strmov(MemVal, p + 1);
  1960.     };
  1961.     KillBlanks(TempName);
  1962.     KillBlanks(MemVal);
  1963.     FileLen = strtol(MemFlag, &p, 0);
  1964.     if (*p != '\0')
  1965.     {
  1966.       fputs(getmessage(Num_ErrMsgInvSwapSize), stderr);
  1967.       exit(4);
  1968.     }
  1969.     if (MEMinitSwapFile(TempName, FileLen << 20) != RTM_OK)
  1970.     {
  1971.       fputs(getmessage(Num_ErrMsgSwapTooBig), stderr);
  1972.       exit(4);
  1973.     }
  1974.   }
  1975. #else
  1976.   /* Bei DOS Auslagerung Overlays in XMS/EMS versuchen */
  1977.  
  1978.   envval = getenv("USEXMS");
  1979.   if ((envval) && (as_toupper(*envval) == 'N'))
  1980.     ovrerg = -1;
  1981.   else
  1982.     ovrerg = _OvrInitExt(0, 0);
  1983.   if (ovrerg != 0)
  1984.   {
  1985.     envval = getenv("USEEMS");
  1986.     if ((!envval) || (as_toupper(*envval) != 'N'))
  1987.       _OvrInitEms(0, 0, 0);
  1988.   }
  1989. #endif
  1990. #endif
  1991. #endif
  1992.  
  1993. #ifdef __TURBOC__
  1994.   StartStack = stackavail();
  1995.   LowStack = stackavail();
  1996.   MinStack = StartStack - STKSIZE + 0x800;
  1997. #else
  1998.   StartStack = LowStack = MinStack = 0;
  1999. #endif
  2000.  
  2001.   as_cmd_register(cmd_params, as_array_size(cmd_params));
  2002.  
  2003.   /* initialize array of valid characters */
  2004.  
  2005.   ValidSymCharLen = (NLS_GetCodepage() == eCodepageUTF8) ? 1280 : 256;
  2006.   ValidSymChar = (Byte*) calloc(ValidSymCharLen, sizeof(Byte));
  2007.  
  2008.   /* The basic ASCII stuff: letters, dot and underscore are allowed
  2009.      anywhere, numbers not at beginning: */
  2010.  
  2011.   SetValidSymChars('a', 'z', VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2012.   SetValidSymChars('A', 'Z', VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2013.   SetValidSymChars('0', '9',            VALID_SN |            VALID_MN);
  2014.   SetValidSymChar ('.'     , VALID_S1 | VALID_SN                      );
  2015.   SetValidSymChar ('_'     , VALID_S1 | VALID_SN                      );
  2016.  
  2017.   /* Extensions, depending on character set: */
  2018.  
  2019.   switch (NLS_GetCodepage())
  2020.   {
  2021.     case eCodepage1251:
  2022.       SetValidSymChar (0xa3      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2023.       SetValidSymChar (0xb3      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2024.       SetValidSymChar (0xa8      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2025.       SetValidSymChar (0xb8      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2026.       SetValidSymChar (0xaa      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2027.       SetValidSymChar (0xba      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2028.       SetValidSymChar (0xaf      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2029.       SetValidSymChar (0xbf      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2030.       SetValidSymChar (0xbd      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2031.       SetValidSymChar (0xbe      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2032.       goto iso8859_1;
  2033.     case eCodepage1252:
  2034.       SetValidSymChar (0x8a      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2035.       SetValidSymChar (0x9a      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2036.       SetValidSymChar (0x8c      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2037.       SetValidSymChar (0x9c      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2038.       SetValidSymChar (0x8e      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2039.       SetValidSymChar (0x9e      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2040.       SetValidSymChar (0x9f      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2041.       goto iso8859_1;
  2042.     case eCodepage850:
  2043.       SetValidSymChars(0xb5, 0xb7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2044.       SetValidSymChars(0xc6, 0xc7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2045.       SetValidSymChars(0xd0, 0xd9, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2046.       SetValidSymChar (0xde      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2047.       SetValidSymChars(0xe0, 0xed, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2048.       /* fall-through */
  2049.     case eCodepage437:
  2050.       SetValidSymChars(128, 165, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2051.       SetValidSymChar (225     , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2052.       break;
  2053.     case eCodepage866:
  2054.       SetValidSymChars(0x80, 0xaf, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2055.       SetValidSymChars(0xe0, 0xf7, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2056.       break;
  2057.     case eCodepageISO8859_15:
  2058.       SetValidSymChar (0xa6      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2059.       SetValidSymChar (0xa8      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2060.       SetValidSymChar (0xb4      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2061.       SetValidSymChar (0xb8      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2062.       SetValidSymChar (0xbc      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2063.       SetValidSymChar (0xbd      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2064.       SetValidSymChar (0xbe      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2065.       /* fall-through */
  2066.     case eCodepageISO8859_1:
  2067.     iso8859_1:
  2068.       SetValidSymChar (0xa1      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2069.       SetValidSymChar (0xa2      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2070.       SetValidSymChars(0xc0, 0xff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2071.       break;
  2072.     case eCodepageKOI8_R:
  2073.       SetValidSymChar (0xa3      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2074.       SetValidSymChar (0xb3      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2075.       SetValidSymChars(0xc0, 0xff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2076.       break;
  2077.     case eCodepageUTF8:
  2078.     {
  2079.       const tNLSCharacterTab *pTab = GetCharacterTab(eCodepageUTF8);
  2080.       tNLSCharacter ch;
  2081.       unsigned Unicode;
  2082.       const char *pCh;
  2083.  
  2084.       for (ch = (tNLSCharacter)0; ch < eCH_cnt; ch++)
  2085.       {
  2086.         if ((ch == eCH_e2) || (ch == eCH_mu) || (ch == eCH_iquest) || (ch == eCH_iexcl))
  2087.           continue;
  2088.         pCh = &((*pTab)[ch][0]);
  2089.         Unicode = UTF8ToUnicode(&pCh);
  2090.         if (Unicode < ValidSymCharLen)
  2091.           SetValidSymChar (Unicode, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2092.       }
  2093.  
  2094.       /* Greek */
  2095.  
  2096.       SetValidSymChar ( 895      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2097.       SetValidSymChar ( 902      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2098.       SetValidSymChar (1011      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2099.       SetValidSymChar (1016      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2100.       SetValidSymChar (1018      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2101.       SetValidSymChar (1019      , VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2102.       SetValidSymChars( 904,  974, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2103.       SetValidSymChars( 984, 1007, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2104.  
  2105.       /* Cyrillic */
  2106.  
  2107.       SetValidSymChars(0x400, 0x481, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2108.       SetValidSymChars(0x48a, 0x4ff, VALID_S1 | VALID_SN | VALID_M1 | VALID_MN);
  2109.     }
  2110.     default:
  2111.       break;
  2112.   }
  2113.  
  2114. #if 0
  2115.   for (z = 0; z < ValidSymCharLen; z++)
  2116.   {
  2117.     if (!(z & 15))
  2118.       fprintf(stderr, "%02x:", z);
  2119.     fprintf(stderr, " %x", ValidSymChar[z]);
  2120.     if ((z & 15) == 15)
  2121.       fprintf(stderr, "\n");
  2122.   }
  2123. #endif
  2124.  
  2125.   version_init();
  2126. }
  2127.