]> diplodocus.org Git - nmh/blob - sbr/fmt_addr.c
Improve fmttest output
[nmh] / sbr / fmt_addr.c
1 /* fmt_addr.c -- format an address field (from fmt_scan)
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include "h/mh.h"
9 #include "fmt_addr.h"
10 #include "h/addrsbr.h"
11 #include "h/fmt_scan.h"
12 #include "h/utils.h"
13
14 static char *buf; /* our current working buffer */
15 static char *bufend; /* end of working buffer */
16 static char *last_dst; /* buf ptr at end of last call */
17 static unsigned int bufsiz; /* current size of buf */
18
19 #define BUFINCR 512 /* how much to expand buf when if fills */
20
21 #define CPY(s) { cp = (s); while ((*dst++ = *cp++)) ; --dst; }
22
23 /* check if there's enough room in buf for str. add more mem if needed */
24 #define CHECKMEM(str) \
25 if ((len = strlen (str)) >= bufend - dst) {\
26 int i = dst - buf;\
27 int n = last_dst - buf;\
28 bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\
29 buf = mh_xrealloc (buf, bufsiz);\
30 dst = buf + i;\
31 last_dst = buf + n;\
32 bufend = buf + bufsiz;\
33 }
34
35
36 /* fmt_scan will call this routine if the user includes the function
37 * "(formataddr {component})" in a format string. "orig" is the
38 * original contents of the string register. "str" is the address
39 * string to be formatted and concatenated onto orig. This routine
40 * returns a pointer to the concatenated address string.
41 *
42 * We try to not do a lot of malloc/copy/free's (which is why we
43 * don't call "getcpy") but still place no upper limit on the
44 * length of the result string.
45 *
46 * This routine is placed in a separate library so it can be
47 * overridden by particular programs (e.g., "replsbr").
48 */
49
50 char *
51 formataddr (char *orig, char *str)
52 {
53 int len;
54 bool isgroup;
55 char *dst;
56 char *cp;
57 char *sp;
58 struct mailname *mp = NULL;
59
60 /* if we don't have a buffer yet, get one */
61 if (bufsiz == 0) {
62 buf = mh_xmalloc (BUFINCR);
63 last_dst = buf; /* XXX */
64 bufsiz = BUFINCR - 6; /* leave some slop */
65 bufend = buf + bufsiz;
66 }
67 /*
68 * If "orig" points to our buffer we can just pick up where we
69 * left off. Otherwise we have to copy orig into our buffer.
70 */
71 if (orig == buf)
72 dst = last_dst;
73 else if (!orig || !*orig) {
74 dst = buf;
75 *dst = '\0';
76 } else {
77 dst = last_dst; /* XXX */
78 CHECKMEM (orig);
79 CPY (orig);
80 }
81
82 /* concatenate all the new addresses onto 'buf' */
83 for (isgroup = false; (cp = getname (str)); ) {
84 if ((mp = getm (cp, NULL, 0, NULL, 0)) == NULL)
85 continue;
86
87 if (isgroup && (mp->m_gname || !mp->m_ingrp)) {
88 *dst++ = ';';
89 isgroup = false;
90 }
91 /* if we get here we're going to add an address */
92 if (dst != buf) {
93 *dst++ = ',';
94 *dst++ = ' ';
95 }
96 if (mp->m_gname) {
97 CHECKMEM (mp->m_gname);
98 CPY (mp->m_gname);
99 isgroup = true;
100 }
101 sp = adrformat (mp);
102 CHECKMEM (sp);
103 CPY (sp);
104 mnfree (mp);
105 }
106
107 if (isgroup)
108 *dst++ = ';';
109
110 *dst = '\0';
111 last_dst = dst;
112 return buf;
113 }
114
115 char *
116 concataddr (char *orig, char *str)
117 {
118 return formataddr(orig, str);
119 }