Update with new functions and comments describing them.
[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  * 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.  
55  */
56 #define CHASH(nm) (((((nm)[0]) - ((nm)[1])) & 0x1f) + (((nm)[2]) & 0x5f))
57
58 /*
59  * Find a component in the hash table.
60  */
61 #define FINDCOMP(comp,name) \
62                 for (comp = wantcomp[CHASH(name)]; \
63                      comp && strcmp(comp->c_name,name); \
64                      comp = comp->c_next) \
65                 ;
66
67 /*
68  * This structure defines one formatting instruction.
69  */
70 struct format {
71     unsigned char f_type;
72     char          f_fill;
73     short         f_width;      /* output field width   */
74     union {
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        */
79     } f_un;
80 };
81
82 #define f_skip f_width          /* instr to skip (false "if") */
83
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
88
89 /*
90  * prototypes used by the format engine
91  */
92
93 /*
94  * Create a new format string.  Arguments are:
95  *
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
100  *                format is given
101  *
102  * This function also takes care of processing \ escapes like \n, \t, etc.
103  *
104  * Returns an allocated format string.
105  */
106
107 char *new_fs (char *form, char *format, char *default_fs);
108
109 /*
110  * Compile a format string into a set of format instructions.  Arguments are:
111  *
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
115  *                format engine.
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.
122  *
123  * Returns the number of components referenced by the format instructions.
124  */
125
126 int fmt_compile (char *fstring, struct format **fmt, int reset);
127
128 /*
129  * Interpret a sequence of compiled format instructions.  Arguments are:
130  *
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
134  *                a newline (\n).
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
143  *                dat[]:
144  *
145  *              dat[0] - %(msg), %(dat)
146  *              dat[1] - %(cur)
147  *              dat[2] - %(size)
148  *              dat[3] - %(width)
149  *              dat[4] - %(unseen)
150  *
151  * The return value is a pointer to the next format instruction to
152  * execute, which is currently always NULL.
153  */
154
155 struct format *fmt_scan (struct format *format, char *scanl, size_t max,
156                          int width, int *dat);
157
158 /*
159  * Free a format structure and/or component hash table.  Arguments are:
160  *
161  * format       - An array of format structures allocated by fmt_compile,
162  *                or NULL.
163  * reset        - If true, reset and remove all references in the component
164  *                hash table.
165  */
166
167 void fmt_free (struct format *fmt, int reset);
168
169 /*
170  * Search for a component structure in the component hash table.  Arguments are:
171  *
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.
176  *
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.
179  */
180
181 struct comp *fmt_findcomp(char *component);
182
183 /*
184  * Add a string to a component hash table entry.  Arguments are:
185  *
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
190  *                return.
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).
202  *
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.
206  */
207
208 int fmt_addcomp(char *component, char *text);
209
210 /*
211  * Append to an existing component.  Arguments are:
212  *
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
218  *                is done.
219  *
220  * This function is designed to be called when you are processing continuation
221  * lines on the same header (state == FLDPLUS).
222  */
223
224 void fmt_appendcomp(int bucket, char *component, char *text);
225
226 /*
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:
230  *
231  * orig         - Existing list of addresses
232  * str          - New address(es) to append to list.
233  *
234  * This function returns an allocated string containing the new list of
235  * addresses.
236  */
237
238 char *formataddr(char *orig, char *str);
239
240 /*
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.
244  */
245
246 char *concataddr(char *orig, char *str);