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