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 280
vxp_add_token(struct vxp *vxp, unsigned tok, const char *b, const char *e)
49
{
50
        struct token *t;
51
52 280
        t = vxp_Alloc(vxp, sizeof *t);
53 280
        AN(t);
54 280
        t->tok = tok;
55 280
        t->b = b;
56 280
        t->e = e;
57 280
        if (vxp->t != NULL)
58 215
                VTAILQ_INSERT_AFTER(&vxp->tokens, vxp->t, t, list);
59
        else
60 65
                VTAILQ_INSERT_TAIL(&vxp->tokens, t, list);
61 280
        vxp->t = t;
62 280
}
63
64
static int
65 123
vxp_decstr(struct vxp *vxp, int quoted)
66
{
67
        const char *b, *e, *p;
68
        char *s;
69
        unsigned l;
70 123
        int esc = 0;
71
72 123
        assert(vxp->t->tok == VAL);
73
74 123
        b = vxp->t->b;
75 123
        e = vxp->t->e;
76 123
        if (quoted) {
77 10
                assert(e - b >= 2);
78 10
                b++;
79 10
                e--;
80
        }
81 123
        l = e - b;
82 123
        s = vxp->t->dec = vxp_Alloc(vxp, l + 1);
83 123
        AN(vxp->t->dec);
84 895
        for (p = b; p < e; p++) {
85 772
                if (!esc && *p == '\\') {
86 0
                        esc = 1;
87 0
                        continue;
88
                }
89 772
                esc = 0;
90 772
                *s++ = *p;
91
        }
92 123
        *s = '\0';
93 123
        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 123
        return (0);
99
}
100
101
/*
102
 * Build a token list
103
 */
104
105
void
106 65
vxp_Lexer(struct vxp *vxp)
107
{
108
        const char *p, *q;
109
        unsigned u;
110
        char quote;
111
112 464
        for (p = vxp->b; p < vxp->e; ) {
113
114
                /* Skip any whitespace */
115 334
                if (isspace(*p)) {
116 119
                        p++;
117 119
                        continue;
118
                }
119
120
                /* Match for the fixed tokens */
121 215
                u = vxp_fixed_token(p, &q);
122 215
                if (u != 0) {
123 92
                        AN(q);
124 92
                        vxp_add_token(vxp, u, p, q);
125 92
                        p = q;
126 92
                        continue;
127
                }
128
129
                /* Match quoted strings */
130 123
                if (*p == '"' || *p == '\'') {
131 10
                        quote = *p;
132 82
                        for (q = p + 1; q < vxp->e; q++) {
133 82
                                if (q[-1] == '\\')
134 0
                                        continue;
135 82
                                if (*q == quote) {
136 10
                                        q++;
137 10
                                        quote = '\0';
138 10
                                        break;
139
                                }
140
                        }
141 10
                        vxp_add_token(vxp, VAL, p, q);
142 10
                        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 10
                        if (vxp_decstr(vxp, 1))
148 0
                                return;
149 10
                        p = q;
150 10
                        continue;
151
                }
152
153
                /* Match bareword */
154 113
                if (isword(*p)) {
155 813
                        for (q = p; q < vxp->e; q++)
156 758
                                if (!isword(*q))
157 58
                                        break;
158 113
                        vxp_add_token(vxp, VAL, p, q);
159 113
                        if (vxp_decstr(vxp, 0))
160 0
                                return;
161 113
                        p = q;
162 113
                        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 65
        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 */