| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.993 2022/01/07 12:33:25 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.994 2022/01/07 12:37:27 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1988, 1989, 1990, 1993 | | 4 | * Copyright (c) 1988, 1989, 1990, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Adam de Boor. | | 8 | * Adam de Boor. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -130,27 +130,27 @@ | | | @@ -130,27 +130,27 @@ |
130 | #include <regex.h> | | 130 | #include <regex.h> |
131 | #endif | | 131 | #endif |
132 | #include <errno.h> | | 132 | #include <errno.h> |
133 | #include <inttypes.h> | | 133 | #include <inttypes.h> |
134 | #include <limits.h> | | 134 | #include <limits.h> |
135 | #include <time.h> | | 135 | #include <time.h> |
136 | | | 136 | |
137 | #include "make.h" | | 137 | #include "make.h" |
138 | #include "dir.h" | | 138 | #include "dir.h" |
139 | #include "job.h" | | 139 | #include "job.h" |
140 | #include "metachar.h" | | 140 | #include "metachar.h" |
141 | | | 141 | |
142 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | | 142 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ |
143 | MAKE_RCSID("$NetBSD: var.c,v 1.993 2022/01/07 12:33:25 rillig Exp $"); | | 143 | MAKE_RCSID("$NetBSD: var.c,v 1.994 2022/01/07 12:37:27 rillig Exp $"); |
144 | | | 144 | |
145 | /* | | 145 | /* |
146 | * Variables are defined using one of the VAR=value assignments. Their | | 146 | * Variables are defined using one of the VAR=value assignments. Their |
147 | * value can be queried by expressions such as $V, ${VAR}, or with modifiers | | 147 | * value can be queried by expressions such as $V, ${VAR}, or with modifiers |
148 | * such as ${VAR:S,from,to,g:Q}. | | 148 | * such as ${VAR:S,from,to,g:Q}. |
149 | * | | 149 | * |
150 | * There are 3 kinds of variables: scope variables, environment variables, | | 150 | * There are 3 kinds of variables: scope variables, environment variables, |
151 | * undefined variables. | | 151 | * undefined variables. |
152 | * | | 152 | * |
153 | * Scope variables are stored in a GNode.scope. The only way to undefine | | 153 | * Scope variables are stored in a GNode.scope. The only way to undefine |
154 | * a scope variable is using the .undef directive. In particular, it must | | 154 | * a scope variable is using the .undef directive. In particular, it must |
155 | * not be possible to undefine a variable during the evaluation of an | | 155 | * not be possible to undefine a variable during the evaluation of an |
156 | * expression, or Var.name might point nowhere. | | 156 | * expression, or Var.name might point nowhere. |
| @@ -2584,86 +2584,55 @@ TryParseTime(const char **pp, time_t *ou | | | @@ -2584,86 +2584,55 @@ TryParseTime(const char **pp, time_t *ou |
2584 | if (!ch_isdigit(**pp)) | | 2584 | if (!ch_isdigit(**pp)) |
2585 | return false; | | 2585 | return false; |
2586 | | | 2586 | |
2587 | errno = 0; | | 2587 | errno = 0; |
2588 | n = strtoul(*pp, &end, 10); | | 2588 | n = strtoul(*pp, &end, 10); |
2589 | if (n == ULONG_MAX && errno == ERANGE) | | 2589 | if (n == ULONG_MAX && errno == ERANGE) |
2590 | return false; | | 2590 | return false; |
2591 | | | 2591 | |
2592 | *pp = end; | | 2592 | *pp = end; |
2593 | *out_time = (time_t)n; /* ignore possible truncation for now */ | | 2593 | *out_time = (time_t)n; /* ignore possible truncation for now */ |
2594 | return true; | | 2594 | return true; |
2595 | } | | 2595 | } |
2596 | | | 2596 | |
2597 | /* :gmtime */ | | 2597 | /* :gmtime and :localtime */ |
2598 | static ApplyModifierResult | | 2598 | static ApplyModifierResult |
2599 | ApplyModifier_Gmtime(const char **pp, ModChain *ch) | | 2599 | ApplyModifier_Time(const char **pp, ModChain *ch, bool gmt) |
2600 | { | | 2600 | { |
2601 | Expr *expr; | | 2601 | Expr *expr; |
2602 | time_t t; | | 2602 | time_t t; |
| | | 2603 | const char *args; |
2603 | | | 2604 | |
2604 | const char *mod = *pp; | | 2605 | const char *mod = *pp; |
2605 | if (!ModMatchEq(mod, "gmtime", ch)) | | 2606 | if (!ModMatchEq(mod, gmt ? "gmtime" : "localtime", ch)) |
2606 | return AMR_UNKNOWN; | | 2607 | return AMR_UNKNOWN; |
| | | 2608 | args = mod + (gmt ? 6 : 9); |
2607 | | | 2609 | |
2608 | if (mod[6] == '=') { | | 2610 | if (args[0] == '=') { |
2609 | const char *p = mod + 7; | | 2611 | const char *p = args + 1; |
2610 | if (!TryParseTime(&p, &t)) { | | 2612 | if (!TryParseTime(&p, &t)) { |
2611 | Parse_Error(PARSE_FATAL, | | 2613 | Parse_Error(PARSE_FATAL, |
2612 | "Invalid time value at \"%s\"", p); | | 2614 | "Invalid time value at \"%s\"", p); |
2613 | return AMR_CLEANUP; | | 2615 | return AMR_CLEANUP; |
2614 | } | | 2616 | } |
2615 | *pp = p; | | 2617 | *pp = p; |
2616 | } else { | | 2618 | } else { |
2617 | t = 0; | | 2619 | t = 0; |
2618 | *pp = mod + 6; | | 2620 | *pp = args; |
2619 | } | | 2621 | } |
2620 | | | 2622 | |
2621 | expr = ch->expr; | | 2623 | expr = ch->expr; |
2622 | if (Expr_ShouldEval(expr)) | | 2624 | if (Expr_ShouldEval(expr)) |
2623 | Expr_SetValueOwn(expr, | | 2625 | Expr_SetValueOwn(expr, VarStrftime(Expr_Str(expr), t, gmt)); |
2624 | VarStrftime(Expr_Str(expr), t, true)); | | | |
2625 | | | | |
2626 | return AMR_OK; | | | |
2627 | } | | | |
2628 | | | | |
2629 | /* :localtime */ | | | |
2630 | static ApplyModifierResult | | | |
2631 | ApplyModifier_Localtime(const char **pp, ModChain *ch) | | | |
2632 | { | | | |
2633 | Expr *expr; | | | |
2634 | time_t t; | | | |
2635 | | | | |
2636 | const char *mod = *pp; | | | |
2637 | if (!ModMatchEq(mod, "localtime", ch)) | | | |
2638 | return AMR_UNKNOWN; | | | |
2639 | | | | |
2640 | if (mod[9] == '=') { | | | |
2641 | const char *p = mod + 10; | | | |
2642 | if (!TryParseTime(&p, &t)) { | | | |
2643 | Parse_Error(PARSE_FATAL, | | | |
2644 | "Invalid time value at \"%s\"", p); | | | |
2645 | return AMR_CLEANUP; | | | |
2646 | } | | | |
2647 | *pp = p; | | | |
2648 | } else { | | | |
2649 | t = 0; | | | |
2650 | *pp = mod + 9; | | | |
2651 | } | | | |
2652 | | | | |
2653 | expr = ch->expr; | | | |
2654 | if (Expr_ShouldEval(expr)) | | | |
2655 | Expr_SetValueOwn(expr, | | | |
2656 | VarStrftime(Expr_Str(expr), t, false)); | | | |
2657 | | | 2626 | |
2658 | return AMR_OK; | | 2627 | return AMR_OK; |
2659 | } | | 2628 | } |
2660 | | | 2629 | |
2661 | /* :hash */ | | 2630 | /* :hash */ |
2662 | static ApplyModifierResult | | 2631 | static ApplyModifierResult |
2663 | ApplyModifier_Hash(const char **pp, ModChain *ch) | | 2632 | ApplyModifier_Hash(const char **pp, ModChain *ch) |
2664 | { | | 2633 | { |
2665 | if (!ModMatch(*pp, "hash", ch)) | | 2634 | if (!ModMatch(*pp, "hash", ch)) |
2666 | return AMR_UNKNOWN; | | 2635 | return AMR_UNKNOWN; |
2667 | *pp += 4; | | 2636 | *pp += 4; |
2668 | | | 2637 | |
2669 | if (ModChain_ShouldEval(ch)) | | 2638 | if (ModChain_ShouldEval(ch)) |
| @@ -3853,35 +3822,35 @@ ApplyModifier(const char **pp, ModChain | | | @@ -3853,35 +3822,35 @@ ApplyModifier(const char **pp, ModChain |
3853 | return ApplyModifier_Words(pp, ch); | | 3822 | return ApplyModifier_Words(pp, ch); |
3854 | case '_': | | 3823 | case '_': |
3855 | return ApplyModifier_Remember(pp, ch); | | 3824 | return ApplyModifier_Remember(pp, ch); |
3856 | #ifndef NO_REGEX | | 3825 | #ifndef NO_REGEX |
3857 | case 'C': | | 3826 | case 'C': |
3858 | return ApplyModifier_Regex(pp, ch); | | 3827 | return ApplyModifier_Regex(pp, ch); |
3859 | #endif | | 3828 | #endif |
3860 | case 'D': | | 3829 | case 'D': |
3861 | case 'U': | | 3830 | case 'U': |
3862 | return ApplyModifier_Defined(pp, ch); | | 3831 | return ApplyModifier_Defined(pp, ch); |
3863 | case 'E': | | 3832 | case 'E': |
3864 | return ApplyModifier_WordFunc(pp, ch, ModifyWord_Suffix); | | 3833 | return ApplyModifier_WordFunc(pp, ch, ModifyWord_Suffix); |
3865 | case 'g': | | 3834 | case 'g': |
3866 | return ApplyModifier_Gmtime(pp, ch); | | 3835 | return ApplyModifier_Time(pp, ch, true); |
3867 | case 'H': | | 3836 | case 'H': |
3868 | return ApplyModifier_WordFunc(pp, ch, ModifyWord_Head); | | 3837 | return ApplyModifier_WordFunc(pp, ch, ModifyWord_Head); |
3869 | case 'h': | | 3838 | case 'h': |
3870 | return ApplyModifier_Hash(pp, ch); | | 3839 | return ApplyModifier_Hash(pp, ch); |
3871 | case 'L': | | 3840 | case 'L': |
3872 | return ApplyModifier_Literal(pp, ch); | | 3841 | return ApplyModifier_Literal(pp, ch); |
3873 | case 'l': | | 3842 | case 'l': |
3874 | return ApplyModifier_Localtime(pp, ch); | | 3843 | return ApplyModifier_Time(pp, ch, false); |
3875 | case 'M': | | 3844 | case 'M': |
3876 | case 'N': | | 3845 | case 'N': |
3877 | return ApplyModifier_Match(pp, ch); | | 3846 | return ApplyModifier_Match(pp, ch); |
3878 | case 'O': | | 3847 | case 'O': |
3879 | return ApplyModifier_Order(pp, ch); | | 3848 | return ApplyModifier_Order(pp, ch); |
3880 | case 'P': | | 3849 | case 'P': |
3881 | return ApplyModifier_Path(pp, ch); | | 3850 | return ApplyModifier_Path(pp, ch); |
3882 | case 'Q': | | 3851 | case 'Q': |
3883 | case 'q': | | 3852 | case 'q': |
3884 | return ApplyModifier_Quote(pp, ch); | | 3853 | return ApplyModifier_Quote(pp, ch); |
3885 | case 'R': | | 3854 | case 'R': |
3886 | return ApplyModifier_WordFunc(pp, ch, ModifyWord_Root); | | 3855 | return ApplyModifier_WordFunc(pp, ch, ModifyWord_Root); |
3887 | case 'r': | | 3856 | case 'r': |