vinyl-cache/lib/libvinylapi/vxp_lexer.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <ctype.h>
35
#include <stdlib.h>
36
#include <string.h>
37
#include <stdint.h>
38
#include <unistd.h> /* for MUSL */
39
40
#include "vdef.h"
41
#include "vas.h"
42
#include "vqueue.h"
43
44
#include "vre.h"
45
#include "vsb.h"
46
47
#include "vxp.h"
48
49
static void
50 4768
vxp_append_token(struct vxp *vxp, unsigned tok, const char *b, const char *e)
51
{
52
        struct token *t;
53
54 4768
        t = vxp_Alloc(vxp, sizeof *t);
55 4768
        AN(t);
56 4768
        t->tok = tok;
57 4768
        t->b = b;
58 4768
        t->e = e;
59 4768
        VTAILQ_INSERT_TAIL(&vxp->tokens, t, list);
60 4768
        vxp->t = t;
61 4768
}
62
63
/* Unquote and unescape string */
64
static void
65 332
vxp_decstr(struct vxp *vxp)
66
{
67
        const char *b, *e, *p;
68
        char *s;
69 332
        int esc = 0;
70
71 332
        assert(vxp->t->tok == VAL);
72
73 332
        b = vxp->t->b;
74 332
        e = vxp->t->e;
75 332
        assert(e - b >= 2);
76 332
        b++;
77 332
        e--;
78
79 332
        s = vxp->t->dec = vxp_Alloc(vxp, (e - b) + 1);
80 332
        AN(vxp->t->dec);
81 2092
        for (p = b; p < e; p++) {
82 1760
                if (!esc && *p == '\\') {
83 4
                        esc = 1;
84 4
                        continue;
85
                }
86 1756
                esc = 0;
87 1756
                *s++ = *p;
88 1756
        }
89 332
        *s = '\0';
90 332
}
91
92
/*
93
 * Build a token list
94
 */
95
96
void
97 956
vxp_Lexer(struct vxp *vxp)
98
{
99
        const char *p, *q;
100
        unsigned u;
101
        char quote;
102
103 6820
        for (p = vxp->b; p < vxp->e; ) {
104
105
                /* Skip any space or tab */
106 5880
                if (isblank(*p)) {
107 1992
                        p++;
108 1992
                        continue;
109
                }
110
111 3888
                if (*p == '\\' && p[1] == '\n') {
112 8
                        p += 2;
113 8
                        continue;
114
                }
115
116
                /* Skip comments */
117 3880
                if (*p == '#') {
118 728
                        while (p < vxp->e && *p != '\n')
119 676
                                p++;
120 52
                        continue;
121
                }
122
123
                /* Match for the fixed tokens */
124 3828
                u = vxp_fixed_token(p, &q);
125 3828
                if (u != 0) {
126 1600
                        AN(q);
127 1600
                        vxp_append_token(vxp, u, p, q);
128 1600
                        p = q;
129 1600
                        continue;
130
                }
131
132
                /* Match quoted strings */
133 2228
                if (*p == '"' || *p == '\'') {
134 344
                        quote = *p;
135 2224
                        for (q = p + 1; q < vxp->e; q++) {
136 2220
                                if (*q == '\\') {
137 12
                                        q++;
138 12
                                        if (q == vxp->e || *q == '\n')
139 4
                                                break;
140 2216
                                } else if (*q == '\n') {
141 4
                                        break;
142 2204
                                } else if (*q == quote) {
143 332
                                        q++;
144 332
                                        quote = '\0';
145 332
                                        break;
146
                                }
147 1880
                        }
148 344
                        vxp_append_token(vxp, VAL, p, q);
149 344
                        if (quote != '\0') {
150 12
                                VSB_cat(vxp->sb, "Unterminated string ");
151 12
                                vxp_ErrWhere(vxp, vxp->t, q - p);
152 12
                                return;
153
                        }
154 332
                        vxp_decstr(vxp);
155 332
                        p = q;
156 332
                        continue;
157
                }
158
159
                /* Match bareword */
160 1884
                if (isword(*p)) {
161 13416
                        for (q = p; q < vxp->e; q++)
162 12884
                                if (!isword(*q))
163 1228
                                        break;
164 1760
                        vxp_append_token(vxp, VAL, p, q);
165 1760
                        vxp->t->dec = vxp_Alloc(vxp, (q - p) + 1);
166 1760
                        AN(vxp->t->dec);
167 1760
                        vmemcpy(vxp->t->dec, p, q - p);
168 1760
                        vxp->t->dec[q - p] = '\0';
169 1760
                        p = q;
170 1760
                        continue;
171
                }
172
173
                /* On to the next query */
174 124
                if (*p == '\n') {
175 120
                        vxp_append_token(vxp, EOI, p, p + 1);
176 120
                        p++;
177 120
                        continue;
178
                }
179
180
                /* Error */
181 4
                vxp_append_token(vxp, EOI, p, p + 1);
182 4
                VSB_cat(vxp->sb, "Syntax error ");
183 4
                vxp_ErrWhere(vxp, vxp->t, q - p);
184 4
                return;
185
        }
186
187
        /* Finished */
188 940
        vxp_append_token(vxp, EOI, vxp->e, vxp->e);
189 956
}
190
191
#ifdef VXP_DEBUG
192
#include <stdio.h>
193
void
194 12
vxp_PrintTokens(const struct vxp *vxp)
195
{
196
        struct token *t;
197
198 12
        fprintf(stderr, "Token list:\n");
199 12
        fprintf(stderr, "  %-5s %-20s %s\n", "TOK", "SUBSTR", "DECODED");
200 156
        VTAILQ_FOREACH(t, &vxp->tokens, list) {
201 144
                fprintf(stderr, "  ");
202 144
                fprintf(stderr, "%-5s", vxp_tnames[t->tok]);
203 144
                fprintf(stderr, " %-20.*s", (unsigned)(t->e - t->b), t->b);
204 144
                if (t->dec)
205 76
                        fprintf(stderr, " '%s'", t->dec);
206 144
                fprintf(stderr, "\n");
207 144
        }
208 12
        fprintf(stderr, "\n");
209 12
}
210
#endif /* VXP_DEBUG */