Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2012 Ran Benita <ran234 (at) gmail.com>
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 #ifndef XKBCOMP_SCANNER_UTILS_H
     25 #define XKBCOMP_SCANNER_UTILS_H
     26 
     27 /* Point to some substring in the file; used to avoid copying. */
     28 struct sval {
     29     const char *start;
     30     unsigned int len;
     31 };
     32 typedef darray(struct sval) darray_sval;
     33 
     34 static inline bool
     35 svaleq(struct sval s1, struct sval s2)
     36 {
     37     return s1.len == s2.len && memcmp(s1.start, s2.start, s1.len) == 0;
     38 }
     39 
     40 static inline bool
     41 svaleq_prefix(struct sval s1, struct sval s2)
     42 {
     43     return s1.len <= s2.len && memcmp(s1.start, s2.start, s1.len) == 0;
     44 }
     45 
     46 struct scanner {
     47     const char *s;
     48     size_t pos;
     49     size_t len;
     50     char buf[1024];
     51     size_t buf_pos;
     52     unsigned line, column;
     53     /* The line/column of the start of the current token. */
     54     unsigned token_line, token_column;
     55     const char *file_name;
     56     struct xkb_context *ctx;
     57     void *priv;
     58 };
     59 
     60 #define scanner_log(scanner, level, fmt, ...) \
     61     xkb_log((scanner)->ctx, (level), 0, \
     62             "%s:%u:%u: " fmt "\n", \
     63              (scanner)->file_name, \
     64              (scanner)->token_line, (scanner)->token_column, ##__VA_ARGS__)
     65 
     66 #define scanner_err(scanner, fmt, ...) \
     67     scanner_log(scanner, XKB_LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
     68 
     69 #define scanner_warn(scanner, fmt, ...) \
     70     scanner_log(scanner, XKB_LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
     71 
     72 static inline void
     73 scanner_init(struct scanner *s, struct xkb_context *ctx,
     74              const char *string, size_t len, const char *file_name,
     75              void *priv)
     76 {
     77     s->s = string;
     78     s->len = len;
     79     s->pos = 0;
     80     s->line = s->column = 1;
     81     s->token_line = s->token_column = 1;
     82     s->file_name = file_name;
     83     s->ctx = ctx;
     84     s->priv = priv;
     85 }
     86 
     87 static inline char
     88 peek(struct scanner *s)
     89 {
     90     if (unlikely(s->pos >= s->len))
     91         return '\0';
     92     return s->s[s->pos];
     93 }
     94 
     95 static inline bool
     96 eof(struct scanner *s)
     97 {
     98     return s->pos >= s->len;
     99 }
    100 
    101 static inline bool
    102 eol(struct scanner *s)
    103 {
    104     return peek(s) == '\n';
    105 }
    106 
    107 static inline void
    108 skip_to_eol(struct scanner *s)
    109 {
    110     const char *nl = memchr(s->s + s->pos, '\n', s->len - s->pos);
    111     const size_t new_pos = nl ? (size_t) (nl - s->s) : s->len;
    112     s->column += new_pos - s->pos;
    113     s->pos = new_pos;
    114 }
    115 
    116 static inline char
    117 next(struct scanner *s)
    118 {
    119     if (unlikely(eof(s)))
    120         return '\0';
    121     if (unlikely(eol(s))) {
    122         s->line++;
    123         s->column = 1;
    124     }
    125     else {
    126         s->column++;
    127     }
    128     return s->s[s->pos++];
    129 }
    130 
    131 static inline bool
    132 chr(struct scanner *s, char ch)
    133 {
    134     if (likely(peek(s) != ch))
    135         return false;
    136     s->pos++; s->column++;
    137     return true;
    138 }
    139 
    140 static inline bool
    141 str(struct scanner *s, const char *string, size_t len)
    142 {
    143     if (s->len - s->pos < len)
    144         return false;
    145     if (memcmp(s->s + s->pos, string, len) != 0)
    146         return false;
    147     s->pos += len; s->column += len;
    148     return true;
    149 }
    150 
    151 #define lit(s, literal) str(s, literal, sizeof(literal) - 1)
    152 
    153 static inline bool
    154 buf_append(struct scanner *s, char ch)
    155 {
    156     if (s->buf_pos + 1 >= sizeof(s->buf))
    157         return false;
    158     s->buf[s->buf_pos++] = ch;
    159     return true;
    160 }
    161 
    162 static inline bool
    163 buf_appends(struct scanner *s, const char *str)
    164 {
    165     int ret;
    166     ret = snprintf(s->buf + s->buf_pos, sizeof(s->buf) - s->buf_pos, "%s", str);
    167     if (ret < 0 || (size_t) ret >= sizeof(s->buf) - s->buf_pos)
    168         return false;
    169     s->buf_pos += ret;
    170     return true;
    171 }
    172 
    173 static inline bool
    174 oct(struct scanner *s, uint8_t *out)
    175 {
    176     int i;
    177     for (i = 0, *out = 0; peek(s) >= '0' && peek(s) <= '7' && i < 3; i++)
    178         *out = *out * 8 + next(s) - '0';
    179     return i > 0;
    180 }
    181 
    182 static inline bool
    183 hex(struct scanner *s, uint8_t *out)
    184 {
    185     int i;
    186     for (i = 0, *out = 0; is_xdigit(peek(s)) && i < 2; i++) {
    187         const char c = next(s);
    188         const char offset = (c >= '0' && c <= '9' ? '0' :
    189                              c >= 'a' && c <= 'f' ? 'a' - 10 : 'A' - 10);
    190         *out = *out * 16 + c - offset;
    191     }
    192     return i > 0;
    193 }
    194 
    195 #endif
    196