| @@ -167,26 +167,28 @@ static void roffhash_init(void); | | | @@ -167,26 +167,28 @@ static void roffhash_init(void); |
167 | static void roffnode_cleanscope(struct roff *); | | 167 | static void roffnode_cleanscope(struct roff *); |
168 | static void roffnode_pop(struct roff *); | | 168 | static void roffnode_pop(struct roff *); |
169 | static void roffnode_push(struct roff *, enum rofft, | | 169 | static void roffnode_push(struct roff *, enum rofft, |
170 | const char *, int, int); | | 170 | const char *, int, int); |
171 | static enum rofferr roff_block(ROFF_ARGS); | | 171 | static enum rofferr roff_block(ROFF_ARGS); |
172 | static enum rofferr roff_block_text(ROFF_ARGS); | | 172 | static enum rofferr roff_block_text(ROFF_ARGS); |
173 | static enum rofferr roff_block_sub(ROFF_ARGS); | | 173 | static enum rofferr roff_block_sub(ROFF_ARGS); |
174 | static enum rofferr roff_cblock(ROFF_ARGS); | | 174 | static enum rofferr roff_cblock(ROFF_ARGS); |
175 | static enum rofferr roff_ccond(ROFF_ARGS); | | 175 | static enum rofferr roff_ccond(ROFF_ARGS); |
176 | static enum rofferr roff_cond(ROFF_ARGS); | | 176 | static enum rofferr roff_cond(ROFF_ARGS); |
177 | static enum rofferr roff_cond_text(ROFF_ARGS); | | 177 | static enum rofferr roff_cond_text(ROFF_ARGS); |
178 | static enum rofferr roff_cond_sub(ROFF_ARGS); | | 178 | static enum rofferr roff_cond_sub(ROFF_ARGS); |
179 | static enum rofferr roff_ds(ROFF_ARGS); | | 179 | static enum rofferr roff_ds(ROFF_ARGS); |
| | | 180 | static void roff_expand_nr_inplace(struct roff *, char **, int *, |
| | | 181 | size_t *); |
180 | static enum roffrule roff_evalcond(const char *, int *); | | 182 | static enum roffrule roff_evalcond(const char *, int *); |
181 | static void roff_free1(struct roff *); | | 183 | static void roff_free1(struct roff *); |
182 | static void roff_freestr(struct roffkv *); | | 184 | static void roff_freestr(struct roffkv *); |
183 | static char *roff_getname(struct roff *, char **, int, int); | | 185 | static char *roff_getname(struct roff *, char **, int, int); |
184 | static const char *roff_getstrn(const struct roff *, | | 186 | static const char *roff_getstrn(const struct roff *, |
185 | const char *, size_t); | | 187 | const char *, size_t); |
186 | static enum rofferr roff_line_ignore(ROFF_ARGS); | | 188 | static enum rofferr roff_line_ignore(ROFF_ARGS); |
187 | static enum rofferr roff_nr(ROFF_ARGS); | | 189 | static enum rofferr roff_nr(ROFF_ARGS); |
188 | static void roff_openeqn(struct roff *, const char *, | | 190 | static void roff_openeqn(struct roff *, const char *, |
189 | int, int, const char *); | | 191 | int, int, const char *); |
190 | static enum rofft roff_parse(struct roff *, const char *, int *); | | 192 | static enum rofft roff_parse(struct roff *, const char *, int *); |
191 | static enum rofferr roff_parsetext(char *); | | 193 | static enum rofferr roff_parsetext(char *); |
192 | static enum rofferr roff_res(struct roff *, | | 194 | static enum rofferr roff_res(struct roff *, |
| @@ -1043,26 +1045,32 @@ roff_cond_sub(ROFF_ARGS) | | | @@ -1043,26 +1045,32 @@ roff_cond_sub(ROFF_ARGS) |
1043 | /* ARGSUSED */ | | 1045 | /* ARGSUSED */ |
1044 | static enum rofferr | | 1046 | static enum rofferr |
1045 | roff_cond_text(ROFF_ARGS) | | 1047 | roff_cond_text(ROFF_ARGS) |
1046 | { | | 1048 | { |
1047 | char *ep; | | 1049 | char *ep; |
1048 | enum roffrule rr; | | 1050 | enum roffrule rr; |
1049 | | | 1051 | |
1050 | rr = r->last->rule; | | 1052 | rr = r->last->rule; |
1051 | roffnode_cleanscope(r); | | 1053 | roffnode_cleanscope(r); |
1052 | | | 1054 | |
1053 | ep = &(*bufp)[pos]; | | 1055 | ep = &(*bufp)[pos]; |
1054 | for ( ; NULL != (ep = strchr(ep, '\\')); ep++) { | | 1056 | for ( ; NULL != (ep = strchr(ep, '\\')); ep++) { |
1055 | ep++; | | 1057 | ep++; |
| | | 1058 | if (*ep == 'n') { |
| | | 1059 | int i = ep - *bufp - 1; |
| | | 1060 | roff_expand_nr_inplace(r, bufp, &i, szp); |
| | | 1061 | ep = *bufp + i; |
| | | 1062 | continue; |
| | | 1063 | } |
1056 | if ('}' != *ep) | | 1064 | if ('}' != *ep) |
1057 | continue; | | 1065 | continue; |
1058 | *ep = '&'; | | 1066 | *ep = '&'; |
1059 | roff_ccond(r, ROFF_ccond, bufp, szp, | | 1067 | roff_ccond(r, ROFF_ccond, bufp, szp, |
1060 | ln, pos, pos + 2, offs); | | 1068 | ln, pos, pos + 2, offs); |
1061 | } | | 1069 | } |
1062 | return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); | | 1070 | return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); |
1063 | } | | 1071 | } |
1064 | | | 1072 | |
1065 | static enum roffrule | | 1073 | static enum roffrule |
1066 | roff_evalcond(const char *v, int *pos) | | 1074 | roff_evalcond(const char *v, int *pos) |
1067 | { | | 1075 | { |
1068 | | | 1076 | |
| @@ -1298,37 +1306,96 @@ roff_nr(ROFF_ARGS) | | | @@ -1298,37 +1306,96 @@ roff_nr(ROFF_ARGS) |
1298 | h->val = mandoc_strntoi(val, strlen(val), 10); | | 1306 | h->val = mandoc_strntoi(val, strlen(val), 10); |
1299 | | | 1307 | |
1300 | if (0 == strcmp(key, "nS")) { | | 1308 | if (0 == strcmp(key, "nS")) { |
1301 | r->regs[(int)REG_nS].set = 1; | | 1309 | r->regs[(int)REG_nS].set = 1; |
1302 | if (h->val >= 0) | | 1310 | if (h->val >= 0) |
1303 | r->regs[(int)REG_nS].u = (unsigned)h->val; | | 1311 | r->regs[(int)REG_nS].u = (unsigned)h->val; |
1304 | else | | 1312 | else |
1305 | r->regs[(int)REG_nS].u = 0u; | | 1313 | r->regs[(int)REG_nS].u = 0u; |
1306 | } | | 1314 | } |
1307 | | | 1315 | |
1308 | return(ROFF_IGN); | | 1316 | return(ROFF_IGN); |
1309 | } | | 1317 | } |
1310 | | | 1318 | |
1311 | size_t | | 1319 | void |
1312 | roff_expand_nr(struct roff *r, const char *key, char *lp, size_t lpl) | | 1320 | roff_expand_nr(struct roff *r, const char *src, int *sp, size_t slen, |
| | | 1321 | char **dst, int *dp, size_t *dlenp) |
1313 | { | | 1322 | { |
1314 | uint32_t hv; | | 1323 | uint32_t hv; |
1315 | struct roff_nr *h; | | 1324 | struct roff_nr *h; |
| | | 1325 | int l, s, d; |
| | | 1326 | char e, *key; |
1316 | | | 1327 | |
1317 | if ((h = hash_find(r, key, &hv)) == NULL) | | 1328 | s = *sp + 2; /* skip \\\n */ |
1318 | return 0; | | 1329 | d = *dp; |
| | | 1330 | |
| | | 1331 | if ('[' == src[s]) { /* XXX: Support builtins */ |
| | | 1332 | s++; |
| | | 1333 | e = ']'; |
| | | 1334 | } else |
| | | 1335 | e = '\0'; |
| | | 1336 | |
| | | 1337 | for (l = s; l < (int)slen; l++) { |
| | | 1338 | if (e) { |
| | | 1339 | if (src[l] == e) |
| | | 1340 | break; |
| | | 1341 | } else { |
| | | 1342 | if (isspace((unsigned char)src[l])) |
| | | 1343 | break; |
| | | 1344 | } |
| | | 1345 | } |
| | | 1346 | *sp = l; |
| | | 1347 | l -= s; |
| | | 1348 | key = mandoc_malloc(l + 1); |
| | | 1349 | memcpy(key, src + s, l); |
| | | 1350 | key[l] = '\0'; |
| | | 1351 | |
| | | 1352 | if ((h = hash_find(r, key, &hv)) == NULL) { |
| | | 1353 | free(key); |
| | | 1354 | return; |
| | | 1355 | } |
| | | 1356 | if (*dst == NULL || *dlenp - *dp < 256) |
| | | 1357 | *dst = mandoc_realloc(*dst, *dlenp += 256); |
1319 | | | 1358 | |
1320 | /* XXX: support .af */ | | 1359 | /* XXX: support .af */ |
1321 | return snprintf(lp, lpl, "%jd", h->val); | | 1360 | *dp += snprintf(*dst + *dp, *dlenp - *dp, "%jd", h->val); |
| | | 1361 | } |
| | | 1362 | |
| | | 1363 | static void |
| | | 1364 | roff_expand_nr_inplace(struct roff *r, char **src, int *sp, size_t *slenp) |
| | | 1365 | { |
| | | 1366 | int j, i, k; |
| | | 1367 | size_t dlen; |
| | | 1368 | char *dst; |
| | | 1369 | |
| | | 1370 | k = i = *sp; |
| | | 1371 | |
| | | 1372 | dst = NULL; |
| | | 1373 | j = 0; |
| | | 1374 | dlen = 0; |
| | | 1375 | |
| | | 1376 | roff_expand_nr(r, *src, &i, *slenp, &dst, &j, &dlen); |
| | | 1377 | |
| | | 1378 | if (j) { |
| | | 1379 | int l = j - (i - k); |
| | | 1380 | if (l > 0) { |
| | | 1381 | *slenp += l; |
| | | 1382 | *src = mandoc_realloc(*src, *slenp); |
| | | 1383 | } |
| | | 1384 | memmove(*src + j + k, *src + i, *slenp - i); |
| | | 1385 | memcpy(*src + k, dst, j); |
| | | 1386 | free(dst); |
| | | 1387 | } |
| | | 1388 | *sp = k + j; |
1322 | } | | 1389 | } |
1323 | | | 1390 | |
1324 | /* ARGSUSED */ | | 1391 | /* ARGSUSED */ |
1325 | static enum rofferr | | 1392 | static enum rofferr |
1326 | roff_rm(ROFF_ARGS) | | 1393 | roff_rm(ROFF_ARGS) |
1327 | { | | 1394 | { |
1328 | const char *name; | | 1395 | const char *name; |
1329 | char *cp; | | 1396 | char *cp; |
1330 | | | 1397 | |
1331 | cp = *bufp + pos; | | 1398 | cp = *bufp + pos; |
1332 | while ('\0' != *cp) { | | 1399 | while ('\0' != *cp) { |
1333 | name = roff_getname(r, &cp, ln, (int)(cp - *bufp)); | | 1400 | name = roff_getname(r, &cp, ln, (int)(cp - *bufp)); |
1334 | if ('\0' != *name) | | 1401 | if ('\0' != *name) |