| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.536 2020/09/23 07:50:58 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.537 2020/09/25 05:04:51 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. |
| @@ -111,27 +111,27 @@ | | | @@ -111,27 +111,27 @@ |
111 | #include <sys/types.h> | | 111 | #include <sys/types.h> |
112 | #include <regex.h> | | 112 | #include <regex.h> |
113 | #endif | | 113 | #endif |
114 | #include <inttypes.h> | | 114 | #include <inttypes.h> |
115 | #include <limits.h> | | 115 | #include <limits.h> |
116 | #include <time.h> | | 116 | #include <time.h> |
117 | | | 117 | |
118 | #include "make.h" | | 118 | #include "make.h" |
119 | #include "dir.h" | | 119 | #include "dir.h" |
120 | #include "job.h" | | 120 | #include "job.h" |
121 | #include "metachar.h" | | 121 | #include "metachar.h" |
122 | | | 122 | |
123 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | | 123 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ |
124 | MAKE_RCSID("$NetBSD: var.c,v 1.536 2020/09/23 07:50:58 rillig Exp $"); | | 124 | MAKE_RCSID("$NetBSD: var.c,v 1.537 2020/09/25 05:04:51 rillig Exp $"); |
125 | | | 125 | |
126 | #define VAR_DEBUG_IF(cond, fmt, ...) \ | | 126 | #define VAR_DEBUG_IF(cond, fmt, ...) \ |
127 | if (!(DEBUG(VAR) && (cond))) \ | | 127 | if (!(DEBUG(VAR) && (cond))) \ |
128 | (void) 0; \ | | 128 | (void) 0; \ |
129 | else \ | | 129 | else \ |
130 | fprintf(debug_file, fmt, __VA_ARGS__) | | 130 | fprintf(debug_file, fmt, __VA_ARGS__) |
131 | | | 131 | |
132 | #define VAR_DEBUG(fmt, ...) VAR_DEBUG_IF(TRUE, fmt, __VA_ARGS__) | | 132 | #define VAR_DEBUG(fmt, ...) VAR_DEBUG_IF(TRUE, fmt, __VA_ARGS__) |
133 | | | 133 | |
134 | ENUM_FLAGS_RTTI_3(VarEvalFlags, | | 134 | ENUM_FLAGS_RTTI_3(VarEvalFlags, |
135 | VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); | | 135 | VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); |
136 | | | 136 | |
137 | /* | | 137 | /* |
| @@ -3710,90 +3710,91 @@ Var_Parse(const char **pp, GNode *ctxt, | | | @@ -3710,90 +3710,91 @@ Var_Parse(const char **pp, GNode *ctxt, |
3710 | * Input: | | 3710 | * Input: |
3711 | * str the string which to substitute | | 3711 | * str the string which to substitute |
3712 | * ctxt the context wherein to find variables | | 3712 | * ctxt the context wherein to find variables |
3713 | * eflags VARE_UNDEFERR if undefineds are an error | | 3713 | * eflags VARE_UNDEFERR if undefineds are an error |
3714 | * VARE_WANTRES if we actually want the result | | 3714 | * VARE_WANTRES if we actually want the result |
3715 | * VARE_ASSIGN if we are in a := assignment | | 3715 | * VARE_ASSIGN if we are in a := assignment |
3716 | * | | 3716 | * |
3717 | * Results: | | 3717 | * Results: |
3718 | * The resulting string. | | 3718 | * The resulting string. |
3719 | */ | | 3719 | */ |
3720 | VarParseResult | | 3720 | VarParseResult |
3721 | Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags, char **out_res) | | 3721 | Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags, char **out_res) |
3722 | { | | 3722 | { |
| | | 3723 | const char *p = str; |
3723 | Buffer buf; /* Buffer for forming things */ | | 3724 | Buffer buf; /* Buffer for forming things */ |
3724 | | | 3725 | |
3725 | /* Set true if an error has already been reported, | | 3726 | /* Set true if an error has already been reported, |
3726 | * to prevent a plethora of messages when recursing */ | | 3727 | * to prevent a plethora of messages when recursing */ |
3727 | static Boolean errorReported; | | 3728 | static Boolean errorReported; |
3728 | | | 3729 | |
3729 | Buf_Init(&buf, 0); | | 3730 | Buf_Init(&buf, 0); |
3730 | errorReported = FALSE; | | 3731 | errorReported = FALSE; |
3731 | | | 3732 | |
3732 | while (*str) { | | 3733 | while (*p != '\0') { |
3733 | if (*str == '$' && str[1] == '$') { | | 3734 | if (p[0] == '$' && p[1] == '$') { |
3734 | /* | | 3735 | /* |
3735 | * A dollar sign may be escaped with another dollar sign. | | 3736 | * A dollar sign may be escaped with another dollar sign. |
3736 | * In such a case, we skip over the escape character and store the | | 3737 | * In such a case, we skip over the escape character and store the |
3737 | * dollar sign into the buffer directly. | | 3738 | * dollar sign into the buffer directly. |
3738 | */ | | 3739 | */ |
3739 | if (save_dollars && (eflags & VARE_ASSIGN)) | | 3740 | if (save_dollars && (eflags & VARE_ASSIGN)) |
3740 | Buf_AddByte(&buf, '$'); | | 3741 | Buf_AddByte(&buf, '$'); |
3741 | Buf_AddByte(&buf, '$'); | | 3742 | Buf_AddByte(&buf, '$'); |
3742 | str += 2; | | 3743 | p += 2; |
3743 | } else if (*str != '$') { | | 3744 | } else if (*p != '$') { |
3744 | /* | | 3745 | /* |
3745 | * Skip as many characters as possible -- either to the end of | | 3746 | * Skip as many characters as possible -- either to the end of |
3746 | * the string or to the next dollar sign (variable expression). | | 3747 | * the string or to the next dollar sign (variable expression). |
3747 | */ | | 3748 | */ |
3748 | const char *cp; | | 3749 | const char *plainStart = p; |
3749 | | | 3750 | |
3750 | for (cp = str++; *str != '$' && *str != '\0'; str++) | | 3751 | for (p++; *p != '$' && *p != '\0'; p++) |
3751 | continue; | | 3752 | continue; |
3752 | Buf_AddBytesBetween(&buf, cp, str); | | 3753 | Buf_AddBytesBetween(&buf, plainStart, p); |
3753 | } else { | | 3754 | } else { |
3754 | const char *nested_str = str; | | 3755 | const char *nested_p = p; |
3755 | void *freeIt; | | 3756 | void *freeIt; |
3756 | const char *val; | | 3757 | const char *val; |
3757 | (void)Var_Parse(&nested_str, ctxt, eflags, &val, &freeIt); | | 3758 | (void)Var_Parse(&nested_p, ctxt, eflags, &val, &freeIt); |
3758 | /* TODO: handle errors */ | | 3759 | /* TODO: handle errors */ |
3759 | | | 3760 | |
3760 | if (val == var_Error || val == varUndefined) { | | 3761 | if (val == var_Error || val == varUndefined) { |
3761 | /* | | 3762 | /* |
3762 | * If performing old-time variable substitution, skip over | | 3763 | * If performing old-time variable substitution, skip over |
3763 | * the variable and continue with the substitution. Otherwise, | | 3764 | * the variable and continue with the substitution. Otherwise, |
3764 | * store the dollar sign and advance str so we continue with | | 3765 | * store the dollar sign and advance str so we continue with |
3765 | * the string... | | 3766 | * the string... |
3766 | */ | | 3767 | */ |
3767 | if (oldVars) { | | 3768 | if (oldVars) { |
3768 | str = nested_str; | | 3769 | p = nested_p; |
3769 | } else if ((eflags & VARE_UNDEFERR) || val == var_Error) { | | 3770 | } else if ((eflags & VARE_UNDEFERR) || val == var_Error) { |
3770 | /* | | 3771 | /* |
3771 | * If variable is undefined, complain and skip the | | 3772 | * If variable is undefined, complain and skip the |
3772 | * variable. The complaint will stop us from doing anything | | 3773 | * variable. The complaint will stop us from doing anything |
3773 | * when the file is parsed. | | 3774 | * when the file is parsed. |
3774 | */ | | 3775 | */ |
3775 | if (!errorReported) { | | 3776 | if (!errorReported) { |
3776 | Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"", | | 3777 | Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"", |
3777 | (int)(size_t)(nested_str - str), str); | | 3778 | (int)(size_t)(nested_p - p), p); |
3778 | } | | 3779 | } |
3779 | str = nested_str; | | 3780 | p = nested_p; |
3780 | errorReported = TRUE; | | 3781 | errorReported = TRUE; |
3781 | } else { | | 3782 | } else { |
3782 | Buf_AddByte(&buf, *str); | | 3783 | Buf_AddByte(&buf, *p); |
3783 | str++; | | 3784 | p++; |
3784 | } | | 3785 | } |
3785 | } else { | | 3786 | } else { |
3786 | str = nested_str; | | 3787 | p = nested_p; |
3787 | Buf_AddStr(&buf, val); | | 3788 | Buf_AddStr(&buf, val); |
3788 | } | | 3789 | } |
3789 | free(freeIt); | | 3790 | free(freeIt); |
3790 | freeIt = NULL; | | 3791 | freeIt = NULL; |
3791 | } | | 3792 | } |
3792 | } | | 3793 | } |
3793 | | | 3794 | |
3794 | *out_res = Buf_DestroyCompact(&buf); | | 3795 | *out_res = Buf_DestroyCompact(&buf); |
3795 | return VPR_OK; | | 3796 | return VPR_OK; |
3796 | } | | 3797 | } |
3797 | | | 3798 | |
3798 | /* Initialize the module. */ | | 3799 | /* Initialize the module. */ |
3799 | void | | 3800 | void |