varnish-cache/lib/libvarnishapi/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 7040
vxp_append_token(struct vxp *vxp, unsigned tok, const char *b, const char *e)
51
{
52
        struct token *t;
53
54 7040
        t = vxp_Alloc(vxp, sizeof *t);
55 7040
        AN(t);
56 7040
        t->tok = tok;
57 7040
        t->b = b;
58 7040
        t->e = e;
59 7040
        VTAILQ_INSERT_TAIL(&vxp->tokens, t, list);
60 7040
        vxp->t = t;
61 7040
}
62
63
/* Unquote and unescape string */
64
static void
65 272
vxp_decstr(struct vxp *vxp)
66
{
67
        const char *b, *e, *p;
68
        char *s;
69 272
        int esc = 0;
70
71 272
        assert(vxp->t->tok == VAL);
72
73 272
        b = vxp->t->b;
74 272
        e = vxp->t->e;
75 272
        assert(e - b >= 2);
76 272
        b++;
77 272
        e--;
78
79 272
        s = vxp->t->dec = vxp_Alloc(vxp, (e - b) + 1);
80 272
        AN(vxp->t->dec);
81 1952
        for (p = b; p < e; p++) {
82 1680
                if (!esc && *p == '\\') {
83 8
                        esc = 1;
84 8
                        continue;
85
                }
86 1672
                esc = 0;
87 1672
                *s++ = *p;
88 1672
        }
89 272
        *s = '\0';
90 272
}
91
92
/*
93
 * Build a token list
94
 */
95
96
void
97 1496
vxp_Lexer(struct vxp *vxp)
98
{
99
        const char *p, *q;
100
        unsigned u;
101
        char quote;
102
103 10216
        for (p = vxp->b; p < vxp->e; ) {
104
105
                /* Skip any space or tab */
106 8752
                if (isblank(*p)) {
107 3056
                        p++;
108 3056
                        continue;
109
                }
110
111 5696
                if (*p == '\\' && p[1] == '\n') {
112 16
                        p += 2;
113 16
                        continue;
114
                }
115
116
                /* Skip comments */
117 5680
                if (*p == '#') {
118 1456
                        while (p < vxp->e && *p != '\n')
119 1352
                                p++;
120 104
                        continue;
121
                }
122
123
                /* Match for the fixed tokens */
124 5576
                u = vxp_fixed_token(p, &q);
125 5576
                if (u != 0) {
126 2296
                        AN(q);
127 2296
                        vxp_append_token(vxp, u, p, q);
128 2296
                        p = q;
129 2296
                        continue;
130
                }
131
132
                /* Match quoted strings */
133 3280
                if (*p == '"' || *p == '\'') {
134 296
                        quote = *p;
135 2216
                        for (q = p + 1; q < vxp->e; q++) {
136 2208
                                if (*q == '\\') {
137 24
                                        q++;
138 24
                                        if (q == vxp->e || *q == '\n')
139 8
                                                break;
140 2200
                                } else if (*q == '\n') {
141 8
                                        break;
142 2176
                                } else if (*q == quote) {
143 272
                                        q++;
144 272
                                        quote = '\0';
145 272
                                        break;
146
                                }
147 1920
                        }
148 296
                        vxp_append_token(vxp, VAL, p, q);
149 296
                        if (quote != '\0') {
150 24
                                VSB_cat(vxp->sb, "Unterminated string ");
151 24
                                vxp_ErrWhere(vxp, vxp->t, q - p);
152 24
                                return;
153
                        }
154 272
                        vxp_decstr(vxp);
155 272
                        p = q;
156 272
                        continue;
157
                }
158
159
                /* Match bareword */
160 2984
                if (isword(*p)) {
161 19056
                        for (q = p; q < vxp->e; q++)
162 18016
                                if (!isword(*q))
163 1696
                                        break;
164 2736
                        vxp_append_token(vxp, VAL, p, q);
165 2736
                        vxp->t->dec = vxp_Alloc(vxp, (q - p) + 1);
166 2736
                        AN(vxp->t->dec);
167 2736
                        memcpy(vxp->t->dec, p, q - p);
168 2736
                        vxp->t->dec[q - p] = '\0';
169 2736
                        p = q;
170 2736
                        continue;
171
                }
172
173
                /* On to the next query */
174 248
                if (*p == '\n') {
175 240
                        vxp_append_token(vxp, EOI, p, p + 1);
176 240
                        p++;
177 240
                        continue;
178
                }
179
180
                /* Error */
181 8
                vxp_append_token(vxp, EOI, p, p + 1);
182 8
                VSB_cat(vxp->sb, "Syntax error ");
183 8
                vxp_ErrWhere(vxp, vxp->t, q - p);
184 8
                return;
185
        }
186
187
        /* Finished */
188 1464
        vxp_append_token(vxp, EOI, vxp->e, vxp->e);
189 1496
}
190
191
#ifdef VXP_DEBUG
192
#include <stdio.h>
193
void
194 24
vxp_PrintTokens(const struct vxp *vxp)
195
{
196
        struct token *t;
197
198 24
        fprintf(stderr, "Token list:\n");
199 24
        fprintf(stderr, "  %-5s %-20s %s\n", "TOK", "SUBSTR", "DECODED");
200 312
        VTAILQ_FOREACH(t, &vxp->tokens, list) {
201 288
                fprintf(stderr, "  ");
202 288
                fprintf(stderr, "%-5s", vxp_tnames[t->tok]);
203 288
                fprintf(stderr, " %-20.*s", (unsigned)(t->e - t->b), t->b);
204 288
                if (t->dec)
205 152
                        fprintf(stderr, " '%s'", t->dec);
206 288
                fprintf(stderr, "\n");
207 288
        }
208 24
        fprintf(stderr, "\n");
209 24
}
210
#endif /* VXP_DEBUG */