-/* $Id: action.c,v 1.3 2009/01/07 15:53:00 kristaps Exp $ */
+/* $Id: action.c,v 1.12 2009/01/19 17:02:58 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
*/
#include <assert.h>
#include <stdlib.h>
+#include <time.h>
#include "private.h"
-typedef int (*a_act)(struct mdoc *, int, int);
-
struct actions {
- a_act action;
+ int (*post)(struct mdoc *);
};
+/* Per-macro action routines. */
-static int action_sh(struct mdoc *, int, int);
+static int post_sh(struct mdoc *);
+static int post_os(struct mdoc *);
+static int post_dt(struct mdoc *);
+static int post_dd(struct mdoc *);
+static int post_nm(struct mdoc *);
+/* Array of macro action routines. */
const struct actions mdoc_actions[MDOC_MAX] = {
{ NULL }, /* \" */
- { NULL }, /* Dd */
- { NULL }, /* Dt */
- { NULL }, /* Os */
- { action_sh }, /* Sh */
+ { post_dd }, /* Dd */
+ { post_dt }, /* Dt */
+ { post_os }, /* Os */
+ { post_sh }, /* Sh */
{ NULL }, /* Ss */
{ NULL }, /* Pp */
{ NULL }, /* D1 */
{ NULL }, /* In */
{ NULL }, /* Li */
{ NULL }, /* Nd */
- { NULL }, /* Nm */
+ { post_nm }, /* Nm */
{ NULL }, /* Op */
{ NULL }, /* Ot */
{ NULL }, /* Pa */
static int
-action_sh(struct mdoc *mdoc, int tok, int pos)
+post_nm(struct mdoc *mdoc)
{
- enum mdoc_sec sec;
- int i;
- struct mdoc_node *n;
- char *args[MDOC_LINEARG_MAX];
+ char buf[64];
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_Nm == mdoc->last->tok);
+
+ if (mdoc->meta.name)
+ return(1);
+
+ if (xstrlcats(buf, mdoc->last->child, 64)) {
+ mdoc->meta.name = xstrdup(buf);
+ return(1);
+ }
+
+ return(mdoc_err(mdoc, "macro parameters too long"));
+}
+
+
+static int
+post_sh(struct mdoc *mdoc)
+{
+ enum mdoc_sec sec;
+ char buf[64];
if (MDOC_HEAD != mdoc->last->type)
return(1);
+ if (xstrlcats(buf, mdoc->last->child, 64)) {
+ if (SEC_CUSTOM != (sec = mdoc_atosec(buf)))
+ mdoc->sec_lastn = sec;
+ mdoc->sec_last = sec;
+ return(1);
+ }
+
+ return(mdoc_err(mdoc, "macro parameters too long"));
+}
+
+
+static int
+post_dt(struct mdoc *mdoc)
+{
+ int i;
+ char *p;
+ struct mdoc_node *n;
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_Dt == mdoc->last->tok);
- n = mdoc->last->child;
- assert(n);
+ assert(NULL == mdoc->meta.title);
- for (i = 0; n && i < MDOC_LINEARG_MAX; n = n->next, i++) {
+ for (i = 0, n = mdoc->last->child; n; n = n->next, i++) {
assert(MDOC_TEXT == n->type);
- assert(NULL == n->child);
- assert(n->data.text.string);
- args[i] = n->data.text.string;
+ p = n->data.text.string;
+
+ switch (i) {
+ case (0):
+ mdoc->meta.title = xstrdup(p);
+ break;
+ case (1):
+ mdoc->meta.msec = mdoc_atomsec(p);
+ if (MSEC_DEFAULT != mdoc->meta.msec)
+ break;
+ return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
+ case (2):
+ mdoc->meta.vol = mdoc_atovol(p);
+ if (VOL_DEFAULT != mdoc->meta.vol)
+ break;
+ mdoc->meta.arch = mdoc_atoarch(p);
+ if (ARCH_DEFAULT != mdoc->meta.arch)
+ break;
+ return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
+ default:
+ return(mdoc_nerr(mdoc, n, "too many parameters"));
+ }
}
- sec = mdoc_atosec((size_t)i, (const char **)args);
- if (SEC_CUSTOM != sec)
- mdoc->sec_lastn = sec;
- mdoc->sec_last = sec;
+ if (NULL == mdoc->meta.title)
+ mdoc->meta.title = xstrdup("untitled");
+ return(1);
+}
+
+static int
+post_os(struct mdoc *mdoc)
+{
+ char buf[64];
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_Os == mdoc->last->tok);
+ assert(NULL == mdoc->meta.os);
+
+ if ( ! xstrlcats(buf, mdoc->last->child, 64))
+ return(mdoc_err(mdoc, "macro parameters too long"));
+
+ mdoc->meta.os = xstrdup(buf[0] ? buf : "local");
+ mdoc->sec_lastn = mdoc->sec_last = SEC_BODY;
return(1);
}
-int
-mdoc_action(struct mdoc *mdoc, int pos)
+static int
+post_dd(struct mdoc *mdoc)
{
- int t;
-
- switch (mdoc->last->type) {
- case (MDOC_BODY):
- t = mdoc->last->data.body.tok;
- break;
- case (MDOC_ELEM):
- t = mdoc->last->data.elem.tok;
- break;
- case (MDOC_BLOCK):
- t = mdoc->last->data.block.tok;
- break;
- case (MDOC_HEAD):
- t = mdoc->last->data.head.tok;
- break;
- default:
- return(1);
+ char date[64];
+ size_t sz;
+ char *p;
+ struct mdoc_node *n;
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_Dd == mdoc->last->tok);
+
+ n = mdoc->last->child;
+ assert(0 == mdoc->meta.date);
+ date[0] = 0;
+
+ sz = 64;
+
+ for ( ; 0 == mdoc->meta.date && n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
+ p = n->data.text.string;
+
+ if (xstrcmp(p, "$Mdocdate: January 19 2009 $")) {
+ mdoc->meta.date = time(NULL);
+ continue;
+ } else if (xstrcmp(p, "$")) {
+ mdoc->meta.date = mdoc_atotime(date);
+ continue;
+ } else if (xstrcmp(p, "$Mdocdate:"))
+ continue;
+
+ if ( ! xstrlcat(date, n->data.text.string, sz))
+ return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
+ if (n->next && ! xstrlcat(date, " ", sz))
+ return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
}
- if (NULL == mdoc_actions[t].action)
+ if (mdoc->meta.date && NULL == n)
+ return(1);
+ else if (n)
+ return(mdoc_err(mdoc, "invalid parameter syntax"));
+ if ((mdoc->meta.date = mdoc_atotime(date)))
return(1);
- /* TODO: MDOC_Nm... ? */
- return((*mdoc_actions[t].action)(mdoc, t, pos));
+ return(mdoc_err(mdoc, "invalid parameter syntax"));
}
+
+int
+mdoc_action_post(struct mdoc *mdoc)
+{
+
+ if (MDOC_ACTED & mdoc->last->flags)
+ return(1);
+ mdoc->last->flags |= MDOC_ACTED;
+
+ if (MDOC_TEXT == mdoc->last->type)
+ return(1);
+ if (MDOC_ROOT == mdoc->last->type)
+ return(1);
+ if (NULL == mdoc_actions[mdoc->last->tok].post)
+ return(1);
+ return((*mdoc_actions[mdoc->last->tok].post)(mdoc));
+}