Annotation of mandoc/eqn.c, Revision 1.7
1.7 ! kristaps 1: /* $Id: eqn.c,v 1.6 2011/07/17 12:13:37 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #ifdef HAVE_CONFIG_H
18: #include "config.h"
19: #endif
20:
21: #include <assert.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <string.h>
25: #include <time.h>
26:
27: #include "mandoc.h"
28: #include "libmandoc.h"
29: #include "libroff.h"
30:
1.6 kristaps 31: static const char *eqn_nexttok(struct mparse *, int, int,
32: const char **, size_t *);
33:
1.1 kristaps 34: /* ARGSUSED */
35: enum rofferr
1.6 kristaps 36: eqn_read(struct eqn_node **epp, int ln,
37: const char *p, int pos, int *offs)
1.1 kristaps 38: {
1.6 kristaps 39: size_t sz;
40: struct eqn_node *ep;
41: const char *start, *end;
42: int i;
1.1 kristaps 43:
44: if (0 == strcmp(p, ".EN")) {
45: *epp = NULL;
46: return(ROFF_EQN);
47: }
48:
49: ep = *epp;
1.6 kristaps 50: end = p + pos;
51: start = eqn_nexttok(ep->parse, ln, pos, &end, &sz);
52:
53: if (NULL == start)
54: return(ROFF_IGN);
55:
56: if (6 == sz && 0 == strncmp("define", start, 6)) {
1.7 ! kristaps 57: if (end && '"' == *end)
! 58: mandoc_msg(MANDOCERR_EQNQUOTE,
! 59: ep->parse, ln, pos, NULL);
! 60:
1.6 kristaps 61: start = eqn_nexttok(ep->parse, ln, pos, &end, &sz);
1.7 ! kristaps 62:
1.6 kristaps 63: for (i = 0; i < (int)ep->defsz; i++) {
64: if (ep->defs[i].keysz != sz)
65: continue;
66: if (0 == strncmp(ep->defs[i].key, start, sz))
67: break;
68: }
69:
70: /*
71: * TODO: merge this code with roff_getstr().
72: */
73:
74: if (i == (int)ep->defsz) {
75: ep->defsz++;
76: ep->defs = mandoc_realloc
77: (ep->defs, ep->defsz *
78: sizeof(struct eqn_def));
79: ep->defs[i].keysz = sz;
80: ep->defs[i].key = mandoc_malloc(sz + 1);
81: memcpy(ep->defs[i].key, start, sz);
82: ep->defs[i].key[(int)sz] = '\0';
83: ep->defs[i].val = NULL;
84: ep->defs[i].valsz = 0;
85: }
86:
87: start = eqn_nexttok(ep->parse, ln, pos, &end, &sz);
88:
89: ep->defs[i].valsz = sz;
90: ep->defs[i].val = mandoc_realloc
91: (ep->defs[i].val, sz + 1);
92: memcpy(ep->defs[i].val, start, sz);
93: ep->defs[i].val[(int)sz] = '\0';
94:
95: if ('\0' == *end)
96: return(ROFF_IGN);
97:
98: *offs = end - (p + pos);
99: assert(*offs > 0);
100:
101: return(ROFF_RERUN);
102: } else
103: end = p + pos;
104:
105: if (0 == (sz = strlen(end)))
106: return(ROFF_IGN);
1.1 kristaps 107:
108: ep->eqn.data = mandoc_realloc(ep->eqn.data, ep->eqn.sz + sz + 1);
109: if (0 == ep->eqn.sz)
110: *ep->eqn.data = '\0';
111:
112: ep->eqn.sz += sz;
1.6 kristaps 113: strlcat(ep->eqn.data, end, ep->eqn.sz + 1);
1.1 kristaps 114: return(ROFF_IGN);
115: }
116:
117: struct eqn_node *
1.5 kristaps 118: eqn_alloc(int pos, int line, struct mparse *parse)
1.1 kristaps 119: {
120: struct eqn_node *p;
121:
122: p = mandoc_calloc(1, sizeof(struct eqn_node));
1.5 kristaps 123: p->parse = parse;
1.2 kristaps 124: p->eqn.line = line;
125: p->eqn.pos = pos;
1.1 kristaps 126:
127: return(p);
128: }
129:
1.3 kristaps 130: /* ARGSUSED */
1.1 kristaps 131: void
132: eqn_end(struct eqn_node *e)
133: {
134:
135: /* Nothing to do. */
136: }
137:
138: void
139: eqn_free(struct eqn_node *p)
140: {
1.6 kristaps 141: int i;
1.1 kristaps 142:
143: free(p->eqn.data);
1.6 kristaps 144:
145: for (i = 0; i < (int)p->defsz; i++) {
146: free(p->defs[i].key);
147: free(p->defs[i].val);
148: }
149:
150: free(p->defs);
1.1 kristaps 151: free(p);
1.6 kristaps 152: }
153:
1.7 ! kristaps 154: /*
! 155: * Return the current equation token setting "next" on the next one,
! 156: * setting the token size in "sz".
! 157: * This does the Right Thing for quoted strings, too.
! 158: * Returns NULL if no more tokens exist.
! 159: */
1.6 kristaps 160: static const char *
161: eqn_nexttok(struct mparse *mp, int ln, int pos,
162: const char **next, size_t *sz)
163: {
164: const char *start;
165: int q;
166:
167: start = *next;
168: q = 0;
169:
170: if ('\0' == *start)
171: return(NULL);
172:
173: if ('"' == *start) {
174: start++;
175: q = 1;
176: }
177:
178: *next = q ? strchr(start, '"') : strchr(start, ' ');
179:
180: if (NULL != *next) {
181: *sz = (size_t)(*next - start);
182: if (q)
183: (*next)++;
184: while (' ' == **next)
185: (*next)++;
186: } else {
1.7 ! kristaps 187: /*
! 188: * XXX: groff gets confused by this and doesn't always
! 189: * do the "right thing" (just terminate it and warn
! 190: * about it).
! 191: */
1.6 kristaps 192: if (q)
193: mandoc_msg(MANDOCERR_BADQUOTE,
194: mp, ln, pos, NULL);
195: *next = strchr(start, '\0');
196: *sz = (size_t)(*next - start);
197: }
198:
199: return(start);
1.1 kristaps 200: }
CVSweb