Add refcounting to struct comp.
[mmh] / h / fmt_scan.h
1
2 /*
3  * fmt_scan.h -- definitions for fmt_scan()
4  */
5
6 /*
7  * This structure describes an "interesting" component.  It holds
8  * the name & text from the component (if found) and one piece of
9  * auxilary info.  The structure for a particular component is located
10  * by (open) hashing the name and using it as an index into the ptr array
11  * "wantcomp".  All format entries that reference a particular component
12  * point to its comp struct (so we only have to do component specific
13  * processing once.  e.g., parse an address.).
14  *
15  * In previous implementations "wantcomp" was made available to other
16  * functions, but now it's private and is accessed via functions.
17  */
18 struct comp {
19     char        *c_name;        /* component name (in lower case) */
20     char        *c_text;        /* component text (if found)      */
21     struct comp *c_next;        /* hash chain linkage             */
22     short        c_flags;       /* misc. flags (from fmt_scan)    */
23     short        c_type;        /* type info   (from fmt_compile) */
24     union {
25         struct tws *c_u_tws;
26         struct mailname *c_u_mn;
27     } c_un;
28     int          c_refcount;    /* Reference count                */
29 };
30
31 #define c_tws c_un.c_u_tws
32 #define c_mn  c_un.c_u_mn
33
34 /*
35  * c_type bits
36  */
37 #define CT_ADDR       (1<<0)    /* referenced as address    */
38 #define CT_DATE       (1<<1)    /* referenced as date       */
39
40 /*
41  * c_flags bits
42  */
43 #define CF_TRUE       (1<<0)    /* usually means component is present */
44 #define CF_PARSED     (1<<1)    /* address/date has been parsed */
45 #define CF_DATEFAB    (1<<2)    /* datefield fabricated */
46 #define CF_TRIMMED    (1<<3)    /* Component has been trimmed */
47
48 extern int fmt_norm;
49
50 /*
51  * This structure defines one formatting instruction.
52  */
53 struct format {
54     unsigned char f_type;
55     char          f_fill;
56     short         f_width;      /* output field width   */
57     union {
58         struct comp *f_u_comp;  /* associated component */
59         char        *f_u_text;  /* literal text         */
60         char         f_u_char;  /* literal character    */
61         int          f_u_value; /* literal value        */
62     } f_un;
63     short         f_flags;      /* misc. flags          */
64 };
65
66 #define f_skip f_width          /* instr to skip (false "if") */
67
68 #define f_comp  f_un.f_u_comp
69 #define f_text  f_un.f_u_text
70 #define f_char  f_un.f_u_char
71 #define f_value f_un.f_u_value
72
73 /*
74  * f_flags bits
75  */
76
77 #define FF_STRALLOC     (1<<0)  /* String has been allocated */
78 #define FF_COMPREF      (1<<1)  /* Component reference */
79
80 /*
81  * prototypes used by the format engine
82  */
83
84 /*
85  * Create a new format string.  Arguments are:
86  *
87  * form         - Name of format file.  Will be searched by etcpath(), see that
88  *                function for details.
89  * format       - The format string to be used if no format file is given
90  * default_fs   - The default format string to be used if neither form nor
91  *                format is given
92  *
93  * This function also takes care of processing \ escapes like \n, \t, etc.
94  *
95  * Returns an allocated format string.
96  */
97
98 char *new_fs (char *form, char *format, char *default_fs);
99
100 /*
101  * Compile a format string into a set of format instructions.  Arguments are:
102  *
103  * fstring      - The format string (the "source code").
104  * fmt          - Returns an allocated array of "struct fmt" elements.  Each
105  *                struct fmt is one format instruction interpreted by the
106  *                format engine.
107  * reset        - If set to true, the format compiler will reset the
108  *                component hash table.  The component hash table contains
109  *                all of the references to message components refered to in
110  *                the format instructions.  If you have multiple format
111  *                strings that you want to compile and operate on the
112  *                same message, this should be set to false.
113  *
114  * Returns the number of components referenced by the format instructions.
115  */
116
117 int fmt_compile (char *fstring, struct format **fmt, int reset);
118
119 /*
120  * Interpret a sequence of compiled format instructions.  Arguments are:
121  *
122  * format       - Array of format instructions generated by fmt_compile()
123  * scanl        - Passed-in character array that will contain the output
124  *                of the format instructions.  Is always terminated with
125  *                a newline (\n).
126  * max          - Maximum number of bytes to be written to "scanl" (in other
127  *                words, the buffer size).  Includes the trailing NUL.
128  * width        - Maximum number of displayed characters.  Does not include
129  *                characters marked as nonprinting or (depending on the
130  *                encoding) bytes in a multibyte encoding that exceed the
131  *                character's column width.
132  * dat          - An integer array that contains data used by certain format
133  *                functions.  Currently the following instructions use
134  *                dat[]:
135  *
136  *              dat[0] - %(msg), %(dat)
137  *              dat[1] - %(cur)
138  *              dat[2] - %(size)
139  *              dat[3] - %(width)
140  *              dat[4] - %(unseen)
141  *
142  * The return value is a pointer to the next format instruction to
143  * execute, which is currently always NULL.
144  */
145
146 struct format *fmt_scan (struct format *format, char *scanl, size_t max,
147                          int width, int *dat);
148
149 /*
150  * Free a format structure and/or component hash table.  Arguments are:
151  *
152  * format       - An array of format structures allocated by fmt_compile,
153  *                or NULL.
154  * reset        - If true, reset and remove all references in the component
155  *                hash table.
156  */
157
158 void fmt_free (struct format *fmt, int reset);
159
160 /*
161  * Search for a component structure in the component hash table.  Arguments are:
162  *
163  * component    - The name of the component to search for.  By convention
164  *                all component names used in format strings are lower case,
165  *                but for backwards compatibility this search is done in
166  *                a case-SENSITIVE manner.
167  *
168  * This function returns a "struct comp" corresponding to the named component,
169  * or NULL if the component is not found in the hash table.
170  */
171
172 struct comp *fmt_findcomp(char *component);
173
174 /*
175  * Add a string to a component hash table entry.  Arguments are:
176  *
177  * component    - The name of the component to add text to.  The component
178  *                is searched for in a case-INSENSITIVE manner (note that
179  *                this is different than fmt_findcomp()).  If the component
180  *                is not found in the hash table, this function will silently
181  *                return.
182  * text         - The text to add to a component hash table entry.  Note that
183  *                if the last character of the existing component
184  *                text is a newline AND it is marked as an address
185  *                component (the the CT_ADDR flag is set) existing
186  *                component buffer is a newline, it will be separated
187  *                from previous text by ",\n\t"; otherwise if the last
188  *                character of the previous text is a newline it will
189  *                simply be seperated by a "\t".  This unusual processing
190  *                is designed to handle the case where you have multiple
191  *                headers with the same name (e.g.: multiple "cc:" headers,
192  *                even though that isn't technically allowed in the RFCs).
193  *
194  * This function is designed to be called when you start processing a new
195  * component.  The function returns the integer value of the hash table
196  * bucket corresponding to this component.
197  */
198
199 int fmt_addcomp(char *component, char *text);
200
201 /*
202  * Append to an existing component.  Arguments are:
203  *
204  * bucket       - The hash table bucket corresponding to this component,
205  *                as returned by fmt_addcomp().
206  * component    - The component to append text to.  Like fmt_addcomp, the
207  *                component is searched case-INSENSITIVELY.
208  * text         - The text to append to the component.  No special processing
209  *                is done.
210  *
211  * This function is designed to be called when you are processing continuation
212  * lines on the same header (state == FLDPLUS).
213  */
214
215 void fmt_appendcomp(int bucket, char *component, char *text);
216
217 /*
218  * The implementation of the %(formataddr) function.  This is available for
219  * programs to provide their own local implementation if they wish to do
220  * special processing (see uip/replsbr.c for an example).  Arguments are:
221  *
222  * orig         - Existing list of addresses
223  * str          - New address(es) to append to list.
224  *
225  * This function returns an allocated string containing the new list of
226  * addresses.
227  */
228
229 char *formataddr(char *orig, char *str);
230
231 /*
232  * The implementation of the %(concataddr) function.  Arguments and behavior
233  * are the same as %(formataddr).  Again, see uip/replsbr.c to see how you
234  * can override this behavior.
235  */
236
237 char *concataddr(char *orig, char *str);