version 1.340, 2018/08/24 23:12:33 |
version 1.345, 2018/12/12 21:54:35 |
|
|
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
#include "mandoc.h" |
|
#include "mandoc_aux.h" |
#include "mandoc_aux.h" |
#include "mandoc_ohash.h" |
#include "mandoc_ohash.h" |
|
#include "mandoc.h" |
#include "roff.h" |
#include "roff.h" |
|
#include "tbl.h" |
#include "libmandoc.h" |
#include "libmandoc.h" |
#include "roff_int.h" |
#include "roff_int.h" |
#include "libroff.h" |
#include "libroff.h" |
Line 176 static int roff_br(ROFF_ARGS); |
|
Line 177 static int roff_br(ROFF_ARGS); |
|
static int roff_cblock(ROFF_ARGS); |
static int roff_cblock(ROFF_ARGS); |
static int roff_cc(ROFF_ARGS); |
static int roff_cc(ROFF_ARGS); |
static int roff_ccond(struct roff *, int, int); |
static int roff_ccond(struct roff *, int, int); |
|
static int roff_char(ROFF_ARGS); |
static int roff_cond(ROFF_ARGS); |
static int roff_cond(ROFF_ARGS); |
static int roff_cond_text(ROFF_ARGS); |
static int roff_cond_text(ROFF_ARGS); |
static int roff_cond_sub(ROFF_ARGS); |
static int roff_cond_sub(ROFF_ARGS); |
Line 397 static struct roffmac roffs[TOKEN_NONE] = { |
|
Line 399 static struct roffmac roffs[TOKEN_NONE] = { |
|
{ roff_insec, NULL, NULL, 0 }, /* cf */ |
{ roff_insec, NULL, NULL, 0 }, /* cf */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* cflags */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* cflags */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* ch */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* ch */ |
{ roff_unsupp, NULL, NULL, 0 }, /* char */ |
{ roff_char, NULL, NULL, 0 }, /* char */ |
{ roff_unsupp, NULL, NULL, 0 }, /* chop */ |
{ roff_unsupp, NULL, NULL, 0 }, /* chop */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* class */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* class */ |
{ roff_insec, NULL, NULL, 0 }, /* close */ |
{ roff_insec, NULL, NULL, 0 }, /* close */ |
Line 1066 roff_node_unlink(struct roff_man *man, struct roff_nod |
|
Line 1068 roff_node_unlink(struct roff_man *man, struct roff_nod |
|
} |
} |
|
|
void |
void |
|
roff_node_relink(struct roff_man *man, struct roff_node *n) |
|
{ |
|
roff_node_unlink(man, n); |
|
n->prev = n->next = NULL; |
|
roff_node_append(man, n); |
|
} |
|
|
|
void |
roff_node_free(struct roff_node *n) |
roff_node_free(struct roff_node *n) |
{ |
{ |
|
|
Line 2106 roff_cond_sub(ROFF_ARGS) |
|
Line 2116 roff_cond_sub(ROFF_ARGS) |
|
if (ep[0] == '\\' && ep[1] == '}') |
if (ep[0] == '\\' && ep[1] == '}') |
rr = 0; |
rr = 0; |
|
|
/* Always check for the closing delimiter `\}'. */ |
/* |
|
* The closing delimiter `\}' rewinds the conditional scope |
|
* but is otherwise ignored when interpreting the line. |
|
*/ |
|
|
while ((ep = strchr(ep, '\\')) != NULL) { |
while ((ep = strchr(ep, '\\')) != NULL) { |
switch (ep[1]) { |
switch (ep[1]) { |
Line 2149 roff_cond_text(ROFF_ARGS) |
|
Line 2162 roff_cond_text(ROFF_ARGS) |
|
if (roffnode_cleanscope(r)) |
if (roffnode_cleanscope(r)) |
irc |= endloop; |
irc |= endloop; |
|
|
|
/* |
|
* If `\}' occurs on a text line with neither preceding |
|
* nor following characters, drop the line completely. |
|
*/ |
|
|
ep = buf->buf + pos; |
ep = buf->buf + pos; |
|
if (strcmp(ep, "\\}") == 0) |
|
rr = 0; |
|
|
|
/* |
|
* The closing delimiter `\}' rewinds the conditional scope |
|
* but is otherwise ignored when interpreting the line. |
|
*/ |
|
|
while ((ep = strchr(ep, '\\')) != NULL) { |
while ((ep = strchr(ep, '\\')) != NULL) { |
if (*(++ep) == '}') { |
switch (ep[1]) { |
*ep = '&'; |
case '}': |
if (roff_ccond(r, ln, ep - buf->buf - 1)) |
memmove(ep, ep + 2, strlen(ep + 2) + 1); |
|
if (roff_ccond(r, ln, ep - buf->buf)) |
irc |= endloop; |
irc |= endloop; |
} |
break; |
if (*ep != '\0') |
case '\0': |
++ep; |
++ep; |
|
break; |
|
default: |
|
ep += 2; |
|
break; |
|
} |
} |
} |
if (rr) |
if (rr) |
irc |= ROFF_CONT; |
irc |= ROFF_CONT; |
Line 3318 roff_cc(ROFF_ARGS) |
|
Line 3350 roff_cc(ROFF_ARGS) |
|
mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse, |
mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse, |
ln, p - buf->buf, "cc ... %s", p); |
ln, p - buf->buf, "cc ... %s", p); |
|
|
|
return ROFF_IGN; |
|
} |
|
|
|
static int |
|
roff_char(ROFF_ARGS) |
|
{ |
|
const char *p, *kp, *vp; |
|
size_t ksz, vsz; |
|
int font; |
|
|
|
/* Parse the character to be replaced. */ |
|
|
|
kp = buf->buf + pos; |
|
p = kp + 1; |
|
if (*kp == '\0' || (*kp == '\\' && |
|
mandoc_escape(&p, NULL, NULL) != ESCAPE_SPECIAL) || |
|
(*p != ' ' && *p != '\0')) { |
|
mandoc_vmsg(MANDOCERR_CHAR_ARG, r->parse, |
|
ln, pos, "char %s", kp); |
|
return ROFF_IGN; |
|
} |
|
ksz = p - kp; |
|
while (*p == ' ') |
|
p++; |
|
|
|
/* |
|
* If the replacement string contains a font escape sequence, |
|
* we have to restore the font at the end. |
|
*/ |
|
|
|
vp = p; |
|
vsz = strlen(p); |
|
font = 0; |
|
while (*p != '\0') { |
|
if (*p++ != '\\') |
|
continue; |
|
switch (mandoc_escape(&p, NULL, NULL)) { |
|
case ESCAPE_FONT: |
|
case ESCAPE_FONTROMAN: |
|
case ESCAPE_FONTITALIC: |
|
case ESCAPE_FONTBOLD: |
|
case ESCAPE_FONTBI: |
|
case ESCAPE_FONTCW: |
|
case ESCAPE_FONTPREV: |
|
font++; |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
if (font > 1) |
|
mandoc_msg(MANDOCERR_CHAR_FONT, r->parse, |
|
ln, vp - buf->buf, vp); |
|
|
|
/* |
|
* Approximate the effect of .char using the .tr tables. |
|
* XXX In groff, .char and .tr interact differently. |
|
*/ |
|
|
|
if (ksz == 1) { |
|
if (r->xtab == NULL) |
|
r->xtab = mandoc_calloc(128, sizeof(*r->xtab)); |
|
assert((unsigned int)*kp < 128); |
|
free(r->xtab[(int)*kp].p); |
|
r->xtab[(int)*kp].sz = mandoc_asprintf(&r->xtab[(int)*kp].p, |
|
"%s%s", vp, font ? "\fP" : ""); |
|
} else { |
|
roff_setstrn(&r->xmbtab, kp, ksz, vp, vsz, 0); |
|
if (font) |
|
roff_setstrn(&r->xmbtab, kp, ksz, "\\fP", 3, 1); |
|
} |
return ROFF_IGN; |
return ROFF_IGN; |
} |
} |
|
|