Lely core libraries 2.3.4
lex.c
Go to the documentation of this file.
1
24#include "util.h"
25
26#if !LELY_NO_STDIO
27
28#define LELY_UTIL_LEX_INLINE extern inline
29#include <lely/libc/string.h>
30#include <lely/libc/uchar.h>
31#include <lely/util/diag.h>
32#include <lely/util/lex.h>
33#include <lely/util/print.h>
34
35#include <assert.h>
36#include <inttypes.h>
37#include <math.h>
38#include <stdlib.h>
39
40size_t
41lex_char(int c, const char *begin, const char *end, struct floc *at)
42{
43 assert(begin);
44
45 const char *cp = begin;
46
47 if ((end && cp >= end) || *cp++ != c)
48 return 0;
49
50 return floc_lex(at, begin, begin + 1);
51}
52
53size_t
54lex_ctype(int (*ctype)(int), const char *begin, const char *end,
55 struct floc *at)
56{
57 assert(ctype);
58 assert(begin);
59
60 const char *cp = begin;
61
62 while ((!end || cp < end) && ctype((unsigned char)*cp))
63 cp++;
64
65 return floc_lex(at, begin, cp);
66}
67
68size_t
69lex_break(const char *begin, const char *end, struct floc *at)
70{
71 assert(begin);
72
73 const char *cp = begin;
74
75 if ((end && cp >= end) || !isbreak((unsigned char)*cp))
76 return 0;
77
78 // Treat "\r\n" as a single line break.
79 if (*cp++ == '\r' && (!end || cp < end) && *cp == '\n')
80 cp++;
81
82 return floc_lex(at, begin, cp);
83}
84
85size_t
86lex_utf8(const char *begin, const char *end, struct floc *at, char32_t *pc32)
87{
88 assert(begin);
89
90 const char *cp = begin;
91
92 if (end && cp >= end)
93 return 0;
94
95 char32_t c32;
96
97 int n;
98 unsigned char c = *cp++;
99 if (!(c & 0x80)) {
100 // 0xxxxxxx is an ASCII character.
101 c32 = c & 0x7f;
102 n = 0;
103 } else if ((c & 0xc0) == 0x80) {
104 // 10xxxxxx is a continuation byte. It cannot appear at the
105 // beginning of a valid UTF-8 sequence. We skip all subsequent
106 // continuation bytes to prevent multiple errors for the same
107 // sequence.
108 while ((!end || cp < end)
109 && ((unsigned char)*cp & 0xc0) == 0x80)
110 cp++;
111 diag_if(DIAG_WARNING, 0, at,
112 "a UTF-8 sequence cannot begin with a continuation byte");
113 goto error;
114 } else if ((c & 0xe0) == 0xc0) {
115 // 110xxxxx is the first byte in a two-byte sequence.
116 c32 = c & 0x1f;
117 n = 1;
118 } else if ((c & 0xf0) == 0xe0) {
119 // 1110xxxx is the first byte in a three-byte sequence.
120 c32 = c & 0x0f;
121 n = 2;
122 } else if ((c & 0xf8) == 0xf0) {
123 // 11110xxx is the first byte in a four-byte sequence.
124 c32 = c & 0x07;
125 n = 3;
126 } else {
127 // Five- and six-byte sequences have been deprecated since 2003.
128 diag_if(DIAG_WARNING, 0, at, "invalid UTF-8 byte");
129 goto error;
130 }
131
132 // Lex the continuation bytes.
133 while (n--) {
134 if ((end && cp > end) || ((unsigned char)*cp & 0xc0) != 0x80)
135 goto error;
136 c32 = (c32 << 6) | ((unsigned char)*cp & 0x3f);
137 }
138
139 // Valid Unicode code points fall in the range between U+0000 and
140 // U+10FFFF, with the exception of U+D800 to U+DFFF, which are reserved
141 // for UTF-16 encoding of high and low surrogates, respectively.
142 if ((c32 >= 0xd800 && c32 <= 0xdfff) || c32 > 0x10ffff) {
143 diag_if(DIAG_WARNING, 0, at,
144 "illegal Unicode code point U+%" PRIX32, c32);
145 goto error;
146 }
147
148done:
149 if (pc32)
150 *pc32 = c32;
151
152 return floc_lex(at, begin, cp);
153
154error:
155 // Replace an invalid code point by the Unicode replacement character
156 // (U+FFFD).
157 c32 = 0xfffd;
158 goto done;
159}
160
161size_t
162lex_c99_id(const char *begin, const char *end, struct floc *at, char *s,
163 size_t *pn)
164{
165 assert(begin);
166
167 const char *cp = begin;
168
169 if ((end && cp >= end) || !(*cp == '_' || isalpha((unsigned char)*cp)))
170 return 0;
171 cp++;
172
173 while ((!end || cp < end)
174 && (*cp == '_' || isalnum((unsigned char)*cp)))
175 cp++;
176
177 if (pn) {
178 if (s)
179 memcpy(s, begin, MIN((size_t)(cp - begin), *pn));
180 *pn = cp - begin;
181 }
182
183 return floc_lex(at, begin, cp);
184}
185
186size_t
187lex_c99_esc(const char *begin, const char *end, struct floc *at, char32_t *pc32)
188{
189 assert(begin);
190
191 const char *cp = begin;
192
193 if (end && cp >= end)
194 return 0;
195
196 if (*cp++ != '\\')
197 return lex_utf8(begin, end, at, pc32);
198
199 // Treat a backslash at the end as '\\'.
200 if (end && cp >= end)
201 cp--;
202
203 char32_t c32 = 0;
204 if (isodigit(*cp)) {
205 c32 = ctoo(*cp);
206 cp++;
207 while ((!end || cp < end) && isodigit((unsigned char)*cp)) {
208 c32 = (c32 << 3) | ctoo(*cp);
209 cp++;
210 }
211 } else {
212 switch (*cp++) {
213 case '\'': c32 = '\''; break;
214 case '\"': c32 = '\"'; break;
215 case '\\': c32 = '\\'; break;
216 case 'a': c32 = '\a'; break;
217 case 'b': c32 = '\b'; break;
218 case 'f': c32 = '\f'; break;
219 case 'n': c32 = '\n'; break;
220 case 'r': c32 = '\r'; break;
221 case 't': c32 = '\t'; break;
222 case 'v': c32 = '\v'; break;
223 case 'x':
224 while ((!end || cp < end)
225 && isxdigit((unsigned char)*cp)) {
226 c32 = (c32 << 4) | ctox(*cp);
227 cp++;
228 }
229 break;
230 default:
231 cp--;
232 diag_if(DIAG_WARNING, 0, at,
233 isgraph((unsigned char)*cp)
234 ? "illegal escape sequence '\\%c'"
235 : "illegal escape sequence '\\\\%o'",
236 *cp);
237 // Treat an invalid escape sequence as '\\'.
238 c32 = '\\';
239 break;
240 }
241 }
242
243 if (pc32)
244 *pc32 = c32;
245
246 return floc_lex(at, begin, cp);
247}
248
249size_t
250lex_c99_str(const char *begin, const char *end, struct floc *at, char *s,
251 size_t *pn)
252{
253 assert(begin);
254
255 struct floc *floc = NULL;
256 struct floc floc_;
257 if (at) {
258 floc = &floc_;
259 *floc = *at;
260 }
261
262 const char *cp = begin;
263
264 size_t n = 0;
265 char *ends = s + (s && pn ? *pn : 0);
266
267 while ((!end || cp < end) && *cp && *cp != '\"'
268 && !isbreak((unsigned char)*cp)) {
269 char32_t c32 = 0;
270 if (*cp == '\\')
271 cp += lex_c99_esc(cp, end, floc, &c32);
272 else
273 cp += lex_utf8(cp, end, floc, &c32);
274 if (s || pn)
275 n += print_utf8(&s, ends, c32);
276 }
277
278 if (pn)
279 *pn = n;
280
281 if (at)
282 *at = *floc;
283
284 return cp - begin;
285}
286
287size_t
288lex_c99_pp_num(const char *begin, const char *end, struct floc *at)
289{
290 assert(begin);
291
292 const char *cp = begin;
293
294 // Parse the optional sign.
295 if ((!end || cp < end) && (*cp == '+' || *cp == '-'))
296 cp++;
297
298 // Any number has to begin with either a digit, or a period followed by
299 // a digit.
300 if ((!end || cp < end) && isdigit((unsigned char)*cp)) {
301 cp++;
302 } else if ((!end || end - cp >= 2) && cp[0] == '.'
303 && isdigit((unsigned char)cp[1])) {
304 cp += 2;
305 } else {
306 return 0;
307 }
308
309 while ((!end || cp < end) && *cp) {
310 if (*cp == 'e' || *cp == 'E' || *cp == 'p' || *cp == 'P') {
311 cp++;
312 // Exponents may contain a sign.
313 if ((!end || cp < end) && (*cp == '+' || *cp == '-'))
314 cp++;
315 } else if (*cp == '.' || *cp == '_'
316 || isalnum((unsigned char)*cp)) {
317 cp++;
318 } else {
319 break;
320 }
321 }
322
323 return floc_lex(at, begin, cp);
324}
325
326#define LELY_UTIL_DEFINE_LEX_SIGNED(type, suffix, strtov, min, max, pname) \
327 size_t lex_c99_##suffix(const char *begin, const char *end, \
328 struct floc *at, type *pname) \
329 { \
330 size_t chars = lex_c99_pp_num(begin, end, NULL); \
331 if (!chars) \
332 return 0; \
333\
334 char *buf = strndup(begin, chars); \
335 if (!buf) { \
336 diag_if(DIAG_ERROR, errno2c(errno), at, \
337 "unable to duplicate string"); \
338 return 0; \
339 } \
340\
341 int errsv = errno; \
342 errno = 0; \
343\
344 char *endptr; \
345 type result = strtov(buf, &endptr); \
346 chars = endptr - buf; \
347\
348 free(buf); \
349\
350 if (errno == ERANGE && result == min) { \
351 set_errnum(ERRNUM_RANGE); \
352 diag_if(DIAG_WARNING, get_errc(), at, \
353 #type " underflow"); \
354 } else if (errno == ERANGE && result == max) { \
355 set_errnum(ERRNUM_RANGE); \
356 diag_if(DIAG_WARNING, get_errc(), at, \
357 #type " overflow"); \
358 } else if (!errno) { \
359 errno = errsv; \
360 } \
361\
362 if (pname) \
363 *pname = result; \
364\
365 return floc_lex(at, begin, begin + chars); \
366 }
367
368#define LELY_UTIL_DEFINE_LEX_UNSIGNED(type, suffix, strtov, max, pname) \
369 size_t lex_c99_##suffix(const char *begin, const char *end, \
370 struct floc *at, type *pname) \
371 { \
372 size_t chars = lex_c99_pp_num(begin, end, NULL); \
373 if (!chars) \
374 return 0; \
375\
376 char *buf = strndup(begin, chars); \
377 if (!buf) { \
378 diag_if(DIAG_ERROR, errno2c(errno), at, \
379 "unable to duplicate string"); \
380 return 0; \
381 } \
382\
383 int errsv = errno; \
384 errno = 0; \
385\
386 char *endptr; \
387 type result = strtov(buf, &endptr); \
388 chars = endptr - buf; \
389\
390 free(buf); \
391\
392 if (errno == ERANGE && result == max) { \
393 set_errnum(ERRNUM_RANGE); \
394 diag_if(DIAG_WARNING, get_errc(), at, \
395 #type " overflow"); \
396 } else if (!errno) { \
397 errno = errsv; \
398 } \
399\
400 if (pname) \
401 *pname = result; \
402\
403 return floc_lex(at, begin, begin + chars); \
404 }
405
406#define strtov(nptr, endptr) strtol(nptr, endptr, 0)
407LELY_UTIL_DEFINE_LEX_SIGNED(long, long, strtov, LONG_MIN, LONG_MAX, pl)
408#undef strtov
409#define strtov(nptr, endptr) strtoul(nptr, endptr, 0)
410LELY_UTIL_DEFINE_LEX_UNSIGNED(unsigned long, ulong, strtov, ULONG_MAX, pul)
411#undef strtov
412#define strtov(nptr, endptr) strtoll(nptr, endptr, 0)
413LELY_UTIL_DEFINE_LEX_SIGNED(long long, llong, strtov, LLONG_MIN, LLONG_MAX, pll)
414#undef strtov
415#define strtov(nptr, endptr) strtoull(nptr, endptr, 0)
416LELY_UTIL_DEFINE_LEX_UNSIGNED(
417 unsigned long long, ullong, strtov, ULLONG_MAX, pull)
418#undef strtov
419LELY_UTIL_DEFINE_LEX_SIGNED(float, flt, strtof, -HUGE_VALF, HUGE_VALF, pf)
420LELY_UTIL_DEFINE_LEX_SIGNED(double, dbl, strtod, -HUGE_VAL, HUGE_VAL, pd)
421LELY_UTIL_DEFINE_LEX_SIGNED(
422 long double, ldbl, strtold, -HUGE_VALL, HUGE_VALL, pld)
423
424#undef LELY_UTIL_DEFINE_LEX_UNSIGNED
425#undef LELY_UTIL_DEFINE_LEX_SIGNED
426
427size_t
428lex_c99_i8(const char *begin, const char *end, struct floc *at,
429 int_least8_t *pi8)
430{
431 long i8;
432 size_t chars = lex_c99_long(begin, end, at, &i8);
433 if (chars) {
434 if (i8 < INT_LEAST8_MIN) {
435 i8 = INT_LEAST8_MIN;
438 "int8_t underflow");
439 } else if (i8 > INT_LEAST8_MAX) {
440 i8 = INT_LEAST8_MAX;
443 "int8_t overflow");
444 }
445 if (pi8)
446 *pi8 = (int_least8_t)i8;
447 }
448 return chars;
449}
450
451size_t
452lex_c99_i16(const char *begin, const char *end, struct floc *at,
453 int_least16_t *pi16)
454{
455 long i16;
456 size_t chars = lex_c99_long(begin, end, at, &i16);
457 if (chars) {
458 if (i16 < INT_LEAST16_MIN) {
459 i16 = INT_LEAST16_MIN;
462 "int16_t underflow");
463 } else if (i16 > INT_LEAST16_MAX) {
464 i16 = INT_LEAST16_MAX;
467 "int16_t overflow");
468 }
469 if (pi16)
470 *pi16 = (int_least16_t)i16;
471 }
472 return chars;
473}
474
475size_t
476lex_c99_i32(const char *begin, const char *end, struct floc *at,
477 int_least32_t *pi32)
478{
479 long i32;
480 size_t chars = lex_c99_long(begin, end, at, &i32);
481 if (chars) {
482#if LONG_BIT == 32
483 if (get_errnum() == ERRNUM_RANGE && i32 == LONG_MIN) {
484#else
485 if (i32 < INT_LEAST32_MIN) {
486 i32 = INT_LEAST32_MIN;
488#endif
490 "int32_t underflow");
491#if LONG_BIT == 32
492 } else if (get_errnum() == ERRNUM_RANGE && i32 == LONG_MAX) {
493#else
494 } else if (i32 > INT_LEAST32_MAX) {
495 i32 = INT_LEAST32_MAX;
497#endif
499 "int32_t overflow");
500 }
501 if (pi32)
502 *pi32 = (int_least32_t)i32;
503 }
504 return chars;
505}
506
507size_t
508lex_c99_i64(const char *begin, const char *end, struct floc *at,
509 int_least64_t *pi64)
510{
511#if LONG_BIT == 64
512 long i64;
513 size_t chars = lex_c99_long(begin, end, at, &i64);
514#else
515 long long i64;
516 size_t chars = lex_c99_llong(begin, end, at, &i64);
517#endif
518 if (chars) {
519#if LONG_BIT == 64
520 if (get_errnum() == ERRNUM_RANGE && i64 == LONG_MIN) {
521#else
522 if ((get_errnum() == ERRNUM_RANGE && i64 == LLONG_MIN)
523 || i64 < INT_LEAST64_MIN) {
524 i64 = INT_LEAST64_MIN;
526#endif
528 "int64_t underflow");
529#if LONG_BIT == 64
530 } else if (get_errnum() == ERRNUM_RANGE && i64 == LONG_MAX) {
531#else
532 } else if ((get_errnum() == ERRNUM_RANGE && i64 == LLONG_MAX)
533 || i64 > INT_LEAST64_MAX) {
534 i64 = INT_LEAST64_MAX;
536#endif
538 "int64_t overflow");
539 }
540 if (pi64)
541 *pi64 = (int_least64_t)i64;
542 }
543 return chars;
544}
545
546size_t
547lex_c99_u8(const char *begin, const char *end, struct floc *at,
548 uint_least8_t *pu8)
549{
550 unsigned long u8;
551 size_t chars = lex_c99_ulong(begin, end, at, &u8);
552 if (chars) {
553 if (u8 > UINT_LEAST8_MAX) {
554 u8 = UINT_LEAST8_MAX;
557 "uint8_t overflow");
558 }
559 if (pu8)
560 *pu8 = (uint_least8_t)u8;
561 }
562 return chars;
563}
564
565size_t
566lex_c99_u16(const char *begin, const char *end, struct floc *at,
567 uint_least16_t *pu16)
568{
569 unsigned long u16;
570 size_t chars = lex_c99_ulong(begin, end, at, &u16);
571 if (chars) {
572 if (u16 > UINT_LEAST16_MAX) {
573 u16 = UINT_LEAST16_MAX;
576 "uint16_t overflow");
577 }
578 if (pu16)
579 *pu16 = (uint_least16_t)u16;
580 }
581 return chars;
582}
583
584size_t
585lex_c99_u32(const char *begin, const char *end, struct floc *at,
586 uint_least32_t *pu32)
587{
588 unsigned long u32;
589 size_t chars = lex_c99_ulong(begin, end, at, &u32);
590 if (chars) {
591#if LONG_BIT == 32
592 if (get_errnum() == ERRNUM_RANGE && u32 == ULONG_MAX) {
593#else
594 if (u32 > UINT_LEAST32_MAX) {
595 u32 = UINT_LEAST32_MAX;
597#endif
599 "uint32_t overflow");
600 }
601 if (pu32)
602 *pu32 = (uint_least32_t)u32;
603 }
604 return chars;
605}
606
607size_t
608lex_c99_u64(const char *begin, const char *end, struct floc *at,
609 uint_least64_t *pu64)
610{
611#if LONG_BIT == 64
612 unsigned long u64;
613 size_t chars = lex_c99_ulong(begin, end, at, &u64);
614#else
615 unsigned long long u64;
616 size_t chars = lex_c99_ullong(begin, end, at, &u64);
617#endif
618 if (chars) {
619#if LONG_BIT == 64
620 if (get_errnum() == ERRNUM_RANGE && u64 == ULONG_MAX) {
621#else
622 if ((get_errnum() == ERRNUM_RANGE && u64 == ULONG_MAX)
623 || u64 > UINT_LEAST64_MAX) {
624 u64 = UINT_LEAST64_MAX;
626#endif
628 "uint64_t overflow");
629 }
630 if (pu64)
631 *pu64 = (uint_least64_t)u64;
632 }
633 return chars;
634}
635
636size_t
637lex_line_comment(const char *delim, const char *begin, const char *end,
638 struct floc *at)
639{
640 assert(begin);
641
642 const char *cp = begin;
643
644 if (delim && *delim) {
645 size_t n = strlen(delim);
646 if ((end && cp + n > end) || strncmp(delim, cp, n))
647 return 0;
648 cp += n;
649 }
650
651 // Skip until end-of-line.
652 while ((!end || cp < end) && *cp && !isbreak((unsigned char)*cp))
653 cp++;
654
655 return floc_lex(at, begin, cp);
656}
657
658size_t
659lex_hex(const char *begin, const char *end, struct floc *at, void *ptr,
660 size_t *pn)
661{
662 assert(begin);
663
664 const char *cp = begin;
665
666 unsigned char *bp = ptr;
667 unsigned char *endb = bp + (ptr && pn ? *pn : 0);
668
669 size_t n = 0, i = 0;
670 for (; (!end || cp < end) && isxdigit((unsigned char)*cp); cp++, i++) {
671 if (bp && bp < endb) {
672 if (i % 2) {
673 *bp <<= 4;
674 *bp++ |= ctox(*cp) & 0xf;
675 } else {
676 *bp = ctox(*cp) & 0xf;
677 n++;
678 }
679 }
680 }
681
682 if (pn)
683 *pn = n;
684
685 return floc_lex(at, begin, cp);
686}
687
688size_t
689lex_base64(const char *begin, const char *end, struct floc *at, void *ptr,
690 size_t *pn)
691{
692 assert(begin);
693
694 const char *cp = begin;
695
696 unsigned char *bp = ptr;
697 unsigned char *endb = bp + (ptr && pn ? *pn : 0);
698
699 size_t n = 0, i = 0;
700 unsigned char s = 0;
701 while ((!end || cp < end) && *cp) {
702 unsigned char b;
703 switch (*cp++) {
704 case 'A': b = 0; break;
705 case 'B': b = 1; break;
706 case 'C': b = 2; break;
707 case 'D': b = 3; break;
708 case 'E': b = 4; break;
709 case 'F': b = 5; break;
710 case 'G': b = 6; break;
711 case 'H': b = 7; break;
712 case 'I': b = 8; break;
713 case 'J': b = 9; break;
714 case 'K': b = 10; break;
715 case 'L': b = 11; break;
716 case 'M': b = 12; break;
717 case 'N': b = 13; break;
718 case 'O': b = 14; break;
719 case 'P': b = 15; break;
720 case 'Q': b = 16; break;
721 case 'R': b = 17; break;
722 case 'S': b = 18; break;
723 case 'T': b = 19; break;
724 case 'U': b = 20; break;
725 case 'V': b = 21; break;
726 case 'W': b = 22; break;
727 case 'X': b = 23; break;
728 case 'Y': b = 24; break;
729 case 'Z': b = 25; break;
730 case 'a': b = 26; break;
731 case 'b': b = 27; break;
732 case 'c': b = 28; break;
733 case 'd': b = 29; break;
734 case 'e': b = 30; break;
735 case 'f': b = 31; break;
736 case 'g': b = 32; break;
737 case 'h': b = 33; break;
738 case 'i': b = 34; break;
739 case 'j': b = 35; break;
740 case 'k': b = 36; break;
741 case 'l': b = 37; break;
742 case 'm': b = 38; break;
743 case 'n': b = 39; break;
744 case 'o': b = 40; break;
745 case 'p': b = 41; break;
746 case 'q': b = 42; break;
747 case 'r': b = 43; break;
748 case 's': b = 44; break;
749 case 't': b = 45; break;
750 case 'u': b = 46; break;
751 case 'v': b = 47; break;
752 case 'w': b = 48; break;
753 case 'x': b = 49; break;
754 case 'y': b = 50; break;
755 case 'z': b = 51; break;
756 case '0': b = 52; break;
757 case '1': b = 53; break;
758 case '2': b = 54; break;
759 case '3': b = 55; break;
760 case '4': b = 56; break;
761 case '5': b = 57; break;
762 case '6': b = 58; break;
763 case '7': b = 59; break;
764 case '8': b = 60; break;
765 case '9': b = 61; break;
766 case '+': b = 62; break;
767 case '/': b = 63; break;
768 default: continue;
769 }
770 if (bp && bp < endb) {
771 switch (i % 4) {
772 case 0: s = b << 2; break;
773 case 1:
774 s |= b >> 4;
775 *bp++ = s;
776 s = b << 4;
777 break;
778 case 2:
779 s |= b >> 2;
780 *bp++ = s;
781 s = b << 6;
782 break;
783 case 3:
784 s |= b;
785 *bp++ = s;
786 s = 0;
787 break;
788 }
789 }
790 if (i++ % 4)
791 n++;
792 }
793
794 if (pn)
795 *pn = n;
796
797 return floc_lex(at, begin, cp);
798}
799
800#endif // !LELY_NO_STDIO
This header file is part of the utilities library; it contains the diagnostic declarations.
size_t floc_lex(struct floc *at, const char *begin, const char *end)
Increments a file location by reading characters from a memory buffer.
Definition: diag.c:65
@ DIAG_WARNING
A warning.
Definition: diag.h:55
void diag_if(enum diag_severity severity, int errc, const struct floc *at, const char *format,...)
Emits a diagnostic message occurring at a location in a text file.
Definition: diag.c:205
@ ERRNUM_RANGE
Result too large.
Definition: errnum.h:218
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:932
errnum_t get_errnum(void)
Returns the last (thread-specific) platform-independent error number set by a system call or library ...
Definition: errnum.h:418
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:424
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
size_t lex_c99_i16(const char *begin, const char *end, struct floc *at, int_least16_t *pi16)
Lexes a C99 int_least16_t from a memory buffer.
Definition: lex.c:448
size_t lex_c99_llong(const char *begin, const char *end, struct floc *at, long long *pll)
Lexes a C99 long long from a memory buffer.
Definition: lex.c:411
size_t lex_char(int c, const char *begin, const char *end, struct floc *at)
Lexes the specified character from a memory buffer.
Definition: lex.c:41
size_t lex_ctype(int(*ctype)(int), const char *begin, const char *end, struct floc *at)
Greedily lexes a sequence of characters of the specified class from a memory buffer.
Definition: lex.c:54
size_t lex_utf8(const char *begin, const char *end, struct floc *at, char32_t *pc32)
Lexes a UTF-8 encoded Unicode character from a memory buffer.
Definition: lex.c:86
size_t lex_c99_id(const char *begin, const char *end, struct floc *at, char *s, size_t *pn)
Lexes a C99 identifier from a memory buffer.
Definition: lex.c:162
size_t lex_c99_long(const char *begin, const char *end, struct floc *at, long *pl)
Lexes a C99 long from a memory buffer.
Definition: lex.c:407
size_t lex_line_comment(const char *delim, const char *begin, const char *end, struct floc *at)
Lexes a single line-comment (excluding the line break) starting with the specified delimiter from a m...
Definition: lex.c:633
size_t lex_c99_u8(const char *begin, const char *end, struct floc *at, uint_least8_t *pu8)
Lexes a C99 uint_least8_t from a memory buffer.
Definition: lex.c:543
size_t lex_c99_esc(const char *begin, const char *end, struct floc *at, char32_t *pc32)
Lexes a C99 character escape sequence from a memory buffer if the buffer begins with '\',...
Definition: lex.c:187
size_t lex_hex(const char *begin, const char *end, struct floc *at, void *ptr, size_t *pn)
Lexes and decodes the hexadecimal representation of binary data from a memory buffer.
Definition: lex.c:655
size_t lex_base64(const char *begin, const char *end, struct floc *at, void *ptr, size_t *pn)
Lexes and decodes the Base64 representation of binary data from a memory buffer.
Definition: lex.c:685
size_t lex_c99_str(const char *begin, const char *end, struct floc *at, char *s, size_t *pn)
Lexes a UTF-8 encoded Unicode string from a memory buffer.
Definition: lex.c:250
size_t lex_c99_i8(const char *begin, const char *end, struct floc *at, int_least8_t *pi8)
Lexes a C99 int_least8_t from a memory buffer.
Definition: lex.c:424
size_t lex_c99_u32(const char *begin, const char *end, struct floc *at, uint_least32_t *pu32)
Lexes a C99 uint_least32_t from a memory buffer.
Definition: lex.c:581
size_t lex_c99_u64(const char *begin, const char *end, struct floc *at, uint_least64_t *pu64)
Lexes a C99 uint_least64_t from a memory buffer.
Definition: lex.c:604
size_t lex_c99_i32(const char *begin, const char *end, struct floc *at, int_least32_t *pi32)
Lexes a C99 int_least32_t from a memory buffer.
Definition: lex.c:472
size_t lex_break(const char *begin, const char *end, struct floc *at)
Lexes a single line break from a memory buffer.
Definition: lex.c:69
size_t lex_c99_u16(const char *begin, const char *end, struct floc *at, uint_least16_t *pu16)
Lexes a C99 uint_least16_t from a memory buffer.
Definition: lex.c:562
size_t lex_c99_ulong(const char *begin, const char *end, struct floc *at, unsigned long *pul)
Lexes a C99 unsigned long from a memory buffer.
Definition: lex.c:409
size_t lex_c99_pp_num(const char *begin, const char *end, struct floc *at)
Lexes a C99 preprocessing number from a memory buffer.
Definition: lex.c:288
size_t lex_c99_ullong(const char *begin, const char *end, struct floc *at, unsigned long long *pull)
Lexes a C99 unsigned long long from a memory buffer.
Definition: lex.c:414
size_t lex_c99_i64(const char *begin, const char *end, struct floc *at, int_least64_t *pi64)
Lexes a C99 int_least64_t from a memory buffer.
Definition: lex.c:504
This header file is part of the utilities library; it contains the lexer function declarations.
int isodigit(int c)
Returns 1 if c is an octal digit, and 0 otherwise.
Definition: lex.h:343
int isbreak(int c)
Returns 1 if c is a line break character, and 0 otherwise.
Definition: lex.h:337
int ctoo(int c)
Returns the octal digit corresponding to the character c.
Definition: lex.h:349
int ctox(int c)
Returns the hexadecimal digit corresponding to the character c.
Definition: lex.h:355
This header file is part of the utilities library; it contains the printing function declarations.
size_t print_utf8(char **pbegin, char *end, char32_t c32)
Prints a UTF-8 encoded Unicode character to a memory buffer.
Definition: print.c:87
This is the internal header file of the utilities library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
This header file is part of the C11 and POSIX compatibility library; it includes <string....
A location in a text file.
Definition: diag.h:39
This header file is part of the C11 and POSIX compatibility library; it includes <uchar....