Remove RCS keywords, since they no longer work after git migration.
[mmh] / 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     register int len;
55     register int isgroup;
56     register char *dst;
57     register char *cp;
58     register char *sp;
59     register 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, fmt_norm, NULL)) == 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 }