=================================================================== RCS file: /cvs/mandoc/mandoc.c,v retrieving revision 1.10 retrieving revision 1.21 diff -u -p -r1.10 -r1.21 --- mandoc/mandoc.c 2010/01/05 19:51:10 1.10 +++ mandoc/mandoc.c 2010/07/06 22:04:31 1.21 @@ -1,6 +1,6 @@ -/* $Id: mandoc.c,v 1.10 2010/01/05 19:51:10 kristaps Exp $ */ +/* $Id: mandoc.c,v 1.21 2010/07/06 22:04:31 kristaps Exp $ */ /* - * Copyright (c) 2008, 2009 Kristaps Dzonsons + * Copyright (c) 2008, 2009 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,20 +27,42 @@ #include #include +#include "mandoc.h" #include "libmandoc.h" -static int a2time(time_t *, const char *, const char *); +static int a2time(time_t *, const char *, const char *); +static int spec_norm(char *, int); +/* + * "Normalise" a special string by converting its ASCII_HYPH entries + * into actual hyphens. + */ +static int +spec_norm(char *p, int sz) +{ + int i; + + for (i = 0; i < sz; i++) + if (ASCII_HYPH == p[i]) + p[i] = '-'; + + return(sz); +} + + int -mandoc_special(const char *p) +mandoc_special(char *p) { int terminator; /* Terminator for \s. */ int lim; /* Limit for N in \s. */ int c, i; + char *sv; + sv = p; + if ('\\' != *p++) - return(0); + return(spec_norm(sv, 0)); switch (*p) { case ('\''): @@ -49,6 +71,8 @@ mandoc_special(const char *p) /* FALLTHROUGH */ case ('q'): /* FALLTHROUGH */ + case (ASCII_HYPH): + /* FALLTHROUGH */ case ('-'): /* FALLTHROUGH */ case ('~'): @@ -61,6 +85,8 @@ mandoc_special(const char *p) /* FALLTHROUGH */ case (' '): /* FALLTHROUGH */ + case ('}'): + /* FALLTHROUGH */ case ('|'): /* FALLTHROUGH */ case ('&'): @@ -70,16 +96,12 @@ mandoc_special(const char *p) case (':'): /* FALLTHROUGH */ case ('c'): - return(2); + /* FALLTHROUGH */ case ('e'): - return(2); - case ('f'): - if ('\0' == *++p || ! isgraph((u_char)*p)) - return(0); - return(3); + return(spec_norm(sv, 2)); case ('s'): if ('\0' == *++p) - return(2); + return(spec_norm(sv, 2)); c = 2; terminator = 0; @@ -109,21 +131,21 @@ mandoc_special(const char *p) if (*p == '\'') { if (terminator) - return(0); + return(spec_norm(sv, 0)); lim = 0; terminator = 1; ++p; ++c; } else if (*p == '[') { if (terminator) - return(0); + return(spec_norm(sv, 0)); lim = 0; terminator = 2; ++p; ++c; } else if (*p == '(') { if (terminator) - return(0); + return(spec_norm(sv, 0)); lim = 2; terminator = 3; ++p; @@ -133,7 +155,7 @@ mandoc_special(const char *p) /* TODO: needs to handle floating point. */ if ( ! isdigit((u_char)*p)) - return(0); + return(spec_norm(sv, 0)); for (i = 0; isdigit((u_char)*p); i++) { if (lim && i >= lim) @@ -144,48 +166,52 @@ mandoc_special(const char *p) if (terminator && terminator < 3) { if (1 == terminator && *p != '\'') - return(0); + return(spec_norm(sv, 0)); if (2 == terminator && *p != ']') - return(0); + return(spec_norm(sv, 0)); ++p; ++c; } - return(c); + return(spec_norm(sv, c)); + case ('f'): + /* FALLTHROUGH */ + case ('F'): + /* FALLTHROUGH */ case ('*'): - if (0 == *++p || ! isgraph((u_char)*p)) - return(0); + if ('\0' == *++p || isspace((u_char)*p)) + return(spec_norm(sv, 0)); switch (*p) { case ('('): - if (0 == *++p || ! isgraph((u_char)*p)) - return(0); - return(4); + if ('\0' == *++p || isspace((u_char)*p)) + return(spec_norm(sv, 0)); + return(spec_norm(sv, 4)); case ('['): for (c = 3, p++; *p && ']' != *p; p++, c++) - if ( ! isgraph((u_char)*p)) + if (isspace((u_char)*p)) break; - return(*p == ']' ? c : 0); + return(spec_norm(sv, *p == ']' ? c : 0)); default: break; } - return(3); + return(spec_norm(sv, 3)); case ('('): - if (0 == *++p || ! isgraph((u_char)*p)) - return(0); - if (0 == *++p || ! isgraph((u_char)*p)) - return(0); - return(4); + if ('\0' == *++p || isspace((u_char)*p)) + return(spec_norm(sv, 0)); + if ('\0' == *++p || isspace((u_char)*p)) + return(spec_norm(sv, 0)); + return(spec_norm(sv, 4)); case ('['): break; default: - return(0); + return(spec_norm(sv, 0)); } for (c = 3, p++; *p && ']' != *p; p++, c++) - if ( ! isgraph((u_char)*p)) + if (isspace((u_char)*p)) break; - return(*p == ']' ? c : 0); + return(spec_norm(sv, *p == ']' ? c : 0)); } @@ -300,3 +326,71 @@ mandoc_a2time(int flags, const char *p) return(0); } + +int +mandoc_eos(const char *p, size_t sz) +{ + + if (0 == sz) + return(0); + + /* + * End-of-sentence recognition must include situations where + * some symbols, such as `)', allow prior EOS punctuation to + * propogate outward. + */ + + for ( ; sz; sz--) { + switch (p[(int)sz - 1]) { + case ('\"'): + /* FALLTHROUGH */ + case ('\''): + /* FALLTHROUGH */ + case (']'): + /* FALLTHROUGH */ + case (')'): + break; + case ('.'): + /* Escaped periods. */ + if (sz > 1 && '\\' == p[(int)sz - 2]) + return(0); + /* FALLTHROUGH */ + case ('!'): + /* FALLTHROUGH */ + case ('?'): + return(1); + default: + return(0); + } + } + + return(0); +} + + +int +mandoc_hyph(const char *start, const char *c) +{ + + /* + * Choose whether to break at a hyphenated character. We only + * do this if it's free-standing within a word. + */ + + /* Skip first/last character of buffer. */ + if (c == start || '\0' == *(c + 1)) + return(0); + /* Skip first/last character of word. */ + if ('\t' == *(c + 1) || '\t' == *(c - 1)) + return(0); + if (' ' == *(c + 1) || ' ' == *(c - 1)) + return(0); + /* Skip double invocations. */ + if ('-' == *(c + 1) || '-' == *(c - 1)) + return(0); + /* Skip escapes. */ + if ('\\' == *(c - 1)) + return(0); + + return(1); +}