aboutsummaryrefslogtreecommitdiff
path: root/src/snarf.m4
blob: f8aae7939d6a55675632216e62cb52775a8daa73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
m4_divert(-1)m4_dnl -*- m4 -*-
# This file is part of mailfromd. 
# Copyright (C) 2006, 2007 Sergey Poznyakoff
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

m4_changequote([<,>])
m4_changecom(/*,*/)

/* MF_MODULE_NAME() - Returns the name of the current module.
 */
m4_define([<MF_MODULE_NAME>],[<m4_dnl
m4_patsubst(m4___file__,\(.*/\)?bi_\(.*\)\.m4,\2)>])

/* MF_SOURCE_DEBUG_NAME(MODULE) - Initialize the "debug" name for the MODULE.
 */
m4_define([<MF_SOURCE_DEBUG_NAME>],[<m4_dnl
#define [<MF_SOURCE_NAME  MF_SOURCE_>]m4_dnl
m4_translit(m4_patsubst($1,\(.*/\)?\(.*\)\.m4,\2),[<a-z->],[<A-Z_>])>])

/* MF_MODULE_MASK() - Returns BUILTIN_MASK_ constant for the current module.
 */
m4_define([<MF_MODULE_MASK>],[<m4_dnl
[<BUILTIN_MASK_>]MF_MODULE_NAME()>])

/* __mf_argtype(arg) -- return Mailfromd value type code corresponding to
 * ARG: 
 *   __mf_argtype(STRING) => dtype_string
 *   __mf_argtype(NUMBER) => dtype_number
 *   __mf_argtype(anything) => dtype_unspecified
 */
m4_define([<__mf_argtype>],m4_dnl
[<m4_ifelse($1,STRING,dtype_string,$1,NUMBER,dtype_number,m4_dnl
dtype_unspecified)>])

/* mf_argtype(TYPE NAME) -- return Mailfromd value type code corresponding to
 * TYPE. See __mf_argtype above.
 */
m4_define([<mf_argtype>],m4_dnl
[<__mf_argtype(m4_patsubst([<$1>],[<[ \t].*>],))>])

/* mf_typelist(arglist) -- convert ARGLIST into a list of corresponding
 * Mailfromd value type codes. e.g.:
 * mf_typelist(STRING a, NUMBER b) => dtype_string, dtype_number
 */
m4_define([<mf_typelist>],m4_dnl
[<m4_ifelse($#, 1, [<mf_argtype($1)>], m4_dnl,
$1, [<OPTIONAL>], [<mf_typelist(m4_shift($@))>],
[<mf_argtype($1), >]m4_dnl
[<mf_typelist(m4_shift($@))>])>])

/* __mf_has_optarg(ARGS..) -- return 1 if ARGS contain OPTIONAL keyword, and
 * 0 otherwise
 */
m4_define([<__mf_has_optarg>],m4_dnl
[<m4_ifelse($1, , 0,$1,[<OPTIONAL>], 1,[<m4_dnl
__mf_has_optarg(m4_shift($@))>])>])

/* __mf_c_type(TYPE) -- return a C type corresponding to the Mailfromd one
 */
m4_define([<__mf_c_type>],m4_dnl
[<m4_ifelse($1,STRING,char *,$1,NUMBER,long , ERROR )>])

/* __mf_c_getarg(TYPE) -- return a get_(.*)_arg function for the given MFL
 * TYPE
 */
m4_define([<__mf_c_getarg>],m4_dnl
[<m4_ifelse($1,STRING,get_string_arg,$1,NUMBER,get_numeric_arg, ERROR )>])

/* mf_c_argdcl(TYPE NAME) -- translate Mailfromd declaration "TYPE NAME"
 * into the corresponding C one, followed by an equals sign, a typecast,
 * and the name of corresponding get_.*_arg function
 * e.g.:
 *   mf_c_argdcl(STRING str) => char *str = (char*) get_string_arg
 */
m4_define([<mf_c_argdcl>],m4_dnl
[<m4_regexp([<$1>],[<\(\w+\)\W+\(\w+\)>],[<__mf_c_type(\1)>] \2 = ([<__mf_c_type(\1)>]) [<__mf_c_getarg(\1)>])>])

/* __mf_c_arglist(NARG, LIST) -- translate Mailfromd declaration list
 * into a set of corresponding C variable declarations with initializations.
 * Arguments:
 *  NARG -- ordinal number of the first variable in LIST
 *  LIST -- comma-separated list of Mailfromd declarations
 */
m4_define([<__mf_c_arglist>],m4_dnl
[<m4_ifelse($2, , ,$2,[<OPTIONAL>],[<m4_dnl
__mf_c_arglist($1, m4_shift(m4_shift($@)))>],
[<mf_c_argdcl($2)(env, m4_eval($1));
        __mf_c_arglist(m4_incr($1), m4_shift(m4_shift($@)))>])>])

/* mf_c_arglist(LIST) -- translate Mailfromd declaration list
 * into a set of corresponding C variable declarations with initializations.
 * Insert an instruction to adjust the stack parameters after obtaining the
 * variables.
 * E.g.:
 *   mf_c_arglist(STRING a, NUMBER n) =>
 *         char *a = (char*)get_string_arg(env, 0);
 *         long n = (long)get_numeric_arg(env, 1);
 *         adjust_stack(env, 2);
 *
 * Or, if the builtin takes optional parameters:
 *
 *  mf_c_arglist(STRING a, NUMBER n) =>
 *         long __bi_argcnt = (long)get_numeric_arg(env, 0);
 *         char *a = (char*)get_string_arg(env, 1);
 *         long n = (long)get_numeric_arg(env, 2);
 *         adjust_stack(env, __bi_argcnt + 1);
 */
m4_define([<mf_c_arglist>],m4_dnl
[<
m4_pushdef([<__ARG1__>], m4_ifelse(__MF_VARARGS__,1,1,[<__mf_has_optarg($@)>]))
m4_ifelse(__ARG1__,0,,[<long __bi_argcnt = (long)get_numeric_arg(env, 0);>])
__mf_c_arglist(__ARG1__, $@)
        adjust_stack(env, m4_ifelse(__ARG1__,0,mf_argcount($@),__bi_argcnt + 1));
m4_popdef([<__ARG1__>])m4_dnl
>])

/* __mf_printf_type(TYPE) -- translate the Mailfromd data type TYPE into the
 * printf metacharacter useful to output it.
 */
m4_define([<__mf_printf_type>],m4_dnl
[<m4_ifelse($1,STRING,s,$1,NUMBER,lu,%?)>])

/* mf_printf_macro(TYPE NAME) -- translate TYPE to the printf metacharacter
 * for use in *printf functions.
 */
m4_define([<mf_printf_macro>],m4_dnl
[<%[<>]m4_regexp([<$1>],[<\(\w+\)\W+.*>],[<__mf_printf_type(\1)>])>])

/* mf_printf_list(LIST) -- convert the list of Mailfromd variable declarations
 * to a space-separated list of printf macros to print them:
 *   mf_printf_list(STRING a, NUMBER b) => %s %lu
 */
m4_define([<mf_printf_list>],m4_dnl
[<m4_ifelse($1,,,$1,[<OPTIONAL>],m4_dnl
[<mf_printf_list(m4_shift($@))>],m4_dnl
[< mf_printf_macro($1)[<>]mf_printf_list(m4_shift($@))>])>])

/* __mf_argname(TYPE NAME) -- return NAME
 */
m4_define([<__mf_argname>],m4_dnl
[<m4_regexp($1,[<\w+\W+\(\w+\)>],\1)>])

/* mf_argnames(LIST) -- extract names from the Mailfromd declaration list:
 *  mf_argnames(STRING a, NUMBER b) => a, b
 */
m4_define([<mf_argnames>],m4_dnl
[<m4_ifelse($#,1, [<__mf_argname($1)>],m4_dnl
$1,[<OPTIONAL>],[<mf_argnames(m4_shift($@))>],m4_dnl
[<__mf_argname($1), mf_argnames(m4_shift($@))>])>])

/* __mf_defined_argname(TYPE NAME) -- Same as __mf_argname, but wrap the
 * argument into MF_OPTVAL if necessary
 */
m4_define([<__mf_defined_argname>],m4_dnl
[<m4_ifelse($1,1,[<m4_dnl
MF_OPTVAL(__mf_argname($2),m4_ifelse(mf_argtype($2),[<dtype_string>],"",0))>],m4_dnl
[<__mf_argname($2)>])>])

/* __mf_defined_argnames(LIST) -- Same as __mf_argnames, but arguments after
 * the OPTIONAL keywords are protected by MF_OPTVAL
 */
m4_define([<__mf_defined_argnames>],m4_dnl
[<m4_ifelse($#,2, [<__mf_defined_argname($1,$2)>],m4_dnl
$2,[<OPTIONAL>],[<__mf_defined_argnames(1,m4_shift(m4_shift($@)))>],m4_dnl
[<__mf_defined_argname($1,$2), m4_dnl
__mf_defined_argnames($1,m4_shift(m4_shift($@)))>])>])

/* mf_defined_argnames(LIST) -- Same as mf_argnames, but arguments after
 * the OPTIONAL keywords are protected by MF_OPTVAL
 */
m4_define([<mf_defined_argnames>],m4_dnl
[<__mf_defined_argnames(0,$@)>])

/* __mf_argpos(POS,NEEDLE,STACK...) - Return position at which NEEDLE occurs in
 * STACK
 * Arguments:
 *  POS    -  Current position
 *  NEEDLE -  String to find
 *  STACK  -  Argument list
 * Example:
 *  __mf_argpos(0, x, a, b, x) => 2
 */
m4_define([<__mf_argpos>],m4_dnl
[<m4_ifelse($2,$3,$1,$3,,[<m4_errprint(m4___file__:m4___line__: No such variable >]$2[<
)>],[<__mf_argpos(m4_incr($1), $2, m4_shift(m4_shift(m4_shift($@))))>])>])

/* mf_argpos(ARG, TYPE1 ARG1, TYPE2 ARG2 ...) - Return (zero-based) position
 * of ARG in the argument list:
 *
 *  mf_argpos(x, STRING a, NUMBER b, OPTIONAL, STRING x) => 3
 */
m4_define([<mf_argpos>],m4_dnl
[<__mf_argpos(0, $1, mf_argnames(m4_shift($@)))>])

/* __mf_defined(NAME, ARGS...) -- Scan ARGS... for the definition
 * of the built-in function parameter NAME, and return a C conditional
 * expression that yields true if it is defined.
 * ARGS are parameter declarations in the form:
 *      TYPE NAME
 */
m4_define([<__mf_defined>],
[<m4_ifelse(__mf_has_optarg($@),0,1,m4_dnl
[<__bi_argcnt > mf_argpos($1,__MF_ARGLIST__)>])>])

/* MF_DEFINED(NAME) -- Return a C conditional expression
 * that yields true if the parameter NAME is defined.
 *
 *  __MF_ARGLIST__ => STRING a, NUMBER b, OPTIONAL, STRING x
 *  MF_DEFINED(x) => (__bi_argcnt > 2)
 *
 *  __MF_ARGLIST__ => STRING a, NUMBER b, STRING x
 *  MF_DEFINED(x) => (1)
 */
m4_define([<MF_DEFINED>],
[<m4_ifdef([<__MF_ARGLIST__>],([<__mf_defined($1, __MF_ARGLIST__)>]),m4_dnl
[<m4_errprint(m4___file__:m4___line__: [<MF_DEFINED used out of functional context>])>])>])

/* MF_OPTVAL(NAME[, DEFVAL]) -- If the parameter NAME is defined, return
 * its value, otherwise return DEFVAL or 0
 */
m4_define([<MF_OPTVAL>],
[<m4_ifdef([<__MF_ARGLIST__>],m4_dnl
[<(MF_DEFINED($1) ? $1 : m4_ifelse([<$2>],,0,$2))>],m4_dnl
[<m4_errprint(m4___file__:m4___line__: [<MF_OPTVAL used out of functional context>])>])>])

/* __mf_check_end() -- signal error if the previous MF_DEFUN statement was
 * not properly closed with END
 */
m4_define([<__mf_check_end>],m4_dnl
[<m4_ifdef([<__MF_FUNCTION__>],m4_dnl
[<m4_errprint(m4___file__:m4___line__: Function '>]__MF_FUNCTION__[<' was not closed
)
m4_popdef([<__MF_FUNCTION__>])
m4_define([<__mf_error_code>],1)>])>])

/* MF_STATE(state) - Declare next MF_DEFUN as valid only in the given state.
 * The state argument is any valid milter state, as declared in
 * enum smtp_state (see mailfromd.h around line 74--87), but withouth the
 * `smtp_state_' prefix.
 *
 * Multiple occurrences of MF_STATE accumulate.
 */
m4_define([<MF_STATE>],
[<m4_ifdef([<__MF_STATE__>],m4_dnl
[<m4_define([<__MF_STATE__>],__MF_STATE__[< | EXMASK(smtp_state_$1)>])>],m4_dnl
[<m4_define([<__MF_STATE__>],[<EXMASK(smtp_state_$1)>])>])>])

/* MF_CAPTURE - Declare next MF_DEFUN as requiring message capturing
 */
m4_define([<MF_CAPTURE>],
[<m4_ifdef([<__MF_CAPTURE__>],,[<m4_define([<__MF_CAPTURE__>],1)>])>])

/* env_get_stream - a wrapper around the library function of the same name.
 * Expand to the function invocation only if the current function is declared
 * with capture attribute or the invocation is issued outside of a defun.
 */
m4_define([<env_get_stream>],m4_dnl
[<m4_ifdef([<__MF_FUNCTION__>],m4_dnl
[<m4_ifdef([<__MF_CAPTURE__>],[<[<env_get_stream>]($@)>],m4_dnl
[<m4_errprint(m4___file__:m4___line__: [<env_get_stream is illegal here, the function `>]__MF_FUNCTION__[<' is not declared with MF_CAPTURE>]
)
m4_define([<__mf_error_code>],1)>])>],m4_dnl
[<env_get_stream>])>])

/* mf_optcount(ARGS...) -- Return the number of optional arguments in ARGS
 */
m4_define([<mf_optcount>],[<m4_dnl
m4_ifelse($#,1,0,$1,[<OPTIONAL>],m4_eval($# - 1),[<mf_optcount(m4_shift($@))>])>])

/* __mf_argcount(COUNT, ARGS...) -- Auxiliary function for mf_argcount
 *   COUNT is number of arguments counted so far
 *   ARGS are the rest of the arguments
 */
m4_define([<__mf_argcount>],[<m4_dnl
m4_ifelse($#,2,$1,$2,[<OPTIONAL>],[<__mf_argcount($1, m4_shift(m4_shift($@)))>],m4_dnl
[<__mf_argcount(m4_incr($1), m4_shift(m4_shift($@)))>])>])

/* mf_argcount(ARGS...) -- Return the number of arguments in ARGS, not
 * counting eventual OPTIONAL modifier.
 */
m4_define([<mf_argcount>],[<m4_dnl
m4_ifelse($1,,0,__mf_argcount(1,$@))>])

/* mf_prog_trace(fname[, args...])
 */
m4_define([<mf_prog_trace>],[<m4_dnl
prog_trace(env, "$1[<>]mf_printf_list(m4_shift($@))"m4_dnl
m4_ifelse($2,,,[<,mf_defined_argnames(m4_shift($@))>]));>])

/* __mf_defun(VARARG, NAME, RETTYPE, ARGS...) -- Begin a built-in function
   declaration
 */
m4_define([<__mf_defun>],m4_dnl
[<__mf_check_end[<>]m4_dnl
void
bi_$2(eval_environ_t env)
m4_pushdef([<__MF_FUNCTION__>], $2)m4_dnl
m4_pushdef([<__MF_ARGLIST__>], [<m4_shift(m4_shift(m4_shift($*)))>])
m4_pushdef([<__MF_VARARGS__>], $1)m4_dnl
m4_divert(1)m4_dnl
va_builtin_install_ex("$2", bi_$2,m4_dnl
 m4_ifdef([<__MF_STATE__>],__MF_STATE__,0),m4_dnl
 m4_ifdef([<__MF_CAPTURE__>],__MF_CAPTURE__,0),m4_dnl
 __mf_argtype($3),m4_dnl
 mf_argcount(m4_shift(m4_shift(m4_shift($@)))),m4_dnl
 mf_optcount(m4_shift(m4_shift(m4_shift($@)))),m4_dnl
 $1,m4_dnl
 mf_typelist(m4_shift(m4_shift(m4_shift($@)))));
m4_divert(0)m4_dnl
{
	mf_c_arglist(m4_shift(m4_shift(m4_shift($@))))
	if (prog_trace_option & MF_MODULE_MASK)
		mf_prog_trace($2,m4_shift(m4_shift(m4_shift($@))));
>])

m4_define([<MF_DEFUN>],[<__mf_defun(0, $@)>])

m4_define([<MF_DEFUN_VARARGS>],[<m4_dnl
m4_ifelse(__mf_has_optarg(m4_shift(m4_shift(m4_shift($@)))),0,m4_dnl
[<__mf_defun(1, $@)>],m4_dnl
[<m4_errprint(m4___file__:m4___line__: A vararg function cannot take optional arguments
)
m4_define([<__mf_error_code>],1)>])>])

/* MF_RETURN(value) - Return a numeric value
 */
m4_define([<MF_RETURN>],[<
m4_ifdef([<__MF_VA_START_USED__>],[<m4_dnl
m4_errprint(m4___file__:m4___line__: [<MF_RETURN>] used before [<MF_VA_END>]
)
m4_define([<__mf_error_code>],1)>],[<m4_dnl
do {
  push(env, (STKVAL) ($1));
  return;
} while (0)>])>])

/* MF_RETURN_STRING(value) - Return a string value
 */
m4_define([<MF_RETURN_STRING>],[<m4_dnl
m4_ifdef([<__MF_VA_START_USED__>],[<m4_dnl
m4_errprint(m4___file__:m4___line__: [<MF_RETURN_STRING>] used before [<MF_VA_END>]
)
m4_define([<__mf_error_code>],1)>],[<do {m4_dnl
pushs(env, $1);
return;
} while (0)>])>])

/* MF_ALLOC_HEAP(off, len) - Allocate LEN bytes from the heap
 */
m4_define([<MF_ALLOC_HEAP>],[<m4_dnl
(char*) env_data_ref(env, ([<$1>] = heap_reserve(env, $2)))>])

/* MF_ALLOC_HEAP_TEMP(len) - Temporarly allocate LEN bytes from the heap.
 */
m4_define([<MF_ALLOC_HEAP_TEMP>],[<heap_tempspace(env, $1)>])

/* MF_COPY_STRING(off, string) - Copy STRING to the heap.  Return the
 * pointer to the copy.
 */
m4_define([<MF_COPY_STRING>],[<m4_dnl
strcpy((char*)env_data_ref(env, $1 = heap_reserve(env, strlen($2) + 1)), $2)>])

/* MF_OBSTACK_BEGIN() - Begin temporary space manipulations
 * NOTE: No other heap manipulation function can be used between
 * MF_OBSTACK_BEGIN and MF_OBSTACK_CANCEL/MF_RETURN_OBSTACK
 */
m4_define([<MF_OBSTACK_BEGIN>],[<heap_obstack_begin(env)>])

m4_define([<MF_OBSTACK_GROW>],[<m4_dnl
m4_ifelse($2,,[<
do {
  char *__s = $1;
  m4_ifelse($#,3,[<$3 = >])heap_obstack_grow(env, __s, strlen(__s));
} while (0)>],[<m4_ifelse($#,3,[<$3 = >])heap_obstack_grow(env, $1, $2)>])>])

m4_define([<MF_OBSTACK_1GROW>],[<m4_dnl
do { int __c = $1; heap_obstack_grow(env, &__c, 1); } while(0)>])

m4_dnl /* MF_OBSTACK_CANCEL - Cancel temporary heap allocation initiated by
m4_dnl  * MF_OBSTACK_BEGIN
m4_fnl  */
m4_dnl m4_define([<MF_OBSTACK_CANCEL>],[<heap_obstack_cancel(env)>])

/* MF_RETURN_OBSTACK() - Relocate and return temporary space 
 */
m4_define([<MF_RETURN_OBSTACK>],[<MF_RETURN(heap_obstack_finish(env))>])

/* MF_VA_START() -- Begin a code section for handing varying number
   of arguments. */
m4_define([<MF_VA_START>],[<
m4_ifelse(__MF_VARARGS__,1,[<m4_dnl
m4_define([<__MF_VA_START_USED__>],m4___file__:m4___line__)m4_dnl
unroll_stack(env, __bi_argcnt + 1)>],
[<m4_errprint(m4___file__:m4___line__: [<MF_VA_START>] used but `__MF_FUNCTION__' does not take variable number of arguments
)m4_dnl
m4_define([<__mf_error_code>],1)>])>])

/* MF_VA_END() -- End a section, started with MF_VA_START */
m4_define([<MF_VA_END>],[<m4_dnl
m4_ifdef([<__MF_VA_START_USED__>],[<m4_dnl
m4_undefine([<__MF_VA_START_USED__>])m4_dnl
adjust_stack(env, __bi_argcnt + 1)>],m4_dnl
[<m4_errprint(m4___file__:m4___line__: [<MF_VA_END>] without previous [<MF_VA_START>]
)
m4_define([<__mf_error_code>],1)>])>])

/* __mf_va_count() -- return number of variable arguments passed to the current
   vararg function */
m4_define([<__mf_va_count>],[<m4_dnl
(__bi_argcnt - mf_argcount(__MF_ARGLIST__))>])

/* MF_VA_COUNT() -- return actual number of variable arguments passed to the
   function.  Bail out if the function is not a vararg one. */
m4_define([<MF_VA_COUNT>],[<m4_dnl
m4_ifelse(__MF_VARARGS__,1,[<__mf_va_count>],
[<m4_errprint(m4___file__:m4___line__: [<MF_VA_COUNT>] used but `__MF_FUNCTION__' does not take variable number of arguments
)m4_dnl
m4_define([<__mf_error_code>],1)>])>])

/* MF_VA_ARG(N, TYPE) -- Produce a code for returning Nth argument of the
   given TYPE in a vararg section. */
m4_define([<MF_VA_ARG>],[<m4_dnl
m4_ifdef([<__MF_VA_START_USED__>],m4_dnl
[<m4_pushdef([<__ARGN__>],[<$1+mf_argcount(__MF_ARGLIST__)>])
 ((__bi_argcnt > __ARGN__) ?m4_dnl 
   __mf_c_getarg($2)(env, __ARGN__ + 1) :m4_dnl
   (MF_THROW(mf_range, "Argument %d is not supplied", __ARGN__),m4_dnl
(__mf_c_type($2)) 0))m4_dnl
m4_popdef([<__ARGN__>])>],
[<m4_errprint(m4___file__:m4___line__: [<MF_VA_ARG>] without previous [<MF_VA_START>]
)
m4_define([<__mf_error_code>],1)>])>])

/* MF_VAR(name,type) - Declare a global variable NAME of type TYPE.
 */
m4_define([<MF_VAR>],[<m4_dnl
static size_t $1_loc
m4_divert(1)m4_dnl
	$1_loc = builtin_variable_install("$1", __mf_argtype($2), VAR_VOLATILE)->off;
m4_divert(0)m4_dnl
>])

/* MF_VAR_REF(name[, value]) - Reference global variable NAME
 * In one-argument form, return its value.  In two-arguments form, assign
 * the VALUE to it.
 */
m4_define([<MF_VAR_REF>],[<m4_dnl
*env_data_ref(env, $1_loc) m4_ifelse($2,,,= (STKVAL) ($2))>])

/* MF_VAR_SET_STRING(name, value) - Set variable NAME to the string VALUE */
m4_define([<MF_VAR_SET_STRING>],[<
{ size_t off;
  if ($2)
     MF_COPY_STRING(off, $2);
  else
     off = 0;
  MF_VAR_REF($1, off); }
>])

/* MF_VAR_INC(name) - Increment the value of the global variable NAME
 */
m4_define([<MF_VAR_INC>],[<m4_dnl
env_var_inc(env, $1_loc)>])

/* MF_DECLARE_DATA(name, init [, destr]) - Declare private data for 
 * the current module.
 *  NAME  - data identifier.
 *  INIT  - initialization function (void init(void))
 *  DESTR - destructor function (void destr(void*))
 */
m4_define([<MF_DECLARE_DATA>],[<
m4_define([<__MF_PRIV_ID__>],$1_id)
static int __MF_PRIV_ID__;
m4_divert(1)m4_dnl
__MF_PRIV_ID__ = builtin_priv_register($2, m4_dnl
m4_ifelse($3,,NULL,$3));
m4_divert(0)m4_dnl
>])

/* MF_GET_DATA - Return pointer to the private data, declared with 
 * MF_DECLARE_DATA
 */
m4_define([<MF_GET_DATA>],[<m4_dnl
m4_ifdef([<__MF_PRIV_ID__>],[<m4_dnl
env_get_builtin_priv(m4_ifelse($1,,env,$1),__MF_PRIV_ID__)>],m4_dnl
[<m4_errprint(m4___file__:m4___line__: private data not declared (call [<MF_DECLARE_DATA>] first)
)
m4_define([<__mf_error_code>],1)
>])>])

/* MF_THROW(exception, ...)
 */
m4_define([<MF_THROW>],[<m4_dnl
	env_throw_bi(env, $1, m4_ifdef([<__MF_FUNCTION__>],m4_dnl
"__MF_FUNCTION__", NULL), m4_shift($@))>])

/* MF_ASSERT(cond, exception, ...)
 */
m4_define([<MF_ASSERT>],[<m4_dnl
	if (!($1))
		MF_THROW(m4_shift($@))
>])

/* END -- Finish the built-in function declaration, created with MF_DEFUN
 */
m4_define([<END>],m4_dnl
[<m4_ifdef([<__MF_VA_START_USED__>],[<m4_dnl
m4_errprint(m4___file__:m4___line__: Missing [<MF_VA_END>]
)m4_dnl
m4_errprint(>]__MF_VA_START_USED__[<: This is the location of [<MF_VA_START>]
)m4_dnl
m4_define([<__mf_error_code>],1)m4_dnl
m4_undefine([<__MF_VA_START_USED__>])>])m4_dnl
m4_popdef([<__MF_FUNCTION__>])m4_dnl
m4_popdef([<__MF_ARGLIST__>])m4_dnl
m4_popdef([<__MF_VARARGS__>])m4_dnl
m4_undefine([<__MF_CAPTURE__>])m4_dnl
m4_undefine([<__MF_STATE__>])m4_dnl
}>])

/* MF_INIT(CODE) -- create the initialization function for the curent module.
 * The function will be named MODNAME_init_builtin.
 */
m4_define([<MF_INIT>],m4_dnl
[<__mf_check_end[<>]m4_dnl
m4_undefine([<__MF_PRIV_ID__>])m4_dnl
m4_define([<__MF_INIT__>],1)
void
MF_MODULE_NAME()_init_builtin()
{
	m4_undivert(1)
	$1	
}>])

m4_m4wrap([<__mf_check_end
m4_ifdef([<__MF_INIT__>],,[<m4_errprint([<MF_INIT>] not defined
)
m4_define([<__mf_error_code>],1)>])
m4_ifdef([<__mf_error_code>],[<m4_m4exit(__mf_error_code)>])>])

m4_divert(0)m4_dnl
/* -*- buffer-read-only: t -*- vi: set ro:
   THIS FILE IS GENERATED AUTOMATICALLY.  PLEASE DO NOT EDIT.
*/
MF_SOURCE_DEBUG_NAME(SOURCE)
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include "mailfromd.h"
#include "prog.h"
#include "builtin.h"

m4_dnl End of snarf.m4

Return to:

Send suggestions and report system problems to the System administrator.