fmttest - Man Page

test programs in nmh's mh-format(5) language


fmttest [-help] [-version] [-form formatfile] [-format formatstring] [-address | -raw | -date | -message] [-file | -nofile] [--component component-text] [-dupaddrs | -nodupaddrs] [-ccme | -noccme] [-outsize size-in-characters] [-width column-width] [-msgnum number] [-msgcur flag] [-msgsize size] [-unseen flag] [-dump | -nodump] [-trace | -notrace] [+folder] [msgs | strings]


fmttest is used to test programs written for the nmh format language as specified by mh-format(5). It is also intended to replace the ap, dp, and fmtdump programs.

Format Program Selection

The -format string and -form formatfile specify a format string or file to read. A format string, if given, must be a single argument to the -format switch.  If a format file name is passed to the -form, switch, the file is searched for using the normal nmh rules: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's Mail directory as specified in their profile.  If not found there, the directory “/etc/nmh” is checked.

Mode Selection and Component Specification

fmttest has four operating modes - address, raw, date, and message - which are selected by the -address, -raw, -date, and -message switches, respectively.

Address mode treats every argument as an email address to be processed by nmh's email parser using the specified format program. The parsed address is made available as a special %{text} component escape, and the output from the program is printed on standard output. If there was an error parsing the email address the error message is stored in the %{error} component escape.  If no format program is given on the command line, the following default program is used:

%<{error}%{error}: %{text}%|%(putstr(proper{text}))%>

Address mode is equivalent to ap(8).

In raw mode, no processing of the specified arguments is done.  Each argument is run against the specified format program with the argument text available in the %{text} component.  You must specify a format with -form or -format when using raw mode.

Date mode is identical to raw mode, with one exception: if no format is specified, the following format string is used:

%<(nodate{text})error: %{text}%|%(putstr(pretty{text}))%>

Date mode is equivalent to dp(8).

In message mode the arguments to fmttest are interpreted as an optional folder and messages. fmttest will read each specified message and make all of the components in the message available to the format program.  Also, the appropriate information for the %(msg), %(cur), %(unseen), and %(size) function escapes will be made available for each message.  If the -file switch is given, the arguments are interpreted as filenames instead of message numbers, but otherwise the behavior is the same (except that the %(msg), %(cur), and %(unseen) function escapes will not provide any useful information).

The default format used in address mode is the default format used by scan. The following command can replicate the functionality of the repl command.

fmttest -nodupaddrs -form replcomps -outsize max [+folder] message

Regardless of the mode, other components can be provided to the format program by the use of the --component switch.  For example, the following program will test the use of the “encrypted” component:

fmttest --encrypted yes -message cur

In message mode, components supplied on the command line will override components from messages.

Additional Switches

The -dupaddrs and -nodupaddrs switches control whether duplicate addresses are allowed or suppressed by the FORMATADDR instruction, which is used by the `%(formataddr)' function escape.  In normal operation duplicate addresses are only suppressed by repl.

The -ccme and -noccme switches control whether or not to count the user's local mailbox as a duplicate address.  This replicates the behavior of the -cc me switch to repl, and only applies if -nodupaddrs is in effect.

The -outsize switch controls the maximum number of printable characters that the format engine will produce.  Characters marked as non-printing by the format engine with `%(zputlit)', characters with zero width, and extra bytes that are part of a multibyte character are not counted against this total. Two special values are supported: “max”, which means as many characters as the format engine can produce (limited by internal buffers), and “width”, which will set the value to the width of the terminal.  In message mode it defaults to “width”, otherwise the default is “max”.

The -width switch controls the column width which is used by the `%(width)' function escape.  It defaults to the terminal width.

The -msgnum, -msgcur, -msgsize, and the -unseen switches all control the values used, respectively, by the following function escapes: `%(num)', `%(cur)', `%(size)', and `%(unseen)'. If none are supplied, these values are taken from the message in message mode; in all other modes the default values are 0.

Compiling and Tracing Format Programs

The -dump switch outputs the complete set of format instructions for the specified format program.  The -trace switch will output each format instruction as it is being executed, and show the values of the num and str registers if they have changed from the previous instruction. The output buffer is also printed if it has changed from the previous instruction.

Format Instructions

It should be noted that there is not a one-to-one correspondence between format escapes and format instructions; many instructions have side effects.  Instructions prefixed with “LV” generally return a integer into the num (value) register; instructions prefixed with a “LS” return a string into the str register.

COMPOutput component
COMPFFormatted output component
LITOutput literal text
CHAROutput single character
NUMOutput the num register
NUMFFormatted output of the num register
STROutput the str register
STRFFormatted output of the str register
STRFWNot used
PUTADDROutput address list in str register
STRLITOutput str, no space compression
STRLITZLike STRLIT, but not counted against width
LS_COMPWrite component to str register
LS_LITWrite literal to str register
LS_GETENVWrite environment var to str register
LS_DECODECOMPDecode RFC 2047 encoded component to str register
LS_DECODEDecode RFC 2047 encoded string to str register
LS_TRIMTrim trailing whitespace from str register
LV_COMPConvert component to integer, store in num register
LV_COMPFLAGSet num to 1 if TRUE set in component
LV_LITLoad literal value into num register
LV_DATLoad value from dat array into num register (see note)
LV_STRLENSet num to the length of str
LV_PLUS_LAdd value to num register
LV_MINUS_LSubtract value from num register
LV_DIVIDE_LDivide num register by value
LV_MODULO_Lnum modulo value
LV_CHAR_LEFTStore remaining number of printable chars in num
LS_MONTHWrite short name of month to str from date component
LS_LMONTHWrite long name of month to str from date component
LS_ZONEWrite time zone offset to str from date component
LS_DAYWrite short name of day of week to str from date component
LS_WEEKDAYWrite long name of day of week to str from date component
LS_822DATEWrite RFC 822 compatible date to str from date component
LS_PRETTYWrite date with “pretty” timezone to str
LV_SECWrite date component seconds to num
LV_MINWrite date component minutes to num
LV_HOURWrite date component hour to num
LV_MONWrite date component numeric month to num (start at 1)
LV_YEARWrite date component year to num
LV_YDAYWrite date component Julian day to num
LV_WDAYWrite date component day of week to num (0 == Sunday)
LV_ZONEWrite date component time zone offset to num
LV_CLOCKWrite date component in Unix epoch time to num
LV_RCLOCKWrite offset of date component from current time to num
LV_DAYFWrite 1 to num if day of week is explicit
LV_DSTWrite 1 to num if DST is in effect for date component
LV_ZONEFWrite 1 to num if timezone is explicit
LS_ADDRWrite email address of addr component to str
LS_PERSWrite personal name of addr component to str
LS_MBOXWrite mailbox (username) of addr component to str
LS_HOSTWrite host of addr component to str
LS_PATHWrite host route of addr component to str
LS_GNAMEWrite group name of addr component to str
LS_NOTEWrite note portion of addr component to str
LS_822ADDRWrite “proper” RFC 822 version of addr component to str
LS_FRIENDLYWrite friendly (name or note) of address component to str
LS_UNQUOTERemove RFC 2822 quotes from string
LV_HOSTTYPESet num to type of host (0=local, 1=network)
LV_INGRPFSet num to 1 if address was inside of group
LV_NOHOSTFSet num to 1 of no host was present in address component
LOCALDATEConvert date component to local timezone
GMTDATEConvert date component to GMT
PARSEDATEParse date component
PARSEADDRParse address component
FORMATADDRAdd address component to list in str
CONCATADDRLike FORMATADDR, but will not suppress duplicates
MYMBOXSet num if address component is a local address
SAVESTRSave str register temporarily
DONEEnd program
NOPNo operation
GOTOJump to new instruction
IF_S_NULLBranch if str is NULL
IF_SBranch if str is not NULL
IF_V_EQBranch if num is equal to value
IF_V_NEBranch if num is not equal to value
IF_V_GTBranch if num is greater than value
IF_MATCHBranch if str contains string
IF_AMATCHBranch if str starts with string
S_NULLSet num to 1 if str is NULL
S_NONNULLSet num to 1 if str is not NULL
V_EQSet num to 1 if num equals value
V_NESet num to 1 if num does not equal value
V_GTSet num to 1 if num is greater than value
V_MATCHSet num to 1 if str contains string
V_AMATCHSet num to 1 if str starts with string

The LV_DAT instruction is a bit special.  Callers of the format library pass in an array of integers that are used by certain format escapes.  The current list of format escapes and the indexes they use are:


See Also

mh-format(5), repl(1), ap(8), dp(8), fmtdump(8)




If a folder is given, it will become the current folder.


It shouldn't require as much code from other programs as it does.

Referenced By

ap(8), dp(8), fmtdump(8), mh-format(5).

2014-08-31 nmh-1.8