16f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin/* 26f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * Copyright © 2012 Ran Benita <ran234@gmail.com> 36f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * 46f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * Permission is hereby granted, free of charge, to any person obtaining a 56f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * copy of this software and associated documentation files (the "Software"), 66f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * to deal in the Software without restriction, including without limitation 76f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * and/or sell copies of the Software, and to permit persons to whom the 96f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * Software is furnished to do so, subject to the following conditions: 106f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * 116f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * The above copyright notice and this permission notice (including the next 126f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * paragraph) shall be included in all copies or substantial portions of the 136f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * Software. 146f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * 156f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 166f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 186f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 206f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 216f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin * DEALINGS IN THE SOFTWARE. 226f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin */ 236f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 246f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin#ifndef XKBCOMP_SCANNER_UTILS_H 256f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin#define XKBCOMP_SCANNER_UTILS_H 266f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 276f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin/* Point to some substring in the file; used to avoid copying. */ 286f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstruct sval { 296f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin const char *start; 306f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin unsigned int len; 316f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin}; 326f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempintypedef darray(struct sval) darray_sval; 336f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 346f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 356f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinsvaleq(struct sval s1, struct sval s2) 366f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 376f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return s1.len == s2.len && memcmp(s1.start, s2.start, s1.len) == 0; 386f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 396f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 406f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 416f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinsvaleq_prefix(struct sval s1, struct sval s2) 426f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 436f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return s1.len <= s2.len && memcmp(s1.start, s2.start, s1.len) == 0; 446f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 456f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 466f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstruct scanner { 476f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin const char *s; 486f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin size_t pos; 496f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin size_t len; 506f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin char buf[1024]; 516f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin size_t buf_pos; 526f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin unsigned line, column; 536f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin /* The line/column of the start of the current token. */ 546f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin unsigned token_line, token_column; 556f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin const char *file_name; 566f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin struct xkb_context *ctx; 576f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin void *priv; 586f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin}; 596f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 606f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin#define scanner_log(scanner, level, fmt, ...) \ 616f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin xkb_log((scanner)->ctx, (level), 0, \ 626f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin "%s:%u:%u: " fmt "\n", \ 636f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin (scanner)->file_name, \ 646f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin (scanner)->token_line, (scanner)->token_column, ##__VA_ARGS__) 656f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 666f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin#define scanner_err(scanner, fmt, ...) \ 676f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin scanner_log(scanner, XKB_LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) 686f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 696f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin#define scanner_warn(scanner, fmt, ...) \ 706f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin scanner_log(scanner, XKB_LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__) 716f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 726f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline void 736f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinscanner_init(struct scanner *s, struct xkb_context *ctx, 746f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin const char *string, size_t len, const char *file_name, 756f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin void *priv) 766f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 776f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->s = string; 786f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->len = len; 796f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->pos = 0; 806f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->line = s->column = 1; 816f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->token_line = s->token_column = 1; 826f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->file_name = file_name; 836f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->ctx = ctx; 846f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->priv = priv; 856f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 866f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 876f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline char 886f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinpeek(struct scanner *s) 896f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 906f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin if (unlikely(s->pos >= s->len)) 916f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return '\0'; 926f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return s->s[s->pos]; 936f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 946f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 956f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 966f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempineof(struct scanner *s) 976f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 986f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return s->pos >= s->len; 996f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1006f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1016f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 1026f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempineol(struct scanner *s) 1036f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1046f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return peek(s) == '\n'; 1056f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1066f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1076f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline void 1086f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinskip_to_eol(struct scanner *s) 1096f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1106f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin const char *nl = memchr(s->s + s->pos, '\n', s->len - s->pos); 1116f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin const size_t new_pos = nl ? (size_t) (nl - s->s) : s->len; 1126f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->column += new_pos - s->pos; 1136f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->pos = new_pos; 1146f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1156f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1166f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline char 1176f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinnext(struct scanner *s) 1186f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1196f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin if (unlikely(eof(s))) 1206f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return '\0'; 1216f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin if (unlikely(eol(s))) { 1226f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->line++; 1236f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->column = 1; 1246f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin } 1256f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin else { 1266f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->column++; 1276f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin } 1286f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return s->s[s->pos++]; 1296f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1306f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1316f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 1326f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinchr(struct scanner *s, char ch) 1336f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1346f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin if (likely(peek(s) != ch)) 1356f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return false; 1366f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->pos++; s->column++; 1376f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return true; 1386f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1396f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1406f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 1416f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstr(struct scanner *s, const char *string, size_t len) 1426f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1436f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin if (s->len - s->pos < len) 1446f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return false; 1456f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin if (memcmp(s->s + s->pos, string, len) != 0) 1466f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return false; 1476f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->pos += len; s->column += len; 1486f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return true; 1496f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1506f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1516f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin#define lit(s, literal) str(s, literal, sizeof(literal) - 1) 1526f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1536f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 1546f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinbuf_append(struct scanner *s, char ch) 1556f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1566f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin if (s->buf_pos + 1 >= sizeof(s->buf)) 1576f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return false; 1586f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->buf[s->buf_pos++] = ch; 1596f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return true; 1606f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1616f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1626f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 1636f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinbuf_appends(struct scanner *s, const char *str) 1646f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1656f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin int ret; 1666f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin ret = snprintf(s->buf + s->buf_pos, sizeof(s->buf) - s->buf_pos, "%s", str); 1676f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin if (ret < 0 || (size_t) ret >= sizeof(s->buf) - s->buf_pos) 1686f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return false; 1696f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin s->buf_pos += ret; 1706f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return true; 1716f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1726f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1736f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 1746f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinoct(struct scanner *s, uint8_t *out) 1756f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1766f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin int i; 1776f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin for (i = 0, *out = 0; peek(s) >= '0' && peek(s) <= '7' && i < 3; i++) 1786f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin *out = *out * 8 + next(s) - '0'; 1796f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return i > 0; 1806f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1816f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1826f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinstatic inline bool 1836f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempinhex(struct scanner *s, uint8_t *out) 1846f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin{ 1856f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin int i; 1866f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin for (i = 0, *out = 0; is_xdigit(peek(s)) && i < 2; i++) { 1876f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin const char c = next(s); 1886f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin const char offset = (c >= '0' && c <= '9' ? '0' : 1896f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin c >= 'a' && c <= 'f' ? 'a' - 10 : 'A' - 10); 1906f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin *out = *out * 16 + c - offset; 1916f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin } 1926f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin return i > 0; 1936f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin} 1946f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin 1956f36ec3ef7a87f9eaa37fc78868dbac2cb958b0Dennis Kempin#endif 196