21e51044ea93ac1fb5dfcbd3d92cc0c786c7b168
[exim.git] / src / src / macro.c
1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
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));
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);
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 */