Subversion Repositories pentevo

Rev

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

  1. /* strcomp.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* Macro Assembler AS                                                        */
  6. /*                                                                           */
  7. /* Definition of a source line's component present after parsing             */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include "datatypes.h"
  15. #include "strutil.h"
  16. #include "strcomp.h"
  17.  
  18. static void check_capacity(const tStrComp *pComp)
  19. {
  20.   if (!pComp->str.capacity)
  21.   {
  22.     fprintf(stderr, "copy to zero-capacity StrComp\n");
  23.     abort();
  24.   }
  25. }
  26.  
  27. static void check_no_capacity(const tStrComp *pComp)
  28. {
  29.   if (pComp->str.capacity)
  30.   {
  31.     fprintf(stderr, "ptr move on non-zero-capacity StrComp\n");
  32.     abort();
  33.   }
  34. }
  35.  
  36. static size_t check_realloc(as_dynstr_t *p_str, size_t req_count)
  37. {
  38.   if ((req_count >= p_str->capacity) && p_str->dynamic)
  39.     as_dynstr_realloc(p_str, as_dynstr_roundup_len(req_count));
  40.   if (req_count >= p_str->capacity)
  41.     req_count = p_str->capacity - 1;
  42.   return req_count;
  43. }
  44.  
  45. /*!------------------------------------------------------------------------
  46.  * \fn     StrCompAlloc(tStrComp *pComp, size_t capacity)
  47.  * \brief  initialize string component with dynamic buffer
  48.  * \param  pComp component to fill
  49.  * \param  capacity requested capacity of buffer
  50.  * ------------------------------------------------------------------------ */
  51.  
  52. void StrCompAlloc(tStrComp *pComp, size_t capacity)
  53. {
  54.   as_dynstr_ini(&pComp->str, capacity);
  55.   StrCompReset(pComp);
  56. }
  57.  
  58. /*!------------------------------------------------------------------------
  59.  * \fn     StrCompReset(tStrComp *pComp)
  60.  * \brief  reset string component to "empty" state
  61.  * \param  pComp component to set
  62.  * ------------------------------------------------------------------------ */
  63.  
  64. void StrCompReset(tStrComp *pComp)
  65. {
  66.   LineCompReset(&pComp->Pos);
  67.   *pComp->str.p_str = '\0';
  68. }
  69.  
  70. /*!------------------------------------------------------------------------
  71.  * \fn     LineCompReset(tLineComp *pComp)
  72.  * \brief  reset line position to "empty" state
  73.  * \param  pComp component to set
  74.  * ------------------------------------------------------------------------ */
  75.  
  76. void LineCompReset(tLineComp *pComp)
  77. {
  78.   pComp->StartCol = -1;
  79.   pComp->Len = 0;
  80. }
  81.  
  82. /*!------------------------------------------------------------------------
  83.  * \fn     StrCompFree(tStrComp *pComp)
  84.  * \brief  free/clean string component
  85.  * \param  pComp string component to be cleared
  86.  * ------------------------------------------------------------------------ */
  87.  
  88. void StrCompFree(tStrComp *pComp)
  89. {
  90.   LineCompReset(&pComp->Pos);
  91.   as_dynstr_free(&pComp->str);
  92. }
  93.  
  94. /*!------------------------------------------------------------------------
  95.  * \fn     StrCompMkTemp(tStrComp *pComp, char *pStr, size_t capacity)
  96.  * \brief  create a dummy StrComp from plain string
  97.  * \param  pComp comp to create
  98.  * \param  pStr string to use
  99.  * \param  capacity string's capacity
  100.  * ------------------------------------------------------------------------ */
  101.  
  102. void StrCompMkTemp(tStrComp *pComp, char *pStr, size_t capacity)
  103. {
  104.   LineCompReset(&pComp->Pos);
  105.   pComp->str.p_str = pStr;
  106.   pComp->str.capacity = capacity;
  107.   pComp->str.dynamic = 0;
  108. }
  109.  
  110. /*!------------------------------------------------------------------------
  111.  * \fn     StrCompRefRight(tStrComp *pDest, const tStrComp *pSrc, size_t StartOffs)
  112.  * \brief  create a right-aligned substring component of string component (no copy)
  113.  * \param  pDest destination component
  114.  * \param  pSrc source component
  115.  * \param  StartOffs how many characters to omit at the left
  116.  * ------------------------------------------------------------------------ */
  117.  
  118. void StrCompRefRight(tStrComp *pDest, const tStrComp *pSrc, size_t StartOffs)
  119. {
  120.   pDest->str.p_str = pSrc->str.p_str + StartOffs;
  121.   pDest->str.capacity = 0;
  122.   pDest->str.dynamic = 0;
  123.   pDest->Pos.StartCol = pSrc->Pos.StartCol + StartOffs;
  124.   pDest->Pos.Len = pSrc->Pos.Len - StartOffs;
  125. }
  126.  
  127. /*!------------------------------------------------------------------------
  128.  * \fn     StrCompCopy(tStrComp *pDest, tStrComp *pSrc)
  129.  * \brief  copy string component
  130.  * \param  pDest destination component
  131.  * \param  pSrc source component
  132.  * ------------------------------------------------------------------------ */
  133.  
  134. void StrCompCopy(tStrComp *pDest, const tStrComp *pSrc)
  135. {
  136.   pDest->Pos = pSrc->Pos;
  137.   pDest->Pos.Len = as_dynstr_copy(&pDest->str, &pSrc->str);
  138. }
  139.  
  140. /*!------------------------------------------------------------------------
  141.  * \fn     StrCompCopySub(tStrComp *pDest, const tStrComp *pSrc, size_t Start, size_t Count)
  142.  * \brief  copy substring
  143.  * \param  pDest destination
  144.  * \param  pSrc source
  145.  * \param  Start start index to copy from
  146.  * \param  Count # of characters to copy
  147.  * ------------------------------------------------------------------------ */
  148.  
  149. void StrCompCopySub(tStrComp *pDest, const tStrComp *pSrc, size_t Start, size_t Count)
  150. {
  151.   unsigned l = strlen(pSrc->str.p_str);
  152.  
  153.   if (Start >= l)
  154.     Count = 0;
  155.   else if (Start + Count > l)
  156.     Count = l - Start;
  157.   check_capacity(pDest);
  158.   Count = check_realloc(&pDest->str, Count);
  159.   memcpy(pDest->str.p_str, pSrc->str.p_str + Start, Count);
  160.   pDest->str.p_str[Count] = '\0';
  161.   pDest->Pos.StartCol = pSrc->Pos.StartCol + Start;
  162.   pDest->Pos.Len = Count;
  163. }
  164.  
  165. /*!------------------------------------------------------------------------
  166.  * \fn     StrCompSplitRight(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
  167.  * \brief  split off another component at the right of the source
  168.  * \param  pSrc source to split off
  169.  * \param  pDest where to put part splitted off
  170.  * \param  pSrcSplitPos split position (not included in source or dest any more)
  171.  * ------------------------------------------------------------------------ */
  172.  
  173. void StrCompSplitRight(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
  174. {
  175.   size_t SrcLen = strlen(pSrcSplitPos + 1);
  176.  
  177.   check_capacity(pDest);
  178.   SrcLen = check_realloc(&pDest->str, SrcLen);
  179.   memcpy(pDest->str.p_str, pSrcSplitPos + 1, SrcLen);
  180.   pDest->str.p_str[SrcLen] = '\0';
  181.   pDest->Pos.StartCol = pSrc->Pos.StartCol + pSrcSplitPos + 1 - pSrc->str.p_str;
  182.   pDest->Pos.Len = SrcLen;
  183.   *pSrcSplitPos = '\0';
  184.   pSrc->Pos.Len = pSrcSplitPos - pSrc->str.p_str;
  185. }
  186.  
  187. /*!------------------------------------------------------------------------
  188.  * \fn     StrCompSplitLeft(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
  189.  * \brief  split off another component at the left of the source
  190.  * \param  pSrc source to split off
  191.  * \param  pDest where to put part splitted off
  192.  * \param  pSrcSplitPos split position (not included in source or dest any more)
  193.  * ------------------------------------------------------------------------ */
  194.  
  195. void StrCompSplitLeft(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
  196. {
  197.   size_t SrcLen;
  198.  
  199.   *pSrcSplitPos = '\0';
  200.   SrcLen = strlen(pSrc->str.p_str);
  201.   check_capacity(pDest);
  202.   SrcLen = check_realloc(&pDest->str, SrcLen);
  203.  
  204.   memcpy(pDest->str.p_str, pSrc->str.p_str, SrcLen);
  205.   pDest->str.p_str[SrcLen] = '\0';
  206.   pDest->Pos.StartCol = pSrc->Pos.StartCol;
  207.   pDest->Pos.Len = pSrcSplitPos - pSrc->str.p_str;
  208.  
  209.   strmov(pSrc->str.p_str, pSrcSplitPos + 1);
  210.   pSrc->Pos.StartCol += pSrcSplitPos - pSrc->str.p_str + 1;
  211.   pSrc->Pos.Len -= pSrcSplitPos - pSrc->str.p_str + 1;
  212. }
  213.  
  214. /*!------------------------------------------------------------------------
  215.  * \fn     StrCompSplitCopy(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
  216.  * \brief  copy left & right part of string to new components
  217.  * \param  pLeft dest for left part
  218.  * \param  pRight dest for right part
  219.  * \param  pSrc character source
  220.  * \param  pSplitPos split position in source
  221.  * ------------------------------------------------------------------------ */
  222.  
  223. void StrCompSplitCopy(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
  224. {
  225.   /* pLeft may be equal to pSrc, use memmove() and save SrcLen */
  226.  
  227.   size_t SrcLen = pSrc->Pos.Len;
  228.  
  229.   check_capacity(pLeft);
  230.   pLeft->Pos.StartCol = pSrc->Pos.StartCol;
  231.   pLeft->Pos.Len = check_realloc(&pLeft->str, pSplitPos - pSrc->str.p_str);
  232.   memmove(pLeft->str.p_str, pSrc->str.p_str, pLeft->Pos.Len);
  233.   pLeft->str.p_str[pLeft->Pos.Len] = '\0';
  234.  
  235.   check_capacity(pRight);
  236.   pRight->Pos.StartCol = pSrc->Pos.StartCol + (pLeft->Pos.Len + 1);
  237.   pRight->Pos.Len = check_realloc(&pRight->str, SrcLen - (pLeft->Pos.Len + 1));
  238.   memcpy(pRight->str.p_str, pSplitPos + 1, pRight->Pos.Len);
  239.   pRight->str.p_str[pRight->Pos.Len] = '\0';
  240. }
  241.  
  242. /*!------------------------------------------------------------------------
  243.  * \fn     StrCompSplitRef(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
  244.  * \brief  split string into left & right and form references
  245.  * \param  pLeft dest for left part
  246.  * \param  pRight dest for right part
  247.  * \param  pSrc character source
  248.  * \param  pSplitPos split position in source
  249.  * ------------------------------------------------------------------------ */
  250.  
  251. char StrCompSplitRef(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
  252. {
  253.   char Old = *pSplitPos;
  254.   /* save because pLeft and pSrc might be equal */
  255.   tLineComp SrcPos = pSrc->Pos;
  256.  
  257.   *pSplitPos = '\0';
  258.   pLeft->str.p_str = pSrc->str.p_str;
  259.   if (pLeft != pSrc)
  260.   {
  261.     pLeft->str.capacity = 0;
  262.     pLeft->str.dynamic = 0;
  263.   }
  264.   pLeft->Pos.StartCol = SrcPos.StartCol;
  265.   pLeft->Pos.Len = pSplitPos - pLeft->str.p_str;
  266.   pRight->str.p_str = pSrc->str.p_str + (pLeft->Pos.Len + 1);
  267.   pRight->str.capacity = 0;
  268.   pRight->str.dynamic = 0;
  269.   pRight->Pos.StartCol = SrcPos.StartCol + (pLeft->Pos.Len + 1);
  270.   pRight->Pos.Len = SrcPos.Len - (pLeft->Pos.Len + 1);
  271.  
  272.   return Old;
  273. }
  274.  
  275. /*!------------------------------------------------------------------------
  276.  * \fn     KillPrefBlanksStrComp(struct sStrComp *pComp)
  277.  * \brief  remove leading spaces on string component
  278.  * \param  pComp component to handle
  279.  * ------------------------------------------------------------------------ */
  280.  
  281. void KillPrefBlanksStrComp(struct sStrComp *pComp)
  282. {
  283.   int Delta = KillPrefBlanks(pComp->str.p_str);
  284.   pComp->Pos.StartCol += Delta;
  285.   pComp->Pos.Len -= Delta;
  286. }
  287.  
  288. /*!------------------------------------------------------------------------
  289.  * \fn     KillPrefBlanksStrCompRef(struct sStrComp *pComp)
  290.  * \brief  remove leading spaces on string component by inc'ing pointer
  291.  * \param  pComp component to handle
  292.  * ------------------------------------------------------------------------ */
  293.  
  294. void KillPrefBlanksStrCompRef(struct sStrComp *pComp)
  295. {
  296.   check_no_capacity(pComp);
  297.   while (isspace(*pComp->str.p_str))
  298.   {
  299.     pComp->str.p_str++;
  300.     if (pComp->str.capacity > 0)
  301.       pComp->str.capacity--;
  302.     pComp->Pos.StartCol++;
  303.     pComp->Pos.Len--;
  304.   }
  305. }
  306.  
  307. /*!------------------------------------------------------------------------
  308.  * \fn     KillPostBlanksStrComp(struct sStrComp *pComp)
  309.  * \brief  remove trailing spaces on string component
  310.  * \param  pComp component to handle
  311.  * ------------------------------------------------------------------------ */
  312.  
  313. void KillPostBlanksStrComp(struct sStrComp *pComp)
  314. {
  315.   pComp->Pos.Len -= KillPostBlanks(pComp->str.p_str);
  316. }
  317.  
  318. /*!------------------------------------------------------------------------
  319.  * \fn     StrCompShorten(struct sStrComp *pComp, size_t Delta)
  320.  * \brief  shorten string component by n characters
  321.  * \param  pComp component to shorten
  322.  * \param  Delta # of characters to chop off (no checks!)
  323.  * ------------------------------------------------------------------------ */
  324.  
  325. void StrCompShorten(struct sStrComp *pComp, size_t Delta)
  326. {
  327.   pComp->str.p_str[strlen(pComp->str.p_str) - Delta] = '\0';
  328.   pComp->Pos.Len -= Delta;
  329. }
  330.  
  331. /*!------------------------------------------------------------------------
  332.  * \fn     StrCompCutLeft(struct sStrComp *pComp, size_t Delta)
  333.  * \brief  remove n characters at start of component
  334.  * \param  pComp component to shorten
  335.  * \param  Delta # of characters to cut off
  336.  * \return actual # of characters cut off
  337.  * ------------------------------------------------------------------------ */
  338.  
  339. size_t StrCompCutLeft(struct sStrComp *pComp, size_t Delta)
  340. {
  341.   size_t len = strlen(pComp->str.p_str);
  342.  
  343.   if (Delta > len)
  344.     Delta = len;
  345.   if (Delta > pComp->Pos.Len)
  346.     Delta = pComp->Pos.Len;
  347.   strmov(pComp->str.p_str, pComp->str.p_str + Delta);
  348.   pComp->Pos.StartCol += Delta;
  349.   pComp->Pos.Len -= Delta;
  350.   return Delta;
  351. }
  352.  
  353. /*!------------------------------------------------------------------------
  354.  * \fn     StrCompIncRefLeft(struct sStrComp *pComp, size_t Delta)
  355.  * \brief  move start of component by n characters
  356.  * \param  pComp component to shorten
  357.  * \param  Delta # of characters to move by (no checks!)
  358.  * ------------------------------------------------------------------------ */
  359.  
  360. void StrCompIncRefLeft(struct sStrComp *pComp, size_t Delta)
  361. {
  362.   check_no_capacity(pComp);
  363.   pComp->str.p_str += Delta;
  364.   pComp->str.capacity = (pComp->str.capacity > Delta) ? pComp->str.capacity - Delta : 0;
  365.   pComp->Pos.StartCol += Delta;
  366.   pComp->Pos.Len -= Delta;
  367. }
  368.  
  369. /*!------------------------------------------------------------------------
  370.  * \fn     DumpStrComp(const char *pTitle, const struct sStrComp *pComp)
  371.  * \brief  debug dump of component
  372.  * \param  pTitle description of component
  373.  * \param  pComp component to dump
  374.  * ------------------------------------------------------------------------ */
  375.  
  376. void DumpStrComp(const char *pTitle, const struct sStrComp *pComp)
  377. {
  378.   fprintf(stderr, "%s: @ col %u len %u '%s'\n", pTitle, pComp->Pos.StartCol, pComp->Pos.Len, pComp->str.p_str);
  379. }
  380.