source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Add mandoc.h, which will eventually replace compilers' inner
@ 2010-05-15 18:35 kristaps
  0 siblings, 0 replies; only message in thread
From: kristaps @ 2010-05-15 18:35 UTC (permalink / raw)
  To: source

Log Message:
-----------
Add mandoc.h, which will eventually replace compilers' inner enum errors with unified ones.
Add initial roff pre-processor shim, a compiler sitting outside of the other compilers that processes pure roff instructions.

Modified Files:
--------------
    mdocml:
        main.c
        roff.c
        roff.h

Added Files:
-----------
    mdocml:
        mandoc.h

Revision Data
-------------
Index: roff.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/roff.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -Lroff.h -Lroff.h -u -p -r1.12 -r1.13
--- roff.h
+++ roff.h
@@ -1,6 +1,6 @@
 /*	$Id$ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -18,9 +18,9 @@
 #define ROFF_H
 
 enum	rofferr {
-	ROFF_CONT,
-	ROFF_IGN,
-	ROFF_ERROR
+	ROFF_CONT, /* re-process line with libmdoc or libman */
+	ROFF_IGN, /* ignore line */
+	ROFF_ERR, /* badness */
 };
 
 __BEGIN_DECLS
@@ -28,7 +28,7 @@ __BEGIN_DECLS
 struct	roff;
 
 void	 	  roff_free(struct roff *);
-struct	roff	 *roff_alloc(void *);
+struct	roff	 *roff_alloc(mandocmsg, void *);
 void		  roff_reset(struct roff *);
 enum	rofferr	  roff_parseln(struct roff *, int, char **, size_t *);
 int		  roff_endparse(struct roff *);
--- /dev/null
+++ mandoc.h
@@ -0,0 +1,39 @@
+/*	$Id: mandoc.h,v 1.1 2010/05/15 18:35:14 kristaps Exp $ */
+/*
+ * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef MANDOC_H
+#define MANDOC_H
+
+__BEGIN_DECLS
+
+enum	mandocerr {
+	MANDOCERR_OK,
+	MANDOCERR_SCOPEEXIT, /* scope open on exit */
+	MANDOCERR_NOSCOPE, /* request scope close w/none open */
+#define	MANDOCERR_WARNING	MANDOCERR_SCOPEEXIT
+
+	MANDOCERR_MEM, /* memory exhausted */
+#define	MANDOCERR_FATAL		MANDOCERR_MEM
+
+	MANDOCERR_MAX
+};
+
+typedef	int	(*mandocmsg)(enum mandocerr, 
+			void *, int, int, const char *);
+
+__END_DECLS
+
+#endif /*!MANDOC_H*/
Index: roff.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/roff.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -Lroff.c -Lroff.c -u -p -r1.66 -r1.67
--- roff.c
+++ roff.c
@@ -1,6 +1,6 @@
 /*	$Id$ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -18,7 +18,311 @@
 #include "config.h"
 #endif
 
+#include <assert.h>
 #include <stdlib.h>
+#include <string.h>
 
+#include "mandoc.h"
 #include "roff.h"
 
+enum	rofft {
+	ROFF_de,
+	ROFF_dei,
+	ROFF_am,
+	ROFF_ami,
+	ROFF_ig,
+	ROFF_close,
+	ROFF_MAX
+};
+
+struct	roff {
+	struct roffnode	*last; /* leaf of stack */
+	mandocmsg	 msg; /* err/warn/fatal messages */
+	void		*data; /* privdata for messages */
+};
+
+struct	roffnode {
+	enum rofft	 tok; /* type of node */
+	struct roffnode	*parent; /* up one in stack */
+	int		 line; /* parse line */
+	int		 col; /* parse col */
+};
+
+#define	ROFF_ARGS	 struct roff *r, /* parse ctx */ \
+		 	 char **bufp, /* input buffer */ \
+			 size_t *szp, /* size of input buffer */ \
+			 int ln, /* parse line */ \
+			 int ppos /* current pos in buffer */
+
+typedef	enum rofferr (*roffproc)(ROFF_ARGS);
+
+struct	roffmac {
+	const char	*name; /* macro name */
+	roffproc	 sub; /* child of control black */
+	roffproc	 new; /* root of stack (type = ROFF_MAX) */
+};
+
+static	enum rofferr	 roff_ignore(ROFF_ARGS);
+static	enum rofferr	 roff_new_close(ROFF_ARGS);
+static	enum rofferr	 roff_new_ig(ROFF_ARGS);
+static	enum rofferr	 roff_sub_ig(ROFF_ARGS);
+
+const	struct roffmac	 roffs[ROFF_MAX] = {
+	{ "de", NULL, roff_ignore },
+	{ "dei", NULL, roff_ignore },
+	{ "am", NULL, roff_ignore },
+	{ "ami", NULL, roff_ignore },
+	{ "ig", roff_sub_ig, roff_new_ig },
+	{ ".", NULL, roff_new_close },
+};
+
+static	void		 roff_alloc1(struct roff *);
+static	void		 roff_free1(struct roff *);
+static	enum rofft	 roff_hash_find(const char *);
+static	int		 roffnode_push(struct roff *, 
+				enum rofft, int, int);
+static	void		 roffnode_pop(struct roff *);
+static	enum rofft	 roff_parse(const char *, int *);
+
+
+/*
+ * Look up a roff token by its name.  Returns ROFF_MAX if no macro by
+ * the nil-terminated string name could be found.
+ */
+static enum rofft
+roff_hash_find(const char *p)
+{
+	int		 i;
+
+	/* FIXME: make this be fast and efficient. */
+
+	for (i = 0; i < (int)ROFF_MAX; i++)
+		if (0 == strcmp(roffs[i].name, p))
+			return((enum rofft)i);
+
+	return(ROFF_MAX);
+}
+
+
+/*
+ * Pop the current node off of the stack of roff instructions currently
+ * pending.
+ */
+static void
+roffnode_pop(struct roff *r)
+{
+	struct roffnode	*p;
+
+	if (NULL == (p = r->last))
+		return;
+	r->last = p->parent;
+	free(p);
+}
+
+
+/*
+ * Push a roff node onto the instruction stack.  This must later be
+ * removed with roffnode_pop().
+ */
+static int
+roffnode_push(struct roff *r, enum rofft tok, int line, int col)
+{
+	struct roffnode	*p;
+
+	if (NULL == (p = calloc(1, sizeof(struct roffnode)))) {
+		(*r->msg)(MANDOCERR_MEM, r->data, line, col, NULL);
+		return(0);
+	}
+
+	p->tok = tok;
+	p->parent = r->last;
+	p->line = line;
+	p->col = col;
+
+	r->last = p;
+	return(1);
+}
+
+
+static void
+roff_free1(struct roff *r)
+{
+
+	while (r->last)
+		roffnode_pop(r);
+}
+
+
+static void
+roff_alloc1(struct roff *r)
+{
+
+	memset(r, 0, sizeof(struct roff));
+}
+
+
+void
+roff_reset(struct roff *r)
+{
+
+	roff_free1(r);
+	roff_alloc1(r);
+}
+
+
+void
+roff_free(struct roff *r)
+{
+
+	roff_free1(r);
+	free(r);
+}
+
+
+struct roff *
+roff_alloc(const mandocmsg msg, void *data)
+{
+	struct roff	*r;
+
+	if (NULL == (r = calloc(1, sizeof(struct roff)))) {
+		(*msg)(MANDOCERR_MEM, data, 0, 0, NULL);
+		return(0);
+	}
+
+	r->msg = msg;
+	r->data = data;
+	return(r);
+}
+
+
+enum rofferr
+roff_parseln(struct roff *r, int ln, char **bufp, size_t *szp)
+{
+	enum rofft	 t;
+	int		 ppos;
+
+	if (NULL != r->last) {
+		/*
+		 * If there's a node on the stack, then jump directly
+		 * into its processing function.
+		 */
+		t = r->last->tok;
+		assert(roffs[t].sub);
+		return((*roffs[t].sub)(r, bufp, szp, ln, 0));
+	} else if ('.' != (*bufp)[0] && NULL == r->last)
+		/* Return when in free text without a context. */
+		return(ROFF_CONT);
+
+	/* There's nothing on the stack: make us anew. */
+
+	if (ROFF_MAX == (t = roff_parse(*bufp, &ppos)))
+		return(ROFF_CONT);
+
+	assert(roffs[t].new);
+	return((*roffs[t].new)(r, bufp, szp, ln, ppos));
+}
+
+
+/*
+ * Parse a roff node's type from the input buffer.  This must be in the
+ * form of ".foo xxx" in the usual way.
+ */
+static enum rofft
+roff_parse(const char *buf, int *pos)
+{
+	int		 j;
+	char		 mac[5];
+	enum rofft	 t;
+
+	assert('.' == buf[0]);
+	*pos = 1;
+
+	while (buf[*pos] && (' ' == buf[*pos] || '\t' == buf[*pos]))
+		(*pos)++;
+
+	if ('\0' == buf[*pos])
+		return(ROFF_MAX);
+
+	for (j = 0; j < 4; j++, (*pos)++)
+		if ('\0' == (mac[j] = buf[*pos]))
+			break;
+		else if (' ' == buf[*pos])
+			break;
+
+	if (j == 4 || j < 1)
+		return(ROFF_MAX);
+
+	mac[j] = '\0';
+
+	if (ROFF_MAX == (t = roff_hash_find(mac)))
+		return(t);
+
+	while (buf[*pos] && ' ' == buf[*pos])
+		(*pos)++;
+
+	return(t);
+}
+
+
+/* ARGSUSED */
+static enum rofferr
+roff_ignore(ROFF_ARGS)
+{
+
+	return(ROFF_IGN);
+}
+
+
+/* ARGSUSED */
+static enum rofferr
+roff_sub_ig(ROFF_ARGS)
+{
+	enum rofft	 t;
+	int		 pos;
+
+	/* Ignore free-text lines. */
+
+	if ('.' != (*bufp)[ppos])
+		return(ROFF_IGN);
+
+	/* Ignore macros unless it's a closing macro. */
+
+	t = roff_parse(*bufp, &pos);
+	if (ROFF_close != t)
+		return(ROFF_IGN);
+
+	roffnode_pop(r);
+	return(ROFF_IGN);
+}
+
+
+/* ARGSUSED */
+static enum rofferr
+roff_new_close(ROFF_ARGS)
+{
+
+	if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
+		return(ROFF_ERR);
+	return(ROFF_IGN);
+}
+
+
+/* ARGSUSED */
+static enum rofferr
+roff_new_ig(ROFF_ARGS)
+{
+
+	return(roffnode_push(r, ROFF_ig, ln, ppos) ? 
+			ROFF_IGN : ROFF_ERR);
+}
+
+
+int
+roff_endparse(struct roff *r)
+{
+
+	if (NULL == r->last)
+		return(1);
+	return((*r->msg)(MANDOCERR_SCOPEEXIT, r->data, 
+				r->last->line, r->last->col, NULL));
+}
Index: main.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/main.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -Lmain.c -Lmain.c -u -p -r1.70 -r1.71
--- main.c
+++ main.c
@@ -29,8 +29,10 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "mandoc.h"
 #include "mdoc.h"
 #include "man.h"
+#include "roff.h"
 #include "main.h"
 
 #define	UNCONST(a)	((void *)(uintptr_t)(const void *)(a))
@@ -70,6 +72,7 @@ struct	curparse {
 	const char	 *file;		/* Current parse. */
 	int		  fd;		/* Current parse. */
 	int		  wflags;
+	/* FIXME: set by max error */
 #define	WARN_WALL	 (1 << 0)	/* All-warnings mask. */
 #define	WARN_WERR	 (1 << 2)	/* Warnings->errors. */
 	int		  fflags;
@@ -82,6 +85,7 @@ struct	curparse {
 	enum intt	  inttype;	/* Input parsers... */
 	struct man	 *man;
 	struct mdoc	 *mdoc;
+	struct roff	 *roff;
 	enum outt	  outtype;	/* Output devices... */
 	out_mdoc	  outmdoc;
 	out_man	  	  outman;
@@ -95,9 +99,12 @@ static	void		  ffile(const char *, struc
 static	int		  foptions(int *, char *);
 static	struct man	 *man_init(struct curparse *);
 static	struct mdoc	 *mdoc_init(struct curparse *);
-static	int		  merr(void *, int, int, const char *);
+static	struct roff	 *roff_init(struct curparse *);
+static	int		  merr(void *, int, int, const char *); /* DEPRECATED */
 static	int		  moptions(enum intt *, char *);
-static	int		  mwarn(void *, int, int, const char *);
+static	int		  mwarn(void *, int, int, const char *); /* DEPRECATED */
+static	int		  mmsg(enum mandocerr, void *, 
+				int, int, const char *);
 static	int		  pset(const char *, int, struct curparse *,
 				struct man **, struct mdoc **);
 static	int		  toptions(struct curparse *, char *);
@@ -177,6 +184,12 @@ main(int argc, char *argv[])
 
 	if (curp.outfree)
 		(*curp.outfree)(curp.outdata);
+	if (curp.mdoc)
+		mdoc_free(curp.mdoc);
+	if (curp.man)
+		man_free(curp.man);
+	if (curp.roff)
+		roff_free(curp.roff);
 
 	return((with_warning || with_error) ? 
 			EXIT_FAILURE :  EXIT_SUCCESS);
@@ -225,6 +238,14 @@ man_init(struct curparse *curp)
 }
 
 
+static struct roff *
+roff_init(struct curparse *curp)
+{
+
+	return(roff_alloc(mmsg, curp));
+}
+
+
 static struct mdoc *
 mdoc_init(struct curparse *curp)
 {
@@ -316,7 +337,7 @@ read_whole_file(struct curparse *curp, s
 			return(0);
 		}
 		*with_mmap = 1;
-		fb->sz = st.st_size;
+		fb->sz = (size_t)st.st_size;
 		fb->buf = mmap(NULL, fb->sz, PROT_READ, 
 				MAP_FILE, curp->fd, 0);
 		if (fb->buf != MAP_FAILED)
@@ -342,7 +363,7 @@ read_whole_file(struct curparse *curp, s
 			if (! resize_buf(fb, 65536))
 				break;
 		}
-		ssz = read(curp->fd, fb->buf + off, fb->sz - off);
+		ssz = read(curp->fd, fb->buf + (int)off, fb->sz - off);
 		if (ssz == 0) {
 			fb->sz = off;
 			return(1);
@@ -351,7 +372,7 @@ read_whole_file(struct curparse *curp, s
 			perror(curp->file);
 			break;
 		}
-		off += ssz;
+		off += (size_t)ssz;
 	}
 
 	free(fb->buf);
@@ -366,11 +387,14 @@ fdesc(struct curparse *curp)
 {
 	struct buf	 ln, blk;
 	int		 i, pos, lnn, lnn_start, with_mmap;
+	enum rofferr	 re;
 	struct man	*man;
 	struct mdoc	*mdoc;
+	struct roff	*roff;
 
 	man = NULL;
 	mdoc = NULL;
+	roff = NULL;
 	memset(&ln, 0, sizeof(struct buf));
 
 	/*
@@ -378,9 +402,14 @@ fdesc(struct curparse *curp)
 	 * memory mapped.  ln is a line buffer and grows on-demand.
 	 */
 
-	if (!read_whole_file(curp, &blk, &with_mmap))
+	if ( ! read_whole_file(curp, &blk, &with_mmap))
 		return;
 
+	if (NULL == curp->roff) 
+		curp->roff = roff_init(curp);
+	if (NULL == (roff = curp->roff))
+		goto bailout;
+
 	for (i = 0, lnn = 1; i < (int)blk.sz;) {
 		pos = 0;
 		lnn_start = lnn;
@@ -436,7 +465,13 @@ fdesc(struct curparse *curp)
  		if (pos >= (int)ln.sz)
 			if (! resize_buf(&ln, 256))
 				goto bailout;
-		ln.buf[pos] = 0;
+		ln.buf[pos] = '\0';
+
+		re = roff_parseln(roff, lnn_start, &ln.buf, &ln.sz);
+		if (ROFF_IGN == re)
+			continue;
+		else if (ROFF_ERR == re)
+			goto bailout;
 
 		/* If unset, assign parser in pset(). */
 
@@ -445,9 +480,9 @@ fdesc(struct curparse *curp)
 
 		/* Pass down into parsers. */
 
-		if (man && ! man_parseln(man, lnn, ln.buf))
+		if (man && ! man_parseln(man, lnn_start, ln.buf))
 			goto bailout;
-		if (mdoc && ! mdoc_parseln(mdoc, lnn, ln.buf))
+		if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf))
 			goto bailout;
 	}
 
@@ -462,6 +497,8 @@ fdesc(struct curparse *curp)
 		goto bailout;
 	if (man && ! man_endparse(man))
 		goto bailout;
+	if (roff && ! roff_endparse(roff))
+		goto bailout;
 
 	/* If unset, allocate output dev now (if applicable). */
 
@@ -502,20 +539,19 @@ fdesc(struct curparse *curp)
 		(*curp->outmdoc)(curp->outdata, mdoc);
 
  cleanup:
-	if (curp->mdoc) {
-		mdoc_free(curp->mdoc);
-		curp->mdoc = NULL;
-	}
-	if (curp->man) {
-		man_free(curp->man);
-		curp->man = NULL;
-	}
+	if (mdoc)
+		mdoc_reset(mdoc);
+	if (man)
+		man_reset(man);
+	if (roff)
+		roff_reset(roff);
 	if (ln.buf)
 		free(ln.buf);
 	if (with_mmap)
 		munmap(blk.buf, blk.sz);
 	else
 		free(blk.buf);
+
 	return;
 
  bailout:
@@ -737,3 +773,19 @@ mwarn(void *arg, int line, int col, cons
 	return(1);
 }
 
+/*
+ * XXX: this is experimental code that will eventually become the
+ * generic means of covering all warnings and errors!
+ */
+/* ARGSUSED */
+static int
+mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
+{
+	struct curparse *cp;
+
+	cp = (struct curparse *)arg;
+
+	fprintf(stderr, "%s:%d:%d: %s\n", cp->file, ln, col + 1, msg);
+
+	return(1);
+}
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2010-05-15 18:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-15 18:35 mdocml: Add mandoc.h, which will eventually replace compilers' inner kristaps

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).