From 5518634037521728ddcb11b8eb4c6dcd7f046f83 Mon Sep 17 00:00:00 2001 From: markus schnalke Date: Tue, 27 Mar 2012 09:31:47 +0200 Subject: [PATCH] Add some comments to the format compiler and engine. Pulled in from nmh. Thanks to Ken Hornstein. --- sbr/fmt_compile.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++- sbr/fmt_scan.c | 3 ++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/sbr/fmt_compile.c b/sbr/fmt_compile.c index c49a6ea..435740e 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,7 +298,6 @@ 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) { @@ -343,6 +401,9 @@ compile(char *sp) } +/* +** Process functions & components (handle field width here as well +*/ static char * do_spec(char *sp) { @@ -391,6 +452,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 +512,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 +609,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 +635,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 +663,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) { diff --git a/sbr/fmt_scan.c b/sbr/fmt_scan.c index b7137d7..94285a6 100644 --- a/sbr/fmt_scan.c +++ b/sbr/fmt_scan.c @@ -4,6 +4,9 @@ ** 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 is the engine that processes the format instructions created by +** fmt_compile (found in fmt_compile.c). */ #include -- 1.7.10.4