1 /* reading characters and escapes */
8 /* return the length of a utf-8 character based on its first byte */
11 if (~c
& 0xc0) /* ASCII or invalid */
22 /* return nonzero if s is a single utf-8 character */
25 return !s
[utf8len((unsigned char) *s
)];
28 /* read a utf-8 character from s and copy it to d */
29 int utf8read(char **s
, char *d
)
31 int l
= utf8len((unsigned char) **s
);
33 for (i
= 0; i
< l
; i
++)
40 /* read a utf-8 character with next() and copy it to s */
41 int utf8next(char *s
, int (*next
)(void))
49 for (i
= 1; i
< l
; i
++)
55 /* read quoted arguments of escape sequences (ESC_Q) */
56 char *quotednext(int (*next
)(void), void (*back
)(int))
58 char delim
[GNLEN
], cs
[GNLEN
];
61 charnext(delim
, next
, back
);
63 while (charnext_delim(cs
, next
, back
, delim
) >= 0) {
70 /* read unquoted arguments of escape sequences (ESC_P) */
71 char *unquotednext(int cmd
, int (*next
)(void), void (*back
)(int))
76 if (cmd
== 's' && (c
== '-' || c
== '+')) {
82 sbuf_add(&sb
, next());
83 sbuf_add(&sb
, next());
84 } else if (!n_cp
&& c
== '[') {
86 while (c
> 0 && c
!= '\n' && c
!= ']') {
92 if (n_cp
&& cmd
== 's' && c
>= '1' && c
<= '3') {
100 return sbuf_out(&sb
);
104 * read the next character or escape sequence (x, \x, \(xy, \[xyz], \C'xyz')
106 * character returned contents of c
114 int charnext(char *c
, int (*next
)(void), void (*back
)(int))
117 if (!utf8next(c
, next
))
120 utf8next(c
+ 1, next
);
124 utf8next(c
+ 1, next
);
126 l
= utf8next(c
, next
);
127 l
+= utf8next(c
+ l
, next
);
129 } else if (!n_cp
&& c
[1] == '[') {
132 while (n
>= 0 && n
!= '\n' && n
!= ']' && l
< GNLEN
- 1) {
138 } else if (c
[1] == 'C') {
139 char *chr
= quotednext(next
, back
);
140 snprintf(c
, GNLEN
, "%s", chr
);
149 /* like nextchar(), but return -1 if delim was read */
150 int charnext_delim(char *c
, int (*next
)(void), void (*back
)(int), char *delim
)
152 int t
= charnext(c
, next
, back
);
153 return strcmp(c
, delim
) ? t
: -1;
156 /* convert back the character read from nextchar() (e.g. xy -> \\(xy) */
157 void charnext_str(char *d
, char *c
)
159 int c0
= (unsigned char) c
[0];
160 if (c0
== c_ec
|| c0
== c_ni
|| !c
[1] || utf8one(c
)) {
164 if (!c
[2] && utf8len(c0
) == 1)
165 sprintf(d
, "%c(%s", c_ec
, c
);
167 sprintf(d
, "%cC'%s'", c_ec
, c
);
170 /* like charnext() for string buffers */
171 int charread(char **s
, char *c
)
175 ret
= charnext(c
, sstr_next
, sstr_back
);
180 /* like charnext_delim() for string buffers */
181 int charread_delim(char **s
, char *c
, char *delim
)
185 ret
= charnext_delim(c
, sstr_next
, sstr_back
, delim
);
190 /* read quoted arguments; this is called only for internal neatroff strings */
191 static void quotedread(char **sp
, char *d
)
195 while (*s
&& *s
!= q
)
203 /* read unquoted arguments; this is called only for internal neatroff strings */
204 static void unquotedread(char **sp
, char *d
)
211 } else if (!n_cp
&& *s
== '[') {
213 while (*s
&& *s
!= ']')
225 * read a glyph or an escape sequence
227 * This function reads from s either an output troff request
228 * (only the ones emitted by wb.c) or a glyph name and updates
229 * s. The return value is the name of the troff request (the
230 * argument is copied into d) or zero for glyph names (it is
231 * copied into d). Returns -1 when the end of s is reached.
232 * Note that to d, a pointer to a static array is assigned.
234 int escread(char **s
, char **d
)
236 static char buf
[1 << 12];
247 utf8read(s
, r
+ strlen(r
));
248 } else if (!n_cp
&& r
[1] == '[') {
249 while (**s
&& **s
!= ']')
254 } else if (strchr("CDfhmsvXx<>", r
[1])) {
257 if (strchr(ESC_P
, c
))
259 if (strchr(ESC_Q
, c
))
261 return c
== 'C' ? 0 : c
;
263 } else if (r
[0] == c_ni
) {
270 * string streams: provide next()/back() interface for string buffers
272 * Functions like charnext() require a next()/back() interface
273 * for reading input streams. In order to provide this interface
274 * for string buffers, the following functions can be used:
277 * charnext(c, sstr_next, sstr_back);
280 * The calls to sstr_push()/sstr_pop() may be nested.
282 static char *sstr_bufs
[NSSTR
]; /* buffer stack */
283 static int sstr_n
; /* numbers of items in sstr_bufs[] */
284 static char *sstr_s
; /* current buffer */
286 void sstr_push(char *s
)
288 sstr_bufs
[sstr_n
++] = sstr_s
;
295 sstr_s
= sstr_bufs
[--sstr_n
];
301 return *sstr_s
? (unsigned char) *sstr_s
++ : -1;
304 void sstr_back(int c
)