Changeset 1168 for trunk/src/kmk


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

Wrote the eval_include_dep parser.

File:
1 edited

Legend:

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

    r1109 r1168  
    462462
    463463#ifdef CONFIG_WITH_INCLUDEDEP
    464 /* no nonsense dependency file including. */
     464/* no nonsense dependency file including.
     465
     466   Because nobody wants bogus dependency files to break their incremental
     467   builds with hard to comprehend error messages, this function does not
     468   use the normal eval routine but does all the parsing itself. This isn't,
     469   as much work as it sounds, because the necessary feature set is very
     470   limited. */
    465471void
    466472eval_include_dep (const char *name, struct floc *f)
    467473{
    468474  FILE *fp;
    469   long max_size;
    470   long size;
    471   char *buf;
    472   unsigned int saved_var_len;
    473   char *saved_var_buf;
    474 
    475   /* ignore non-existing dependency files. */
     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. */
    476480  if (!file_exists_p (name))
    477481    return;
    478 
    479   /* open it and determin the size. */
    480482  errno = 0;
    481   fp = fopen (name, "r");
     483  fp = fopen (name, "rb");
    482484  if (!fp)
    483485    {
     
    486488    }
    487489
    488   if (fseek (fp, 0, SEEK_END))
    489     fatal (f, "%s: fseek failed - %s", name, strerror (errno));
    490   max_size = ftell (fp);
    491   if (max_size < 0)
    492     fatal (f, "%s: ftell failed - %s", name, strerror (errno));
    493   if (fseek (fp, 0, SEEK_SET))
    494     fatal (f, "%s: fseek failed - %s", name, strerror (errno));
    495 
    496   /* ignore empty files. */
    497   if (max_size == 0)
    498   {
    499       fclose (fp);
    500       return;
    501   }
    502 
    503   /* allocate a buffer and read the file. \r\n -> \n conversion
    504      make this intersting ... */
    505   buf = xmalloc (max_size + 1);
    506   size = fread (buf, 1, max_size, fp); /* FIXME: EINTR? incomplete reads? */
    507   if (   size == -1
    508       || (ferror (fp) && !feof (fp)))
    509       fatal (f, "%s: fread failed - %s", name, strerror (errno));
    510   if (size < max_size / 2)
    511       fatal (f, "%s: fread failed - %s", name, strerror (errno));
    512   buf[size] = '\0';
    513 
    514   /* evaluate the buffer and cleanup. */
    515   install_variable_buffer (&saved_var_buf, &saved_var_len);
    516   eval_buffer (buf);
    517   restore_variable_buffer (saved_var_buf, saved_var_len);
    518 
    519   free (buf);
     490  /* parse the file line by line... */
     491  while (fgets (line_buf, sizeof (line_buf), fp))
     492    {
     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;
     502
     503      /* define var ... endef for command tracking. */
     504      if (strneq (p, "define ", 7))
     505        {
     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;
     511          const char *var;
     512          unsigned var_len;
     513
     514          /* 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]))
     520            --endp;
     521          var_len = endp - p;
     522          if (!var_len)
     523          {
     524              error (f, "%s(%d): bogus define statement.", name, line_no);
     525              break;
     526          }
     527          var = strcache_add_len (p, var_len);
     528
     529          /* read the define contents. */
     530          while (fgets (line_buf, sizeof (line_buf), fp))
     531            {
     532              size_t len;
     533
     534              line_no++;
     535
     536              /* check for endef */
     537              if (newline)
     538                {
     539                  p = line_buf;
     540                  while (isblank ((unsigned char)*p))
     541                    ++p;
     542                  if (strneq (p, "endef", 5))
     543                    {
     544                      p += 5;
     545                      while (isspace ((unsigned char)*p))
     546                        p++;
     547                      if (*p == '\0')
     548                        {
     549                          found_endef = 1;
     550                          break;
     551                        }
     552                    }
     553                }
     554
     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;
     572            }
     573
     574          if (!found_endef)
     575            {
     576              error (f, "%s(%d): bogus define statement.", name, line_no);
     577              break;
     578            }
     579
     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
     590        }
     591      /* file: deps */
     592      else
     593        {
     594          struct nameseq *filenames = 0;
     595          struct dep *deps = 0;
     596          struct dep **nextdep = &deps;
     597          struct dep *dep;
     598          int next_line = 1;
     599          char *colonp;
     600
     601          /* look for a colon. */
     602          colonp = strchr (p, ':');
     603#ifdef HAVE_DOS_PATHS
     604          while (   colonp
     605                 && (colonp[1] == '/' || colonp[1] == '\\')
     606                 && colonp > p
     607                 && isalpha ((unsigned char)colonp[-1])
     608                 && (   colonp == p + 1
     609                     || strchr (" \t(", colonp[-2]) != 0))
     610              colonp = strchr (colonp + 1, ':');
     611#endif
     612          if (!colonp)
     613            {
     614              error (f, "%s(%d): no colon.", name, line_no);
     615              break;
     616            }
     617
     618          /* extract the filename, ASSUME a single one. */
     619          endp = colonp;
     620          while (endp > p && isblank ((unsigned char)endp[-1]))
     621            --endp;
     622          if (p == endp)
     623            {
     624              error (f, "%s(%d): empty filename.", name, line_no);
     625              break;
     626            }
     627          filenames = xmalloc (sizeof (struct nameseq));
     628          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 (;;)
     634            {
     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'))
     643                {
     644                  if (!fgets (line_buf, sizeof (line_buf), fp))
     645                    break;
     646                  p = line_buf;
     647                  line_no++;
     648                  continue;
     649                }
     650
     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))
     662                {
     663                  size_t len = endp - p;
     664                  if (len > (sizeof (line_buf) / 4) * 3)
     665                    {
     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;
     680                    }
     681                }
     682
     683              /* add it to the list. */
     684              *nextdep = dep = alloc_dep ();
     685              dep->name = strcache_add_len (p, endp - p);
     686              nextdep = &dep->next;
     687
     688              p = endp;
     689            }
     690
     691          /* enter the file with its dependencies. */
     692          record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, NULL);
     693        }
     694    } /* while (fgets) */
     695
    520696  fclose (fp);
    521697}
Note: See TracChangeset for help on using the changeset viewer.