-
-/*
- * fmt_compile.c -- "compile" format strings for fmt_scan
+/* fmt_compile.c -- "compile" format strings for fmt_scan
*
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
*
* - Add code to fmttest.c to display your new function.
*
- * - Document the new function in the mh-format(5) man page.
+ * - Document the new function in mh-format(5).
*
*/
#include <h/fmt_compile.h>
#include <h/mts.h>
#include <h/utils.h>
+#include "terminal.h"
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
{ "localmbox", TF_LMBOX, FT_LS_LIT, 0, TFL_PUTS },
{ "plus", TF_NUM, FT_LV_PLUS_L, 0, TFL_PUTN },
{ "minus", TF_NUM, FT_LV_MINUS_L, 0, TFL_PUTN },
+ { "multiply", TF_NUM, FT_LV_MULTIPLY_L, 0, TFL_PUTN },
{ "divide", TF_NUM, FT_LV_DIVIDE_L, 0, TFL_PUTN },
{ "modulo", TF_NUM, FT_LV_MODULO_L, 0, TFL_PUTN },
{ "charleft", TF_NONE, FT_LV_CHAR_LEFT, 0, TFL_PUTN },
{ NULL, 0, 0 }
};
-/*
- * Hash function for component name. The function should be
- * case independent and probably shouldn't involve a routine
- * call. This function is pretty good but will not work on
- * single character component names.
- */
-#define CHASH(nm) (((((nm)[0]) - ((nm)[1])) & 0x1f) + (((nm)[2]) & 0x5f))
+/* Hash function for component name. Deliberately avoids a function
+ * call. Is case independent. Covers interval [0, 126] so never uses
+ * the last element of wantcomp[]. This function is "pretty good". */
+#define CHASH(nm) ( \
+ (( \
+ ((nm)[0]) - ((nm)[0] ? ((nm)[1]) : 0) \
+ ) & 0x1f) + \
+ ((nm[1]) ? (((nm)[2]) & 0x5f) : 0) \
+ )
/*
* Find a component in the hash table.
*/
-#define FINDCOMP(comp,name) \
- for (comp = wantcomp[CHASH(name)]; \
- comp && strcmp(comp->c_name,name); \
- comp = comp->c_next) \
- ;
+#define FINDCOMP(comp,name) do { \
+ for (comp = wantcomp[CHASH(name)]; \
+ comp && strcmp(comp->c_name,name); \
+ comp = comp->c_next) \
+ ; \
+ } while (0)
/* Add new component to the hash table */
#define NEWCOMP(cm,name) do { \
- cm = ((struct comp *) mh_xcalloc (1, sizeof (struct comp)));\
- cm->c_name = getcpy(name);\
+ NEW0(cm);\
+ cm->c_name = mh_xstrdup(name);\
cm->c_refcount++;\
ncomp++;\
i = CHASH(name);\
wantcomp[i] = cm; \
} while (0)
-#define NEWFMT (next_fp++)
-#define NEW(type,fill,wid) do {\
- fp=NEWFMT; fp->f_type=(type); fp->f_fill=(fill); fp->f_width=(wid); \
+#define NEW_FP(type,fill,wid) do {\
+ fp=next_fp++; fp->f_type=(type); fp->f_fill=(fill); fp->f_width=(wid); \
} while (0)
/* Add (possibly new) component to the hash table */
cm->c_refcount++; \
} while (0)
-#define LV(type, value) do { NEW(type,0,0); fp->f_value = (value); } while (0)
-#define LS(type, str) do { NEW(type,0,0); fp->f_text = getcpy(str); fp->f_flags |= FF_STRALLOC; } while (0)
+#define LV(type, value) do { NEW_FP(type,0,0); fp->f_value = (value); } while (0)
+#define LS(type, str) do { NEW_FP(type,0,0); fp->f_text = getcpy(str); fp->f_flags |= FF_STRALLOC; } while (0)
-#define PUTCOMP(comp) do { NEW(FT_COMP,0,0); ADDC(comp); } while (0)
-#define PUTLIT(str) do { NEW(FT_LIT,0,0); fp->f_text = getcpy(str); fp->f_flags |= FF_STRALLOC; } while (0)
-#define PUTC(c) do { NEW(FT_CHAR,0,0); fp->f_char = (c); } while (0)
+#define PUTCOMP(comp) do { NEW_FP(FT_COMP,0,0); ADDC(comp); } while (0)
+#define PUTLIT(str) do { NEW_FP(FT_LIT,0,0); fp->f_text = getcpy(str); fp->f_flags |= FF_STRALLOC; } while (0)
+#define PUTC(c) do { NEW_FP(FT_CHAR,0,0); fp->f_char = (c); } while (0)
static char *format_string;
static char *usr_fstring; /* for CERROR */
static struct ftable *
lookup(char *name)
{
- register struct ftable *t = functable;
- register char *nm;
- register char c = *name;
+ struct ftable *t = functable;
+ char *nm;
+ char c = *name;
while ((nm = t->name)) {
if (*nm == c && strcmp (nm, name) == 0)
- return (ftbl = t);
+ return ftbl = t;
t++;
}
- return (struct ftable *) 0;
+ return NULL;
}
int i, errpos, errctx;
errpos = cp - format_string;
- errctx = errpos > 20 ? 20 : errpos;
+ errctx = min(errpos, 20);
usr_fstring[errpos] = '\0';
for (i = errpos-errctx; i < errpos; i++) {
usr_fstring[i] = '_';
}
- advise(NULL, "\"%s\": format compile error - %s",
+ inform("\"%s\": format compile error - %s",
&usr_fstring[errpos-errctx], str);
adios (NULL, "%*s", errctx+1, "^");
}
int
fmt_compile(char *fstring, struct format **fmt, int reset_comptable)
{
- register char *cp;
+ char *cp;
size_t i;
static int comptable_initialized = 0;
- format_string = getcpy (fstring);
+ format_string = mh_xstrdup(fstring);
usr_fstring = fstring;
if (reset_comptable || !comptable_initialized) {
comptable_initialized = 1;
}
- memset((char *) &fmt_mnull, 0, sizeof(fmt_mnull));
-
/* it takes at least 4 char to generate one format so we
* allocate a worst-case format array using 1/4 the length
* of the format string. We actually need twice this much
*/
i = strlen(fstring)/2 + 1;
if (i==1) i++;
- next_fp = formatvec = (struct format *)mh_xcalloc ((size_t) i,
- sizeof(struct format));
- if (next_fp == NULL)
- adios (NULL, "unable to allocate format storage");
-
+ next_fp = formatvec = mh_xcalloc(i, sizeof *next_fp);
infunction = 0;
cp = compile(format_string);
*fmt = formatvec;
free(format_string);
- return (ncomp);
+ return ncomp;
}
static char *
compile (char *sp)
{
- register char *cp = sp;
- register int c;
+ char *cp = sp;
+ int c;
for (;;) {
sp = cp;
break;
}
if (c == 0)
- return (cp);
+ return cp;
switch (c = *++cp) {
case '%':
case '>':
case '?':
case ']':
- return (cp);
+ return cp;
case '<':
cp = do_if(++cp);
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 = ' ';
+ char *cp = sp;
+ int c;
+ int ljust = 0;
+ int wid = 0;
+ char fill = ' ';
c = *cp++;
if (c == '-') {
fp->f_width = wid;
fp->f_fill = fill;
- return (cp);
+ return cp;
}
/*
static char *
do_name(char *sp, int preprocess)
{
- register char *cp = sp;
- register int c;
- register int i;
+ char *cp = sp;
+ int c;
+ int i;
static int primed = 0;
while (isalnum(c = *cp++) || c == '-' || c == '_')
CERROR("component used as both date and address");
}
if (cm->c_tws) {
- memset (cm->c_tws, 0, sizeof *cm->c_tws);
+ ZERO(cm->c_tws);
} else {
- cm->c_tws = mh_xcalloc (1, sizeof *cm->c_tws);
+ NEW0(cm->c_tws);
}
fp->f_type = preprocess;
PUTCOMP(sp);
case FT_GETMYMBOX:
case FT_GETMYADDR:
if (!primed) {
- ismymbox ((struct mailname *) 0);
+ ismymbox(NULL);
primed++;
}
- /* fall through */
+ /* FALLTHRU */
case FT_PARSEADDR:
if (cm->c_type & CT_DATE) {
CERROR("component used as both date and address");
cm->c_type |= CT_ADDR;
break;
}
- return (cp);
+ return cp;
}
/*
static char *
do_func(char *sp)
{
- register char *cp = sp;
- register int c;
- register struct ftable *t;
- register int n;
+ char *cp = sp;
+ int c;
+ struct ftable *t;
+ int n;
int mflag; /* minus sign in NUM */
infunction++;
}
case TF_NOW:
- LV(t->f_type, time((time_t *) 0));
+ LV(t->f_type, time(NULL));
break;
case TF_EXPR_SV:
LV(FT_SAVESTR, 0);
- /* fall through */
+ /* FALLTHRU */
case TF_EXPR:
*--cp = c;
cp = do_expr(cp, t->extra);
CERROR("')' expected");
}
--infunction;
- return (cp);
+ return cp;
}
/*
static char *
do_expr (char *sp, int preprocess)
{
- register char *cp = sp;
- register int c;
+ char *cp = sp;
+ int c;
if ((c = *cp++) == '{') {
cp = do_name (cp, preprocess);
} else if (c == '(') {
cp = do_func (cp);
} else if (c == ')') {
- return (--cp);
+ return --cp;
} else if (c == '%' && *cp == '<') {
cp = do_if (cp+1);
} else {
CERROR ("'(', '{', '%<' or ')' expected");
}
- return (cp);
+ return cp;
}
/*
*
* Okay, got some more information on this from John L. Romine! From an
* email he sent to the nmh-workers mailing list on December 2, 2010, he
- * explains it thusly:
+ * explains it so:
*
* In this case (scan, formatsbr) it has to do with an extension to
* the mh-format syntax to allow for looping.
static char *
do_loop(char *sp)
{
- register char *cp = sp;
+ char *cp = sp;
struct format *floop;
floop = next_fp;
static char *
do_if(char *sp)
{
- register char *cp = sp;
- register struct format *fexpr,
- *fif = (struct format *)NULL;
- register int c = '<';
+ char *cp = sp;
+ struct format *fexpr,
+ *fif = NULL;
+ int c = '<';
for (;;) {
if (c == '<') { /* doing an IF */
fif = fp; /* loc of GOTO */
fexpr->f_skip = next_fp - fexpr;
- fexpr = (struct format *)NULL;/* no extra ENDIF */
+ fexpr = NULL; /* no extra ENDIF */
cp = compile (cp); /* compile ELSE stmts */
fif->f_skip = next_fp - fif;
if (fexpr) /* IF ... [ELSIF ...] ENDIF */
fexpr->f_skip = next_fp - fexpr;
- return (cp);
+ return cp;
}
/*
unsigned int i;
struct comp *cm;
- for (i = 0; i < sizeof(wantcomp)/sizeof(wantcomp[0]); i++)
- for (cm = wantcomp[i]; cm; cm = cm->c_next)
- if (cm->c_text) {
- free(cm->c_text);
- cm->c_text = NULL;
- }
+ for (i = 0; i < DIM(wantcomp); i++)
+ for (cm = wantcomp[i]; cm; cm = cm->c_next) {
+ free(cm->c_text);
+ cm->c_text = NULL;
+ }
}
/*
struct comp *cm;
for (cm = wantcomp[CHASH(component)]; cm; cm = cm->c_next)
- if (strcasecmp(component, cm->c_name ? cm->c_name : "") == 0)
+ if (strcasecmp(component, FENDNULL(cm->c_name)) == 0)
break;
return cm;
char *cp;
while (cptr) {
- if (strcasecmp(component, cptr->c_name ? cptr->c_name : "") == 0) {
+ if (strcasecmp(component, FENDNULL(cptr->c_name)) == 0) {
found++;
if (! cptr->c_text) {
cptr->c_text = getcpy(text);
if (bucket != -1) {
for (cptr = wantcomp[bucket]; cptr; cptr = cptr->c_next)
- if (strcasecmp(component, cptr->c_name ? cptr->c_name : "") == 0)
+ if (strcasecmp(component, FENDNULL(cptr->c_name)) == 0)
cptr->c_text = add(text, cptr->c_text);
}
}
else
comp = comp->c_next;
- while (comp == NULL && *bucket < sizeof(wantcomp)/sizeof(wantcomp[0])) {
+ while (comp == NULL && *bucket < DIM(wantcomp)) {
comp = wantcomp[(*bucket)++];
}
unsigned int i;
struct comp *cm, *cm2;
- for (i = 0; i < sizeof(wantcomp)/sizeof(wantcomp[0]); i++) {
+ for (i = 0; i < DIM(wantcomp); i++) {
cm = wantcomp[i];
while (cm != NULL) {
cm2 = cm->c_next;
{
if (--cm->c_refcount <= 0) {
/* Shouldn't ever be NULL, but just in case ... */
- if (cm->c_name)
- free(cm->c_name);
- if (cm->c_text)
- free(cm->c_text);
+ free(cm->c_name);
+ free(cm->c_text);
if (cm->c_type & CT_DATE)
free(cm->c_tws);
if (cm->c_type & CT_ADDR && cm->c_mn && cm->c_mn != &fmt_mnull)