VirtualBox

Changeset 3519 in kBuild


Ignore:
Timestamp:
Dec 18, 2021 1:39:20 PM (3 years ago)
Author:
bird
Message:

kmk: Added functions: qone-unquoted, qtarget, qdeps, qdeps-all, qdeps-newer, qdeps-oo, qfilter and qfilter-out.

Location:
trunk/src/kmk
Files:
2 edited

Legend:

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

    r3491 r3519  
    480480  return !strcmp (percent + 1, str + (strlength - sfxlen));
    481481}
     482
     483#ifdef KMK
     484/* Return 1 if PATTERN matches STR, 0 if not.
     485
     486   PATTERN is the pattern to match against.  PERCENT points to the '%' wildcard
     487   inside PATTERN. SFXLEN is the length of pattern following PERCENT. */
     488
     489static int
     490pattern_matches_ex (const char *pattern, const char *percent,
     491                    unsigned int sfxlen,
     492                    const char *str, unsigned int strlength)
     493{
     494  if (strlength < (percent - pattern) + sfxlen
     495      || !strneq (pattern, str, percent - pattern)
     496      || strcmp (percent + 1, str + (strlength - sfxlen)))
     497    return 0;
     498  return 1;
     499}
     500#endif
    482501
    483502
     
    15561575  char *percent;
    15571576  int length;
     1577#ifdef KMK
     1578  unsigned int sfxlen;
     1579#endif
    15581580};
    15591581
     
    15981620      if (pat->percent == 0)
    15991621        literals++;
     1622#ifdef KMK
     1623      pat->sfxlen = pat->percent ? strlen(pat->percent + 1) : 0;
     1624#endif
    16001625
    16011626      /* find_percent() might shorten the string so LEN is wrong.  */
     
    16491674          if (pp->percent)
    16501675            for (wp = wordhead; wp != 0; wp = wp->next)
     1676#ifdef KMK
     1677              wp->matched |= pattern_matches_ex (pp->str, pp->percent, pp->sfxlen,
     1678                                                 wp->str, wp->length);
     1679#else
    16511680              wp->matched |= pattern_matches (pp->str, pp->percent, wp->str);
     1681#endif
    16521682          else if (hashing)
    16531683            {
     
    37873817}
    37883818#endif /* CONFIG_WITH_STRING_FUNCTIONS */
    3789 
    3790 
    3791 #ifdef CONFIG_WITH_LAZY_DEPS_VARS
    3792 
    3793 /* This is also in file.c (bad).  */
    3794 # if VMS
    3795 #  define FILE_LIST_SEPARATOR ','
    3796 # else
    3797 #  define FILE_LIST_SEPARATOR ' '
    3798 # endif
    3799 
    3800 /* Implements $^ and $+.
    3801 
    3802    The first comes with FUNCNAME 'deps', the second as 'deps-all'.
    3803 
    3804    If no second argument is given, or if it's empty, or if it's zero,
    3805    all dependencies will be returned.  If the second argument is non-zero
    3806    the dependency at that position will be returned.  If the argument is
    3807    negative a fatal error is thrown.  */
    3808 static char *
    3809 func_deps (char *o, char **argv, const char *funcname)
    3810 {
    3811   unsigned int idx = 0;
    3812   struct file *file;
    3813 
    3814   /* Handle the argument if present. */
    3815 
    3816   if (argv[1])
    3817     {
    3818       char *p = argv[1];
    3819       while (ISSPACE (*p))
    3820         p++;
    3821       if (*p != '\0')
    3822         {
    3823           char *n;
    3824           long l = strtol (p, &n, 0);
    3825           while (ISSPACE (*n))
    3826             n++;
    3827           idx = l;
    3828           if (*n != '\0' || l < 0 || (long)idx != l)
    3829             OSS (fatal, NILF, _("%s: invalid index value: `%s'\n"), funcname, p);
    3830         }
    3831     }
    3832 
    3833   /* Find the file and select the list corresponding to FUNCNAME. */
    3834 
    3835   file = lookup_file (argv[0]);
    3836   if (file)
    3837     {
    3838       struct dep *deps;
    3839       struct dep *d;
    3840       if (funcname[4] == '\0')
    3841         {
    3842           deps = file->deps_no_dupes;
    3843           if (!deps && file->deps)
    3844             deps = file->deps = create_uniqute_deps_chain (file->deps);
    3845         }
    3846       else
    3847         deps = file->deps;
    3848 
    3849       if (   file->double_colon
    3850           && (   file->double_colon != file
    3851               || file->last != file))
    3852           OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
    3853                funcname, file->name);
    3854 
    3855       if (idx == 0 /* all */)
    3856         {
    3857           unsigned int total_len = 0;
    3858 
    3859           /* calc the result length. */
    3860 
    3861           for (d = deps; d; d = d->next)
    3862             if (!d->ignore_mtime)
    3863               {
    3864                 const char *c = dep_name (d);
    3865 
    3866 #ifndef NO_ARCHIVES
    3867                 if (ar_name (c))
    3868                   {
    3869                     c = strchr (c, '(') + 1;
    3870                     total_len += strlen (c);
    3871                   }
    3872                 else
    3873 #endif
    3874 #ifdef CONFIG_WITH_STRCACHE2
    3875                 if (!d->need_2nd_expansion)
    3876                   total_len += strcache2_get_len (&file_strcache, c) + 1;
    3877                 else
    3878 #endif
    3879                   total_len += strlen (c) + 1;
    3880               }
    3881 
    3882           if (total_len)
    3883             {
    3884               /* prepare the variable buffer dude wrt to the output size and
    3885                  pass along the strings.  */
    3886 
    3887               o = variable_buffer_output (o + total_len, "", 0) - total_len; /* a hack */
    3888 
    3889               for (d = deps; d; d = d->next)
    3890                 if (!d->ignore_mtime)
    3891                   {
    3892                     unsigned int len;
    3893                     const char *c = dep_name (d);
    3894 
    3895 #ifndef NO_ARCHIVES
    3896                     if (ar_name (c))
    3897                       {
    3898                         c = strchr (c, '(') + 1;
    3899                         len = strlen (c);
    3900                       }
    3901                     else
    3902 #endif
    3903 #ifdef CONFIG_WITH_STRCACHE2
    3904                     if (!d->need_2nd_expansion)
    3905                       len = strcache2_get_len (&file_strcache, c) + 1;
    3906                     else
    3907 #endif
    3908                       len = strlen (c) + 1;
    3909                     o = variable_buffer_output (o, c, len);
    3910                     o[-1] = FILE_LIST_SEPARATOR;
    3911                   }
    3912 
    3913                 --o;        /* nuke the last list separator */
    3914                 *o = '\0';
    3915             }
    3916         }
    3917       else
    3918         {
    3919           /* Dependency given by index.  */
    3920 
    3921           for (d = deps; d; d = d->next)
    3922             if (!d->ignore_mtime)
    3923               {
    3924                 if (--idx == 0) /* 1 based indexing */
    3925                   {
    3926                     unsigned int len;
    3927                     const char *c = dep_name (d);
    3928 
    3929 #ifndef NO_ARCHIVES
    3930                     if (ar_name (c))
    3931                       {
    3932                         c = strchr (c, '(') + 1;
    3933                         len = strlen (c) - 1;
    3934                       }
    3935                     else
    3936 #endif
    3937 #ifdef CONFIG_WITH_STRCACHE2
    3938                     if (!d->need_2nd_expansion)
    3939                       len = strcache2_get_len (&file_strcache, c);
    3940                     else
    3941 #endif
    3942                       len = strlen (c);
    3943                     o = variable_buffer_output (o, c, len);
    3944                     break;
    3945                   }
    3946               }
    3947         }
    3948     }
    3949 
    3950   return o;
    3951 }
    3952 
    3953 /* Implements $?.
    3954 
    3955    If no second argument is given, or if it's empty, or if it's zero,
    3956    all dependencies will be returned.  If the second argument is non-zero
    3957    the dependency at that position will be returned.  If the argument is
    3958    negative a fatal error is thrown.  */
    3959 static char *
    3960 func_deps_newer (char *o, char **argv, const char *funcname)
    3961 {
    3962   unsigned int idx = 0;
    3963   struct file *file;
    3964 
    3965   /* Handle the argument if present. */
    3966 
    3967   if (argv[1])
    3968     {
    3969       char *p = argv[1];
    3970       while (ISSPACE (*p))
    3971         p++;
    3972       if (*p != '\0')
    3973         {
    3974           char *n;
    3975           long l = strtol (p, &n, 0);
    3976           while (ISSPACE (*n))
    3977             n++;
    3978           idx = l;
    3979           if (*n != '\0' || l < 0 || (long)idx != l)
    3980             OSS (fatal, NILF, _("%s: invalid index value: `%s'\n"), funcname, p);
    3981         }
    3982     }
    3983 
    3984   /* Find the file. */
    3985 
    3986   file = lookup_file (argv[0]);
    3987   if (file)
    3988     {
    3989       struct dep *deps = file->deps;
    3990       struct dep *d;
    3991 
    3992       if (   file->double_colon
    3993           && (   file->double_colon != file
    3994               || file->last != file))
    3995           OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
    3996                funcname, file->name);
    3997 
    3998       if (idx == 0 /* all */)
    3999         {
    4000           unsigned int total_len = 0;
    4001 
    4002           /* calc the result length. */
    4003 
    4004           for (d = deps; d; d = d->next)
    4005             if (!d->ignore_mtime && d->changed)
    4006               {
    4007                 const char *c = dep_name (d);
    4008 
    4009 #ifndef NO_ARCHIVES
    4010                 if (ar_name (c))
    4011                   {
    4012                     c = strchr (c, '(') + 1;
    4013                     total_len += strlen (c);
    4014                   }
    4015                 else
    4016 #endif
    4017 #ifdef CONFIG_WITH_STRCACHE2
    4018                 if (!d->need_2nd_expansion)
    4019                   total_len += strcache2_get_len (&file_strcache, c) + 1;
    4020                 else
    4021 #endif
    4022                   total_len += strlen (c) + 1;
    4023               }
    4024 
    4025           if (total_len)
    4026             {
    4027               /* prepare the variable buffer dude wrt to the output size and
    4028                  pass along the strings.  */
    4029 
    4030               o = variable_buffer_output (o + total_len, "", 0) - total_len; /* a hack */
    4031 
    4032               for (d = deps; d; d = d->next)
    4033                 if (!d->ignore_mtime && d->changed)
    4034                   {
    4035                     unsigned int len;
    4036                     const char *c = dep_name (d);
    4037 
    4038 #ifndef NO_ARCHIVES
    4039                     if (ar_name (c))
    4040                       {
    4041                         c = strchr (c, '(') + 1;
    4042                         len = strlen (c);
    4043                       }
    4044                     else
    4045 #endif
    4046 #ifdef CONFIG_WITH_STRCACHE2
    4047                     if (!d->need_2nd_expansion)
    4048                       len = strcache2_get_len (&file_strcache, c) + 1;
    4049                     else
    4050 #endif
    4051                       len = strlen (c) + 1;
    4052                     o = variable_buffer_output (o, c, len);
    4053                     o[-1] = FILE_LIST_SEPARATOR;
    4054                   }
    4055 
    4056                 --o;        /* nuke the last list separator */
    4057                 *o = '\0';
    4058             }
    4059         }
    4060       else
    4061         {
    4062           /* Dependency given by index.  */
    4063 
    4064           for (d = deps; d; d = d->next)
    4065             if (!d->ignore_mtime && d->changed)
    4066               {
    4067                 if (--idx == 0) /* 1 based indexing */
    4068                   {
    4069                     unsigned int len;
    4070                     const char *c = dep_name (d);
    4071 
    4072 #ifndef NO_ARCHIVES
    4073                     if (ar_name (c))
    4074                       {
    4075                         c = strchr (c, '(') + 1;
    4076                         len = strlen (c) - 1;
    4077                       }
    4078                     else
    4079 #endif
    4080 #ifdef CONFIG_WITH_STRCACHE2
    4081                     if (!d->need_2nd_expansion)
    4082                       len = strcache2_get_len (&file_strcache, c);
    4083                     else
    4084 #endif
    4085                       len = strlen (c);
    4086                     o = variable_buffer_output (o, c, len);
    4087                     break;
    4088                   }
    4089               }
    4090         }
    4091     }
    4092 
    4093   return o;
    4094 }
    4095 
    4096 /* Implements $|, the order only dependency list.
    4097 
    4098    If no second argument is given, or if it's empty, or if it's zero,
    4099    all dependencies will be returned.  If the second argument is non-zero
    4100    the dependency at that position will be returned.  If the argument is
    4101    negative a fatal error is thrown.  */
    4102 static char *
    4103 func_deps_order_only (char *o, char **argv, const char *funcname)
    4104 {
    4105   unsigned int idx = 0;
    4106   struct file *file;
    4107 
    4108   /* Handle the argument if present. */
    4109 
    4110   if (argv[1])
    4111     {
    4112       char *p = argv[1];
    4113       while (ISSPACE (*p))
    4114         p++;
    4115       if (*p != '\0')
    4116         {
    4117           char *n;
    4118           long l = strtol (p, &n, 0);
    4119           while (ISSPACE (*n))
    4120             n++;
    4121           idx = l;
    4122           if (*n != '\0' || l < 0 || (long)idx != l)
    4123             OSS (fatal, NILF, _("%s: invalid index value: `%s'\n"), funcname, p);
    4124         }
    4125     }
    4126 
    4127   /* Find the file. */
    4128 
    4129   file = lookup_file (argv[0]);
    4130   if (file)
    4131     {
    4132       struct dep *deps = file->deps;
    4133       struct dep *d;
    4134 
    4135       if (   file->double_colon
    4136           && (   file->double_colon != file
    4137               || file->last != file))
    4138           OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
    4139                funcname, file->name);
    4140 
    4141       if (idx == 0 /* all */)
    4142         {
    4143           unsigned int total_len = 0;
    4144 
    4145           /* calc the result length. */
    4146 
    4147           for (d = deps; d; d = d->next)
    4148             if (d->ignore_mtime)
    4149               {
    4150                 const char *c = dep_name (d);
    4151 
    4152 #ifndef NO_ARCHIVES
    4153                 if (ar_name (c))
    4154                   {
    4155                     c = strchr (c, '(') + 1;
    4156                     total_len += strlen (c);
    4157                   }
    4158                 else
    4159 #endif
    4160 #ifdef CONFIG_WITH_STRCACHE2
    4161                 if (!d->need_2nd_expansion)
    4162                   total_len += strcache2_get_len (&file_strcache, c) + 1;
    4163                 else
    4164 #endif
    4165                   total_len += strlen (c) + 1;
    4166               }
    4167 
    4168           if (total_len)
    4169             {
    4170               /* prepare the variable buffer dude wrt to the output size and
    4171                  pass along the strings.  */
    4172 
    4173               o = variable_buffer_output (o + total_len, "", 0) - total_len; /* a hack */
    4174 
    4175               for (d = deps; d; d = d->next)
    4176                 if (d->ignore_mtime)
    4177                   {
    4178                     unsigned int len;
    4179                     const char *c = dep_name (d);
    4180 
    4181 #ifndef NO_ARCHIVES
    4182                     if (ar_name (c))
    4183                       {
    4184                         c = strchr (c, '(') + 1;
    4185                         len = strlen (c);
    4186                       }
    4187                     else
    4188 #endif
    4189 #ifdef CONFIG_WITH_STRCACHE2
    4190                     if (!d->need_2nd_expansion)
    4191                       len = strcache2_get_len (&file_strcache, c) + 1;
    4192                     else
    4193 #endif
    4194                       len = strlen (c) + 1;
    4195                     o = variable_buffer_output (o, c, len);
    4196                     o[-1] = FILE_LIST_SEPARATOR;
    4197                   }
    4198 
    4199                 --o;        /* nuke the last list separator */
    4200                 *o = '\0';
    4201             }
    4202         }
    4203       else
    4204         {
    4205           /* Dependency given by index.  */
    4206 
    4207           for (d = deps; d; d = d->next)
    4208             if (d->ignore_mtime)
    4209               {
    4210                 if (--idx == 0) /* 1 based indexing */
    4211                   {
    4212                     unsigned int len;
    4213                     const char *c = dep_name (d);
    4214 
    4215 #ifndef NO_ARCHIVES
    4216                     if (ar_name (c))
    4217                       {
    4218                         c = strchr (c, '(') + 1;
    4219                         len = strlen (c) - 1;
    4220                       }
    4221                     else
    4222 #endif
    4223 #ifdef CONFIG_WITH_STRCACHE2
    4224                     if (!d->need_2nd_expansion)
    4225                       len = strcache2_get_len (&file_strcache, c);
    4226                     else
    4227 #endif
    4228                       len = strlen (c);
    4229                     o = variable_buffer_output (o, c, len);
    4230                     break;
    4231                   }
    4232               }
    4233         }
    4234     }
    4235 
    4236   return o;
    4237 }
    4238 #endif /* CONFIG_WITH_LAZY_DEPS_VARS */
    4239 
    42403819
    42413820
     
    61605739#define Q_RET_SHELL_IN_SQ       0x0008
    61615740
    6162 #define Q_IN_MASK               0x0030
     5741#define Q_IN_MASK               0x0070
    61635742#define Q_IN_QUOTED             0x0000
    61645743#define Q_IN_UNQUOTED           0x0010
    61655744#define Q_IN_QUOTED_DEP         0x0020  /** @todo needed? */
    61665745#define Q_IN_QUOTED_TGT         0x0030  /** @todo needed? */
    6167 #define Q_IN_SEP_COMMA          0x0040  /* for VMS hacks, file lists only */
     5746#define Q_IN_UNQUOTED_SINGLE    0x0040
     5747#define Q_IN_SEP_COMMA          0x0080  /* for VMS hacks, file lists only */
    61685748
    61695749#define Q_SEP_MASK              0x0700
     
    61955775        {
    61965776          /* Skip blanks: */
    6197           while (ISBLANK(*style))
     5777          while (ISBLANK (*style))
    61985778            style++;
    61995779          if (*style != '\0')
     
    62035783              size_t len;
    62045784              char ch;
    6205               while (!ISBLANK((ch = *style)) && ch != '\0')
     5785              while (!ISBLANK ((ch = *style)) && ch != '\0')
    62065786                style++;
    62075787              len = style - start;
     
    62265806                intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL;
    62275807              else if (MATCH ("shell-in-dq")    || MATCH ("sh-i-d"))
    6228                 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL_IN_DQ;
     5808                intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL_IN_DQ; /* returned string is used inside double shell quotes */
    62295809              else if (MATCH ("shell-in-sq")    || MATCH ("sh-i-s"))
    6230                 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL_IN_SQ;
     5810                intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL_IN_SQ; /* returned string is used inside single shell quotes */
    62315811              /* input styles: */
    62325812              else if (MATCH ("in-quoted")         || MATCH ("i-q"))
     
    62345814              else if (MATCH ("in-unquoted")       || MATCH ("i-unq")   || MATCH ("i-u"))
    62355815                intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_UNQUOTED;
     5816              else if (MATCH ("in-unquoted-single")|| MATCH ("i-unq-s") || MATCH ("i-u-s")
     5817                    || MATCH ("in-unquoted-file")  || MATCH ("i-unq-f") || MATCH ("i-u-f"))
     5818                intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_UNQUOTED_SINGLE;
    62365819              else if (MATCH ("in-quoted-dep")     || MATCH ("i-q-dep") || MATCH ("i-q-d"))
    62375820                intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_QUOTED_DEP;
     
    62395822                intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_QUOTED_TGT;
    62405823              else if (MATCH ("in-sep-comma")      || MATCH ("i-s-com") || MATCH ("i-s-c"))
    6241                 intstyle = (intstyle & ~Q_SEP_MASK) | Q_IN_SEP_COMMA;
     5824                intstyle |= Q_IN_SEP_COMMA; /*?*/
    62425825              /* separator styles (output): */
    62435826              else if (MATCH ("sep-space")  || MATCH ("s-space")  || MATCH ("s-s"))
     
    62555838                  char savedch = *style;
    62565839                  *style = '\0';
    6257                   OS (error, reading_file, "Unknown file return style: %s", start);
     5840                  OS (error, reading_file, "Unknown file style: %s", start);
    62585841                  *style = savedch;
    62595842                }
     
    62925875                                seps[(style & Q_SEP_MASK) >> Q_SEP_SHIFT].len);
    62935876}
     5877
     5878/* Removes one separator from the output.
     5879
     5880This is typically used when outputting lists where there is no simple way of
     5881telling whether an entry is the last one or not.  So, is_last is always false
     5882and the last separator is removed afterwards by this function. */
     5883
     5884MY_INLINE char *helper_drop_separator (char *o, unsigned int style)
     5885{
     5886  o -= (style & Q_SEP_MASK) != Q_SEP_NL_TAB ? 2 : 1;
     5887  *o = '\0'; /* not strictly necessary */
     5888  return o;
     5889}
     5890
    62945891
    62955892/* Outputs (returns) the given file. */
     
    63455942/* Outputs (returns) the given file. */
    63465943
    6347 static char *helper_return_file (char *o, const char *file, unsigned int style, int is_last)
     5944static char *helper_return_file (char *o, const char *file,
     5945                                 unsigned int style, int is_last)
    63485946{
    63495947  return helper_return_file_len (o,file, strlen (file), style, is_last);
     
    64296027/* Parses a file/word list according to STYLE and returns a name list.
    64306028
    6431    Note! The FILELIST parameter may be modified.
     6029   The FILELIST parameter may be modified!
     6030
     6031   The GLOB param is for wildcard/qwildcard.
    64326032
    64336033   TODO/XXX: Unquote and split up the FILELIST directly.  All function
     
    64766076
    64776077          case Q_IN_UNQUOTED:
    6478            {
    6479              struct nameseq *chain = NULL;
    6480              struct nameseq **ppnext = &chain;
    6481              const char *it = filelist;
    6482              const char *cur;
    6483              unsigned int curlen;
    6484              while ((cur = find_next_token (&it, &curlen)) != NULL)
    6485                {
     6078            {
     6079              struct nameseq *chain = NULL;
     6080              struct nameseq **ppnext = &chain;
     6081              const char *it = filelist;
     6082              const char *cur;
     6083              unsigned int curlen;
     6084              while ((cur = find_next_token (&it, &curlen)) != NULL)
     6085                {
    64866086#ifndef CONFIG_WITH_ALLOC_CACHES
    64876087                  struct nameseq *newp = xcalloc (sizeof (*newp));
     
    64936093                  *ppnext = newp;
    64946094                  ppnext = &newp->next;
    6495                }
    6496              if (!glob)
    6497                return chain;
    6498              return helper_glob_chain (chain);
    6499            }
     6095                }
     6096              if (!glob)
     6097                return chain;
     6098              return helper_glob_chain (chain);
     6099            }
     6100
     6101          case Q_IN_UNQUOTED_SINGLE:
     6102            if (*filelist != '\0')
     6103              {
     6104#ifndef CONFIG_WITH_ALLOC_CACHES
     6105                struct nameseq *newp = xcalloc (sizeof (*newp));
     6106#else
     6107                struct nameseq *newp = alloccache_calloc (&nameseq_cache);
     6108#endif
     6109                newp->name = xstrdup (filelist);
     6110                newp->next = NULL;
     6111                if (!glob)
     6112                  return newp;
     6113                return helper_glob_chain (newp);
     6114              }
     6115            return NULL;
    65006116
    65016117          default:
     
    73836999}
    73847000
     7001static char *
     7002worker_filter_filterout (char *o, char **argv, unsigned style, int is_filter)
     7003{
     7004  struct nameseq *wordchain;
     7005  struct a_word *wordhead;
     7006  struct a_word **wordtail;
     7007  struct a_word *wp;
     7008  struct nameseq *patchain;
     7009  struct a_pattern *pathead;
     7010  struct a_pattern **pattail;
     7011  struct a_pattern *pp;
     7012  struct nameseq *cur;
     7013  struct hash_table a_word_table;
     7014  int literals;
     7015  int words;
     7016  int hashing;
     7017  unsigned int words_len; /* for output estimation */
     7018
     7019  /* Chop ARGV[0] up into patterns to match against the words. */
     7020  /** @todo this very inefficient as we convert between two list format and
     7021   *        duplicates the patterns on the heap.  We could just modify argv[0]
     7022   *        directly. */
     7023  patchain = helper_parse_file_list (argv[0], style, 0 /*glob*/);
     7024  pattail = &pathead;
     7025  for (cur = patchain, literals = 0; cur; cur = cur->next)
     7026    {
     7027      struct a_pattern *pat = alloca (sizeof (struct a_pattern));
     7028
     7029      *pattail = pat;
     7030      pattail = &pat->next;
     7031
     7032      pat->str = (char *)cur->name; /* (safe - PARSEFS_NOCACHE) */
     7033      pat->percent = find_percent (pat->str); /* may modify name */
     7034      if (pat->percent == 0)
     7035        literals++;
     7036      pat->sfxlen = pat->percent ? strlen(pat->percent + 1) : 0;
     7037      pat->length = strlen (pat->str);
     7038    }
     7039  *pattail = NULL;
     7040
     7041  /* Chop ARGV[1] up into words to match against the patterns.  */
     7042  /** @todo this very inefficient as we convert between two list format and
     7043   *        duplicates the words on the heap.  We could just modify argv[1]
     7044   *        directly. */
     7045  wordchain = helper_parse_file_list (argv[1], style, 0 /*glob*/);
     7046  wordtail = &wordhead;
     7047  for (cur = wordchain, words = 0, words_len = 0; cur; cur = cur->next)
     7048    {
     7049      struct a_word *word = alloca (sizeof (struct a_word));
     7050
     7051      *wordtail = word;
     7052      wordtail = &word->next;
     7053
     7054      word->str = (char *)cur->name; /* (safe - PARSEFS_NOCACHE) */
     7055      word->length = strlen (cur->name);
     7056      words_len += word->length + 1;
     7057      word->matched = 0;
     7058      word->chain = NULL;
     7059      words++;
     7060    }
     7061  *wordtail = NULL;
     7062
     7063  /* Only use a hash table if arg list lengths justifies the cost.  */
     7064  hashing = (literals >= 2 && (literals * words) >= 10);
     7065  if (hashing)
     7066    {
     7067      hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2,
     7068                 a_word_hash_cmp);
     7069      for (wp = wordhead; wp != 0; wp = wp->next)
     7070        {
     7071          struct a_word *owp = hash_insert (&a_word_table, wp);
     7072          if (owp)
     7073            wp->chain = owp;
     7074        }
     7075    }
     7076
     7077  if (words)
     7078    {
     7079      int doneany = 0;
     7080
     7081      if (is_filter)
     7082        words_len = 0;
     7083
     7084      /* Run each pattern through the words, killing words.  */
     7085      for (pp = pathead; pp != 0; pp = pp->next)
     7086        {
     7087          if (pp->percent)
     7088            for (wp = wordhead; wp != 0; wp = wp->next)
     7089              if (!wp->matched
     7090                  && pattern_matches_ex (pp->str, pp->percent, pp->sfxlen,
     7091                                         wp->str, wp->length))
     7092                {
     7093                  wp->matched = 1;
     7094                  if (is_filter)
     7095                    words_len += wp->length + 1;
     7096                  else
     7097                    words_len -= wp->length + 1;
     7098                }
     7099          else if (hashing)
     7100            {
     7101              struct a_word a_word_key;
     7102              a_word_key.str = pp->str;
     7103              a_word_key.length = pp->length;
     7104              wp = hash_find_item (&a_word_table, &a_word_key);
     7105              while (wp)
     7106                {
     7107                  if (!wp->matched)
     7108                    {
     7109                      wp->matched = 1;
     7110                      if (is_filter)
     7111                        words_len += wp->length + 1;
     7112                      else
     7113                        words_len -= wp->length + 1;
     7114                    }
     7115                  wp = wp->chain;
     7116                }
     7117            }
     7118          else
     7119            for (wp = wordhead; wp != 0; wp = wp->next)
     7120              if (!wp->matched
     7121                  && wp->length == pp->length
     7122                  && strneq (pp->str, wp->str, wp->length))
     7123                {
     7124                  wp->matched = 1;
     7125                  if (is_filter)
     7126                    words_len += wp->length + 1;
     7127                  else
     7128                    words_len -= wp->length + 1;
     7129                }
     7130        }
     7131
     7132      /* Output the words that matched (or didn't, for filter-out).  */
     7133      o = ensure_variable_buffer_space (o, words_len);
     7134
     7135      for (wp = wordhead; wp != 0; wp = wp->next)
     7136        if (wp->matched == is_filter)
     7137          {
     7138            o = helper_return_file_len (o, wp->str, wp->length,
     7139                                        style, 0 /*is_last*/);
     7140            doneany = 1;
     7141          }
     7142
     7143      /* Kill the last separator. */
     7144      if (doneany)
     7145        o = helper_drop_separator (o, style);
     7146    }
     7147
     7148  /* Clean up. */
     7149  if (hashing)
     7150    hash_free (&a_word_table, 0);
     7151  free_ns_chain_no_strcache (wordchain);
     7152  free_ns_chain_no_strcache (patchain);
     7153
     7154  return o;
     7155}
     7156
     7157/* Implements $(qfilter ) and $(qfilter-out ). */
     7158static char *
     7159func_q_filter_filterout (char *o, char **argv, const char *funcname)
     7160{
     7161  unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
     7162  return worker_filter_filterout (o, &argv[1], style, funcname[7] == '\0');
     7163}
     7164
    73857165#endif /* KMK */
    73867166
     7167
     7168#ifdef CONFIG_WITH_LAZY_DEPS_VARS
     7169
     7170/* Helper that parses the index argument for the $(deps* ) and $(qdeps* )
     7171   functions. */
     7172static unsigned int parse_dep_index (const char *index, const char *funcname)
     7173{
     7174  unsigned int idx = 0;
     7175  if (index)
     7176    {
     7177      while (ISSPACE (*index))
     7178        index++;
     7179      if (*index != '\0')
     7180        {
     7181          char *next = (char *)index;
     7182          long l = strtol (index, &next, 0);
     7183          while (ISSPACE (*next))
     7184            next++;
     7185          idx = (unsigned int)l;
     7186          if (*next != '\0' || l < 0 || (long)idx != l)
     7187            OSS (fatal, NILF, _("%s: invalid index value: `%s'\n"), funcname, index);
     7188        }
     7189    }
     7190  return idx;
     7191}
     7192
     7193/* Helper that calculates the output length for a dependency */
     7194
     7195MY_INLINE unsigned int helper_dep_output_len (struct dep *d)
     7196{
     7197  const char *c = dep_name (d);
     7198#ifndef NO_ARCHIVES
     7199  if (ar_name (c))
     7200    return strlen (strchr (c, '(') + 1);
     7201#endif
     7202#ifdef CONFIG_WITH_STRCACHE2
     7203  if (!d->need_2nd_expansion)
     7204    return strcache2_get_len (&file_strcache, c) + 1;
     7205#endif
     7206  return strlen (c) + 1;
     7207}
     7208
     7209/* Helper that outputs a depndency. */
     7210
     7211MY_INLINE char *helper_dep_output_one (char *o, struct dep *d,
     7212                                       unsigned int style, int is_last)
     7213{
     7214  const char *c = dep_name (d);
     7215#ifndef NO_ARCHIVES
     7216  if (ar_name (c))
     7217    {
     7218      c = strchr(c, '(') + 1;
     7219      o = helper_return_file_len (o, c, strlen(c) - 1, style, is_last);
     7220    }
     7221  else
     7222#endif
     7223#ifdef CONFIG_WITH_STRCACHE2
     7224  if (!d->need_2nd_expansion)
     7225    {
     7226      unsigned int len = strcache2_get_len (&file_strcache, c);
     7227      o = helper_return_file_len (o, c, len, style, is_last);
     7228    }
     7229  else
     7230#endif
     7231    o = helper_return_file (o, c, style, is_last);
     7232  return o;
     7233}
     7234
     7235/* Implements $^/$(deps )/$(qdeps ) and $+/$(deps-all )/$(qdeps-all ).
     7236
     7237   If no second argument is given, or if it's empty, or if it's zero,
     7238   all dependencies will be returned.  If the second argument is non-zero
     7239   the dependency at that position will be returned.  If the argument is
     7240   negative a fatal error is thrown.  */
     7241static char *
     7242worker_deps (char *o, char **argv, const char *funcname, unsigned int style,
     7243             int all_deps)
     7244{
     7245  unsigned int idx = parse_dep_index (argv[1], funcname);
     7246  struct file *file;
     7247
     7248  /* Find the file and select the list corresponding to FUNCNAME. */
     7249
     7250  file = lookup_file (argv[0]);
     7251  if (file)
     7252    {
     7253      struct dep *deps;
     7254      struct dep *d;
     7255      if (!all_deps)
     7256        {
     7257          deps = file->deps_no_dupes;
     7258          if (!deps && file->deps)
     7259            deps = file->deps_no_dupes = create_uniqute_deps_chain (file->deps);
     7260        }
     7261      else
     7262        deps = file->deps;
     7263
     7264      if (   file->double_colon
     7265          && (   file->double_colon != file
     7266              || file->last != file))
     7267          OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
     7268               funcname, file->name);
     7269
     7270      if (idx == 0 /* all */)
     7271        {
     7272          /* Since this may be a long list, calculate the output space needed if
     7273             no quoting takes place and no multichar separators are used. */
     7274
     7275          unsigned int total_len = 0;
     7276          for (d = deps; d; d = d->next)
     7277            if (!d->ignore_mtime)
     7278              total_len += helper_dep_output_len (d);
     7279          if (total_len > 0)
     7280            {
     7281              o = ensure_variable_buffer_space (o, total_len);
     7282
     7283              for (d = deps; d; d = d->next)
     7284                if (!d->ignore_mtime)
     7285                  o = helper_dep_output_one (o, d, style, 0 /*is_last*/);
     7286
     7287              /* nuke the last list separator */
     7288              o = helper_drop_separator (o, style);
     7289            }
     7290        }
     7291      else
     7292        {
     7293          /* Dependency given by index.  */
     7294
     7295          for (d = deps; d; d = d->next)
     7296            if (!d->ignore_mtime)
     7297              if (--idx == 0) /* 1 based indexing */
     7298                return helper_dep_output_one (o, d, style, 1 /*is_last*/);
     7299        }
     7300    }
     7301
     7302  return o;
     7303}
     7304
     7305/* Implements $? / $(deps-newer ) / $(qdeps-newer ).
     7306
     7307   If no second argument is given, or if it's empty, or if it's zero,
     7308   all dependencies will be returned.  If the second argument is non-zero
     7309   the dependency at that position will be returned.  If the argument is
     7310   negative a fatal error is thrown.  */
     7311static char *
     7312worker_deps_newer (char *o, char **argv, const char *funcname, unsigned int style)
     7313{
     7314  unsigned int idx = parse_dep_index (argv[1], funcname);
     7315  struct file *file;
     7316
     7317  /* Find the file. */
     7318
     7319  file = lookup_file (argv[0]);
     7320  if (file)
     7321    {
     7322      struct dep *deps = file->deps;
     7323      struct dep *d;
     7324
     7325      if (   file->double_colon
     7326          && (   file->double_colon != file
     7327              || file->last != file))
     7328          OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
     7329               funcname, file->name);
     7330
     7331      if (idx == 0 /* all */)
     7332        {
     7333          unsigned int total_len = 0;
     7334
     7335          /* calc the result length. */
     7336
     7337          for (d = deps; d; d = d->next)
     7338            if (!d->ignore_mtime && d->changed)
     7339              total_len += helper_dep_output_len (d);
     7340          if (total_len)
     7341            {
     7342              o = ensure_variable_buffer_space (o, total_len);
     7343
     7344              for (d = deps; d; d = d->next)
     7345                if (!d->ignore_mtime && d->changed)
     7346                  o = helper_dep_output_one (o, d, style, 0 /*is_last*/);
     7347
     7348              /* nuke the last list separator */
     7349              o = helper_drop_separator (o, style);
     7350            }
     7351        }
     7352      else
     7353        {
     7354          /* Dependency given by index.  */
     7355
     7356          for (d = deps; d; d = d->next)
     7357            if (!d->ignore_mtime && d->changed)
     7358              if (--idx == 0) /* 1 based indexing */
     7359                return helper_dep_output_one (o, d, style, 1 /*is_last*/);
     7360        }
     7361    }
     7362
     7363  return o;
     7364}
     7365
     7366/* Implements $|, the order only dependency list.
     7367
     7368   If no second argument is given, or if it's empty, or if it's zero,
     7369   all dependencies will be returned.  If the second argument is non-zero
     7370   the dependency at that position will be returned.  If the argument is
     7371   negative a fatal error is thrown.  */
     7372static char *
     7373worker_deps_order_only (char *o, char **argv, const char *funcname, unsigned int style)
     7374{
     7375  unsigned int idx = parse_dep_index (argv[1], funcname);
     7376  struct file *file;
     7377
     7378  /* Find the file. */
     7379
     7380  file = lookup_file (argv[0]);
     7381  if (file)
     7382    {
     7383      struct dep *deps = file->deps;
     7384      struct dep *d;
     7385
     7386      if (   file->double_colon
     7387          && (   file->double_colon != file
     7388              || file->last != file))
     7389          OSS (error, NILF, _("$(%s ) cannot be used on files with multiple double colon rules like `%s'\n"),
     7390               funcname, file->name);
     7391
     7392      if (idx == 0 /* all */)
     7393        {
     7394          unsigned int total_len = 0;
     7395
     7396          /* calc the result length. */
     7397
     7398          for (d = deps; d; d = d->next)
     7399            if (d->ignore_mtime)
     7400              total_len += helper_dep_output_len (d);
     7401          if (total_len)
     7402            {
     7403              o = ensure_variable_buffer_space (o, total_len);
     7404
     7405              for (d = deps; d; d = d->next)
     7406                if (d->ignore_mtime)
     7407                  o = helper_dep_output_one (o, d, style, 0 /*is_last*/);
     7408
     7409              /* nuke the last list separator */
     7410              o = helper_drop_separator (o, style);
     7411            }
     7412        }
     7413      else
     7414        {
     7415          /* Dependency given by index.  */
     7416
     7417          for (d = deps; d; d = d->next)
     7418            if (d->ignore_mtime)
     7419              if (--idx == 0) /* 1 based indexing */
     7420                return helper_dep_output_one (o, d, style, 1 /*is_last*/);
     7421        }
     7422    }
     7423
     7424  return o;
     7425}
     7426
     7427/* Implements $^ and $+.
     7428
     7429   The first comes with FUNCNAME 'deps', the second as 'deps-all'.
     7430
     7431   If no second argument is given, or if it's empty, or if it's zero,
     7432   all dependencies will be returned.  If the second argument is non-zero
     7433   the dependency at that position will be returned.  If the argument is
     7434   negative a fatal error is thrown.  */
     7435static char *
     7436func_deps (char *o, char **argv, const char *funcname)
     7437{
     7438# ifdef VMS
     7439  return worker_deps (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_COMMA,
     7440# else
     7441  return worker_deps (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_SPACE,
     7442# endif
     7443                      funcname[4] != '\0');
     7444}
     7445
     7446/* Implements $?.
     7447
     7448   If no second argument is given, or if it's empty, or if it's zero,
     7449   all dependencies will be returned.  If the second argument is non-zero
     7450   the dependency at that position will be returned.  If the argument is
     7451   negative a fatal error is thrown.  */
     7452static char *
     7453func_deps_newer (char *o, char **argv, const char *funcname)
     7454{
     7455# ifdef VMS
     7456  return worker_deps_newer (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_COMMA);
     7457# else
     7458  return worker_deps_newer (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_SPACE);
     7459# endif
     7460}
     7461
     7462/* Implements $|, the order only dependency list.
     7463
     7464   If no second argument is given, or if it's empty, or if it's zero,
     7465   all dependencies will be returned.  If the second argument is non-zero
     7466   the dependency at that position will be returned.  If the argument is
     7467   negative a fatal error is thrown.  */
     7468static char *
     7469func_deps_order_only (char *o, char **argv, const char *funcname)
     7470{
     7471# ifdef VMS
     7472  return worker_deps_order_only (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_COMMA);
     7473# else
     7474  return worker_deps_order_only (o, argv, funcname, Q_RET_UNQUOTED | Q_SEP_SPACE);
     7475# endif
     7476}
     7477
     7478#endif /* CONFIG_WITH_LAZY_DEPS_VARS */
     7479#ifdef KMK
     7480
     7481/* Implements $(qdeps ) and $(qdeps-all )
     7482
     7483   If no third argument is given, or if it's empty, or if it's zero,
     7484   all dependencies will be returned.  If the third argument is non-zero
     7485   the dependency at that position will be returned.  If the argument is
     7486   negative a fatal error is thrown.  */
     7487static char *
     7488func_q_deps (char *o, char **argv, const char *funcname)
     7489{
     7490  unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
     7491  return worker_deps (o, &argv[1], funcname, style, funcname[5] != '\0');
     7492}
     7493
     7494/* Implements $(qdeps-newer ).
     7495
     7496   If no third argument is given, or if it's empty, or if it's zero,
     7497   all dependencies will be returned.  If the third argument is non-zero
     7498   the dependency at that position will be returned.  If the argument is
     7499   negative a fatal error is thrown.  */
     7500static char *
     7501func_q_deps_newer (char *o, char **argv, const char *funcname)
     7502{
     7503  unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
     7504  return worker_deps_newer (o, &argv[1], funcname, style);
     7505}
     7506
     7507/* Implements $(qdeps-oo ), the order only dependency list.
     7508
     7509   If no third argument is given, or if it's empty, or if it's zero,
     7510   all dependencies will be returned.  If the third argument is non-zero
     7511   the dependency at that position will be returned.  If the argument is
     7512   negative a fatal error is thrown.  */
     7513static char *
     7514func_q_deps_order_only (char *o, char **argv, const char *funcname)
     7515{
     7516  unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
     7517  return worker_deps_order_only (o, &argv[1], funcname, style);
     7518}
     7519
     7520/* Implements $(qtarget ), converting a single unquoted file to the given
     7521   quoting style.
     7522
     7523   Typically used like this:
     7524      $(qtarget sh,$@)
     7525      $(qone-unquoted sh,$@) */
     7526static char *
     7527func_q_one_unquoted (char *o, char **argv, const char *funcname)
     7528{
     7529  unsigned int const style = helper_file_quoting_style (argv[0], Q_QDEFAULT);
     7530  return helper_return_file (o, argv[1], style, 1 /*is_last*/);
     7531}
     7532
     7533#endif /* KMK */
    73877534
    73887535/* Lookup table for builtin functions.
     
    76367783# endif
    76377784  FT_ENTRY ("qwildcard",    1+0, 1+1, 1, func_q_wildcard),
    7638 /** @todo XXX: Add more qxxxx variants. */
     7785  FT_ENTRY ("qone-unquoted",1+1, 1+1, 1, func_q_one_unquoted),
     7786  FT_ENTRY ("qtarget",      1+1, 1+1, 1, func_q_one_unquoted),    /* For requoting plain $@ to given style. */
     7787  FT_ENTRY ("qdeps",        1+1, 1+2, 1, func_q_deps),            /* $^ with quoting style */
     7788  FT_ENTRY ("qdeps-all",    1+1, 1+2, 1, func_q_deps),            /* $+ with quoting style */
     7789  FT_ENTRY ("qdeps-newer",  1+1, 1+2, 1, func_q_deps_newer),      /* $? with quoting style */
     7790  FT_ENTRY ("qdeps-oo",     1+1, 1+2, 1, func_q_deps_order_only), /* $| with quoting style */
     7791  FT_ENTRY ("qfilter",      1+2, 1+2, 1, func_q_filter_filterout),
     7792  FT_ENTRY ("qfilter-out",  1+2, 1+2, 1, func_q_filter_filterout),
     7793  /** @todo XXX: Add more qxxxx variants. */
    76397794#endif
    76407795};
  • trunk/src/kmk/read.c

    r3156 r3519  
    30563056  return find_char_unquote (pattern, MAP_PERCENT);
    30573057#else
    3058   char *eos = strchr(pattern, '\0');
     3058  char *eos = strchr (pattern, '\0');
    30593059  return find_char_unquote_0 (pattern, '%', MAP_PERCENT, &eos);
    30603060#endif
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