Changeset 3519 in kBuild
- Timestamp:
- Dec 18, 2021 1:39:20 PM (3 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/function.c
r3491 r3519 480 480 return !strcmp (percent + 1, str + (strlength - sfxlen)); 481 481 } 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 489 static int 490 pattern_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 482 501 483 502 … … 1556 1575 char *percent; 1557 1576 int length; 1577 #ifdef KMK 1578 unsigned int sfxlen; 1579 #endif 1558 1580 }; 1559 1581 … … 1598 1620 if (pat->percent == 0) 1599 1621 literals++; 1622 #ifdef KMK 1623 pat->sfxlen = pat->percent ? strlen(pat->percent + 1) : 0; 1624 #endif 1600 1625 1601 1626 /* find_percent() might shorten the string so LEN is wrong. */ … … 1649 1674 if (pp->percent) 1650 1675 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 1651 1680 wp->matched |= pattern_matches (pp->str, pp->percent, wp->str); 1681 #endif 1652 1682 else if (hashing) 1653 1683 { … … 3787 3817 } 3788 3818 #endif /* CONFIG_WITH_STRING_FUNCTIONS */ 3789 3790 3791 #ifdef CONFIG_WITH_LAZY_DEPS_VARS3792 3793 /* This is also in file.c (bad). */3794 # if VMS3795 # define FILE_LIST_SEPARATOR ','3796 # else3797 # define FILE_LIST_SEPARATOR ' '3798 # endif3799 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-zero3806 the dependency at that position will be returned. If the argument is3807 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 else3847 deps = file->deps;3848 3849 if ( file->double_colon3850 && ( file->double_colon != file3851 || 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_ARCHIVES3867 if (ar_name (c))3868 {3869 c = strchr (c, '(') + 1;3870 total_len += strlen (c);3871 }3872 else3873 #endif3874 #ifdef CONFIG_WITH_STRCACHE23875 if (!d->need_2nd_expansion)3876 total_len += strcache2_get_len (&file_strcache, c) + 1;3877 else3878 #endif3879 total_len += strlen (c) + 1;3880 }3881 3882 if (total_len)3883 {3884 /* prepare the variable buffer dude wrt to the output size and3885 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_ARCHIVES3896 if (ar_name (c))3897 {3898 c = strchr (c, '(') + 1;3899 len = strlen (c);3900 }3901 else3902 #endif3903 #ifdef CONFIG_WITH_STRCACHE23904 if (!d->need_2nd_expansion)3905 len = strcache2_get_len (&file_strcache, c) + 1;3906 else3907 #endif3908 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 else3918 {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_ARCHIVES3930 if (ar_name (c))3931 {3932 c = strchr (c, '(') + 1;3933 len = strlen (c) - 1;3934 }3935 else3936 #endif3937 #ifdef CONFIG_WITH_STRCACHE23938 if (!d->need_2nd_expansion)3939 len = strcache2_get_len (&file_strcache, c);3940 else3941 #endif3942 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-zero3957 the dependency at that position will be returned. If the argument is3958 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_colon3993 && ( file->double_colon != file3994 || 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_ARCHIVES4010 if (ar_name (c))4011 {4012 c = strchr (c, '(') + 1;4013 total_len += strlen (c);4014 }4015 else4016 #endif4017 #ifdef CONFIG_WITH_STRCACHE24018 if (!d->need_2nd_expansion)4019 total_len += strcache2_get_len (&file_strcache, c) + 1;4020 else4021 #endif4022 total_len += strlen (c) + 1;4023 }4024 4025 if (total_len)4026 {4027 /* prepare the variable buffer dude wrt to the output size and4028 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_ARCHIVES4039 if (ar_name (c))4040 {4041 c = strchr (c, '(') + 1;4042 len = strlen (c);4043 }4044 else4045 #endif4046 #ifdef CONFIG_WITH_STRCACHE24047 if (!d->need_2nd_expansion)4048 len = strcache2_get_len (&file_strcache, c) + 1;4049 else4050 #endif4051 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 else4061 {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_ARCHIVES4073 if (ar_name (c))4074 {4075 c = strchr (c, '(') + 1;4076 len = strlen (c) - 1;4077 }4078 else4079 #endif4080 #ifdef CONFIG_WITH_STRCACHE24081 if (!d->need_2nd_expansion)4082 len = strcache2_get_len (&file_strcache, c);4083 else4084 #endif4085 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-zero4100 the dependency at that position will be returned. If the argument is4101 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_colon4136 && ( file->double_colon != file4137 || 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_ARCHIVES4153 if (ar_name (c))4154 {4155 c = strchr (c, '(') + 1;4156 total_len += strlen (c);4157 }4158 else4159 #endif4160 #ifdef CONFIG_WITH_STRCACHE24161 if (!d->need_2nd_expansion)4162 total_len += strcache2_get_len (&file_strcache, c) + 1;4163 else4164 #endif4165 total_len += strlen (c) + 1;4166 }4167 4168 if (total_len)4169 {4170 /* prepare the variable buffer dude wrt to the output size and4171 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_ARCHIVES4182 if (ar_name (c))4183 {4184 c = strchr (c, '(') + 1;4185 len = strlen (c);4186 }4187 else4188 #endif4189 #ifdef CONFIG_WITH_STRCACHE24190 if (!d->need_2nd_expansion)4191 len = strcache2_get_len (&file_strcache, c) + 1;4192 else4193 #endif4194 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 else4204 {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_ARCHIVES4216 if (ar_name (c))4217 {4218 c = strchr (c, '(') + 1;4219 len = strlen (c) - 1;4220 }4221 else4222 #endif4223 #ifdef CONFIG_WITH_STRCACHE24224 if (!d->need_2nd_expansion)4225 len = strcache2_get_len (&file_strcache, c);4226 else4227 #endif4228 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 4240 3819 4241 3820 … … 6160 5739 #define Q_RET_SHELL_IN_SQ 0x0008 6161 5740 6162 #define Q_IN_MASK 0x00 305741 #define Q_IN_MASK 0x0070 6163 5742 #define Q_IN_QUOTED 0x0000 6164 5743 #define Q_IN_UNQUOTED 0x0010 6165 5744 #define Q_IN_QUOTED_DEP 0x0020 /** @todo needed? */ 6166 5745 #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 */ 6168 5748 6169 5749 #define Q_SEP_MASK 0x0700 … … 6195 5775 { 6196 5776 /* Skip blanks: */ 6197 while (ISBLANK (*style))5777 while (ISBLANK (*style)) 6198 5778 style++; 6199 5779 if (*style != '\0') … … 6203 5783 size_t len; 6204 5784 char ch; 6205 while (!ISBLANK ((ch = *style)) && ch != '\0')5785 while (!ISBLANK ((ch = *style)) && ch != '\0') 6206 5786 style++; 6207 5787 len = style - start; … … 6226 5806 intstyle = (intstyle & ~Q_RET_MASK) | Q_RET_SHELL; 6227 5807 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 */ 6229 5809 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 */ 6231 5811 /* input styles: */ 6232 5812 else if (MATCH ("in-quoted") || MATCH ("i-q")) … … 6234 5814 else if (MATCH ("in-unquoted") || MATCH ("i-unq") || MATCH ("i-u")) 6235 5815 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; 6236 5819 else if (MATCH ("in-quoted-dep") || MATCH ("i-q-dep") || MATCH ("i-q-d")) 6237 5820 intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_QUOTED_DEP; … … 6239 5822 intstyle = (intstyle & ~Q_IN_MASK) | Q_IN_QUOTED_TGT; 6240 5823 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; /*?*/ 6242 5825 /* separator styles (output): */ 6243 5826 else if (MATCH ("sep-space") || MATCH ("s-space") || MATCH ("s-s")) … … 6255 5838 char savedch = *style; 6256 5839 *style = '\0'; 6257 OS (error, reading_file, "Unknown file returnstyle: %s", start);5840 OS (error, reading_file, "Unknown file style: %s", start); 6258 5841 *style = savedch; 6259 5842 } … … 6292 5875 seps[(style & Q_SEP_MASK) >> Q_SEP_SHIFT].len); 6293 5876 } 5877 5878 /* Removes one separator from the output. 5879 5880 This is typically used when outputting lists where there is no simple way of 5881 telling whether an entry is the last one or not. So, is_last is always false 5882 and the last separator is removed afterwards by this function. */ 5883 5884 MY_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 6294 5891 6295 5892 /* Outputs (returns) the given file. */ … … 6345 5942 /* Outputs (returns) the given file. */ 6346 5943 6347 static char *helper_return_file (char *o, const char *file, unsigned int style, int is_last) 5944 static char *helper_return_file (char *o, const char *file, 5945 unsigned int style, int is_last) 6348 5946 { 6349 5947 return helper_return_file_len (o,file, strlen (file), style, is_last); … … 6429 6027 /* Parses a file/word list according to STYLE and returns a name list. 6430 6028 6431 Note! The FILELIST parameter may be modified. 6029 The FILELIST parameter may be modified! 6030 6031 The GLOB param is for wildcard/qwildcard. 6432 6032 6433 6033 TODO/XXX: Unquote and split up the FILELIST directly. All function … … 6476 6076 6477 6077 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 { 6486 6086 #ifndef CONFIG_WITH_ALLOC_CACHES 6487 6087 struct nameseq *newp = xcalloc (sizeof (*newp)); … … 6493 6093 *ppnext = newp; 6494 6094 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; 6500 6116 6501 6117 default: … … 7383 6999 } 7384 7000 7001 static char * 7002 worker_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 ). */ 7158 static char * 7159 func_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 7385 7165 #endif /* KMK */ 7386 7166 7167 7168 #ifdef CONFIG_WITH_LAZY_DEPS_VARS 7169 7170 /* Helper that parses the index argument for the $(deps* ) and $(qdeps* ) 7171 functions. */ 7172 static 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 7195 MY_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 7211 MY_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. */ 7241 static char * 7242 worker_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. */ 7311 static char * 7312 worker_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. */ 7372 static char * 7373 worker_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. */ 7435 static char * 7436 func_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. */ 7452 static char * 7453 func_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. */ 7468 static char * 7469 func_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. */ 7487 static char * 7488 func_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. */ 7500 static char * 7501 func_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. */ 7513 static char * 7514 func_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,$@) */ 7526 static char * 7527 func_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 */ 7387 7534 7388 7535 /* Lookup table for builtin functions. … … 7636 7783 # endif 7637 7784 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. */ 7639 7794 #endif 7640 7795 }; -
trunk/src/kmk/read.c
r3156 r3519 3056 3056 return find_char_unquote (pattern, MAP_PERCENT); 3057 3057 #else 3058 char *eos = strchr (pattern, '\0');3058 char *eos = strchr (pattern, '\0'); 3059 3059 return find_char_unquote_0 (pattern, '%', MAP_PERCENT, &eos); 3060 3060 #endif
Note:
See TracChangeset
for help on using the changeset viewer.