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