Lely core libraries  2.2.5
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 
37 size_t
38 lex_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 
50 size_t
51 lex_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 
65 size_t
66 lex_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 
82 size_t
83 lex_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 
145 done:
146  if (pc32)
147  *pc32 = c32;
148 
149  return floc_lex(at, begin, cp);
150 
151 error:
152  // Replace an invalid code point by the Unicode replacement character
153  // (U+FFFD).
154  c32 = 0xfffd;
155  goto done;
156 }
157 
158 size_t
159 lex_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 
183 size_t
184 lex_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 
246 size_t
247 lex_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 
284 size_t
285 lex_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)
404 LELY_UTIL_DEFINE_LEX_SIGNED(long, long, strtov, LONG_MIN, LONG_MAX, pl)
405 #undef strtov
406 #define strtov(nptr, endptr) strtoul(nptr, endptr, 0)
407 LELY_UTIL_DEFINE_LEX_UNSIGNED(unsigned long, ulong, strtov, ULONG_MAX, pul)
408 #undef strtov
409 #define strtov(nptr, endptr) strtoll(nptr, endptr, 0)
410 LELY_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)
413 LELY_UTIL_DEFINE_LEX_UNSIGNED(
414  unsigned long long, ullong, strtov, ULLONG_MAX, pull)
415 #undef strtov
416 LELY_UTIL_DEFINE_LEX_SIGNED(float, flt, strtof, -HUGE_VALF, HUGE_VALF, pf)
417 LELY_UTIL_DEFINE_LEX_SIGNED(double, dbl, strtod, -HUGE_VAL, HUGE_VAL, pd)
418 LELY_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 
424 size_t
425 lex_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 
448 size_t
449 lex_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 
472 size_t
473 lex_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 
504 size_t
505 lex_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 
543 size_t
544 lex_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 
562 size_t
563 lex_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 
581 size_t
582 lex_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 
604 size_t
605 lex_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 
633 size_t
634 lex_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 
655 size_t
656 lex_hex(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  unsigned char *bp = ptr;
664  unsigned char *endb = bp + (ptr && pn ? *pn : 0);
665 
666  size_t n = 0, i = 0;
667  for (; (!end || cp < end) && isxdigit((unsigned char)*cp); cp++, i++) {
668  if (bp && bp < endb) {
669  if (i % 2) {
670  *bp <<= 4;
671  *bp++ |= ctox(*cp) & 0xf;
672  } else {
673  *bp = ctox(*cp) & 0xf;
674  n++;
675  }
676  }
677  }
678 
679  if (pn)
680  *pn = n;
681 
682  return floc_lex(at, begin, cp);
683 }
684 
685 size_t
686 lex_base64(const char *begin, const char *end, struct floc *at, void *ptr,
687  size_t *pn)
688 {
689  assert(begin);
690 
691  const char *cp = begin;
692 
693  unsigned char *bp = ptr;
694  unsigned char *endb = bp + (ptr && pn ? *pn : 0);
695 
696  size_t n = 0, i = 0;
697  unsigned char s = 0;
698  while ((!end || cp < end) && *cp) {
699  unsigned char b;
700  switch (*cp++) {
701  case 'A': b = 0; break;
702  case 'B': b = 1; break;
703  case 'C': b = 2; break;
704  case 'D': b = 3; break;
705  case 'E': b = 4; break;
706  case 'F': b = 5; break;
707  case 'G': b = 6; break;
708  case 'H': b = 7; break;
709  case 'I': b = 8; break;
710  case 'J': b = 9; break;
711  case 'K': b = 10; break;
712  case 'L': b = 11; break;
713  case 'M': b = 12; break;
714  case 'N': b = 13; break;
715  case 'O': b = 14; break;
716  case 'P': b = 15; break;
717  case 'Q': b = 16; break;
718  case 'R': b = 17; break;
719  case 'S': b = 18; break;
720  case 'T': b = 19; break;
721  case 'U': b = 20; break;
722  case 'V': b = 21; break;
723  case 'W': b = 22; break;
724  case 'X': b = 23; break;
725  case 'Y': b = 24; break;
726  case 'Z': b = 25; break;
727  case 'a': b = 26; break;
728  case 'b': b = 27; break;
729  case 'c': b = 28; break;
730  case 'd': b = 29; break;
731  case 'e': b = 30; break;
732  case 'f': b = 31; break;
733  case 'g': b = 32; break;
734  case 'h': b = 33; break;
735  case 'i': b = 34; break;
736  case 'j': b = 35; break;
737  case 'k': b = 36; break;
738  case 'l': b = 37; break;
739  case 'm': b = 38; break;
740  case 'n': b = 39; break;
741  case 'o': b = 40; break;
742  case 'p': b = 41; break;
743  case 'q': b = 42; break;
744  case 'r': b = 43; break;
745  case 's': b = 44; break;
746  case 't': b = 45; break;
747  case 'u': b = 46; break;
748  case 'v': b = 47; break;
749  case 'w': b = 48; break;
750  case 'x': b = 49; break;
751  case 'y': b = 50; break;
752  case 'z': b = 51; break;
753  case '0': b = 52; break;
754  case '1': b = 53; break;
755  case '2': b = 54; break;
756  case '3': b = 55; break;
757  case '4': b = 56; break;
758  case '5': b = 57; break;
759  case '6': b = 58; break;
760  case '7': b = 59; break;
761  case '8': b = 60; break;
762  case '9': b = 61; break;
763  case '+': b = 62; break;
764  case '/': b = 63; break;
765  default: continue;
766  }
767  if (bp && bp < endb) {
768  switch (i % 4) {
769  case 0: s = b << 2; break;
770  case 1:
771  s |= b >> 4;
772  *bp++ = s;
773  s = b << 4;
774  break;
775  case 2:
776  s |= b >> 2;
777  *bp++ = s;
778  s = b << 6;
779  break;
780  case 3:
781  s |= b;
782  *bp++ = s;
783  s = 0;
784  break;
785  }
786  }
787  if (i++ % 4)
788  n++;
789  }
790 
791  if (pn)
792  *pn = n;
793 
794  return floc_lex(at, begin, cp);
795 }
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:445
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:421
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_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:652
Result too large.
Definition: errnum.h:215
This header file is part of the C11 and POSIX compatibility library; it includes <string.h> and defines any missing functionality.
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:469
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:406
A location in a text file.
Definition: diag.h:31
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:601
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
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
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
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_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:501
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_pp_num(const char *begin, const char *end, struct floc *at)
Lexes a C99 preprocessing number from a memory buffer.
Definition: lex.c:285
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
This header file is part of the utilities library; it contains the lexer function declarations...
This is the internal header file of the utilities library.
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:630
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
Definition: errnum.c:947
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
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:540
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_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:682
This header file is part of the utilities library; it contains the diagnostic declarations.
int isbreak(int c)
Returns 1 if c is a line break character, and 0 otherwise.
Definition: lex.h:395
This header file is part of the C11 and POSIX compatibility library; it includes <uchar.h>, if it exists, and defines any missing functionality.
int ctoo(int c)
Returns the octal digit corresponding to the character c.
Definition: lex.h:407
A warning.
Definition: diag.h:47
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
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
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:559
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:411
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
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_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:578
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:408
int ctox(int c)
Returns the hexadecimal digit corresponding to the character c.
Definition: lex.h:413
int isodigit(int c)
Returns 1 if c is an octal digit, and 0 otherwise.
Definition: lex.h:401
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 &#39;\&#39;...
Definition: lex.c:184