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


Ignore:
Timestamp:
Oct 5, 2007, 10:22:50 PM (18 years ago)
Author:
bird
Message:

added variable assignment to the includedep parser.

File:
1 edited

Legend:

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

    r1173 r1181  
    477477   use the normal eval routine but does all the parsing itself. This isn't,
    478478   as much work as it sounds, because the necessary feature set is very
    479    limited. */
     479   limited.
     480
     481   eval_include_dep groks:
     482
     483   define var
     484   endef
     485
     486   var [|:|?|>]= value [\]
     487
     488   [\]
     489   file: [deps] [\]
     490
     491   */
    480492void
    481493eval_include_dep (const char *name, struct floc *f)
     
    556568        }
    557569
    558       /* define var ... endef for command tracking. */
     570      /* define var
     571         ...
     572         endef */
    559573      if (strneq (cur, "define ", 7))
    560574        {
     
    652666                                  NULL /* global set */, f);
    653667        }
    654       /* file: deps */
     668
     669      /* file: deps
     670         OR
     671         variable [:]= value */
    655672      else
    656673        {
    657           struct nameseq *filenames = 0;
    658           struct dep *deps = 0;
    659           struct dep **nextdep = &deps;
    660           struct dep *dep;
    661           int next_line = 1;
    662           char *colonp;
    663 
    664           /* look for a colon, ASSUME it's on the same line. */
     674          const char *colonp;
     675          const char *equalp;
     676
     677          /* Look for a colon and an equal sign, optimize for colon.
     678             Only one file is support and the colon / equal must be on
     679             the same line. */
    665680          colonp = memchr (cur, ':', file_end - cur);
    666681#ifdef HAVE_DOS_PATHS
    667682          while (   colonp
     683                 && colonp + 1 < file_end
    668684                 && (colonp[1] == '/' || colonp[1] == '\\')
    669685                 && colonp > cur
     
    673689              colonp = memchr (colonp + 1, ':', file_end - (colonp + 1));
    674690#endif
    675           if (!colonp || memchr (cur, '\n', colonp - cur))
     691          endp = NULL;
     692          if (   !colonp
     693              ||  (endp = memchr (cur, '\n', colonp - cur)))
    676694            {
    677               error (f, "%s(%d): no colon.", name, line_no);
    678               break;
    679             }
    680 
    681           /* extract the filename, ASSUME a single one. */
    682           endp = colonp;
    683           while (endp > cur && isblank ((unsigned char)endp[-1]))
    684             --endp;
    685           if (cur == endp)
    686             {
    687               error (f, "%s(%d): empty filename.", name, line_no);
    688               break;
    689             }
    690           filenames = xmalloc (sizeof (struct nameseq));
    691           memset (filenames, 0, sizeof (*filenames));
    692           filenames->name = strcache_add_len (cur, endp - cur);
    693 
    694           /* parse any dependencies. */
    695           cur = colonp + 1;
    696           while (cur < file_end)
    697             {
    698               /* skip blanks and count lines. */
    699               while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
    700                 ++cur;
    701               if (cur >= file_end)
    702                 break;
    703               if (*cur == '\n')
     695              colonp = NULL;
     696              equalp = memchr (cur, '=', (endp ? endp : file_end) - cur);
     697              if (   !equalp
     698                  || (!endp && memchr (cur, '\n', equalp - cur)))
    704699                {
    705                   cur++;
    706                   line_no++;
     700                  error (f, "%s(%d): no colon.", name, line_no);
    707701                  break;
    708702                }
    709 
    710               /* continuation + eol? */
    711               if (*cur == '\\')
     703            }
     704          else
     705            equalp = memchr (cur, '=', (colonp + 2 <= file_end
     706                                        ? colonp + 2 : file_end) - cur);
     707          if (equalp)
     708            {
     709              /* An assignment of some sort. */
     710              const char *var;
     711              unsigned var_len;
     712              const char *value_start;
     713              const char *value_end;
     714              char *value;
     715              unsigned value_len;
     716              unsigned multi_line = 0;
     717              enum variable_flavor flavor;
     718
     719              /* figure the flavor first. */
     720              flavor = f_recursive;
     721              if (equalp > cur)
    712722                {
    713                   unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
    714                                    : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
    715                                    : (file_end - cur == 1) ? 1 : 0;
    716                   if (eol_len)
     723                  if (equalp[-1] == ':')
     724                    flavor = f_simple;
     725                  else if (equalp[-1] == '?')
     726                    flavor = f_conditional;
     727                  else if (equalp[-1] == '+')
     728                    flavor = f_append;
     729                  else if (equalp[-1] == '>')
     730                    flavor = f_prepend;
     731                }
     732
     733              /* extract the variable name. */
     734              endp = flavor == f_recursive ? equalp : equalp - 1;
     735              while (endp > cur && isblank ((unsigned char)endp[-1]))
     736                --endp;
     737              var_len = endp - cur;
     738              if (!var_len)
     739                {
     740                  error (f, "%s(%d): empty variable. (includedep)", name, line_no);
     741                  break;
     742                }
     743              if (   memchr (cur, '$', var_len)
     744                  || memchr (cur, ' ', var_len)
     745                  || memchr (cur, '\t', var_len))
     746                {
     747                  error (f, "%s(%d): fancy variable name. (includedep)", name, line_no);
     748                  break;
     749                }
     750              var = strcache_add_len (cur, var_len);
     751
     752              /* find the start of the value. */
     753              cur = equalp + 1;
     754              while (cur < file_end && isblank ((unsigned char)*cur))
     755                cur++;
     756              value_start = cur;
     757
     758              /* find the end of the value / line (this isn't 101% correct). */
     759              value_end = cur;
     760              while (cur < file_end)
     761                {
     762                  endp = value_end = memchr (cur, '\n', file_end - cur);
     763                  if (!value_end)
     764                    value_end = file_end;
     765                  if (value_end - 1 >= cur && value_end[-1] == '\r')
     766                    --value_end;
     767                  if (value_end - 1 < cur || value_end[-1] != '\\')
    717768                    {
    718                       cur += eol_len;
     769                      cur = endp ? endp + 1 : file_end;
     770                      break;
     771                    }
     772                  --value_end;
     773                  if (value_end - 1 >= cur && value_end[-1] == '\\')
     774                    {
     775                      error (f, "%s(%d): fancy escaping! (includedep)", name, line_no);
     776                      cur = NULL;
     777                      break;
     778                    }
     779                  if (!endp)
     780                    {
     781                      cur = file_end;
     782                      break;
     783                    }
     784
     785                  cur = endp + 1;
     786                  ++multi_line;
     787                  ++line_no;
     788                }
     789              if (!cur)
     790                break;
     791              ++line_no;
     792
     793              /* make a copy of the value, converting \r\n to \n, and define it. */
     794              value_len = value_end - value_start;
     795              value = xmalloc (value_len + 1);
     796              if (!multi_line)
     797                  memcpy (value, value_start, value_len);
     798              else
     799                {
     800                  /* unescape it */
     801                  const char *src = value_start;
     802                  char *dst = value;
     803                  while (src < value_end)
     804                    {
     805                      const char *nextp;
     806
     807                      endp = memchr (src, '\n', value_end - src);
     808                      if (!endp)
     809                        nextp = endp = value_end;
     810                      else
     811                        nextp = endp + 1;
     812                      if (endp > src && endp[-1] == '\r')
     813                        --endp;
     814                      if (endp > src && endp[-1] == '\\')
     815                        --endp;
     816
     817                      if (src != value_start)
     818                        *dst++ = '\n';
     819                      memcpy (dst, src, endp - src);
     820                      dst += endp - src;
     821                      src = nextp;
     822                    }
     823                  value_len = dst - value;
     824                }
     825              value [value_len] = '\0';
     826
     827              /* do the definition */
     828              if (flavor == f_recursive
     829               || (   flavor == f_simple
     830                   && !memchr (value, '$', value_len)))
     831                define_variable_in_set (var, var_len, value, value_len,
     832                                        0 /* don't duplicate */, o_file,
     833                                        flavor == f_recursive /* recursive */,
     834                                        NULL /* global set */, f);
     835              else
     836                {
     837                  do_variable_definition (f, var, value, o_file, flavor,
     838                                          0 /* not target var */);
     839                  free (value);
     840                }
     841            }
     842          else
     843            {
     844              /* file: dependencies */
     845
     846              struct nameseq *filenames = 0;
     847              struct dep *deps = 0;
     848              struct dep **nextdep = &deps;
     849              struct dep *dep;
     850              int next_line = 1;
     851
     852              /* extract the filename, ASSUME a single one. */
     853              endp = colonp;
     854              while (endp > cur && isblank ((unsigned char)endp[-1]))
     855                --endp;
     856              if (cur == endp)
     857                {
     858                  error (f, "%s(%d): empty filename.", name, line_no);
     859                  break;
     860                }
     861              if (   memchr (cur, '$', endp - cur)
     862                  || memchr (cur, ' ', endp - cur)
     863                  || memchr (cur, '\t', endp - cur))
     864                {
     865                  error (f, "%s(%d): multiple / fancy file name. (includedep)", name, line_no);
     866                  break;
     867                }
     868              filenames = xmalloc (sizeof (struct nameseq));
     869              memset (filenames, 0, sizeof (*filenames));
     870              filenames->name = strcache_add_len (cur, endp - cur);
     871
     872              /* parse any dependencies. */
     873              cur = colonp + 1;
     874              while (cur < file_end)
     875                {
     876                  /* skip blanks and count lines. */
     877                  while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
     878                    ++cur;
     879                  if (cur >= file_end)
     880                    break;
     881                  if (*cur == '\n')
     882                    {
     883                      cur++;
    719884                      line_no++;
    720                       continue;
     885                      break;
    721886                    }
     887
     888                  /* continuation + eol? */
     889                  if (*cur == '\\')
     890                    {
     891                      unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
     892                                       : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
     893                                       : (file_end - cur == 1) ? 1 : 0;
     894                      if (eol_len)
     895                        {
     896                          cur += eol_len;
     897                          line_no++;
     898                          continue;
     899                        }
     900                    }
     901
     902                  /* find the end of the filename */
     903                  endp = cur;
     904                  while (endp < file_end && !isspace ((unsigned char)*endp))
     905                    ++endp;
     906
     907                  /* add it to the list. */
     908                  *nextdep = dep = alloc_dep ();
     909                  dep->name = strcache_add_len (cur, endp - cur);
     910                  nextdep = &dep->next;
     911
     912                  cur = endp;
    722913                }
    723914
    724               /* find the end of the filename */
    725               endp = cur;
    726               while (endp < file_end && !isspace ((unsigned char)*endp))
    727                 ++endp;
    728 
    729               /* add it to the list. */
    730               *nextdep = dep = alloc_dep ();
    731               dep->name = strcache_add_len (cur, endp - cur);
    732               nextdep = &dep->next;
    733 
    734               cur = endp;
     915              /* enter the file with its dependencies. */
     916              record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, f);
    735917            }
    736 
    737           /* enter the file with its dependencies. */
    738           record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, f);
    739918        }
    740919    }
Note: See TracChangeset for help on using the changeset viewer.