Changeset 1169 for trunk/src/kmk/read.c


Ignore:
Timestamp:
Oct 1, 2007, 5:32:06 AM (18 years ago)
Author:
bird
Message:

reworte it to use a whole file buffer so we can use mmap later...

File:
1 edited

Legend:

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

    r1168 r1169  
    3434# include "kbuild.h"
    3535#endif
    36 
     36#ifdef CONFIG_WITH_INCLUDEDEP
     37# ifdef HAVE_FCNTL_H
     38#  include <fcntl.h>
     39# else
     40#  include <sys/file.h>
     41#endif
     42# ifdef WINDOWS32
     43#  include <io.h>
     44# endif
     45#endif
    3746
    3847#ifndef WINDOWS32
     
    472481eval_include_dep (const char *name, struct floc *f)
    473482{
    474   FILE *fp;
    475   char line_buf[8192];
    476   unsigned line_no = 0;
    477 
    478   /* open it, ignore non-existing dependency files and don't
    479      fail fataly if we cannot open it. */
     483  int fd;
     484  char *file_base;
     485  const char *file_end, *cur, *endp;
     486  struct stat st;
     487  unsigned line_no;
     488
     489  /* open and read it into memory. ignore non-existing dependency files
     490     or that we can't read. */
    480491  if (!file_exists_p (name))
    481492    return;
    482493  errno = 0;
    483   fp = fopen (name, "rb");
    484   if (!fp)
     494#ifdef O_BINARY
     495  fd = open (name, O_RDONLY | O_BINARY, 0);
     496#else
     497  fd = open (name, O_RDONLY, 0);
     498#endif
     499  if (fd < 0)
    485500    {
    486501      error (f, "%s: %s", name, strerror (errno));
    487502      return;
    488503    }
    489 
    490   /* parse the file line by line... */
    491   while (fgets (line_buf, sizeof (line_buf), fp))
     504  if (fstat (fd, &st))
    492505    {
    493       char *p;
    494       char *endp;
    495 
    496       line_no++;
    497       p = line_buf;
    498       while (isspace ((unsigned char)*p))
    499         ++p;
    500       if (*p == '\0' || *p == '#')
    501         continue;
     506      error (f, "%s: fstat: %s", name, strerror (errno));
     507      close (fd);
     508      return;
     509    }
     510  file_base = xmalloc (st.st_size + 1);
     511  if (read (fd, file_base, st.st_size) != st.st_size)
     512    {
     513      error (f, "%s: read: %s", name, strerror (errno));
     514      close (fd);
     515      free (file_base);
     516      return;
     517    }
     518  close (fd);
     519  file_end = file_base + st.st_size;
     520  file_base[st.st_size] = '\0';
     521
     522  /* now parse the file. */
     523  line_no = 1;
     524  cur = file_base;
     525  while (cur < file_end)
     526    {
     527      /* skip empty lines */
     528      while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
     529        ++cur;
     530      if (cur >= file_end)
     531        break;
     532      if (*cur == '#')
     533        {
     534          cur = memchr (cur, '\n', file_end - cur);
     535          if (!cur)
     536            break;
     537        }
     538      if (*cur == '\n')
     539        {
     540          cur++;
     541          line_no++;
     542          continue;
     543        }
    502544
    503545      /* define var ... endef for command tracking. */
    504       if (strneq (p, "define ", 7))
     546      if (strneq (cur, "define ", 7))
    505547        {
    506           size_t value_len = 0;
    507           size_t value_alloc_size = 0;
    508           char *value = 0;
    509           int newline = 1;
    510           int found_endef = 0;
    511548          const char *var;
    512549          unsigned var_len;
     550          const char *value_start;
     551          const char *value_end;
     552          char *value;
     553          unsigned value_len;
     554          int found_endef = 0;
    513555
    514556          /* extract the variable name. */
    515           p += 7;
    516           while (isblank ((unsigned char)*p))
    517             ++p;
    518           endp = strchr(p, '\0');
    519           while (endp > p && isspace ((unsigned char)endp[-1]))
     557          cur += 7;
     558          while (isblank ((unsigned char)*cur))
     559            ++cur;
     560          value_start = endp = memchr (cur, '\n', file_end - cur);
     561          if (!endp)
     562              endp = cur;
     563          while (endp > cur && isspace ((unsigned char)endp[-1]))
    520564            --endp;
    521           var_len = endp - p;
     565          var_len = endp - cur;
    522566          if (!var_len)
    523567          {
     
    525569              break;
    526570          }
    527           var = strcache_add_len (p, var_len);
    528 
    529           /* read the define contents. */
    530           while (fgets (line_buf, sizeof (line_buf), fp))
     571          var = strcache_add_len (cur, var_len);
     572
     573          /* find the end of the variable. */
     574          cur = value_end = value_start = value_start + 1;
     575          ++line_no;
     576          while (cur < file_end)
    531577            {
    532               size_t len;
    533 
    534               line_no++;
    535 
    536               /* check for endef */
    537               if (newline)
     578              /* check for endef, don't bother with skipping leading spaces. */
     579              if (   file_end - cur >= 5
     580                  && strneq (cur, "endef", 5))
    538581                {
    539                   p = line_buf;
    540                   while (isblank ((unsigned char)*p))
    541                     ++p;
    542                   if (strneq (p, "endef", 5))
     582                  endp = cur + 5;
     583                  while (endp < file_end && isspace ((unsigned char)*endp) && *endp != '\n')
     584                    endp++;
     585                  if (endp >= file_end || *endp == '\n')
    543586                    {
    544                       p += 5;
    545                       while (isspace ((unsigned char)*p))
    546                         p++;
    547                       if (*p == '\0')
    548                         {
    549                           found_endef = 1;
    550                           break;
    551                         }
     587                      found_endef = 1;
     588                      cur = endp >= file_end ? file_end : endp + 1;
     589                      break;
    552590                    }
    553591                }
    554592
    555               /* append the line to the buffer. */
    556               len = strlen (line_buf);
    557               if (value_len + len + 1 > value_alloc_size)
    558                 {
    559                   if (value_alloc_size == 0)
    560                       value_alloc_size = (len + 1 + 0x100) & ~(size_t)0xff;
    561                   else
    562                     {
    563                       value_alloc_size *= 2;
    564                       if (value_len + len + 1 > value_alloc_size)
    565                           value_alloc_size = (value_len + len * 2 + 1) & ~(size_t)0xff;
    566                     }
    567                   value = xrealloc (value, value_alloc_size);
    568                 }
    569               memcpy (value + value_len, line_buf, len + 1);
    570               value_len += len;
    571               newline = len ? line_buf[len - 1] == '\n' : 0;
     593              /* skip a line ahead. */
     594              cur = value_end = memchr (cur, '\n', file_end - cur);
     595              if (cur != NULL)
     596                ++cur;
     597              else
     598                cur = value_end = file_end;
     599              ++line_no;
    572600            }
    573601
     
    578606            }
    579607
    580           /* all that's left is to define it. */
    581 #ifdef CONFIG_WITH_VALUE_LENGTH
    582           define_variable_in_set (var, var_len, value, value_len, 0 /* don't duplicate */,
    583                                   o_file, 0 /* not recursive */, NULL /* global set */,
    584                                   NULL /*no floc*/);
    585 #else
    586           define_variable_in_set (var, var_len, value, o_file, 0 /* not recursive */,
    587                                   NULL /* global set */, NULL /*no floc*/);
    588           free (value);
    589 #endif
     608          /* make a copy of the value, converting \r\n to \n, and define it. */
     609          value_len = value_end - value_start;
     610          value = xmalloc (value_len + 1);
     611          endp = memchr (value_start, '\r', value_len);
     612          if (endp)
     613            {
     614              const char *src = value_start;
     615              char *dst = value;
     616              for (;;)
     617                {
     618                  size_t len = endp - src;
     619                  memcpy (dst, src, len);
     620                  dst += len;
     621                  src = endp;
     622                  if (src + 1 < file_end && src[1] == '\n')
     623                      src++; /* skip the '\r' */
     624                  if (src >= value_end)
     625                    break;
     626                  endp = memchr (endp + 1, '\r', src - value_end);
     627                  if (!endp)
     628                    endp = value_end;
     629                }
     630              value_len = dst - value;
     631            }
     632          else
     633            memcpy (value, value_start, value_len);
     634          value [value_len] = '\0';
     635
     636          define_variable_in_set (var, var_len, value, value_len,
     637                                  0 /* don't duplicate */, o_file,
     638                                  0 /* defines are recursive but this is faster */,
     639                                  NULL /* global set */, f);
    590640        }
    591641      /* file: deps */
     
    599649          char *colonp;
    600650
    601           /* look for a colon. */
    602           colonp = strchr (p, ':');
     651          /* look for a colon, ASSUME it's on the same line. */
     652          colonp = memchr (cur, ':', file_end - cur);
    603653#ifdef HAVE_DOS_PATHS
    604654          while (   colonp
    605655                 && (colonp[1] == '/' || colonp[1] == '\\')
    606                  && colonp > p
     656                 && colonp > cur
    607657                 && isalpha ((unsigned char)colonp[-1])
    608                  && (   colonp == p + 1
     658                 && (   colonp == cur + 1
    609659                     || strchr (" \t(", colonp[-2]) != 0))
    610               colonp = strchr (colonp + 1, ':');
    611 #endif
    612           if (!colonp)
     660              colonp = memchr (colonp + 1, ':', file_end - (colonp + 1));
     661#endif
     662          if (!colonp || memchr (cur, '\n', colonp - cur))
    613663            {
    614664              error (f, "%s(%d): no colon.", name, line_no);
     
    618668          /* extract the filename, ASSUME a single one. */
    619669          endp = colonp;
    620           while (endp > p && isblank ((unsigned char)endp[-1]))
     670          while (endp > cur && isblank ((unsigned char)endp[-1]))
    621671            --endp;
    622           if (p == endp)
     672          if (cur == endp)
    623673            {
    624674              error (f, "%s(%d): empty filename.", name, line_no);
     
    627677          filenames = xmalloc (sizeof (struct nameseq));
    628678          memset (filenames, 0, sizeof (*filenames));
    629           filenames->name = strcache_add_len (p, endp - p);
    630 
    631           /* parse any dependencies, taking care with very long lines. */
    632           p = colonp + 1;
    633           for (;;)
     679          filenames->name = strcache_add_len (cur, endp - cur);
     680
     681          /* parse any dependencies. */
     682          cur = colonp + 1;
     683          while (cur < file_end)
    634684            {
    635               while (isblank ((unsigned char)*p))
    636                 ++p;
    637 
    638               /* eol + continuation mark? read the next line.  */
    639               if (*p == '\\'
    640                && (     (p[1] == '\n' && p[2] == '\0')
    641                    ||   (p[1] == '\r' && p[2] == '\n' && p[3] == '\0')
    642                    ||   p[1] == '\0'))
     685              /* skip blanks and count lines. */
     686              while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
     687                ++cur;
     688              if (cur >= file_end)
     689                break;
     690              if (*cur == '\n')
    643691                {
    644                   if (!fgets (line_buf, sizeof (line_buf), fp))
    645                     break;
    646                   p = line_buf;
     692                  cur++;
    647693                  line_no++;
    648                   continue;
     694                  break;
    649695                }
    650696
    651               /* eol? */
    652               if ((p[0] == '\n' && p[1] == '\0')
    653                || p[0] == '\0'
    654                || (p[0] == '\r' && p[1] == '\n' && p[2] == '\0'))
    655                   break;
    656 
    657               /* find the end of the filename */
    658               endp = p;
    659               while (!isspace ((unsigned char) *endp) && *endp != '\0')
    660                 ++endp;
    661               if (*endp == '\0' && !feof (fp))
     697              /* continuation + eol? */
     698              if (*cur == '\\')
    662699                {
    663                   size_t len = endp - p;
    664                   if (len > (sizeof (line_buf) / 4) * 3)
     700                  unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
     701                                   : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
     702                                   : (file_end - cur == 1) ? 1 : 0;
     703                  if (eol_len)
    665704                    {
    666                       error (f, "%s(%d): dependency name too long.", name, line_no);
    667                       break;
    668                     }
    669                   memmove (line_buf, p, len);
    670                   p -= len;
    671                   endp -= len;
    672                   if (!fgets (endp, sizeof (line_buf) - len, fp))
    673                       break;
    674                   while (!isblank ((unsigned char) *endp) && *endp != '\0')
    675                     ++endp;
    676                   if (*endp == '\0' && !feof (fp))
    677                     {
    678                       error (f, "%s(%d): dependency name too long.", name, line_no);
    679                       break;
     705                      cur += eol_len;
     706                      line_no++;
     707                      continue;
    680708                    }
    681709                }
    682710
     711              /* find the end of the filename */
     712              endp = cur;
     713              while (endp < file_end && !isspace ((unsigned char)*endp))
     714                ++endp;
     715
    683716              /* add it to the list. */
    684717              *nextdep = dep = alloc_dep ();
    685               dep->name = strcache_add_len (p, endp - p);
     718              dep->name = strcache_add_len (cur, endp - cur);
    686719              nextdep = &dep->next;
    687720
    688               p = endp;
     721              cur = endp;
    689722            }
    690723
    691724          /* enter the file with its dependencies. */
    692           record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, NULL);
     725          record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, f);
    693726        }
    694     } /* while (fgets) */
    695 
    696   fclose (fp);
     727    }
     728  free (file_base);
    697729}
    698730#endif /* CONFIG_WITH_INCLUDEDEP */
Note: See TracChangeset for help on using the changeset viewer.