-/* $Id: mdoc_strings.c,v 1.3 2009/04/12 19:45:26 kristaps Exp $ */
+/* $Id: mdoc_strings.c,v 1.18 2010/05/09 21:06:50 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <sys/types.h>
#include <assert.h>
-#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include "libmdoc.h"
-/*
- * Various string-literal operations: converting scalars to and from
- * strings, etc.
- */
+/* FIXME: this file is poorly named. */
struct mdoc_secname {
- const char *name;
- int flag;
-#define MSECNAME_META (1 << 0)
+ const char *name; /* Name of section. */
+ enum mdoc_sec sec; /* Corresponding section. */
};
-/* Section names corresponding to mdoc_sec. */
-
-static const struct mdoc_secname secnames[] = {
- { "PROLOGUE", MSECNAME_META },
- { "BODY", MSECNAME_META },
- { "NAME", 0 },
- { "LIBRARY", 0 },
- { "SYNOPSIS", 0 },
- { "DESCRIPTION", 0 },
- { "IMPLEMENTATION NOTES", 0 },
- { "RETURN VALUES", 0 },
- { "ENVIRONMENT", 0 },
- { "FILES", 0 },
- { "EXAMPLES", 0 },
- { "DIAGNOSTICS", 0 },
- { "COMPATIBILITY", 0 },
- { "ERRORS", 0 },
- { "SEE ALSO", 0 },
- { "STANDARDS", 0 },
- { "HISTORY", 0 },
- { "AUTHORS", 0 },
- { "CAVEATS", 0 },
- { "BUGS", 0 },
- { NULL, 0 }
+#define SECNAME_MAX (20)
+
+static const struct mdoc_secname secnames[SECNAME_MAX] = {
+ { "NAME", SEC_NAME },
+ { "LIBRARY", SEC_LIBRARY },
+ { "SYNOPSIS", SEC_SYNOPSIS },
+ { "DESCRIPTION", SEC_DESCRIPTION },
+ { "IMPLEMENTATION NOTES", SEC_IMPLEMENTATION },
+ { "EXIT STATUS", SEC_EXIT_STATUS },
+ { "RETURN VALUES", SEC_RETURN_VALUES },
+ { "ENVIRONMENT", SEC_ENVIRONMENT },
+ { "FILES", SEC_FILES },
+ { "EXAMPLES", SEC_EXAMPLES },
+ { "DIAGNOSTICS", SEC_DIAGNOSTICS },
+ { "COMPATIBILITY", SEC_COMPATIBILITY },
+ { "ERRORS", SEC_ERRORS },
+ { "SEE ALSO", SEC_SEE_ALSO },
+ { "STANDARDS", SEC_STANDARDS },
+ { "HISTORY", SEC_HISTORY },
+ { "AUTHORS", SEC_AUTHORS },
+ { "CAVEATS", SEC_CAVEATS },
+ { "BUGS", SEC_BUGS },
+ { "SECURITY CONSIDERATIONS", SEC_SECURITY }
};
-#ifdef __linux__
-extern char *strptime(const char *, const char *, struct tm *);
-#endif
-
-
-size_t
-mdoc_isescape(const char *p)
-{
- size_t c;
-
- if ('\\' != *p++)
- return(0);
-
- switch (*p) {
- case ('\\'):
- /* FALLTHROUGH */
- case ('\''):
- /* FALLTHROUGH */
- case ('`'):
- /* FALLTHROUGH */
- case ('q'):
- /* FALLTHROUGH */
- case ('-'):
- /* FALLTHROUGH */
- case ('~'):
- /* FALLTHROUGH */
- case ('^'):
- /* FALLTHROUGH */
- case ('%'):
- /* FALLTHROUGH */
- case ('0'):
- /* FALLTHROUGH */
- case (' '):
- /* FALLTHROUGH */
- case ('|'):
- /* FALLTHROUGH */
- case ('&'):
- /* FALLTHROUGH */
- case ('.'):
- /* FALLTHROUGH */
- case (':'):
- /* FALLTHROUGH */
- case ('e'):
- return(2);
- case ('*'):
- if (0 == *++p || ! isgraph((u_char)*p))
- return(0);
- switch (*p) {
- case ('('):
- if (0 == *++p || ! isgraph((u_char)*p))
- return(0);
- return(4);
- case ('['):
- for (c = 3, p++; *p && ']' != *p; p++, c++)
- if ( ! isgraph((u_char)*p))
- break;
- return(*p == ']' ? c : 0);
- default:
- break;
- }
- return(3);
- case ('('):
- if (0 == *++p || ! isgraph((u_char)*p))
- return(0);
- if (0 == *++p || ! isgraph((u_char)*p))
- return(0);
- return(4);
- case ('['):
- break;
- default:
- return(0);
- }
-
- for (c = 3, p++; *p && ']' != *p; p++, c++)
- if ( ! isgraph((u_char)*p))
- break;
-
- return(*p == ']' ? c : 0);
-}
-
+/*
+ * FIXME: this is repeated in print_text() (html.c) and term_word()
+ * (term.c).
+ */
int
mdoc_iscdelim(char p)
{
switch (p) {
+ case('|'):
+ /* FALLTHROUGH */
+ case('('):
+ /* FALLTHROUGH */
+ case('['):
+ return(1);
case('.'):
/* FALLTHROUGH */
case(','):
/* FALLTHROUGH */
case('!'):
/* FALLTHROUGH */
- case('('):
- /* FALLTHROUGH */
case(')'):
/* FALLTHROUGH */
- case('['):
- /* FALLTHROUGH */
case(']'):
- /* FALLTHROUGH */
- case('{'):
- /* FALLTHROUGH */
- case('}'):
- return(1);
+ return(2);
default:
break;
}
mdoc_isdelim(const char *p)
{
- if (0 == *p)
+ if ('\0' == p[0])
return(0);
- if (0 != *(p + 1))
- return(0);
- return(mdoc_iscdelim(*p));
+ if ('\0' == p[1])
+ return(mdoc_iscdelim(p[0]));
+
+ /*
+ * XXX; account for groff bubu where the \*(Ba reserved string
+ * is treated in exactly the same way as the vertical bar. This
+ * is the only function that checks for this.
+ */
+ return(0 == strcmp(p, "\\*(Ba"));
}
enum mdoc_sec
mdoc_atosec(const char *p)
{
- const struct mdoc_secname *n;
- int i;
+ int i;
- for (i = 0, n = secnames; n->name; n++, i++)
- if ( ! (n->flag & MSECNAME_META))
- if (0 == strcmp(p, n->name))
- return((enum mdoc_sec)i);
+ for (i = 0; i < SECNAME_MAX; i++)
+ if (0 == strcmp(p, secnames[i].name))
+ return(secnames[i].sec);
return(SEC_CUSTOM);
}
-time_t
-mdoc_atotime(const char *p)
-{
- struct tm tm;
- char *pp;
-
- (void)memset(&tm, 0, sizeof(struct tm));
-
- if (0 == strcmp(p, "$Mdocdate: April 12 2009 $"))
- return(time(NULL));
- if ((pp = strptime(p, "$Mdocdate: April 12 2009 $", &tm)) && 0 == *pp)
- return(mktime(&tm));
- /* XXX - this matches "June 1999", which is wrong. */
- if ((pp = strptime(p, "%b %d %Y", &tm)) && 0 == *pp)
- return(mktime(&tm));
- if ((pp = strptime(p, "%b %d, %Y", &tm)) && 0 == *pp)
- return(mktime(&tm));
-
- return(0);
-}
-
-
+/* FIXME: move this into an editable .in file. */
size_t
-mdoc_macro2len(int macro)
+mdoc_macro2len(enum mdoct macro)
{
switch (macro) {
case(MDOC_Em):
return(10);
case(MDOC_Er):
- return(12);
+ return(17);
case(MDOC_Ev):
return(15);
case(MDOC_Fa):