VirtualBox

Changeset 3322 in kBuild for trunk/src


Ignore:
Timestamp:
Apr 16, 2020 10:23:49 PM (5 years ago)
Author:
bird
Message:

kmk/kbuild: kbuild_apply_defpath must walk quoted file tokens rather than simple space separated tokens. Added find_next_file_token to do the parsing. Updated find_next_token_eos with correct variable expansion skipping.

Location:
trunk/src/kmk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kbuild.c

    r3278 r3322  
    382382kbuild_apply_defpath(struct variable *pDefPath, char **ppsz, unsigned int *pcch, unsigned int *pcchAlloc, int fCanFree)
    383383{
    384     const char *pszIterator;
    385     const char *pszInCur;
    386384    unsigned int cchInCur;
    387385    unsigned int cchMaxRelative = 0;
    388     unsigned int cRelativePaths;
     386    const char *pszInCur;
    389387
    390388    /*
    391389     * The first pass, count the relative paths.
    392390     */
    393     cRelativePaths = 0;
    394     pszIterator = *ppsz;
    395     while ((pszInCur = find_next_token(&pszIterator, &cchInCur)) != NULL)
     391    const char *pszIterator = *ppsz;
     392    const char * const pszEos = pszIterator + *pcch;
     393    unsigned int cRelativePaths = 0;
     394    assert(*pszEos == '\0');
     395    while ((pszInCur = find_next_file_token(&pszIterator, pszEos, &cchInCur)) != NULL)
    396396    {
    397397        /* is relative? */
     
    438438        cRelativePaths = 0;
    439439        pszIterator = *ppsz;
    440         while ((pszInCur = find_next_token(&pszIterator, &cchInCur)))
     440        while ((pszInCur = find_next_file_token(&pszIterator, pszEos, &cchInCur)))
    441441        {
    442442            /* is relative? */
  • trunk/src/kmk/makeint.h

    r3273 r3322  
    679679#ifdef KMK
    680680char *find_next_token_eos (const char **ptr, const char *eos, unsigned int *lengthptr);
     681char *find_next_file_token (const char **ptr, const char *eos, unsigned int *lengthptr);
    681682#endif
    682683#ifndef CONFIG_WITH_VALUE_LENGTH
  • trunk/src/kmk/misc.c

    r3230 r3322  
    600600#endif
    601601}
     602
    602603#ifdef KMK
     604/* Finds the ends of the variable expansion starting at S, stopping at EOS if
     605   not found before. */
     606static char *find_end_of_variable_expansion (const char *s, char const *eos)
     607{
     608  char const openparen  = s[1];
     609  char const closeparen = openparen == '(' ? ')' : '}';
     610  int levels = 0;
     611
     612  assert (s[0] == '$');
     613  assert (s[1] == '(' || s[1] == '{');
     614
     615  s += 2;
     616  while (s != eos)
     617    {
     618      unsigned char ch = *s;
     619      if (ch != '\0')
     620        {
     621          if (ch != closeparen)
     622            {
     623              if (ch != openparen)
     624                { /* likely */ }
     625              else
     626                levels++;
     627            }
     628          else if (levels <= 1)
     629            break;
     630          else
     631            levels--;
     632        }
     633      else
     634        break;
     635      s++;
     636    }
     637
     638  return (char *)s;
     639}
    603640
    604641/* Same as find_next_token with two exception:
     
    611648  const char *p = *ptr;
    612649  const char *e;
    613   int level = 0;
    614650
    615651  /* skip blanks */
    616   for (; p != eos; p++)
    617     {
    618       unsigned char ch = *p;
    619       if (!MY_IS_BLANK(ch))
    620         {
    621           if (!ch)
    622             return NULL;
    623           break;
    624         }
     652  while (p != eos)
     653    {
     654      unsigned char const ch = *p;
     655      unsigned int const map = stopchar_map[ch] & (MAP_NUL | MAP_BLANK);
     656      if (map & MAP_BLANK)
     657        p++;
     658      else if (!(map & MAP_NUL))
     659        break;
     660      else
     661        return NULL;
    625662    }
    626663  if (p == eos)
     
    628665
    629666  /* skip ahead until EOS or blanks. */
    630   for (e = p; e != eos; e++)
    631     {
    632       unsigned char ch = *e;
    633       if (MY_IS_BLANK_OR_EOS(ch))
    634         {
    635           if (!ch || level == 0)
     667  e = p;
     668  while (e != eos)
     669    {
     670      unsigned char const ch = *e;
     671      unsigned int const map = stopchar_map[ch] & (MAP_NUL | MAP_BLANK | MAP_VARIABLE);
     672      if (!map)
     673        e++; /* likely */
     674      /* Dollar can be escaped by duplication ($$) and when not, they need to
     675         be skipped over. */
     676      else if (map & MAP_VARIABLE)
     677        {
     678          e++;
     679          if (&e[1] != eos)
     680            {
     681              unsigned ch2 = *e;
     682              if (ch2 == ch)
     683                e++; /* escaped */
     684              else if (ch == '(' || ch == '}')
     685                e = find_end_of_variable_expansion (e - 1, eos);
     686            }
     687          else
    636688            break;
    637689        }
    638       else if (ch == '$')
    639         {
    640           if (&e[1] != eos && (e[1] == '(' || e[1] == '{'))
     690      else
     691        break; /* MAP_NUL or MAP_BLANK */
     692    }
     693
     694  *ptr = e;
     695  if (lengthptr != 0)
     696    *lengthptr = e - p;
     697
     698  return (char *)p;
     699}
     700
     701/* Same as find_next_token_eos but takes GNU make quoting into account,
     702   but without doing any unquoting like find_char_unquote & parse_file_seq. */
     703
     704char *
     705find_next_file_token (const char **ptr, const char *eos, unsigned int *lengthptr)
     706{
     707  const char *p = *ptr;
     708  const char *e;
     709
     710  /* skip blanks */
     711  while (p != eos)
     712    {
     713      unsigned char const ch = *p;
     714      unsigned int const map = stopchar_map[ch] & (MAP_NUL | MAP_BLANK);
     715      if (map & MAP_BLANK)
     716        p++;
     717      else if (!(map & MAP_NUL))
     718        break;
     719      else
     720        return NULL;
     721    }
     722  if (p == eos)
     723    return NULL;
     724
     725  /* skip ahead until EOS or blanks. */
     726  e = p;
     727  while (e != eos)
     728    {
     729      unsigned char const ch = *e;
     730      unsigned int const map = stopchar_map[ch] & (MAP_NUL | MAP_BLANK | MAP_VARIABLE);
     731      if (!map)
     732        e++; /* likely */
     733      /* Dollar can be escaped by duplication ($$) and when not, they need to
     734         be skipped over. */
     735      else if (map & MAP_VARIABLE)
     736        {
     737          e++;
     738          if (&e[1] != eos)
    641739            {
    642               level++;
    643               e++;
     740              unsigned ch2 = *e;
     741              if (ch2 == ch)
     742                e++; /* escaped */
     743              else if (ch == '(' || ch == '}')
     744                e = find_end_of_variable_expansion (e - 1, eos);
    644745            }
    645         }
    646       else if ((ch == ')' || ch == '}') &&  level > 0)
    647         level--;
     746          else
     747            break;
     748        }
     749      else if (map & MAP_NUL)
     750        break;
     751      /* A blank can be escaped using a backslash. */
     752      else if (e[-1] != '\\')
     753        break;
     754      else
     755        {
     756          int slashes = 1;
     757          while (&e[-slashes] != p && e[-slashes - 1] == '\\')
     758            slashes++;
     759          if (slashes & 1)
     760            e++;
     761          else
     762            break;
     763        }
    648764    }
    649765
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette