source: lib/libvcl/vcc_action.c @ 6a9b5a

Revision 6a9b5a, 6.9 KB checked in by Poul-Henning Kamp <phk@…>, 7 years ago (diff)

Move string stuff to vcc_string.c, there's going to be a fair bit of it.

Give vcc_StringVal() a return value to say if it did anything so we can
emit better error messages when confused.

git-svn-id:  http://www.varnish-cache.org/svn/trunk/varnish-cache@1662 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2007 Linpro AS
4 * All rights reserved.
5 *
6 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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 * $Id$
30 */
31
32#include <stdio.h>
33
34#include "vsb.h"
35
36#include "vcc_priv.h"
37#include "vcc_compile.h"
38#include "libvarnish.h"
39
40/*--------------------------------------------------------------------*/
41
42#define VCL_RET_MAC(l,u,b,i)                            \
43static void                                             \
44parse_##l(struct tokenlist *tl)                         \
45{                                                       \
46                                                        \
47        Fb(tl, 1, "VRT_done(sp, VCL_RET_%s);\n", #u);   \
48        vcc_ProcAction(tl->curproc, i, tl->t);          \
49        vcc_NextToken(tl);                              \
50}
51
52#include "vcl_returns.h"
53#undef VCL_RET_MAC
54
55/*--------------------------------------------------------------------*/
56
57static void
58parse_call(struct tokenlist *tl)
59{
60
61        vcc_NextToken(tl);
62        ExpectErr(tl, ID);
63        vcc_AddCall(tl, tl->t);
64        vcc_AddRef(tl, tl->t, R_FUNC);
65        Fb(tl, 1, "if (VGC_function_%.*s(sp))\n", PF(tl->t));
66        Fb(tl, 1, "\treturn (1);\n");
67        vcc_NextToken(tl);
68        return;
69}
70
71/*--------------------------------------------------------------------*/
72
73static void
74parse_error(struct tokenlist *tl)
75{
76        unsigned a;
77
78        vcc_NextToken(tl);
79        if (tl->t->tok == CNUM)
80                a = vcc_UintVal(tl);
81        else
82                a = 0;
83        Fb(tl, 1, "VRT_error(sp, %u", a);
84        if (tl->t->tok == CSTR) {
85                Fb(tl, 0, ", %.*s", PF(tl->t));
86                vcc_NextToken(tl);
87        } else {
88                Fb(tl, 0, ", (const char *)0");
89        }
90        Fb(tl, 0, ");\n");
91        Fb(tl, 1, "VRT_done(sp, VCL_RET_ERROR);\n");
92}
93
94/*--------------------------------------------------------------------*/
95
96static void
97illegal_assignment(const struct tokenlist *tl, const char *type)
98{
99
100        vsb_printf(tl->sb, "Invalid assignment operator ");
101        vcc_ErrToken(tl, tl->t);
102        vsb_printf(tl->sb,
103            " only '=' is legal for %s\n", type);
104}
105
106static void
107check_writebit(struct tokenlist *tl, const struct var *vp)
108{
109
110        if (vp->access == V_RW || vp->access == V_WO)
111                return;
112        vsb_printf(tl->sb, "Variable %.*s cannot be modified.\n", PF(tl->t));
113        vcc_ErrWhere(tl, tl->t);
114}
115
116static void
117parse_set(struct tokenlist *tl)
118{
119        struct var *vp;
120        struct token *at, *vt;
121
122        vcc_NextToken(tl);
123        ExpectErr(tl, VAR);
124        vt = tl->t;
125        vp = vcc_FindVar(tl, tl->t, vcc_vars);
126        ERRCHK(tl);
127        assert(vp != NULL);
128        check_writebit(tl, vp);
129        ERRCHK(tl);
130        Fb(tl, 1, "%s", vp->lname);
131        vcc_NextToken(tl);
132        switch (vp->fmt) {
133        case INT:
134        case SIZE:
135        case RATE:
136        case TIME:
137        case FLOAT:
138                if (tl->t->tok != '=')
139                        Fb(tl, 0, "%s %c ", vp->rname, *tl->t->b);
140                at = tl->t;
141                vcc_NextToken(tl);
142                switch (at->tok) {
143                case T_MUL:
144                case T_DIV:
145                        Fb(tl, 0, "%g", vcc_DoubleVal(tl));
146                        break;
147                case T_INCR:
148                case T_DECR:
149                case '=':
150                        if (vp->fmt == TIME)
151                                vcc_TimeVal(tl);
152                        else if (vp->fmt == SIZE)
153                                vcc_SizeVal(tl);
154                        else if (vp->fmt == RATE)
155                                vcc_RateVal(tl);
156                        else if (vp->fmt == FLOAT)
157                                Fb(tl, 0, "%g", vcc_DoubleVal(tl));
158                        else if (vp->fmt == INT)
159                                Fb(tl, 0, "%u", vcc_UintVal(tl));
160                        else {
161                                vsb_printf(tl->sb, "Cannot assign this variable type.\n");
162                                vcc_ErrWhere(tl, vt);
163                                return;
164                        }
165                        break;
166                default:
167                        vsb_printf(tl->sb, "Invalid assignment operator.\n");
168                        vcc_ErrWhere(tl, at);
169                        return;
170                }
171                Fb(tl, 0, ");\n");
172                break;
173#if 0   /* XXX: enable if we find a legit use */
174        case IP:
175                if (tl->t->tok != '=') {
176                        illegal_assignment(tl, "IP numbers");
177                        return;
178                }
179                vcc_NextToken(tl);
180                u = vcc_vcc_IpVal(tl);
181                Fb(tl, 0, "= %uU; /* %u.%u.%u.%u */\n",
182                    u,
183                    (u >> 24) & 0xff,
184                    (u >> 16) & 0xff,
185                    (u >> 8) & 0xff,
186                    u & 0xff);
187                break;
188#endif
189        case BACKEND:
190                if (tl->t->tok != '=') {
191                        illegal_assignment(tl, "backend");
192                        return;
193                }
194                vcc_NextToken(tl);
195                vcc_AddRef(tl, tl->t, R_BACKEND);
196                Fb(tl, 0, "VGC_backend_%.*s", PF(tl->t));
197                vcc_NextToken(tl);
198                Fb(tl, 0, ");\n");
199                break;
200        case HASH:
201                ExpectErr(tl, T_INCR);
202                vcc_NextToken(tl);
203                if (!vcc_StringVal(tl)) {
204                        ERRCHK(tl);
205                        vcc_ExpectedStringval(tl);
206                        return;
207                }
208                Fb(tl, 0, ");\n");
209                break;
210        case STRING:
211                if (tl->t->tok != '=') {
212                        illegal_assignment(tl, "strings");
213                        return;
214                }
215                vcc_NextToken(tl);
216                if (!vcc_StringVal(tl)) {
217                        ERRCHK(tl);
218                        vcc_ExpectedStringval(tl);
219                        return;
220                }
221                do 
222                        Fb(tl, 0, ", ");
223                while (vcc_StringVal(tl));
224                if (tl->t->tok != ';') {
225                        ERRCHK(tl);
226                        vsb_printf(tl->sb,
227                            "Expected variable, string or semicolon\n");
228                        vcc_ErrWhere(tl, tl->t);
229                        return;
230                }
231                Fb(tl, 0, "0);\n");
232                break;
233        default:
234                vsb_printf(tl->sb,
235                    "Assignments not possible for '%s'\n", vp->name);
236                vcc_ErrWhere(tl, tl->t);
237                return;
238        }
239}
240
241/*--------------------------------------------------------------------*/
242
243static void
244parse_remove(struct tokenlist *tl)
245{
246        struct var *vp;
247
248        vcc_NextToken(tl);
249        ExpectErr(tl, VAR);
250        vp = vcc_FindVar(tl, tl->t, vcc_vars);
251        ERRCHK(tl);
252        assert(vp != NULL);
253        if (vp->fmt != STRING || vp->hdr == NULL) {
254                vsb_printf(tl->sb, "Only http header lines can be removed.\n");
255                vcc_ErrWhere(tl, tl->t);
256                return;
257        }
258        check_writebit(tl, vp);
259        ERRCHK(tl);
260        Fb(tl, 1, "%s0);\n", vp->lname);
261        vcc_NextToken(tl);
262}
263
264/*--------------------------------------------------------------------*/
265
266typedef void action_f(struct tokenlist *tl);
267
268static struct action_table {
269        const char              *name;
270        action_f                *func;
271} action_table[] = {
272#define VCL_RET_MAC(l, u, b, i) { #l, parse_##l },
273#define VCL_RET_MAC_E(l, u, b, i) VCL_RET_MAC(l, u, b, i)
274#include "vcl_returns.h"
275#undef VCL_RET_MAC
276#undef VCL_RET_MAC_E
277        { "call",       parse_call },
278        { "set",        parse_set },
279        { "remove",     parse_remove },
280        { NULL,         NULL }
281};
282
283void
284vcc_ParseAction(struct tokenlist *tl)
285{
286        struct token *at;
287        struct action_table *atp;
288
289        at = tl->t;
290        if (at->tok == ID) {
291                for(atp = action_table; atp->name != NULL; atp++) {
292                        if (vcc_IdIs(at, atp->name)) {
293                                atp->func(tl);
294                                return;
295                        }
296                }
297        }
298        vsb_printf(tl->sb, "Expected action, 'if' or '}'\n");
299        vcc_ErrWhere(tl, at);
300}
Note: See TracBrowser for help on using the repository browser.