source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mandoc: Using an undefined string or macro will cause it to be defined
@ 2018-04-09  2:31 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2018-04-09  2:31 UTC (permalink / raw)
  To: source

Log Message:
-----------
Using an undefined string or macro will cause it to be defined as empty.
Observed by Werner Lemberg on Nov 14, 2011 
and rotting on my TODO list ever since.

Modified Files:
--------------
    mandoc:
        TODO
        roff.c
    mandoc/regress/roff/string:
        Makefile

Added Files:
-----------
    mandoc/regress/roff/string:
        undef.in
        undef.out_ascii
        undef.out_lint

Revision Data
-------------
Index: TODO
===================================================================
RCS file: /home/cvs/mandoc/mandoc/TODO,v
retrieving revision 1.248
retrieving revision 1.249
diff -LTODO -LTODO -u -p -r1.248 -r1.249
--- TODO
+++ TODO
@@ -87,10 +87,6 @@ are mere guesses, and some may be wrong.
   Found by naddy@ in devel/cutils cobfusc(1)  Mon, 16 Feb 2015 19:10:52 +0100
   loc ***  exist ***  algo ***  size **  imp *
 
-- using undefined strings or macros defines them to be empty
-  wl@  Mon, 14 Nov 2011 14:37:01 +0000
-  loc *  exist *  algo *  size *  imp *
-
 --- missing mdoc features ----------------------------------------------
 
 - .Bl -column .Xo support is missing
Index: roff.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/roff.c,v
retrieving revision 1.324
retrieving revision 1.325
diff -Lroff.c -Lroff.c -u -p -r1.324 -r1.325
--- roff.c
+++ roff.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -46,6 +46,7 @@
 #define	ROFFDEF_STD	(1 << 4)  /* mdoc(7) or man(7) macro. */
 #define	ROFFDEF_ANY	(ROFFDEF_USER | ROFFDEF_PRE | \
 			 ROFFDEF_REN | ROFFDEF_STD)
+#define	ROFFDEF_UNDEF	(1 << 5)  /* Completely undefined. */
 
 /* --- data types --------------------------------------------------------- */
 
@@ -185,7 +186,7 @@ static	int		 roff_getregn(const struct r
 				const char *, size_t);
 static	int		 roff_getregro(const struct roff *,
 				const char *name);
-static	const char	*roff_getstrn(const struct roff *,
+static	const char	*roff_getstrn(struct roff *,
 				const char *, size_t, int *);
 static	int		 roff_hasregn(const struct roff *,
 				const char *, size_t);
@@ -1639,6 +1640,11 @@ roff_parse(struct roff *r, char *buf, in
 	}
 	if (t != TOKEN_NONE)
 		*pos = cp - buf;
+	else if (deftype == ROFFDEF_UNDEF) {
+		/* Using an undefined macro defines it to be empty. */
+		roff_setstrn(&r->strtab, mac, maclen, "", 0, 0);
+		roff_setstrn(&r->rentab, mac, maclen, NULL, 0, 0);
+	}
 	return t;
 }
 
@@ -3537,62 +3543,95 @@ roff_setstrn(struct roffkv **r, const ch
 }
 
 static const char *
-roff_getstrn(const struct roff *r, const char *name, size_t len,
+roff_getstrn(struct roff *r, const char *name, size_t len,
     int *deftype)
 {
 	const struct roffkv	*n;
-	int			 i;
+	int			 found, i;
 	enum roff_tok		 tok;
 
-	if (*deftype & ROFFDEF_USER) {
-		for (n = r->strtab; n != NULL; n = n->next) {
-			if (strncmp(name, n->key.p, len) == 0 &&
-			    n->key.p[len] == '\0' &&
-			    n->val.p != NULL) {
-				*deftype = ROFFDEF_USER;
-				return n->val.p;
-			}
+	found = 0;
+	for (n = r->strtab; n != NULL; n = n->next) {
+		if (strncmp(name, n->key.p, len) != 0 ||
+		    n->key.p[len] != '\0' || n->val.p == NULL)
+			continue;
+		if (*deftype & ROFFDEF_USER) {
+			*deftype = ROFFDEF_USER;
+			return n->val.p;
+		} else {
+			found = 1;
+			break;
 		}
 	}
-	if (*deftype & ROFFDEF_PRE) {
-		for (i = 0; i < PREDEFS_MAX; i++) {
-			if (strncmp(name, predefs[i].name, len) == 0 &&
-			    predefs[i].name[len] == '\0') {
-				*deftype = ROFFDEF_PRE;
-				return predefs[i].str;
-			}
+	for (n = r->rentab; n != NULL; n = n->next) {
+		if (strncmp(name, n->key.p, len) != 0 ||
+		    n->key.p[len] != '\0' || n->val.p == NULL)
+			continue;
+		if (*deftype & ROFFDEF_REN) {
+			*deftype = ROFFDEF_REN;
+			return n->val.p;
+		} else {
+			found = 1;
+			break;
 		}
 	}
-	if (*deftype & ROFFDEF_REN) {
-		for (n = r->rentab; n != NULL; n = n->next) {
-			if (strncmp(name, n->key.p, len) == 0 &&
-			    n->key.p[len] == '\0' &&
-			    n->val.p != NULL) {
-				*deftype = ROFFDEF_REN;
-				return n->val.p;
-			}
+	for (i = 0; i < PREDEFS_MAX; i++) {
+		if (strncmp(name, predefs[i].name, len) != 0 ||
+		    predefs[i].name[len] != '\0')
+			continue;
+		if (*deftype & ROFFDEF_PRE) {
+			*deftype = ROFFDEF_PRE;
+			return predefs[i].str;
+		} else {
+			found = 1;
+			break;
 		}
 	}
-	if (*deftype & ROFFDEF_STD) {
-		if (r->man->macroset != MACROSET_MAN) {
-			for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) {
-				if (strncmp(name, roff_name[tok], len) == 0 &&
-				    roff_name[tok][len] == '\0') {
-					*deftype = ROFFDEF_STD;
-					return NULL;
-				}
+	if (r->man->macroset != MACROSET_MAN) {
+		for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) {
+			if (strncmp(name, roff_name[tok], len) != 0 ||
+			    roff_name[tok][len] != '\0')
+				continue;
+			if (*deftype & ROFFDEF_STD) {
+				*deftype = ROFFDEF_STD;
+				return NULL;
+			} else {
+				found = 1;
+				break;
 			}
 		}
-		if (r->man->macroset != MACROSET_MDOC) {
-			for (tok = MAN_TH; tok < MAN_MAX; tok++) {
-				if (strncmp(name, roff_name[tok], len) == 0 &&
-				    roff_name[tok][len] == '\0') {
-					*deftype = ROFFDEF_STD;
-					return NULL;
-				}
+	}
+	if (r->man->macroset != MACROSET_MDOC) {
+		for (tok = MAN_TH; tok < MAN_MAX; tok++) {
+			if (strncmp(name, roff_name[tok], len) != 0 ||
+			    roff_name[tok][len] != '\0')
+				continue;
+			if (*deftype & ROFFDEF_STD) {
+				*deftype = ROFFDEF_STD;
+				return NULL;
+			} else {
+				found = 1;
+				break;
 			}
 		}
 	}
+
+	if (found == 0 && *deftype != ROFFDEF_ANY) {
+		if (*deftype & ROFFDEF_REN) {
+			/*
+			 * This might still be a request,
+			 * so do not treat it as undefined yet.
+			 */
+			*deftype = ROFFDEF_UNDEF;
+			return NULL;
+		}
+
+		/* Using an undefined string defines it to be empty. */
+
+		roff_setstrn(&r->strtab, name, len, "", 0, 0);
+		roff_setstrn(&r->rentab, name, len, NULL, 0, 0);
+	}
+
 	*deftype = 0;
 	return NULL;
 }
--- /dev/null
+++ regress/roff/string/undef.out_ascii
@@ -0,0 +1,37 @@
+STRING-UNDEF(1)             General Commands Manual            STRING-UNDEF(1)
+
+
+
+N\bNA\bAM\bME\bE
+       string-undef - expanding undefined strings
+
+D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
+   U\bUs\bse\ber\br d\bde\bef\bfi\bin\bne\bed\bd s\bst\btr\bri\bin\bng\bg
+       The sting "mys" is undefined and remains undefined.
+
+       Its value is "", and now it is defined, and its value is still "".
+
+       After redefining it to "newval", it is of course still defined.
+
+       After removing the definition, it is now undefined.
+
+   U\bUs\bse\ber\br d\bde\bef\bfi\bin\bne\bed\bd m\bma\bac\bcr\bro\bo
+       The macro "mym" is undefined.
+
+       It has no effect: But now it is defined.
+
+       After defining it as: neweffect it is of course still defined.
+
+       After removing the definition, it is now undefined.
+
+   R\bRe\ben\bna\bam\bme\bed\bd m\bma\bac\bcr\bro\bo
+       The standard .BR macro is defined, and it w\bwo\bor\brk\bks\bs.
+
+       After renaming it, the new name is defined, and w\bwo\bor\brk\bks\bs.
+
+   P\bPr\bre\bed\bde\bef\bfi\bin\bne\bed\bd s\bst\btr\bri\bin\bng\bg
+       A predefined string is defined and has the value "(R)".
+
+
+
+OpenBSD                          April 9, 2018                 STRING-UNDEF(1)
--- /dev/null
+++ regress/roff/string/undef.out_lint
@@ -0,0 +1,2 @@
+mandoc: undef.in:14:15: WARNING: undefined string, using "": mys
+mandoc: undef.in:34:2: ERROR: skipping unknown macro: .mym
--- /dev/null
+++ regress/roff/string/undef.in
@@ -0,0 +1,69 @@
+.\" $OpenBSD: std.in,v 1.2 2017/07/04 14:53:27 schwarze Exp $
+.TH STRING-UNDEF 1 "April 9, 2018"
+.SH NAME
+string-undef - expanding undefined strings
+.SH DESCRIPTION
+.SS User defined string
+The sting "mys" is
+.ie dmys defined
+.el undefined
+and remains
+.ie dmys defined.
+.el undefined.
+.PP
+Its value is "\*[mys]", and now it is
+.ie dmys defined,
+.el undefined,
+and its value is still "\*[mys]".
+.PP
+.ds mys newval
+After redefining it to "\*[mys]", it is of course still
+.ie dmys defined.
+.el undefined.
+.PP
+.rm mys
+After removing the definition, it is now
+.ie dmys defined.
+.el undefined.
+.SS User defined macro
+The macro "mym" is
+.ie dmym defined.
+.el undefined.
+.PP
+It has no effect:
+.mym
+But now it is
+.ie dmym defined.
+.el undefined.
+.PP
+.de mym
+neweffect
+..
+After defining it as:
+.mym
+it is of course still
+.ie dmym defined.
+.el undefined.
+.PP
+.rm mym
+After removing the definition, it is now
+.ie dmym defined.
+.el undefined.
+.SS Renamed macro
+The standard .BR macro is
+.ie dBR defined,
+.el undefined,
+and it
+.BR works .
+.PP
+.rn BR newBR
+After renaming it, the new name is
+.ie dnewBR defined,
+.el undefined,
+and
+.newBR works .
+.SS Predefined string
+A predefined string is
+.ie dR defined
+.el undefined
+and has the value "\*R".
Index: Makefile
===================================================================
RCS file: /home/cvs/mandoc/mandoc/regress/roff/string/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lregress/roff/string/Makefile -Lregress/roff/string/Makefile -u -p -r1.2 -r1.3
--- regress/roff/string/Makefile
+++ regress/roff/string/Makefile
@@ -1,7 +1,7 @@
 # $OpenBSD: Makefile,v 1.6 2014/07/06 19:08:57 schwarze Exp $
 
-REGRESS_TARGETS	 = escape infinite name std zerolength
-LINT_TARGETS	 = name std
+REGRESS_TARGETS	 = escape infinite name std undef zerolength
+LINT_TARGETS	 = name std undef
 
 # The infinite test fails badly with groff-1.20.1:
 # It fails to print the following text.
--
 To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv

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

only message in thread, other threads:[~2018-04-09  2:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-09  2:31 mandoc: Using an undefined string or macro will cause it to be defined schwarze

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).