3 * fmt_scan.h -- definitions for fmt_scan()
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.).
15 * In previous implementations "wantcomp" was made available to other
16 * functions, but now it's private and is accessed via functions.
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) */
26 struct mailname *c_u_mn;
28 int c_refcount; /* Reference count */
31 #define c_tws c_un.c_u_tws
32 #define c_mn c_un.c_u_mn
37 #define CT_ADDR (1<<0) /* referenced as address */
38 #define CT_DATE (1<<1) /* referenced as date */
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 */
51 * Hash function for component name. The function should be
52 * case independent and probably shouldn't involve a routine
53 * call. This function is pretty good but will not work on
54 * single character component names.
56 #define CHASH(nm) (((((nm)[0]) - ((nm)[1])) & 0x1f) + (((nm)[2]) & 0x5f))
59 * Find a component in the hash table.
61 #define FINDCOMP(comp,name) \
62 for (comp = wantcomp[CHASH(name)]; \
63 comp && strcmp(comp->c_name,name); \
64 comp = comp->c_next) \
68 * This structure defines one formatting instruction.
73 short f_width; /* output field width */
75 struct comp *f_u_comp; /* associated component */
76 char *f_u_text; /* literal text */
77 char f_u_char; /* literal character */
78 int f_u_value; /* literal value */
82 #define f_skip f_width /* instr to skip (false "if") */
84 #define f_comp f_un.f_u_comp
85 #define f_text f_un.f_u_text
86 #define f_char f_un.f_u_char
87 #define f_value f_un.f_u_value
90 * prototypes used by the format engine
94 * Create a new format string. Arguments are:
96 * form - Name of format file. Will be searched by etcpath(), see that
97 * function for details.
98 * format - The format string to be used if no format file is given
99 * default_fs - The default format string to be used if neither form nor
102 * This function also takes care of processing \ escapes like \n, \t, etc.
104 * Returns an allocated format string.
107 char *new_fs (char *form, char *format, char *default_fs);
110 * Compile a format string into a set of format instructions. Arguments are:
112 * fstring - The format string (the "source code").
113 * fmt - Returns an allocated array of "struct fmt" elements. Each
114 * struct fmt is one format instruction interpreted by the
116 * reset - If set to true, the format compiler will reset the
117 * component hash table. The component hash table contains
118 * all of the references to message components refered to in
119 * the format instructions. If you have multiple format
120 * strings that you want to compile and operate on the
121 * same message, this should be set to false.
123 * Returns the number of components referenced by the format instructions.
126 int fmt_compile (char *fstring, struct format **fmt, int reset);
129 * Interpret a sequence of compiled format instructions. Arguments are:
131 * format - Array of format instructions generated by fmt_compile()
132 * scanl - Passed-in character array that will contain the output
133 * of the format instructions. Is always terminated with
135 * max - Maximum number of bytes to be written to "scanl" (in other
136 * words, the buffer size). Includes the trailing NUL.
137 * width - Maximum number of displayed characters. Does not include
138 * characters marked as nonprinting or (depending on the
139 * encoding) bytes in a multibyte encoding that exceed the
140 * character's column width.
141 * dat - An integer array that contains data used by certain format
142 * functions. Currently the following instructions use
145 * dat[0] - %(msg), %(dat)
151 * The return value is a pointer to the next format instruction to
152 * execute, which is currently always NULL.
155 struct format *fmt_scan (struct format *format, char *scanl, size_t max,
156 int width, int *dat);
159 * Free a format structure and/or component hash table. Arguments are:
161 * format - An array of format structures allocated by fmt_compile,
163 * reset - If true, reset and remove all references in the component
167 void fmt_free (struct format *fmt, int reset);
170 * Search for a component structure in the component hash table. Arguments are:
172 * component - The name of the component to search for. By convention
173 * all component names used in format strings are lower case,
174 * but for backwards compatibility this search is done in
175 * a case-SENSITIVE manner.
177 * This function returns a "struct comp" corresponding to the named component,
178 * or NULL if the component is not found in the hash table.
181 struct comp *fmt_findcomp(char *component);
184 * Add a string to a component hash table entry. Arguments are:
186 * component - The name of the component to add text to. The component
187 * is searched for in a case-INSENSITIVE manner (note that
188 * this is different than fmt_findcomp()). If the component
189 * is not found in the hash table, this function will silently
191 * text - The text to add to a component hash table entry. Note that
192 * if the last character of the existing component
193 * text is a newline AND it is marked as an address
194 * component (the the CT_ADDR flag is set) existing
195 * component buffer is a newline, it will be separated
196 * from previous text by ",\n\t"; otherwise if the last
197 * character of the previous text is a newline it will
198 * simply be seperated by a "\t". This unusual processing
199 * is designed to handle the case where you have multiple
200 * headers with the same name (e.g.: multiple "cc:" headers,
201 * even though that isn't technically allowed in the RFCs).
203 * This function is designed to be called when you start processing a new
204 * component. The function returns the integer value of the hash table
205 * bucket corresponding to this component.
208 int fmt_addcomp(char *component, char *text);
211 * Append to an existing component. Arguments are:
213 * bucket - The hash table bucket corresponding to this component,
214 * as returned by fmt_addcomp().
215 * component - The component to append text to. Like fmt_addcomp, the
216 * component is searched case-INSENSITIVELY.
217 * text - The text to append to the component. No special processing
220 * This function is designed to be called when you are processing continuation
221 * lines on the same header (state == FLDPLUS).
224 void fmt_appendcomp(int bucket, char *component, char *text);
227 * The implementation of the %(formataddr) function. This is available for
228 * programs to provide their own local implementation if they wish to do
229 * special processing (see uip/replsbr.c for an example). Arguments are:
231 * orig - Existing list of addresses
232 * str - New address(es) to append to list.
234 * This function returns an allocated string containing the new list of
238 char *formataddr(char *orig, char *str);
241 * The implementation of the %(concataddr) function. Arguments and behavior
242 * are the same as %(formataddr). Again, see uip/replsbr.c to see how you
243 * can override this behavior.
246 char *concataddr(char *orig, char *str);