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 
40 size_t
41 lex_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 
53 size_t
54 lex_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 
68 size_t
69 lex_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 
85 size_t
86 lex_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 
148 done:
149  if (pc32)
150  *pc32 = c32;
151 
152  return floc_lex(at, begin, cp);
153 
154 error:
155  // Replace an invalid code point by the Unicode replacement character
156  // (U+FFFD).
157  c32 = 0xfffd;
158  goto done;
159 }
160 
161 size_t
162 lex_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 
186 size_t
187 lex_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 
249 size_t
250 lex_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 
287 size_t
288 lex_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)
407 LELY_UTIL_DEFINE_LEX_SIGNED(long, long, strtov, LONG_MIN, LONG_MAX, pl)
408 #undef strtov
409 #define strtov(nptr, endptr) strtoul(nptr, endptr, 0)
410 LELY_UTIL_DEFINE_LEX_UNSIGNED(unsigned long, ulong, strtov, ULONG_MAX, pul)
411 #undef strtov
412 #define strtov(nptr, endptr) strtoll(nptr, endptr, 0)
413 LELY_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)
416 LELY_UTIL_DEFINE_LEX_UNSIGNED(
417  unsigned long long, ullong, strtov, ULLONG_MAX, pull)
418 #undef strtov
419 LELY_UTIL_DEFINE_LEX_SIGNED(float, flt, strtof, -HUGE_VALF, HUGE_VALF, pf)
420 LELY_UTIL_DEFINE_LEX_SIGNED(double, dbl, strtod, -HUGE_VAL, HUGE_VAL, pd)
421 LELY_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 
427 size_t
428 lex_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 
451 size_t
452 lex_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 
475 size_t
476 lex_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 
507 size_t
508 lex_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 
546 size_t
547 lex_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 
565 size_t
566 lex_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 
584 size_t
585 lex_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 
607 size_t
608 lex_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 
636 size_t
637 lex_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 
658 size_t
659 lex_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 
688 size_t
689 lex_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....