X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=sbr%2Ffmt_compile.c;h=173f12d44c0f8e5eb3a10b4a059c2855735efbb7;hp=c49a6eab7f13ae0c4127e67ee0ea2fb710173bca;hb=b33ba7a7953d06a123ee59811903f0eb7f69e120;hpb=b3628819b4ab903269cd83cc68e453b13534346c diff --git a/sbr/fmt_compile.c b/sbr/fmt_compile.c index c49a6ea..173f12d 100644 --- a/sbr/fmt_compile.c +++ b/sbr/fmt_compile.c @@ -4,6 +4,38 @@ ** This code is Copyright (c) 2002, by the authors of nmh. See the ** COPYRIGHT file in the root directory of the nmh distribution for ** complete copyright information. +** +** This code compiles the format strings (documented in mh-format(5)) into +** an internal form to be later processed by fmt_scan.c. +** +** What happens here is that the format strings are parsed and an array +** of struct format structures are returned. Each format structure is +** a single operation interpreted by the the routines in fmt_scan.c. +** +** There is a NOT a one-to-one correspondence between format strings and +** format instructions; some functions have side effects that can result +** in multiple instructions being generated. The exact list of instructions +** generated by a format string can be seem with the nmh fmtdump utility. +** +** A list of format instructions can be found in fmt_compile.h. +** +** If you wish to add a new function, you will need to do the following +** things: +** +** - Add a new instruction to the list of instructions in fmt_compile.h. +** Note that test instructions (starting with FT_IF_S_NULL) have special +** handling, so if you are NOT writing a test function then you need +** to insert it into the list before that _and_ bump all of the +** following instruction numbers. +** +** - Add the function name to the functable[] array below, and write any +** special code that your function may require in terms of parsing +** (it very well may not need anything). +** +** - Add the code in fmt_scan.c to handle your new function. +** +** - Document the new function in the mh-format(5) man page. +** */ #include @@ -51,6 +83,30 @@ extern struct mailname fmt_mnull; #define TFL_PUTS 1 /* implicit putstr if top level */ #define TFL_PUTN 2 /* implicit putnum if top level */ +/* +** The functable array maps between the text names of format functions and +** the format instructions interpreted by the engine in fmt_scan.c. +** +** The elements of this structure are as follows: +** +** name: The name of the function as seen in the format string. This is +** what maps a particular function name into a format instruction. +** type: The type of argument this function expects. Those types are +** listed above (with the TF_ prefix). This affects what gets +** placed in the format instruction (the f_un union). +** f_type: The instruction corresponding to this function (from the list +** in fmt_compile.h). +** extra: Used by some functions to provide extra data to the compiler. +** Uses include: +** - Providing an alternate instruction to combine a load +** and test operation (see do_if()). +** - Passed in f_value in the format instruction to provide +** extra information for the engine (see FT_LV_DAT handling +** in fmt_scan.c). +** - Provide a hint as to preprocessing that is required for +** this instruction (see do_name()). +** flags: See the definitions for TFL_PUTS & TFL_PUTN above. +*/ struct ftable { char *name; /* function name */ char type; /* argument type */ @@ -198,6 +254,9 @@ static char *do_loop(char *); static char *do_if(char *); +/* +** Lookup a function name in the functable +*/ static struct ftable * lookup(char *name) { @@ -239,12 +298,11 @@ compile_error(char *str, char *cp) ** Return the number of header components found in the format ** string. */ - int fmt_compile(char *fstring, struct format **fmt) { register char *cp; - int i; + size_t i; if (format_string) free(format_string); @@ -343,14 +401,15 @@ compile(char *sp) } +/* +** Process functions & components (handle field width here as well +*/ static char * do_spec(char *sp) { register char *cp = sp; register int c; -#ifndef lint register int ljust = 0; -#endif /* not lint */ register int wid = 0; register char fill = ' '; @@ -391,6 +450,12 @@ do_spec(char *sp) return (cp); } + +/* +** Process a component name. Normally this involves generating an FT_COMP +** instruction for the specified component. If preprocess is set, then we +** do some extra processing. +*/ static char * do_name(char *sp, int preprocess) { @@ -445,6 +510,11 @@ do_name(char *sp, int preprocess) return (cp); } + +/* +** Generate one or more instructions corresponding to the named function. +** The different type of function arguments are handled here. +*/ static char * do_func(char *sp) { @@ -537,6 +607,11 @@ do_func(char *sp) return (cp); } + +/* +** Handle an expression as an argument. Basically we call one of do_name(), +** do_func(), or do_if() +*/ static char * do_expr(char *sp, int preprocess) { @@ -558,6 +633,16 @@ do_expr(char *sp, int preprocess) return (cp); } + +/* +** I am guessing this was for some kind of loop statement, which would have +** looked like %[ .... %]. It looks like the way this would have worked +** is that the format engine would have seen that FT_DONE had a 1 in the +** f_un.f_un_value and then decided whether or not to continue the loop. +** There is no support for this in the format engine, so right now if +** you try using it you will reach the FT_DONE and simply stop. I'm leaving +** this here in case someone wants to continue the work. +*/ static char * do_loop(char *sp) { @@ -576,6 +661,13 @@ do_loop(char *sp) return cp; } + +/* +** Handle an if-elsif-endif statement. Note here that the branching +** is handled by the f_skip member of the struct format (which is really +** just f_width overloaded). This number controls how far to move forward +** (or back) in the format instruction array. +*/ static char * do_if(char *sp) {