| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.737 2020/12/19 22:10:17 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.738 2020/12/20 00:47:21 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. |
| @@ -121,27 +121,27 @@ | | | @@ -121,27 +121,27 @@ |
121 | #include <regex.h> | | 121 | #include <regex.h> |
122 | #endif | | 122 | #endif |
123 | #include <errno.h> | | 123 | #include <errno.h> |
124 | #include <inttypes.h> | | 124 | #include <inttypes.h> |
125 | #include <limits.h> | | 125 | #include <limits.h> |
126 | #include <time.h> | | 126 | #include <time.h> |
127 | | | 127 | |
128 | #include "make.h" | | 128 | #include "make.h" |
129 | #include "dir.h" | | 129 | #include "dir.h" |
130 | #include "job.h" | | 130 | #include "job.h" |
131 | #include "metachar.h" | | 131 | #include "metachar.h" |
132 | | | 132 | |
133 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | | 133 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ |
134 | MAKE_RCSID("$NetBSD: var.c,v 1.737 2020/12/19 22:10:17 rillig Exp $"); | | 134 | MAKE_RCSID("$NetBSD: var.c,v 1.738 2020/12/20 00:47:21 rillig Exp $"); |
135 | | | 135 | |
136 | /* A string that may need to be freed after use. */ | | 136 | /* A string that may need to be freed after use. */ |
137 | typedef struct FStr { | | 137 | typedef struct FStr { |
138 | const char *str; | | 138 | const char *str; |
139 | void *freeIt; | | 139 | void *freeIt; |
140 | } FStr; | | 140 | } FStr; |
141 | | | 141 | |
142 | typedef enum VarFlags { | | 142 | typedef enum VarFlags { |
143 | VAR_NONE = 0, | | 143 | VAR_NONE = 0, |
144 | | | 144 | |
145 | /* | | 145 | /* |
146 | * The variable's value is currently being used by Var_Parse or | | 146 | * The variable's value is currently being used by Var_Parse or |
147 | * Var_Subst. This marker is used to avoid endless recursion. | | 147 | * Var_Subst. This marker is used to avoid endless recursion. |
| @@ -2803,26 +2803,54 @@ ApplyModifier_ToSep(const char **pp, App | | | @@ -2803,26 +2803,54 @@ ApplyModifier_ToSep(const char **pp, App |
2803 | (*pp)++; /* just for backwards compatibility */ | | 2803 | (*pp)++; /* just for backwards compatibility */ |
2804 | return AMR_BAD; | | 2804 | return AMR_BAD; |
2805 | } | | 2805 | } |
2806 | | | 2806 | |
2807 | *pp = p; | | 2807 | *pp = p; |
2808 | } | | 2808 | } |
2809 | | | 2809 | |
2810 | ok: | | 2810 | ok: |
2811 | st->newVal = ModifyWords(st->val, ModifyWord_Copy, NULL, | | 2811 | st->newVal = ModifyWords(st->val, ModifyWord_Copy, NULL, |
2812 | st->oneBigWord, st->sep); | | 2812 | st->oneBigWord, st->sep); |
2813 | return AMR_OK; | | 2813 | return AMR_OK; |
2814 | } | | 2814 | } |
2815 | | | 2815 | |
| | | 2816 | static char * |
| | | 2817 | str_toupper(const char *str) |
| | | 2818 | { |
| | | 2819 | char *res; |
| | | 2820 | size_t i, len; |
| | | 2821 | |
| | | 2822 | len = strlen(str); |
| | | 2823 | res = bmake_malloc(len + 1); |
| | | 2824 | for (i = 0; i < len + 1; i++) |
| | | 2825 | res[i] = ch_toupper(str[i]); |
| | | 2826 | |
| | | 2827 | return res; |
| | | 2828 | } |
| | | 2829 | |
| | | 2830 | static char * |
| | | 2831 | str_tolower(const char *str) |
| | | 2832 | { |
| | | 2833 | char *res; |
| | | 2834 | size_t i, len; |
| | | 2835 | |
| | | 2836 | len = strlen(str); |
| | | 2837 | res = bmake_malloc(len + 1); |
| | | 2838 | for (i = 0; i < len + 1; i++) |
| | | 2839 | res[i] = ch_tolower(str[i]); |
| | | 2840 | |
| | | 2841 | return res; |
| | | 2842 | } |
| | | 2843 | |
2816 | /* :tA, :tu, :tl, :ts<separator>, etc. */ | | 2844 | /* :tA, :tu, :tl, :ts<separator>, etc. */ |
2817 | static ApplyModifierResult | | 2845 | static ApplyModifierResult |
2818 | ApplyModifier_To(const char **pp, ApplyModifiersState *st) | | 2846 | ApplyModifier_To(const char **pp, ApplyModifiersState *st) |
2819 | { | | 2847 | { |
2820 | const char *mod = *pp; | | 2848 | const char *mod = *pp; |
2821 | assert(mod[0] == 't'); | | 2849 | assert(mod[0] == 't'); |
2822 | | | 2850 | |
2823 | if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0') { | | 2851 | if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0') { |
2824 | *pp = mod + 1; | | 2852 | *pp = mod + 1; |
2825 | return AMR_BAD; /* Found ":t<endc>" or ":t:". */ | | 2853 | return AMR_BAD; /* Found ":t<endc>" or ":t:". */ |
2826 | } | | 2854 | } |
2827 | | | 2855 | |
2828 | if (mod[1] == 's') | | 2856 | if (mod[1] == 's') |
| @@ -2832,41 +2860,33 @@ ApplyModifier_To(const char **pp, ApplyM | | | @@ -2832,41 +2860,33 @@ ApplyModifier_To(const char **pp, ApplyM |
2832 | *pp = mod + 1; | | 2860 | *pp = mod + 1; |
2833 | return AMR_BAD; /* Found ":t<unrecognised><unrecognised>". */ | | 2861 | return AMR_BAD; /* Found ":t<unrecognised><unrecognised>". */ |
2834 | } | | 2862 | } |
2835 | | | 2863 | |
2836 | /* Check for two-character options: ":tu", ":tl" */ | | 2864 | /* Check for two-character options: ":tu", ":tl" */ |
2837 | if (mod[1] == 'A') { /* absolute path */ | | 2865 | if (mod[1] == 'A') { /* absolute path */ |
2838 | st->newVal = ModifyWords(st->val, ModifyWord_Realpath, NULL, | | 2866 | st->newVal = ModifyWords(st->val, ModifyWord_Realpath, NULL, |
2839 | st->oneBigWord, st->sep); | | 2867 | st->oneBigWord, st->sep); |
2840 | *pp = mod + 2; | | 2868 | *pp = mod + 2; |
2841 | return AMR_OK; | | 2869 | return AMR_OK; |
2842 | } | | 2870 | } |
2843 | | | 2871 | |
2844 | if (mod[1] == 'u') { /* :tu */ | | 2872 | if (mod[1] == 'u') { /* :tu */ |
2845 | size_t i; | | 2873 | st->newVal = str_toupper(st->val); |
2846 | size_t len = strlen(st->val); | | | |
2847 | st->newVal = bmake_malloc(len + 1); | | | |
2848 | for (i = 0; i < len + 1; i++) | | | |
2849 | st->newVal[i] = ch_toupper(st->val[i]); | | | |
2850 | *pp = mod + 2; | | 2874 | *pp = mod + 2; |
2851 | return AMR_OK; | | 2875 | return AMR_OK; |
2852 | } | | 2876 | } |
2853 | | | 2877 | |
2854 | if (mod[1] == 'l') { /* :tl */ | | 2878 | if (mod[1] == 'l') { /* :tl */ |
2855 | size_t i; | | 2879 | st->newVal = str_tolower(st->val); |
2856 | size_t len = strlen(st->val); | | | |
2857 | st->newVal = bmake_malloc(len + 1); | | | |
2858 | for (i = 0; i < len + 1; i++) | | | |
2859 | st->newVal[i] = ch_tolower(st->val[i]); | | | |
2860 | *pp = mod + 2; | | 2880 | *pp = mod + 2; |
2861 | return AMR_OK; | | 2881 | return AMR_OK; |
2862 | } | | 2882 | } |
2863 | | | 2883 | |
2864 | if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */ | | 2884 | if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */ |
2865 | st->oneBigWord = mod[1] == 'W'; | | 2885 | st->oneBigWord = mod[1] == 'W'; |
2866 | st->newVal = st->val; | | 2886 | st->newVal = st->val; |
2867 | *pp = mod + 2; | | 2887 | *pp = mod + 2; |
2868 | return AMR_OK; | | 2888 | return AMR_OK; |
2869 | } | | 2889 | } |
2870 | | | 2890 | |
2871 | /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ | | 2891 | /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ |
2872 | *pp = mod + 1; | | 2892 | *pp = mod + 1; |