Subversion Repositories pentevo

Rev

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

  1. /* codepseudo.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Haeufiger benutzte Pseudo-Befehle                                         */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. /*****************************************************************************
  12.  * Includes
  13.  *****************************************************************************/
  14.  
  15. #include "stdinc.h"
  16. #include <string.h>
  17. #include <ctype.h>
  18. #include <math.h>
  19.  
  20. #include "nls.h"
  21. #include "bpemu.h"
  22. #include "be_le.h"
  23. #include "strutil.h"
  24. #include "chunks.h"
  25. #include "asmdef.h"
  26. #include "asmsub.h"
  27. #include "asmpars.h"
  28. #include "asmallg.h"
  29. #include "asmitree.h"
  30. #include "errmsg.h"
  31.  
  32. #include "codepseudo.h"
  33. #include "motpseudo.h"
  34.  
  35. /*****************************************************************************
  36.  * Global Functions
  37.  *****************************************************************************/
  38.  
  39. /*****************************************************************************
  40.  * Function:    IsIndirect
  41.  * Purpose:     check whether argument is syntactically 'indirect', i.e.
  42.  *              enclosed in 'extra' parentheses.
  43.  * Result:      TRUE if indirect
  44.  *****************************************************************************/
  45.  
  46. Boolean IsIndirectGen(const char *Asc, const char *pBeginEnd)
  47. {
  48.   int z,Level,l;
  49.  
  50.   if (((l = strlen(Asc)) <= 2)
  51.    || (Asc[0] != pBeginEnd[0])
  52.    || (Asc[l - 1] != pBeginEnd[1]))
  53.     return False;
  54.  
  55.   Level = 0;
  56.   for (z = 1; z <= l - 2; z++)
  57.   {
  58.     if (Asc[z] == pBeginEnd[0]) Level++;
  59.     if (Asc[z] == pBeginEnd[1]) Level--;
  60.     if (Level < 0) return False;
  61.   }
  62.  
  63.   return True;
  64. }
  65.  
  66. Boolean IsIndirect(const char *Asc)
  67. {
  68.   return IsIndirectGen(Asc, "()");
  69. }
  70.  
  71. /*!------------------------------------------------------------------------
  72.  * \fn     FindDispBaseSplitWithQualifier(const char *pArg, int *pArgLen, tDispBaseSplitQualifier Qualifier, const char *pBracks)
  73.  * \brief  check for argument of type xxx(yyyy)
  74.  * \param  pArg argument to check
  75.  * \param  pArgLen returns argument length
  76.  * \param  Qualifier possible qualifier to allow more positive decisions
  77.  * \param  pBracks Opening/Closing Parentheses
  78.  * \return index to opening parenthese or -1 if not like pattern
  79.  * ------------------------------------------------------------------------ */
  80.  
  81. typedef struct
  82. {
  83.   as_quoted_iterator_cb_data_t data;
  84.   int nest, split_pos, last_nonspace_pos;
  85.   char last_nonspace;
  86.   tDispBaseSplitQualifier qualifier;
  87.   const char *p_bracks;
  88. } disp_base_split_cb_data_t;
  89.  
  90. /* We are looking for expressions of the form xxx(yyy),
  91.    but we want to avoid false positives on things like
  92.    xxx+(yyy*zzz).  So we look at the (non-blank) character
  93.    right before the opening parenthese in question.  If it is
  94.    something that might be the last letter of an identifier,
  95.    or another parenthized expression, and not an operator,
  96.    it might be OK...
  97.  
  98.    We generally look for the last candidate in the string,
  99.    i.e. we continue to search after a finding.
  100.  */
  101.  
  102. static Boolean disp_base_split_cb(const char *p_pos, as_quoted_iterator_cb_data_t *p_cb_data)
  103. {
  104.   disp_base_split_cb_data_t *p_data = (disp_base_split_cb_data_t*)p_cb_data;
  105.   int pos = p_pos - p_cb_data->p_str;
  106.  
  107.   if (*p_pos == p_data->p_bracks[0])
  108.   {
  109.     if (!p_data->nest)
  110.     {
  111.       if ((p_data->last_nonspace_pos < 0) || as_isalnum(p_data->last_nonspace) || (p_data->last_nonspace == ')') || (p_data->last_nonspace == '\'') || (p_data->last_nonspace == '"'))
  112.         p_data->split_pos = pos;
  113.       else if (p_data->qualifier)
  114.       {
  115.         int qual = p_data->qualifier(p_cb_data->p_str, p_data->last_nonspace_pos, pos);
  116.         if (qual >= 0)
  117.           p_data->split_pos = qual;
  118.       }
  119.     }
  120.     p_data->nest++;
  121.   }
  122.   else if (*p_pos == p_data->p_bracks[1])
  123.     p_data->nest--;
  124.   if (!as_isspace(*p_pos))
  125.   {
  126.     p_data->last_nonspace_pos = pos;
  127.     p_data->last_nonspace = *p_pos;
  128.   }
  129.   return True;
  130. }
  131.  
  132. int FindDispBaseSplitWithQualifier(const char *pArg, int *pArgLen, tDispBaseSplitQualifier Qualifier, const char *pBracks)
  133. {
  134.   disp_base_split_cb_data_t data;
  135.  
  136.   *pArgLen = strlen(pArg);
  137.  
  138.   if (!*pArgLen || (pArg[*pArgLen - 1] != pBracks[1]))
  139.     return -1;
  140.  
  141.   data.nest = 0;
  142.   data.split_pos = -1;
  143.   data.last_nonspace_pos = -1;
  144.   data.last_nonspace = ' ';
  145.   data.qualifier = Qualifier;
  146.   data.p_bracks = pBracks;
  147.  
  148.   as_iterate_str_quoted(pArg, disp_base_split_cb, &data.data);
  149.  
  150.   return data.split_pos;
  151. }
  152.  
  153. /*****************************************************************************
  154.  * Function:    CodeEquate
  155.  * Purpose:     EQU for different segment
  156.  * Result:      -
  157.  *****************************************************************************/
  158.  
  159. void CodeEquate(as_addrspace_t DestSeg, LargeInt Min, LargeInt Max)
  160. {
  161.   Boolean OK;
  162.   tSymbolFlags Flags;
  163.   LargeInt Erg;
  164.  
  165.   if (ChkArgCnt(1, 1))
  166.   {
  167.     Erg = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
  168.     if (OK && !mFirstPassUnknown(Flags))
  169.     {
  170.       if (Min > Erg) WrError(ErrNum_UnderRange);
  171.       else if (
  172. #ifndef HAS64
  173.         (!(Max & 0x80000000ul)) &&   /* cannot check >=2G range if LargeInt is 32 bits */
  174. #endif
  175.         (Erg > Max)) WrError(ErrNum_OverRange);
  176.       else
  177.       {
  178.         TempResult t;
  179.  
  180.         PushLocHandle(-1);
  181.         EnterIntSymbol(&LabPart, Erg, DestSeg, False);
  182.         PopLocHandle();
  183.         if (MakeUseList)
  184.           if (AddChunk(SegChunks + DestSeg, Erg, 1, False)) WrError(ErrNum_Overlap);
  185.  
  186.         as_tempres_ini(&t);
  187.         as_tempres_set_int(&t, Erg);
  188.         SetListLineVal(&t);
  189.         as_tempres_free(&t);
  190.       }
  191.     }
  192.   }
  193. }
  194.  
  195. /*!------------------------------------------------------------------------
  196.  * \fn     QualifyQuote_SingleQuoteConstant(const char *pStart, const char *pQuotePos)
  197.  * \brief  check whether ' in source is lead-in to character string or int constant
  198.  * \param  pStart complete string
  199.  * \param  pQuotePos single quote position
  200.  * \return True if this is NO lead-in of int constant
  201.  * ------------------------------------------------------------------------ */
  202.  
  203. Boolean QualifyQuote_SingleQuoteConstant(const char *pStart, const char *pQuotePos)
  204. {
  205.   const char *pRun;
  206.   Boolean OK;
  207.   int Base;
  208.  
  209.   /* previous character must be H X B O */
  210.  
  211.   if (pQuotePos == pStart)
  212.     return True;
  213.   switch (as_toupper(*(pQuotePos - 1)))
  214.   {
  215.     case 'B':
  216.       Base = 2; break;
  217.     case 'O':
  218.       Base = 8; break;
  219.     case 'X':
  220.     case 'H':
  221.       Base = 16; break;
  222.     default:
  223.       return True;
  224.   }
  225.  
  226.   /* Scan for following valid (binary/octal/hex) character(s) */
  227.  
  228.   for (pRun = pQuotePos + 1; *pRun; pRun++)
  229.   {
  230.     switch (Base)
  231.     {
  232.       case 16: OK = as_isxdigit(*pRun); break;
  233.       case 8: OK = as_isdigit(*pRun) && (*pRun < '8'); break;
  234.       case 2: OK = as_isdigit(*pRun) && (*pRun < '2'); break;
  235.       default: OK = False;
  236.     }
  237.     if (!OK)
  238.       break;
  239.   }
  240.  
  241.   /* none? -> bad */
  242.  
  243.   if (pRun <= pQuotePos + 1)
  244.     return True;
  245.  
  246.   /* If we've hit another ' after them, it is the "harmless" x'...' form,
  247.      and no special treatment is needed */
  248.  
  249.   if ('\'' == *pRun)
  250.     return True;
  251.  
  252.   /* Other token or string continues -> cannot be such a constant, otherwise we
  253.      have a match and the ' does NOT lead in a character string: */
  254.  
  255.   return as_isalnum(*pRun);
  256. }
  257.  
  258. /*!------------------------------------------------------------------------
  259.  * \fn     string_2_xasm_code(const struct as_nonz_dynstr *p_str, int bytes_per_dword, Boolean big_endian)
  260.  * \brief  put characters from string into xx bit words of machine code - translation done outside!
  261.  * \param  p_str source string
  262.  * \param  bytes_per_dword # of characters in a word
  263.  * \param  big_endian fill words starting with MSB?
  264.  * \return 0 or error code
  265.  * ------------------------------------------------------------------------ */
  266.  
  267. #define declare_string_2_xasm_code(NAME, TYPE, VAR) \
  268. int NAME(const struct as_nonz_dynstr *p_str, int bytes_per_dword, Boolean big_endian) \
  269. { \
  270.   int byte_fill, ret; \
  271.   const char *p_ch, *p_end; \
  272.   TYPE character; \
  273.  \
  274.   for (byte_fill = 0, p_ch = p_str->p_str, p_end = p_ch + p_str->len; \
  275.        p_ch < p_end; p_ch++) \
  276.   { \
  277.     if (!byte_fill) \
  278.     { \
  279.       ret = SetMaxCodeLen((CodeLen + 1) * sizeof(TYPE)); \
  280.       if (ret) \
  281.         return ret; \
  282.       VAR[CodeLen++] = 0; \
  283.     } \
  284.     character = *p_ch & 0xff; \
  285.     if (big_endian) \
  286.       VAR[CodeLen - 1] = (VAR[CodeLen - 1] << 8) | character; \
  287.     else \
  288.       VAR[CodeLen - 1] |= character << (byte_fill * 8); \
  289.     if (++byte_fill >= bytes_per_dword) \
  290.       byte_fill = 0; \
  291.   } \
  292.   if (byte_fill && big_endian) \
  293.     VAR[CodeLen - 1] <<= 8 * (bytes_per_dword - byte_fill); \
  294.   return 0; \
  295. }
  296.  
  297. declare_string_2_xasm_code(string_2_dasm_code, LongWord, DAsmCode)
  298. declare_string_2_xasm_code(string_2_wasm_code, Word, WAsmCode)
  299.