Ignore:
Timestamp:
Apr 1, 2020, 9:05:32 AM (5 years ago)
Author:
bird
Message:

kmk/incdep.c: Unescaping.

File:
1 edited

Legend:

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

    r3316 r3318  
    13031303   */
    13041304static const char *
    1305 incdep_unescape_and_cache_filename(struct incdep *curdep,
    1306                                    char *start, const char *end, const char **nextp)
    1307 {
    1308   int const is_dep = nextp == NULL;
     1305incdep_unescape_and_cache_filename(struct incdep *curdep, char *start, const char *end,
     1306                                   int const is_dep, const char **nextp, unsigned int *linenop)
     1307{
    13091308  unsigned const esc_mask = MAP_BLANK        /*  ' ' + '\t' */
    13101309                          | MAP_COLON        /* ':' */
     
    13161315                             : MAP_PERCENT); /* '%' */
    13171316  unsigned const all_esc_mask = esc_mask | MAP_BLANK | MAP_NEWLINE;
    1318   unsigned const stop_mask = nextp ? MAP_BLANK | MAP_NEWLINE | MAP_COLON : 0;
     1317  unsigned const stop_mask = nextp ? MAP_BLANK | MAP_NEWLINE | (!is_dep ? MAP_COLON : 0) : 0;
    13191318  char volatile *src;
    13201319  char volatile *dst;
     
    13871386      else
    13881387        {
    1389           const char ch2 = *src++;  /* No bounds checking to handle "/dir/file\ : ..."  when end points at " :". */
     1388          char ch2 = *src++;  /* No bounds checking to handle "/dir/file\ : ..."  when end points at " :". */
    13901389          if (ch == '$')
    13911390            {
     
    13961395          else
    13971396            {
    1398               unsigned int const ch2_map = stopchar_map[(unsigned char)ch2];
     1397              unsigned int ch2_map;
     1398
     1399              /* Eat all the slashes and see what's at the end of them as that's all
     1400                 that's relevant.  If there is an escapable char, we'll emit half of
     1401                 the slashes. */
     1402              size_t const max_slashes = src - start - 1;
     1403              size_t slashes = 1;
     1404              while (ch2 == '\\')
     1405                {
     1406                  ch2 = *src++;
     1407                  slashes++;
     1408                }
     1409
     1410              /* Is it escapable? */
     1411              ch2_map = stopchar_map[(unsigned char)ch2];
    13991412              if (ch2_map & all_esc_mask)
    14001413                {
    1401                   /* Count preceeding slashes, unwind half of them regardless of odd/even count. */
    1402                   size_t const max_slashes = src - start - 1;
    1403                   size_t slashes = 1;
    1404                   while (slashes < max_slashes && src[-2 - slashes] == '\\')
    1405                     slashes++;
    1406 
    14071414                  /* Non-whitespace is simple: Slash slashes, output or stop. */
    14081415                  if (!(ch2_map & (MAP_BLANK | MAP_NEWLINE)))
    14091416                    {
    14101417                      assert(ch2_map & esc_mask);
    1411                       dst -= slashes / 2;
    1412                       if ((slashes & 1) || !(stop_mask & ch2_map))
     1418                      while (slashes >= 2)
     1419                        {
     1420                          *dst++ = '\\';
     1421                          slashes -= 2;
     1422                        }
     1423                      if (slashes || !(stop_mask & ch2_map))
    14131424                        *dst++ = ch2;
    14141425                      else
     
    14401451                          if (ch3 == '\\' && src[1] == '\n')
    14411452                            src += 2; /* Escaped blank & newline joins into single space. */
    1442                           else if (ch3 == '\\' && src[1] == '\r' && src[1] == '\n')
     1453                          else if (ch3 == '\\' && src[1] == '\r' && src[2] == '\n')
    14431454                            src += 3; /* -> Join the escaped newline code below on the next line. */
     1455                          else if (STOP_SET(ch3, stop_mask & MAP_NEWLINE))
     1456                            { /* last thing on the line, no blanks to escape. */
     1457                              while (slashes-- > 0)
     1458                                *dst++ = '\\';
     1459                              break;
     1460                            }
    14441461                          else
    14451462                            {
    14461463                              src = src_saved;
    1447                               dst -= slashes / 2;
    1448                               if (slashes & 1)
     1464                              while (slashes >= 2)
     1465                                {
     1466                                  *dst++ = '\\';
     1467                                  slashes -= 2;
     1468                                }
     1469                              if (slashes)
    14491470                                {
    14501471                                  *dst++ = ch2;
    14511472                                  continue;
    14521473                                }
    1453                               assert(nextp);
     1474                              assert (nextp || (uintptr_t)src >= (uintptr_t)end);
    14541475                              break;
    14551476                            }
     
    14641485                      else
    14651486                        {
    1466                           assert(ch2_map & MAP_NEWLINE);
     1487                          assert (ch2_map & MAP_NEWLINE);
    14671488                          if (ch2 == '\r' && *src == '\n')
    14681489                            src++;
     
    14721493                      for (;;)
    14731494                        {
     1495                          if (linenop)
     1496                            *linenop += 1;
    14741497                          while ((uintptr_t)src < (uintptr_t)end && ISBLANK(*src))
    14751498                            src++;
     
    14851508                          if (ch3 == '\n')
    14861509                            src += 2;
    1487                           else if (ch3 == '\r' && src[1] == '\n')
     1510                          else if (ch3 == '\r' && src[2] == '\n')
    14881511                            src += 3;
    14891512                          else
     
    14911514                        }
    14921515
    1493                       if (!ch3 && is_dep)
    1494                         break; /* last thing on the line. */
    1495                       dst -= slashes / 2;
    1496                       if (slashes & 1)
     1516                      if (is_dep && STOP_SET(ch3, stop_mask | MAP_NUL))
     1517                        { /* last thing on the line, no blanks to escape. */
     1518                          while (slashes-- > 0)
     1519                            *dst++ = '\\';
     1520                          break;
     1521                        }
     1522                      while (slashes >= 2)
     1523                        {
     1524                          *dst++ = '\\';
     1525                          slashes -= 2;
     1526                        }
     1527                      if (slashes)
    14971528                        *dst++ = ' ';
    14981529                      else
    14991530                        {
    1500                           assert(nextp);
     1531                          assert (nextp || (uintptr_t)src >= (uintptr_t)end);
    15011532                          break;
    15021533                        }
     
    15071538                {
    15081539                  src--;
     1540                  while (slashes-- > 0)
     1541                    *dst++ = '\\';
    15091542                  *dst++ = ch;
    15101543                }
     
    18541887
    18551888              /* Locate the next file colon.  If it's not within the bounds of
    1856                  the current line, check that all new line chars are escaped,
    1857                  and simplify them while we're at it. */
     1889                 the current line, check that all new line chars are escaped. */
    18581890
    18591891              colonp = memchr (cur, ':', file_end - cur);
     
    18781910                  break;
    18791911                }
    1880               if ((uintptr_t)colonp >= (uintptr_t)eol)
     1912
     1913              if ((uintptr_t)colonp < (uintptr_t)eol)
     1914                  unescape_filename = memchr (cur, '\\', colonp - cur) != NULL
     1915                                   || memchr (cur, '$', colonp - cur) != NULL;
     1916              else if (memchr (eol, '=', colonp - eol))
    18811917                {
    1882                   const char *sol;
    1883 
    1884                   if (memchr (eol, '=', colonp - eol))
    1885                     {
    1886                       incdep_warn (curdep, line_no, "multi line assignment / dependency confusion.");
    1887                       break;
    1888                     }
    1889 
    1890                   sol = cur;
     1918                  incdep_warn (curdep, line_no, "multi line assignment / dependency confusion.");
     1919                  break;
     1920                }
     1921              else
     1922                {
     1923                  const char *sol = cur;
    18911924                  do
    18921925                    {
     
    19001933                      else
    19011934                        {
    1902                           eol2[0] = ' ';
    1903                           eol2[1] = ' ';
    1904                           if (eol2 != eol - 1)
    1905                             eol2[2] = ' ';
    19061935                          line_no++;
    1907 
    19081936                          sol = eol + 1;
    19091937                          eol = memchr (sol, '\n', colonp - sol);
     
    19161944                  if (!sol)
    19171945                    break;
     1946                  unescape_filename = 1;
    19181947                }
    19191948
     
    19281957                }
    19291958              fnnext = cur;
    1930               if (   !memchr (cur, '\\', fnend - cur)
    1931                   && !memchr (cur, '$', fnend - cur))
     1959              if (!unescape_filename)
    19321960                {
    19331961                  while (fnnext != fnend && !ISBLANK (*fnnext))
     
    19361964                }
    19371965              else
    1938                 {
    1939                   filename = incdep_unescape_and_cache_filename (curdep, (char *)fnnext, fnend, &fnnext);
    1940                   unescape_filename = 1;
    1941                 }
     1966                filename = incdep_unescape_and_cache_filename (curdep, (char *)fnnext, fnend, 0, &fnnext, NULL);
    19421967
    19431968              /* parse any dependencies. */
     
    19451970              while ((uintptr_t)cur < (uintptr_t)file_end)
    19461971                {
     1972                  const char *dep_file;
     1973
    19471974                  /* skip blanks and count lines. */
    1948                   while ((uintptr_t)cur < (uintptr_t)file_end && ISSPACE (*cur) && *cur != '\n')
     1975                  char ch = 0;
     1976                  while ((uintptr_t)cur < (uintptr_t)file_end && ISSPACE ((ch = *cur)) && ch != '\n')
    19491977                    ++cur;
    19501978                  if ((uintptr_t)cur >= (uintptr_t)file_end)
    19511979                    break;
    1952                   if (*cur == '\n')
     1980                  if (ch == '\n')
    19531981                    {
    19541982                      cur++;
     
    19581986
    19591987                  /* continuation + eol? */
    1960                   if (*cur == '\\')
     1988                  if (ch == '\\')
    19611989                    {
    19621990                      unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
     
    19711999                    }
    19722000
    1973                   /* find the end of the filename */
     2001                  /* find the end of the filename and cache it */
     2002                  dep_file = NULL;
    19742003                  endp = cur;
    1975                   while (   (uintptr_t)endp < (uintptr_t)file_end
    1976                          && (   !ISSPACE (*endp)
    1977                              || (endp[-1] == '\\' && incdep_count_slashes_backwards(&endp[-1], cur) & 1)))
    1978                     ++endp;
     2004                  for (;;)
     2005                    if ((uintptr_t)endp < (uintptr_t)file_end)
     2006                      {
     2007                         ch = *endp;
     2008                         if (ch != '\\' && ch != '$' )
     2009                           {
     2010                             if (!ISSPACE (ch))
     2011                               endp++;
     2012                             else
     2013                               {
     2014                                 dep_file = incdep_dep_strcache(curdep, cur, endp - cur);
     2015                                 break;
     2016                               }
     2017                           }
     2018                         else
     2019                           {
     2020                             /* potential escape sequence, let the unescaper do the rest. */
     2021                             dep_file = incdep_unescape_and_cache_filename (curdep, (char *)cur, file_end, 1, &endp, &line_no);
     2022                             break;
     2023                           }
     2024                      }
     2025                    else
     2026                      {
     2027                        dep_file = incdep_dep_strcache(curdep, cur, endp - cur);
     2028                        break;
     2029                      }
    19792030
    19802031                  /* add it to the list. */
    19812032                  *nextdep = dep = incdep_alloc_dep (curdep);
    19822033                  dep->includedep = 1;
    1983                   if (   !memchr (cur, '\\', endp - cur)
    1984                       && !memchr (cur, '$', endp - cur))
    1985                     dep->name = incdep_dep_strcache(curdep, cur, endp - cur);
    1986                   else
    1987                     dep->name = incdep_unescape_and_cache_filename (curdep, (char *)cur, endp, NULL);
     2034                  dep->name = dep_file;
    19882035                  nextdep = &dep->next;
    19892036
     
    20032050                    if (fnnext == fnend)
    20042051                      break;
     2052                    if (*fnnext == '\\')
     2053                      {
     2054                        if (fnnext[1] == '\n')
     2055                          {
     2056                            line_no++;
     2057                            fnnext += 2;
     2058                            continue;
     2059                          }
     2060                        if (fnnext[1] == '\r' && fnnext[2] == '\n')
     2061                          {
     2062                            line_no++;
     2063                            fnnext += 3;
     2064                            continue;
     2065                          }
     2066                      }
    20052067
    20062068                    if (!unescape_filename)
     
    20122074                      }
    20132075                    else
    2014                       filename = incdep_unescape_and_cache_filename (curdep, (char *)fnnext, fnend, &fnnext);
     2076                      filename = incdep_unescape_and_cache_filename (curdep, (char *)fnnext, fnend, 0, &fnnext, NULL);
    20152077                    if (filename != filename_prev) /* clang optimization. */
    20162078                      incdep_record_file (curdep, filename, incdep_dup_dep_list (curdep, deps), f);
Note: See TracChangeset for help on using the changeset viewer.