Builtin macros for sha3-hash and ed25519-signing support
[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 Ustrcpy(m->tnode.name, name);
44 m->tnode.data.ptr = string_copyn(val, m->replen);
45 (void) tree_insertnode(&tree_macros, &m->tnode);
46
47 return m;
48 }
49
50
51 /* Search for a macro, with an exact match on the name.
52 Return the node, or NULL for not-found.
53
54 Arguments: name key to search for
55 */
56
57 macro_item *
58 macro_search(const uschar * name)
59 {
60 tree_node * t;
61
62 t = tree_search(tree_macros, name);
63 return tnode_to_mitem(t);
64 }
65
66
67 /* Search for a macro with a (possibly improper) leading substring
68 matching the given name. Return the node, or NULL for not-found.
69
70 Arguments: name key to search on
71 */
72
73 macro_item *
74 macro_search_prefix(const uschar * s)
75 {
76 tree_node * t;
77 int c;
78
79 for (t = tree_macros; t; t = c < 0 ? t->left : t->right)
80 if ((c = Ustrncmp(s, t->name, tnode_to_mitem(t)->namelen)) == 0)
81 return tnode_to_mitem(t);
82 return NULL;
83 }
84
85
86 /* Search for the macro with the largest possible leading substring
87 matching the given name. */
88
89 macro_item *
90 macro_search_largest_prefix(const uschar * s)
91 {
92 macro_item * found;
93 tree_node * child;
94 int c;
95
96 if ((found = macro_search_prefix(s)))
97 {
98 /* There could be a node with a larger substring also matching the
99 name. If so it must be in the right subtree; either the right child
100 or (if that sorts after the name) in the left subtree of the right child. */
101
102 child = found->tnode.right;
103 while (child)
104 if ((c = Ustrncmp(s, child->name, tnode_to_mitem(child)->namelen)) == 0)
105 {
106 found = tnode_to_mitem(child);
107 child = found->tnode.right;
108 }
109 else if (c < 0 && (child = child->left))
110 continue;
111 else
112 break;
113 }
114 return found;
115 }
116
117
118
119 void
120 macro_print(uschar * name, uschar * val, void * ctx)
121 {
122 BOOL names_only = (BOOL)(long)ctx;
123 if (names_only)
124 printf("%s\n", CS name);
125 else
126 printf("%s=%s\n", CS name, CS val);
127 }
128
129
130
131 /* vi: aw ai sw=2
132 */
133 /* End of macro.c */