forked from rmyorston/pdpmake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
macro.c
120 lines (107 loc) · 2.51 KB
/
macro.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* Macro control for make
*/
#include "make.h"
struct macro *macrohead[HTABSIZE];
struct macro *
getmp(const char *name)
{
struct macro *mp;
for (mp = macrohead[getbucket(name)]; mp; mp = mp->m_next)
if (strcmp(name, mp->m_name) == 0)
return mp;
return NULL;
}
static int
is_valid_macro(const char *name)
{
const char *s;
for (s = name; *s; ++s) {
// In POSIX mode only a limited set of characters are guaranteed
// to be allowed in macro names.
if (IF_FEATURE_MAKE_EXTENSIONS(posix &&)
((
IF_FEATURE_MAKE_EXTENSIONS((pragma & P_MACRO_NAME) ||)
(ENABLE_FEATURE_MAKE_POSIX_202X && !POSIX_2017)
) ? !isfname(*s) : !ispname(*s)))
return FALSE;
// As an extension allow anything that can get through the
// input parser, apart from the following.
if (*s == '=')
return FALSE;
#if ENABLE_FEATURE_MAKE_POSIX_202X
if (isblank(*s) || iscntrl(*s))
return FALSE;
#endif
}
return TRUE;
}
#if ENABLE_FEATURE_MAKE_EXTENSIONS
static int
potentially_valid_macro(const char *name)
{
int ret = FALSE;
if (!(pragma & P_MACRO_NAME)) {
pragma |= P_MACRO_NAME;
ret = is_valid_macro(name);
pragma &= ~P_MACRO_NAME;
}
return ret;
}
#endif
void
setmacro(const char *name, const char *val, int level)
{
struct macro *mp;
bool valid = level & M_VALID;
#if ENABLE_FEATURE_MAKE_EXTENSIONS || ENABLE_FEATURE_MAKE_POSIX_202X
bool immediate = level & M_IMMEDIATE;
#endif
level &= ~(M_IMMEDIATE | M_VALID);
mp = getmp(name);
if (mp) {
// Don't replace existing macro from a lower level
if (level > mp->m_level)
return;
// Replace existing macro
free(mp->m_val);
} else {
// If not defined, allocate space for new
unsigned int bucket;
if (!valid && !is_valid_macro(name))
#if ENABLE_FEATURE_MAKE_EXTENSIONS
error("invalid macro name '%s'%s", name,
potentially_valid_macro(name) ?
": allow with pragma macro_name" : "");
#else
error("invalid macro name '%s'", name);
#endif
bucket = getbucket(name);
mp = xmalloc(sizeof(struct macro));
mp->m_next = macrohead[bucket];
macrohead[bucket] = mp;
mp->m_flag = FALSE;
mp->m_name = xstrdup(name);
}
#if ENABLE_FEATURE_MAKE_EXTENSIONS || ENABLE_FEATURE_MAKE_POSIX_202X
mp->m_immediate = immediate;
#endif
mp->m_level = level;
mp->m_val = xstrdup(val ? val : "");
}
#if ENABLE_FEATURE_CLEAN_UP
void
freemacros(void)
{
int i;
struct macro *mp, *nextmp;
for (i = 0; i < HTABSIZE; i++) {
for (mp = macrohead[i]; mp; mp = nextmp) {
nextmp = mp->m_next;
free(mp->m_name);
free(mp->m_val);
free(mp);
}
}
}
#endif