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