Update copyright year to 2018
[exim.git] / src / src / macro.c
CommitLineData
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.
23Items are numbered so we can avoid recursion in expansions.
24
25Args:
26 name Name of the macro. Will be copied.
27 val Expansion result for the macro. Will be copied.
28*/
29
30macro_item *
31macro_create(const uschar * name, const uschar * val, BOOL command_line)
32{
33int namelen = Ustrlen(name);
34macro_item * m = store_get(sizeof(macro_item) + namelen);
35
36/* fprintf(stderr, "%s: '%s' '%s'\n", __FUNCTION__, name, val); */
37
38m->command_line = command_line;
39m->namelen = namelen;
40m->replen = Ustrlen(val);
41m->m_number = m_number++;
42memset(&m->tnode, 0, sizeof(tree_node));
38e3d2df
JH
43/* Use memcpy here not Ustrcpy to avoid spurious compiler-inserted check
44when building with fortify-source. We know there is room for the copy into
45this dummy for a variable-size array because of the way we did the memory
46allocation above. */
47memcpy(m->tnode.name, name, namelen+1);
165acdd1
JH
48m->tnode.data.ptr = string_copyn(val, m->replen);
49(void) tree_insertnode(&tree_macros, &m->tnode);
50
51return m;
52}
53
54
55/* Search for a macro, with an exact match on the name.
56Return the node, or NULL for not-found.
57
58Arguments: name key to search for
59*/
60
61macro_item *
62macro_search(const uschar * name)
63{
64tree_node * t;
65
66t = tree_search(tree_macros, name);
67return tnode_to_mitem(t);
68}
69
70
71/* Search for a macro with a (possibly improper) leading substring
72matching the given name. Return the node, or NULL for not-found.
73
74Arguments: name key to search on
75*/
76
77macro_item *
78macro_search_prefix(const uschar * s)
79{
80tree_node * t;
81int c;
82
83for (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);
86return NULL;
87}
88
89
90/* Search for the macro with the largest possible leading substring
91matching the given name. */
92
93macro_item *
94macro_search_largest_prefix(const uschar * s)
95{
96macro_item * found;
97tree_node * child;
98int c;
99
100if ((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 }
118return found;
119}
120
121
122
123void
124macro_print(uschar * name, uschar * val, void * ctx)
125{
126BOOL names_only = (BOOL)(long)ctx;
127if (names_only)
128 printf("%s\n", CS name);
129else
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 */