summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@kolpackov.net>2009-09-28 12:31:55 +0000
committerBoris Kolpackov <boris@kolpackov.net>2009-09-28 12:31:55 +0000
commitf5891a26d8d3ed87b059856650b2bdb0c7ea355e (patch)
tree507533e9a2622b0b39cf5d0141b71ce1c6c864c4 /variable.c
parentf9c15cac3504546cb5ebf74241fc13ba2700691a (diff)
downloadgunmake-f5891a26d8d3ed87b059856650b2bdb0c7ea355e.tar.gz
Implement the shortest stem first search order for pattern-specific variables and pattern rules.
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/variable.c b/variable.c
index 90c447c..6a74dcd 100644
--- a/variable.c
+++ b/variable.c
@@ -35,28 +35,62 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
static struct pattern_var *pattern_vars;
-/* Pointer to last struct in the chain, so we can add onto the end. */
+/* Pointer to the last struct in the pack of a specific size, from 1 to 255.*/
-static struct pattern_var *last_pattern_var;
+static struct pattern_var *last_pattern_vars[256];
-/* Create a new pattern-specific variable struct. */
+/* Create a new pattern-specific variable struct. The new variable is
+ inserted into the PATTERN_VARS list in the shortest patterns first
+ order to support the shortest stem matching (the variables are
+ matched in the reverse order so the ones with the longest pattern
+ will be considered first). Variables with the same pattern length
+ are inserted in the definition order. */
struct pattern_var *
create_pattern_var (const char *target, const char *suffix)
{
+ register unsigned int len = strlen (target);
register struct pattern_var *p = xmalloc (sizeof (struct pattern_var));
- if (last_pattern_var != 0)
- last_pattern_var->next = p;
+ if (pattern_vars != 0)
+ {
+ if (len < 256 && last_pattern_vars[len] != 0)
+ {
+ p->next = last_pattern_vars[len]->next;
+ last_pattern_vars[len]->next = p;
+ }
+ else
+ {
+ /* Find the position where we can insert this variable. */
+ register struct pattern_var **v;
+
+ for (v = &pattern_vars; ; v = &(*v)->next)
+ {
+ /* Insert at the end of the pack so that patterns with the
+ same length appear in the order they were defined .*/
+
+ if (*v == 0 || (*v)->len > len)
+ {
+ p->next = *v;
+ *v = p;
+ break;
+ }
+ }
+ }
+ }
else
- pattern_vars = p;
- last_pattern_var = p;
- p->next = 0;
+ {
+ pattern_vars = p;
+ p->next = 0;
+ }
p->target = target;
- p->len = strlen (target);
+ p->len = len;
p->suffix = suffix + 1;
+ if (len < 256)
+ last_pattern_vars[len] = p;
+
return p;
}