Subversion Repositories pentevo

Rev

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

  1. /* intformat.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS                                                                        */
  6. /*                                                                           */
  7. /* enums regarding integer constant notations                                */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "strutil.h"
  12. #include "datatypes.h"
  13. #include "stdinc.h"
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17. #include "intformat.h"
  18.  
  19. static const Word BaseVals[4] =
  20. {
  21.   2, 8, 16, 256
  22. };
  23.  
  24. LongWord NativeIntConstModeMask, OtherIntConstModeMask;
  25. tIntFormatList *IntFormatList = NULL;
  26. tIntConstMode IntConstMode;
  27. Boolean IntConstModeIBMNoTerm, RelaxedMode;
  28. int RadixBase;
  29.  
  30. static Boolean ChkIntFormatCHex(tIntCheckCtx *pCtx, char Ch)
  31. {
  32.   if ((pCtx->ExprLen > 2)
  33.    && (*pCtx->pExpr == '0')
  34.    && (RadixBase <= Ch - 'A' + 10)
  35.    && (as_toupper(pCtx->pExpr[1]) == Ch))
  36.   {
  37.     pCtx->pExpr += 2;
  38.     pCtx->ExprLen -= 2;
  39.     return True;
  40.   }
  41.   return False;
  42. }
  43.  
  44. static Boolean ChkIntFormatCBin(tIntCheckCtx *pCtx, char Ch)
  45. {
  46.   if ((pCtx->ExprLen > 2)
  47.    && (*pCtx->pExpr == '0')
  48.    && (RadixBase <= Ch - 'A' + 10)
  49.    && (as_toupper(pCtx->pExpr[1]) == Ch))
  50.   {
  51.     const char *pRun;
  52.  
  53.     for (pRun = pCtx->pExpr + 2; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++)
  54.       if (DigitVal(*pRun, 2) < 0)
  55.         return False;
  56.     pCtx->pExpr += 2;
  57.     pCtx->ExprLen -= 2;
  58.     return True;
  59.   }
  60.   return False;
  61. }
  62.  
  63. static Boolean ChkIntFormatMot(tIntCheckCtx *pCtx, char Ch)
  64. {
  65.   if ((pCtx->ExprLen > 1)
  66.    && (*pCtx->pExpr == Ch))
  67.   {
  68.     pCtx->pExpr++;
  69.     pCtx->ExprLen--;
  70.     return True;
  71.   }
  72.   return False;
  73. }
  74.  
  75. static Boolean ChkIntFormatInt(tIntCheckCtx *pCtx, char Ch)
  76. {
  77.   if ((pCtx->ExprLen < 2) || !as_isdigit(*pCtx->pExpr))
  78.     return False;
  79.   if ((RadixBase <= Ch - 'A' + 10)
  80.    && (as_toupper(pCtx->pExpr[pCtx->ExprLen - 1]) == Ch))
  81.   {
  82.     pCtx->ExprLen--;
  83.     return True;
  84.   }
  85.   return False;
  86. }
  87.  
  88. static Boolean ChkIntFormatIBM(tIntCheckCtx *pCtx, char Ch)
  89. {
  90.   if ((pCtx->ExprLen < 3)
  91.    || (as_toupper(*pCtx->pExpr) != Ch)
  92.    || (pCtx->pExpr[1] != '\''))
  93.     return False;
  94.   if ((pCtx->ExprLen > 3) && (pCtx->pExpr[pCtx->ExprLen - 1] == '\''))
  95.   {
  96.     pCtx->pExpr += 2;
  97.     pCtx->ExprLen -= 3;
  98.     return True;
  99.   }
  100.   else if (IntConstModeIBMNoTerm)
  101.   {
  102.     pCtx->pExpr += 2;
  103.     pCtx->ExprLen -= 2;
  104.     return True;
  105.   }
  106.   return False;
  107. }
  108.  
  109. static Boolean ChkIntFormatCOct(tIntCheckCtx *pCtx, char Ch)
  110. {
  111.   const char *pRun;
  112.   UNUSED(Ch);
  113.  
  114.   if ((pCtx->ExprLen < 2)
  115.    || (*pCtx->pExpr != '0'))
  116.     return False;
  117.   for (pRun = pCtx->pExpr + 1; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++)
  118.     if (DigitVal(*pRun, 8) < 0)
  119.       return False;
  120.   return True;
  121. }
  122.  
  123. static Boolean ChkIntFormatNatHex(tIntCheckCtx *pCtx, char Ch)
  124. {
  125.   const char *pRun;
  126.   UNUSED(Ch);
  127.  
  128.   if ((pCtx->ExprLen < 2)
  129.    || (*pCtx->pExpr != '0'))
  130.     return False;
  131.   for (pRun = pCtx->pExpr + 1; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++)
  132.     if (!as_isxdigit(*pRun))
  133.       return False;
  134.   return True;
  135. }
  136.  
  137. static Boolean ChkIntFormatDef(tIntCheckCtx *pCtx, char Ch)
  138. {
  139.   UNUSED(pCtx);
  140.   UNUSED(Ch);
  141.   return True;
  142. }
  143.  
  144. static const tIntFormatList IntFormatList_All[] =
  145. {
  146.   { ChkIntFormatCHex  , eIntFormatCHex,    16, 'X', "0xhex"  },
  147.   { ChkIntFormatCBin  , eIntFormatCBin,     2, 'B', "0bbin"  },
  148.   { ChkIntFormatMot   , eIntFormatMotHex,  16, '$', "$hex"   },
  149.   { ChkIntFormatMot   , eIntFormatMotBin,   2, '%', "%bin"   },
  150.   { ChkIntFormatMot   , eIntFormatMotOct,   8, '@', "@oct"   },
  151.   { ChkIntFormatInt   , eIntFormatIntHex,  16, 'H', "hexh"   },
  152.   { ChkIntFormatInt   , eIntFormatIntBin,   2, 'B', "binb"   },
  153.   { ChkIntFormatInt   , eIntFormatIntOOct,  8, 'O', "octo"   },
  154.   { ChkIntFormatInt   , eIntFormatIntQOct,  8, 'Q', "octq"   },
  155.   { ChkIntFormatIBM   , eIntFormatIBMHHex, 16, 'H', "h'hex'" },
  156.   { ChkIntFormatIBM   , eIntFormatIBMXHex, 16, 'X', "x'hex'" },
  157.   { ChkIntFormatIBM   , eIntFormatIBMBin,   2, 'B', "b'bin'" },
  158.   { ChkIntFormatIBM   , eIntFormatIBMOct,   8, 'O', "o'oct'" },
  159.   { ChkIntFormatIBM   , eIntFormatIBMAsc, 256, 'A', "a'asc'" },
  160.   { ChkIntFormatCOct  , eIntFormatCOct,     8, '0', "0oct"   },
  161.   { ChkIntFormatNatHex, eIntFormatNatHex,  16, '0', "0hex"   },
  162.   { ChkIntFormatDef   , eIntFormatDefRadix,-1, '\0', "dec"   }, /* -1 -> RadixBase */
  163.   { NULL              , (tIntFormatId)0,    0, '\0', ""      }
  164. };
  165.  
  166. /*!------------------------------------------------------------------------
  167.  * \fn     GetIntConstIntelSuffix(unsigned Radix)
  168.  * \brief  return Intel-style suffix letter fitting to number system
  169.  * \param  Radix req'd number system
  170.  * \return * to suffix string (may be empty)
  171.  * ------------------------------------------------------------------------ */
  172.  
  173. const char *GetIntConstIntelSuffix(unsigned Radix)
  174. {
  175.   static const char BaseLetters[3] =
  176.   {
  177.     'B', 'O', 'H'
  178.   };
  179.   unsigned BaseIdx;
  180.  
  181.   for (BaseIdx = 0; BaseIdx < as_array_size(BaseLetters); BaseIdx++)
  182.     if (Radix == BaseVals[BaseIdx])
  183.     {
  184.       static char Result[2] = { '\0', '\0' };
  185.  
  186.       Result[0] = BaseLetters[BaseIdx] + (HexStartCharacter - 'A');
  187.       return Result;
  188.     }
  189.   return "";
  190. }
  191.  
  192. /*!------------------------------------------------------------------------
  193.  * \fn     GetIntConstMotoPrefix(unsigned Radix)
  194.  * \brief  return Motorola-style prefix letter fitting to number system
  195.  * \param  Radix req'd number system
  196.  * \return * to prefix string (may be empty)
  197.  * ------------------------------------------------------------------------ */
  198.  
  199. const char *GetIntConstMotoPrefix(unsigned Radix)
  200. {
  201.   static const char BaseIds[3] =
  202.   {
  203.     '%', '@', '$'
  204.   };
  205.   unsigned BaseIdx;
  206.  
  207.   for (BaseIdx = 0; BaseIdx < as_array_size(BaseIds); BaseIdx++)
  208.     if (Radix == BaseVals[BaseIdx])
  209.     {
  210.       static char Result[2] = { '\0', '\0' };
  211.  
  212.       Result[0] = BaseIds[BaseIdx];
  213.       return Result;
  214.     }
  215.   return "";
  216. }
  217.  
  218. /*!------------------------------------------------------------------------
  219.  * \fn     GetIntConstCPrefix(unsigned Radix)
  220.  * \brief  return C-style prefix letter fitting to number system
  221.  * \param  Radix req'd number system
  222.  * \return * to prefix string (may be empty)
  223.  * ------------------------------------------------------------------------ */
  224.  
  225. const char *GetIntConstCPrefix(unsigned Radix)
  226. {
  227.   static const char BaseIds[3][3] =
  228.   {
  229.     "0b", "0", "0x"
  230.   };
  231.   unsigned BaseIdx;
  232.  
  233.   for (BaseIdx = 0; BaseIdx < as_array_size(BaseIds); BaseIdx++)
  234.     if (Radix == BaseVals[BaseIdx])
  235.       return BaseIds[BaseIdx];;
  236.   return "";
  237. }
  238.  
  239. /*!------------------------------------------------------------------------
  240.  * \fn     GetIntConstIBMPrefix(unsigned Radix)
  241.  * \brief  return IBM-style prefix letter fitting to number system
  242.  * \param  Radix req'd number system
  243.  * \return * to prefix string (may be empty)
  244.  * ------------------------------------------------------------------------ */
  245.  
  246. const char *GetIntConstIBMPrefix(unsigned Radix)
  247. {
  248.   static const char BaseIds[4] =
  249.   {
  250.     'B', 'O', 'X', 'A'
  251.   };
  252.   unsigned BaseIdx;
  253.  
  254.   for (BaseIdx = 0; BaseIdx < as_array_size(BaseIds); BaseIdx++)
  255.     if (Radix == BaseVals[BaseIdx])
  256.     {
  257.       static char Result[3] = { '\0', '\'', '\0' };
  258.  
  259.       Result[0] = BaseIds[BaseIdx] + (HexStartCharacter - 'A');
  260.       return Result;
  261.     }
  262.   return "";
  263. }
  264.  
  265. /*!------------------------------------------------------------------------
  266.  * \fn     GetIntConstIBMSuffix(unsigned Radix)
  267.  * \brief  return IBM-style suffix fitting to number system
  268.  * \param  Radix req'd number system
  269.  * \return * to prefix string (may be empty)
  270.  * ------------------------------------------------------------------------ */
  271.  
  272. const char *GetIntConstIBMSuffix(unsigned Radix)
  273. {
  274.   unsigned BaseIdx;
  275.  
  276.   for (BaseIdx = 0; BaseIdx < as_array_size(BaseVals); BaseIdx++)
  277.     if (Radix == BaseVals[BaseIdx])
  278.       return "\'";
  279.   return "";
  280. }
  281.  
  282. /*!------------------------------------------------------------------------
  283.  * \fn     SetIntConstModeByMask(LongWord Mask)
  284.  * \brief  set new (non-relaxed) integer constant mode by bit mask
  285.  * \param  Mask modes to set
  286.  * ------------------------------------------------------------------------ */
  287.  
  288. void SetIntConstModeByMask(LongWord Mask)
  289. {
  290.   const tIntFormatList *pSrc;
  291.   tIntFormatList *pDest;
  292.  
  293.   if (!IntFormatList)
  294.     IntFormatList = (tIntFormatList*)malloc(sizeof(IntFormatList_All));
  295.   for (pDest = IntFormatList, pSrc = IntFormatList_All; pSrc->Check; pSrc++)
  296.   {
  297.     if (!((Mask >> pSrc->Id) & 1))
  298.       continue;
  299.     *pDest++ = *pSrc;
  300.   }
  301.   memset(pDest, 0, sizeof(*pDest));
  302. }
  303.  
  304. /*!------------------------------------------------------------------------
  305.  * \fn     ModifyIntConstModeByMask(LongWord ANDMask, LongWord ORMask)
  306.  * \brief  add or remove integer notations to/from native list
  307.  * \param  ANDMask notations to remove
  308.  * \param  ORMask notations to add
  309.  * \return True if mask was set up successfully
  310.  * ------------------------------------------------------------------------ */
  311.  
  312. #define BadMask ((1ul << eIntFormatCOct) | (1ul << eIntFormatNatHex))
  313.  
  314. Boolean ModifyIntConstModeByMask(LongWord ANDMask, LongWord ORMask)
  315. {
  316.   LongWord NewMask = (NativeIntConstModeMask & ~ANDMask) | ORMask;
  317.  
  318.   if ((NewMask & BadMask) == BadMask)
  319.     return False;
  320.   else
  321.   {
  322.     NativeIntConstModeMask = NewMask;
  323.     SetIntConstModeByMask(NativeIntConstModeMask | (RelaxedMode ? OtherIntConstModeMask : 0));
  324.     return True;
  325.   }
  326. }
  327.  
  328. /*!------------------------------------------------------------------------
  329.  * \fn     SetIntConstMode(tIntConstMode Mode)
  330.  * \brief  set new (non-relaxed) integer constant mode
  331.  * \param  Mode mode to set
  332.  * ------------------------------------------------------------------------ */
  333.  
  334. void SetIntConstMode(tIntConstMode Mode)
  335. {
  336.   IntConstMode = Mode;
  337.   switch (Mode)
  338.   {
  339.     case eIntConstModeC:
  340.       NativeIntConstModeMask = eIntFormatMaskC;
  341.       OtherIntConstModeMask = eIntFormatMaskIntel | eIntFormatMaskMoto | eIntFormatMaskIBM;
  342.       break;
  343.     case eIntConstModeIntel:
  344.       NativeIntConstModeMask = eIntFormatMaskIntel;
  345.       OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskMoto | eIntFormatMaskIBM;
  346.       break;
  347.     case eIntConstModeMoto:
  348.       NativeIntConstModeMask = eIntFormatMaskMoto;
  349.       OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskIntel | eIntFormatMaskIBM;
  350.       break;
  351.     case eIntConstModeIBM:
  352.       NativeIntConstModeMask = eIntFormatMaskIBM;
  353.       OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskIntel | eIntFormatMaskMoto;
  354.       break;
  355.     default:
  356.       NativeIntConstModeMask = 0;
  357.   }
  358.   NativeIntConstModeMask |= (1ul << eIntFormatDefRadix);
  359.   SetIntConstModeByMask(NativeIntConstModeMask | (RelaxedMode ? OtherIntConstModeMask : 0));
  360. }
  361.  
  362. /*!------------------------------------------------------------------------
  363.  * \fn     SetIntConstRelaxedMode(Boolean NewRelaxedMode)
  364.  * \brief  update relaxed mode - parser list
  365.  * \param  NewRelaxedMode mode to set
  366.  * ------------------------------------------------------------------------ */
  367.  
  368. void SetIntConstRelaxedMode(Boolean NewRelaxedMode)
  369. {
  370.   SetIntConstModeByMask(NativeIntConstModeMask | (NewRelaxedMode ? OtherIntConstModeMask : 0));
  371. }
  372.  
  373. /*!------------------------------------------------------------------------
  374.  * \fn     GetIntFormatId(const char *pIdent)
  375.  * \brief  transform identifier to id
  376.  * \param  pIdent textual identifier
  377.  * \return resulting Id or None if not found
  378.  * ------------------------------------------------------------------------ */
  379.  
  380. tIntFormatId GetIntFormatId(const char *pIdent)
  381. {
  382.   const tIntFormatList *pList;
  383.   for (pList = IntFormatList_All; pList->Check; pList++)
  384.    if (!as_strcasecmp(pIdent, pList->Ident))
  385.      return (tIntFormatId)pList->Id;
  386.   return eIntFormatNone;
  387. }
  388.  
  389. /*!------------------------------------------------------------------------
  390.  * \fn     intformat_init(void)
  391.  * \brief  module initialization
  392.  * ------------------------------------------------------------------------ */
  393.  
  394. void intformat_init(void)
  395. {
  396.   /* Allow all int const modes for handling possible -D options: */
  397.  
  398.   RelaxedMode = True;
  399.   SetIntConstMode(eIntConstModeC);
  400. }
  401.