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