Commit | Line | Data |
---|---|---|
165acdd1 JH |
1 | /************************************************* |
2 | * Exim - an Internet mail transport agent * | |
3 | *************************************************/ | |
4 | ||
f9ba5e22 | 5 | /* Copyright (c) University of Cambridge 1995 - 2018 */ |
165acdd1 JH |
6 | /* See the file NOTICE for conditions of use and distribution. */ |
7 | ||
8 | /* Functions for handling macros */ | |
9 | ||
10 | #include "exim.h" | |
11 | ||
12 | #ifdef MACRO_PREDEF | |
13 | # undef store_get | |
14 | # define store_get(nbytes) malloc((size_t)(nbytes)) | |
15 | #define string_copyn(s, len) strndup(CS(s), (len)) | |
16 | #endif | |
17 | ||
18 | /************************************************* | |
19 | * Deal with an assignment to a macro * | |
20 | *************************************************/ | |
21 | ||
22 | /* We have a new definition; add to the collection. | |
23 | Items are numbered so we can avoid recursion in expansions. | |
24 | ||
25 | Args: | |
26 | name Name of the macro. Will be copied. | |
27 | val Expansion result for the macro. Will be copied. | |
28 | */ | |
29 | ||
30 | macro_item * | |
31 | macro_create(const uschar * name, const uschar * val, BOOL command_line) | |
32 | { | |
33 | int namelen = Ustrlen(name); | |
34 | macro_item * m = store_get(sizeof(macro_item) + namelen); | |
35 | ||
36 | /* fprintf(stderr, "%s: '%s' '%s'\n", __FUNCTION__, name, val); */ | |
37 | ||
38 | m->command_line = command_line; | |
39 | m->namelen = namelen; | |
40 | m->replen = Ustrlen(val); | |
41 | m->m_number = m_number++; | |
42 | memset(&m->tnode, 0, sizeof(tree_node)); | |
38e3d2df JH |
43 | /* Use memcpy here not Ustrcpy to avoid spurious compiler-inserted check |
44 | when building with fortify-source. We know there is room for the copy into | |
45 | this dummy for a variable-size array because of the way we did the memory | |
46 | allocation above. */ | |
47 | memcpy(m->tnode.name, name, namelen+1); | |
165acdd1 JH |
48 | m->tnode.data.ptr = string_copyn(val, m->replen); |
49 | (void) tree_insertnode(&tree_macros, &m->tnode); | |
50 | ||
51 | return m; | |
52 | } | |
53 | ||
54 | ||
55 | /* Search for a macro, with an exact match on the name. | |
56 | Return the node, or NULL for not-found. | |
57 | ||
58 | Arguments: name key to search for | |
59 | */ | |
60 | ||
61 | macro_item * | |
62 | macro_search(const uschar * name) | |
63 | { | |
64 | tree_node * t; | |
65 | ||
66 | t = tree_search(tree_macros, name); | |
67 | return tnode_to_mitem(t); | |
68 | } | |
69 | ||
70 | ||
71 | /* Search for a macro with a (possibly improper) leading substring | |
72 | matching the given name. Return the node, or NULL for not-found. | |
73 | ||
74 | Arguments: name key to search on | |
75 | */ | |
76 | ||
77 | macro_item * | |
78 | macro_search_prefix(const uschar * s) | |
79 | { | |
80 | tree_node * t; | |
81 | int c; | |
82 | ||
83 | for (t = tree_macros; t; t = c < 0 ? t->left : t->right) | |
84 | if ((c = Ustrncmp(s, t->name, tnode_to_mitem(t)->namelen)) == 0) | |
85 | return tnode_to_mitem(t); | |
86 | return NULL; | |
87 | } | |
88 | ||
89 | ||
90 | /* Search for the macro with the largest possible leading substring | |
91 | matching the given name. */ | |
92 | ||
93 | macro_item * | |
94 | macro_search_largest_prefix(const uschar * s) | |
95 | { | |
96 | macro_item * found; | |
97 | tree_node * child; | |
98 | int c; | |
99 | ||
100 | if ((found = macro_search_prefix(s))) | |
101 | { | |
102 | /* There could be a node with a larger substring also matching the | |
103 | name. If so it must be in the right subtree; either the right child | |
104 | or (if that sorts after the name) in the left subtree of the right child. */ | |
105 | ||
106 | child = found->tnode.right; | |
107 | while (child) | |
108 | if ((c = Ustrncmp(s, child->name, tnode_to_mitem(child)->namelen)) == 0) | |
109 | { | |
110 | found = tnode_to_mitem(child); | |
111 | child = found->tnode.right; | |
112 | } | |
113 | else if (c < 0 && (child = child->left)) | |
114 | continue; | |
115 | else | |
116 | break; | |
117 | } | |
118 | return found; | |
119 | } | |
120 | ||
121 | ||
122 | ||
123 | void | |
124 | macro_print(uschar * name, uschar * val, void * ctx) | |
125 | { | |
126 | BOOL names_only = (BOOL)(long)ctx; | |
127 | if (names_only) | |
128 | printf("%s\n", CS name); | |
129 | else | |
130 | printf("%s=%s\n", CS name, CS val); | |
131 | } | |
132 | ||
133 | ||
134 | ||
135 | /* vi: aw ai sw=2 | |
136 | */ | |
137 | /* End of macro.c */ |