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
37
#include "vdef.h"
38
#include "vas.h"
39
#include "vqueue.h"
40
41
#include "vre.h"
42
#include "vsb.h"
43
44
#include "vxp.h"
45
46
static void
47 276
vxp_add_token(struct vxp *vxp, unsigned tok, const char *b, const char *e)
48
{
49
        struct token *t;
50
51 276
        t = vxp_Alloc(vxp, sizeof *t);
52 276
        AN(t);
53 276
        t->tok = tok;
54 276
        t->b = b;
55 276
        t->e = e;
56 276
        if (vxp->t != NULL)
57 213
                VTAILQ_INSERT_AFTER(&vxp->tokens, vxp->t, t, list);
58
        else
59 63
                VTAILQ_INSERT_TAIL(&vxp->tokens, t, list);
60 276
        vxp->t = t;
61 276
}
62
63
static int
64 121
vxp_decstr(struct vxp *vxp, int quoted)
65
{
66
        const char *b, *e, *p;
67
        char *s;
68
        unsigned l;
69 121
        int esc = 0;
70
71 121
        assert(vxp->t->tok == VAL);
72
73 121
        b = vxp->t->b;
74 121
        e = vxp->t->e;
75 121
        if (quoted) {
76 10
                assert(e - b >= 2);
77 10
                b++;
78 10
                e--;
79
        }
80 121
        l = e - b;
81 121
        s = vxp->t->dec = vxp_Alloc(vxp, l + 1);
82 121
        AN(vxp->t->dec);
83 881
        for (p = b; p < e; p++) {
84 760
                if (!esc && *p == '\\') {
85 0
                        esc = 1;
86 0
                        continue;
87
                }
88 760
                esc = 0;
89 760
                *s++ = *p;
90
        }
91 121
        *s = '\0';
92 121
        if (esc || p != e) {
93 0
                VSB_printf(vxp->sb, "Syntax error ");
94 0
                vxp_ErrWhere(vxp, vxp->t, -1);
95 0
                return (1);
96
        }
97 121
        return (0);
98
}
99
100
/*
101
 * Build a token list
102
 */
103
104
void
105 63
vxp_Lexer(struct vxp *vxp)
106
{
107
        const char *p, *q;
108
        unsigned u;
109
        char quote;
110
111 458
        for (p = vxp->b; p < vxp->e; ) {
112
113
                /* Skip any whitespace */
114 332
                if (isspace(*p)) {
115 119
                        p++;
116 119
                        continue;
117
                }
118
119
                /* Match for the fixed tokens */
120 213
                u = vxp_fixed_token(p, &q);
121 213
                if (u != 0) {
122 92
                        AN(q);
123 92
                        vxp_add_token(vxp, u, p, q);
124 92
                        p = q;
125 92
                        continue;
126
                }
127
128
                /* Match quoted strings */
129 121
                if (*p == '"' || *p == '\'') {
130 10
                        quote = *p;
131 82
                        for (q = p + 1; q < vxp->e; q++) {
132 82
                                if (q[-1] == '\\')
133 0
                                        continue;
134 82
                                if (*q == quote) {
135 10
                                        q++;
136 10
                                        quote = '\0';
137 10
                                        break;
138
                                }
139
                        }
140 10
                        vxp_add_token(vxp, VAL, p, q);
141 10
                        if (quote != '\0') {
142 0
                                VSB_printf(vxp->sb, "Unterminated string ");
143 0
                                vxp_ErrWhere(vxp, vxp->t, q - p);
144 0
                                return;
145
                        }
146 10
                        if (vxp_decstr(vxp, 1))
147 0
                                return;
148 10
                        p = q;
149 10
                        continue;
150
                }
151
152
                /* Match bareword */
153 111
                if (isword(*p)) {
154 799
                        for (q = p; q < vxp->e; q++)
155 746
                                if (!isword(*q))
156 58
                                        break;
157 111
                        vxp_add_token(vxp, VAL, p, q);
158 111
                        if (vxp_decstr(vxp, 0))
159 0
                                return;
160 111
                        p = q;
161 111
                        continue;
162
                }
163
164
                /* Error */
165 0
                vxp_add_token(vxp, EOI, p, p + 1);
166 0
                VSB_printf(vxp->sb, "Syntax error ");
167 0
                vxp_ErrWhere(vxp, vxp->t, q - p);
168 0
                return;
169
        }
170
171
        /* Finished */
172 63
        vxp_add_token(vxp, EOI, vxp->e, vxp->e);
173
}
174
175
#ifdef VXP_DEBUG
176
#include <stdio.h>
177
void
178
vxp_PrintTokens(const struct vxp *vxp)
179
{
180
        struct token *t;
181
182
        fprintf(stderr, "Token list:\n");
183
        fprintf(stderr, "  %-5s %-20s %s\n", "TOK", "SUBSTR", "DECODED");
184
        VTAILQ_FOREACH(t, &vxp->tokens, list) {
185
                fprintf(stderr, "  ");
186
                fprintf(stderr, "%-5s", vxp_tnames[t->tok]);
187
                fprintf(stderr, " %-20.*s", (unsigned)(t->e - t->b), t->b);
188
                if (t->dec)
189
                        fprintf(stderr, " '%s'", t->dec);
190
                fprintf(stderr, "\n");
191
        }
192
        fprintf(stderr, "\n");
193
}
194
#endif /* VXP_DEBUG */