From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from krisdoz.my.domain (kristaps@localhost [127.0.0.1]) by krisdoz.my.domain (8.14.3/8.14.3) with ESMTP id p6HE8n6W004458 for ; Sun, 17 Jul 2011 10:08:49 -0400 (EDT) Received: (from kristaps@localhost) by krisdoz.my.domain (8.14.3/8.14.3/Submit) id p6HE8nQR029604; Sun, 17 Jul 2011 10:08:49 -0400 (EDT) Date: Sun, 17 Jul 2011 10:08:49 -0400 (EDT) Message-Id: <201107171408.p6HE8nQR029604@krisdoz.my.domain> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: kristaps@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: Provide implementations of `define', `set', and `unset'. X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 Log Message: ----------- Provide implementations of `define', `set', and `unset'. Tie them into the stream of data. Document these appropriate, bringing in the grammar as defined by the original eqn manual (Kernighan/Richie). Modified Files: -------------- mdocml: eqn.7 eqn.c mandoc.h read.c Revision Data ------------- Index: eqn.c =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/eqn.c,v retrieving revision 1.7 retrieving revision 1.8 diff -Leqn.c -Leqn.c -u -p -r1.7 -r1.8 --- eqn.c +++ eqn.c @@ -28,18 +28,46 @@ #include "libmandoc.h" #include "libroff.h" -static const char *eqn_nexttok(struct mparse *, int, int, +#define EQN_ARGS struct eqn_node *ep, \ + int ln, \ + int pos, \ + const char **end + +struct eqnpart { + const char *name; + size_t sz; + int (*fp)(EQN_ARGS); +}; + +enum eqnpartt { + EQN_DEFINE = 0, + EQN_SET, + EQN_UNDEF, + EQN__MAX +}; + +static int eqn_do_define(EQN_ARGS); +static int eqn_do_set(EQN_ARGS); +static int eqn_do_undef(EQN_ARGS); +static const char *eqn_nexttok(struct mparse *, int, int, const char **, size_t *); +static const struct eqnpart eqnparts[EQN__MAX] = { + { "define", 6, eqn_do_define }, /* EQN_DEFINE */ + { "set", 3, eqn_do_set }, /* EQN_SET */ + { "undef", 5, eqn_do_undef }, /* EQN_UNDEF */ +}; + /* ARGSUSED */ enum rofferr eqn_read(struct eqn_node **epp, int ln, const char *p, int pos, int *offs) { - size_t sz; - struct eqn_node *ep; - const char *start, *end; - int i; + size_t sz; + struct eqn_node *ep; + struct mparse *mp; + const char *start, *end; + int i, c; if (0 == strcmp(p, ".EN")) { *epp = NULL; @@ -47,70 +75,59 @@ eqn_read(struct eqn_node **epp, int ln, } ep = *epp; + mp = ep->parse; end = p + pos; - start = eqn_nexttok(ep->parse, ln, pos, &end, &sz); - if (NULL == start) + if (NULL == (start = eqn_nexttok(mp, ln, pos, &end, &sz))) return(ROFF_IGN); - if (6 == sz && 0 == strncmp("define", start, 6)) { - if (end && '"' == *end) - mandoc_msg(MANDOCERR_EQNQUOTE, - ep->parse, ln, pos, NULL); - - start = eqn_nexttok(ep->parse, ln, pos, &end, &sz); - - for (i = 0; i < (int)ep->defsz; i++) { - if (ep->defs[i].keysz != sz) - continue; - if (0 == strncmp(ep->defs[i].key, start, sz)) - break; - } + for (i = 0; i < (int)EQN__MAX; i++) { + if (eqnparts[i].sz != sz) + continue; + if (strncmp(eqnparts[i].name, start, sz)) + continue; + + if ((c = (*eqnparts[i].fp)(ep, ln, pos, &end)) < 0) + return(ROFF_ERR); + else if (0 == c || '\0' == *end) + return(ROFF_IGN); - /* - * TODO: merge this code with roff_getstr(). + /* + * Re-calculate offset and rerun, if trailing text. + * This allows multiple definitions (say) on each line. */ - if (i == (int)ep->defsz) { - ep->defsz++; - ep->defs = mandoc_realloc - (ep->defs, ep->defsz * - sizeof(struct eqn_def)); - ep->defs[i].keysz = sz; - ep->defs[i].key = mandoc_malloc(sz + 1); - memcpy(ep->defs[i].key, start, sz); - ep->defs[i].key[(int)sz] = '\0'; - ep->defs[i].val = NULL; - ep->defs[i].valsz = 0; - } - - start = eqn_nexttok(ep->parse, ln, pos, &end, &sz); - - ep->defs[i].valsz = sz; - ep->defs[i].val = mandoc_realloc - (ep->defs[i].val, sz + 1); - memcpy(ep->defs[i].val, start, sz); - ep->defs[i].val[(int)sz] = '\0'; + *offs = end - (p + pos); + return(ROFF_RERUN); + } - if ('\0' == *end) - return(ROFF_IGN); + end = p + pos; + while (NULL != (start = eqn_nexttok(mp, ln, pos, &end, &sz))) { + if (0 == sz) + continue; - *offs = end - (p + pos); - assert(*offs > 0); + for (i = 0; i < (int)ep->defsz; i++) { + if (0 == ep->defs[i].keysz) + continue; + if (ep->defs[i].keysz != sz) + continue; + if (strncmp(ep->defs[i].key, start, sz)) + continue; + start = ep->defs[i].val; + sz = ep->defs[i].valsz; + break; + } - return(ROFF_RERUN); - } else - end = p + pos; + ep->eqn.data = mandoc_realloc + (ep->eqn.data, ep->eqn.sz + sz + 1); - if (0 == (sz = strlen(end))) - return(ROFF_IGN); + if (0 == ep->eqn.sz) + *ep->eqn.data = '\0'; - ep->eqn.data = mandoc_realloc(ep->eqn.data, ep->eqn.sz + sz + 1); - if (0 == ep->eqn.sz) - *ep->eqn.data = '\0'; + ep->eqn.sz += sz; + strlcat(ep->eqn.data, start, ep->eqn.sz + 1); + } - ep->eqn.sz += sz; - strlcat(ep->eqn.data, end, ep->eqn.sz + 1); return(ROFF_IGN); } @@ -197,4 +214,128 @@ eqn_nexttok(struct mparse *mp, int ln, i } return(start); +} + +static int +eqn_do_set(struct eqn_node *ep, int ln, int pos, const char **end) +{ + const char *start; + struct mparse *mp; + size_t sz; + + mp = ep->parse; + + start = eqn_nexttok(ep->parse, ln, pos, end, &sz); + if (NULL == start || 0 == sz) { + mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL); + return(0); + } + + start = eqn_nexttok(ep->parse, ln, pos, end, &sz); + if (NULL == start || 0 == sz) { + mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL); + return(0); + } + + return(1); +} + +static int +eqn_do_define(struct eqn_node *ep, int ln, int pos, const char **end) +{ + const char *start; + struct mparse *mp; + size_t sz; + int i; + + mp = ep->parse; + + start = eqn_nexttok(mp, ln, pos, end, &sz); + if (NULL == start || 0 == sz) { + mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL); + return(0); + } + + /* TODO: merge this code with roff_getstr(). */ + + /* + * Search for a key that already exists. + * Note that the string array can have "holes" (null key). + */ + + for (i = 0; i < (int)ep->defsz; i++) { + if (0 == ep->defs[i].keysz || ep->defs[i].keysz != sz) + continue; + if (0 == strncmp(ep->defs[i].key, start, sz)) + break; + } + + /* Create a new key. */ + + if (i == (int)ep->defsz) { + /* Find holes in string array. */ + for (i = 0; i < (int)ep->defsz; i++) + if (0 == ep->defs[i].keysz) + break; + + if (i == (int)ep->defsz) { + ep->defsz++; + ep->defs = mandoc_realloc + (ep->defs, ep->defsz * + sizeof(struct eqn_def)); + } + + ep->defs[i].keysz = sz; + ep->defs[i].key = mandoc_realloc + (ep->defs[i].key, sz + 1); + + memcpy(ep->defs[i].key, start, sz); + ep->defs[i].key[(int)sz] = '\0'; + ep->defs[i].val = NULL; + ep->defs[i].valsz = 0; + } + + start = eqn_nexttok(mp, ln, pos, end, &sz); + + if (NULL == start || 0 == sz) { + ep->defs[i].keysz = 0; + mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL); + return(0); + } + + ep->defs[i].valsz = sz; + ep->defs[i].val = mandoc_realloc + (ep->defs[i].val, sz + 1); + memcpy(ep->defs[i].val, start, sz); + ep->defs[i].val[(int)sz] = '\0'; + + return(sz ? 1 : 0); +} + +static int +eqn_do_undef(struct eqn_node *ep, int ln, int pos, const char **end) +{ + const char *start; + struct mparse *mp; + size_t sz; + int i; + + mp = ep->parse; + + start = eqn_nexttok(mp, ln, pos, end, &sz); + if (NULL == start || 0 == sz) { + mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL); + return(0); + } + + for (i = 0; i < (int)ep->defsz; i++) { + if (0 == ep->defs[i].keysz || ep->defs[i].keysz != sz) + continue; + if (strncmp(ep->defs[i].key, start, sz)) + continue; + ep->defs[i].keysz = 0; + break; + } + + return(1); } Index: mandoc.h =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandoc.h,v retrieving revision 1.79 retrieving revision 1.80 diff -Lmandoc.h -Lmandoc.h -u -p -r1.79 -r1.80 --- mandoc.h +++ mandoc.h @@ -109,6 +109,9 @@ enum mandocerr { MANDOCERR_ERROR, /* ===== start of errors ===== */ + /* related to equations */ + MANDOCERR_EQNARGS, /* bad equation macro arguments */ + /* related to tables */ MANDOCERR_TBL, /* bad table syntax */ MANDOCERR_TBLOPT, /* bad table option */ Index: eqn.7 =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/eqn.7,v retrieving revision 1.2 retrieving revision 1.3 diff -Leqn.7 -Leqn.7 -u -p -r1.2 -r1.3 --- eqn.7 +++ eqn.7 @@ -40,26 +40,69 @@ Equations within .Xr mdoc 7 or .Xr man 7 -are enclosed by the -.Sq EQ +documents are enclosed by the standalone +.Sq \&.EQ and -.Sq EN -macro tags, whose precise syntax is documented in -.Xr roff 7 . -Equations consist of multi-line equation data. -.Pp -For the time being, -.Xr mandoc 1 -reproduces the contents of -.Nm -equations verbatim in its output. +.Sq \&.EN +tags. +Equations are multi-line blocks consisting of formulas and control +statements. +.Sh EQUATION STRUCTURE +Each equation is bracketed by +.Sq \&.EQ +and +.Sq \&.EN +strings. +.Em Note : +these are not the same as +.Xr roff 7 +macros, and may only be invoked as +.Sq \&.EQ . +.Pp +The equation grammar is as follows: +.Bd -literal -offset indent +eqn : box | eqn box +box : text + | DEFINE text text + | SET text text + | UNDEF text +text : TEXT +.Ed +.Pp +Data in TEXT form is a non-empty sequence of non-space characters or a +non-empty quoted string. +White-space (and enclosing literal quote pairs) is thrown away and +productions may not be broken by newlines. .Pp -The +The following control statements are available: +.Bl -tag -width Ds +.It Cm define +Replace all occurances of a key with a value. +Its syntax is as follows: +.Pp +.D1 define Ar key val +.Pp +It is an error to have an empty +.Ar key or +.Ar value . +Note that a quoted +.Ar key +causes errors in some .Nm -implementation in -.Xr mandoc 1 -is -.Ud +implementations and should not be considered portable. +.It Cm set +Set an equation mode. +Both arguments are thrown away. +.It Cm undef +Unset a previously-defined key. +Its syntax is as follows: +.Pp +.D1 define Ar key +.Pp +Once invoked, the definition for +.Ar key +is discarded. +.El .Sh SEE ALSO .Xr mandoc 1 , .Xr man 7 , Index: read.c =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/read.c,v retrieving revision 1.16 retrieving revision 1.17 diff -Lread.c -Lread.c -u -p -r1.16 -r1.17 --- read.c +++ read.c @@ -152,6 +152,9 @@ static const char * const mandocerrs[MAN "generic error", + /* related to equations */ + "bad equation macro syntax", + /* related to tables */ "bad table syntax", "bad table option", -- To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv