source: lib/libvcl/vcc_parse.c @ 6f038c

Revision 6f038c, 6.7 KB checked in by Poul-Henning Kamp <phk@…>, 3 years ago (diff)

Remove $Id$ from the source code, git does not support it.

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2010 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
30#include "config.h"
31
32#include <stdio.h>
33#include <string.h>
34
35#include "vsb.h"
36
37#include "vcc_priv.h"
38#include "vcc_compile.h"
39#include "libvarnish.h"
40
41/*--------------------------------------------------------------------*/
42
43static void vcc_Compound(struct vcc *tl);
44
45/*--------------------------------------------------------------------*/
46
47#define L(tl, foo)      do {    \
48        tl->indent += INDENT;   \
49        foo;                    \
50        tl->indent -= INDENT;   \
51} while (0)
52
53#define C(tl, sep)      do {                                    \
54        Fb(tl, 1, "VRT_count(sp, %u)%s\n", ++tl->cnt, sep);     \
55        tl->t->cnt = tl->cnt;                                   \
56} while (0)
57
58/*--------------------------------------------------------------------
59 * SYNTAX:
60 *    Conditional:
61 *      '(' Cond_0 ')'
62 */
63
64static void
65vcc_Conditional(struct vcc *tl)
66{
67
68        SkipToken(tl, '(');
69        Fb(tl, 0, "(\n");
70        L(tl, vcc_Expr(tl, BOOL));
71        ERRCHK(tl);
72        Fb(tl, 1, ")\n");
73        SkipToken(tl, ')');
74}
75
76/*--------------------------------------------------------------------
77 * SYNTAX:
78 *    IfStmt:
79 *      'if' Conditional  Compound Branch1* Branch2
80 *    Branch1:
81 *      'elseif' Conditional Compound
82 *    Branch2:
83 *      'else' Compound
84 *      null
85 */
86
87static void
88vcc_IfStmt(struct vcc *tl)
89{
90
91        SkipToken(tl, T_IF);
92        Fb(tl, 1, "if ");
93        vcc_Conditional(tl);
94        ERRCHK(tl);
95        L(tl, vcc_Compound(tl));
96        ERRCHK(tl);
97        while (1) {
98                switch (tl->t->tok) {
99                case T_ELSE:
100                        vcc_NextToken(tl);
101                        if (tl->t->tok != T_IF) {
102                                Fb(tl, 1, "else\n");
103                                L(tl, vcc_Compound(tl));
104                                ERRCHK(tl);
105                                return;
106                        }
107                        /* FALLTHROUGH */
108                case T_ELSEIF:
109                case T_ELSIF:
110                        Fb(tl, 1, "else if ");
111                        vcc_NextToken(tl);
112                        vcc_Conditional(tl);
113                        ERRCHK(tl);
114                        L(tl, vcc_Compound(tl));
115                        ERRCHK(tl);
116                        break;
117                default:
118                        C(tl, ";");
119                        return;
120                }
121        }
122}
123
124/*--------------------------------------------------------------------
125 * SYNTAX:
126 *    Compound:
127 *      '{' Stmt* '}'
128 *
129 *    Stmt:
130 *      Compound
131 *      IfStmt
132 *      CSRC
133 *      Id(Action) (XXX)
134 */
135
136static void
137vcc_Compound(struct vcc *tl)
138{
139        int i;
140
141        SkipToken(tl, '{');
142        Fb(tl, 1, "{\n");
143        tl->indent += INDENT;
144        C(tl, ";");
145        while (1) {
146                ERRCHK(tl);
147                switch (tl->t->tok) {
148                case '{':
149                        vcc_Compound(tl);
150                        break;
151                case T_IF:
152                        vcc_IfStmt(tl);
153                        break;
154                case '}':
155                        vcc_NextToken(tl);
156                        tl->indent -= INDENT;
157                        Fb(tl, 1, "}\n");
158                        return;
159                case CSRC:
160                        Fb(tl, 1, "%.*s\n",
161                            tl->t->e - (tl->t->b + 2),
162                            tl->t->b + 1);
163                        vcc_NextToken(tl);
164                        break;
165                case EOI:
166                        vsb_printf(tl->sb,
167                            "End of input while in compound statement\n");
168                        tl->err = 1;
169                        return;
170                case ID:
171                        i = vcc_ParseAction(tl);
172                        ERRCHK(tl);
173                        if (i) {
174                                SkipToken(tl, ';');
175                                break;
176                        }
177                        /* FALLTHROUGH */
178                default:
179                        /* We deliberately do not mention inline C */
180                        vsb_printf(tl->sb,
181                            "Expected an action, 'if', '{' or '}'\n");
182                        vcc_ErrWhere(tl, tl->t);
183                        return;
184                }
185        }
186}
187
188/*--------------------------------------------------------------------
189 * SYNTAX:
190 *    Function:
191 *      'sub' ID(name) Compound
192 */
193
194static void
195vcc_Function(struct vcc *tl)
196{
197        int m;
198
199        vcc_NextToken(tl);
200        ExpectErr(tl, ID);
201
202        m = IsMethod(tl->t);
203        if (m != -1) {
204                assert(m < VCL_MET_MAX);
205                tl->fb = tl->fm[m];
206                if (tl->mprocs[m] == NULL) {
207                        vcc_AddDef(tl, tl->t, SYM_SUB);
208                        vcc_AddRef(tl, tl->t, SYM_SUB);
209                        tl->mprocs[m] = vcc_AddProc(tl, tl->t);
210                }
211                tl->curproc = tl->mprocs[m];
212                Fb(tl, 1, "  /* ... from ");
213                vcc_Coord(tl, tl->fb, NULL);
214                Fb(tl, 0, " */\n");
215        } else {
216                tl->fb = tl->fc;
217                vcc_AddDef(tl, tl->t, SYM_SUB);
218                tl->curproc = vcc_AddProc(tl, tl->t);
219                Fh(tl, 0, "static int VGC_function_%.*s (struct sess *sp);\n",
220                    PF(tl->t));
221                Fc(tl, 1, "\nstatic int\n");
222                Fc(tl, 1, "VGC_function_%.*s (struct sess *sp)\n", PF(tl->t));
223        }
224        vcc_NextToken(tl);
225        tl->indent += INDENT;
226        Fb(tl, 1, "{\n");
227        L(tl, vcc_Compound(tl));
228        if (m == -1) {
229                /*
230                 * non-method subroutines must have an explicit non-action
231                 * return in case they just fall through the bottom.
232                 */
233                Fb(tl, 1, "  return(0);\n");
234        }
235        Fb(tl, 1, "}\n");
236        tl->indent -= INDENT;
237        tl->fb = NULL;
238        tl->curproc = NULL;
239}
240
241/*--------------------------------------------------------------------
242 * Top level of parser, recognize:
243 *      Inline C-code
244 *      ACL definitions
245 *      Function definitions
246 *      Backend & Director definitions
247 *      End of input
248 */
249
250typedef void parse_f(struct vcc *tl);
251
252static struct toplev {
253        const char      *name;
254        parse_f         *func;
255} toplev[] = {
256        { "acl",                vcc_Acl },
257        { "sub",                vcc_Function },
258        { "backend",            vcc_ParseDirector },
259        { "director",           vcc_ParseDirector },
260        { "probe",              vcc_ParseProbe },
261        { "import",             vcc_ParseImport },
262        { NULL, NULL }
263};
264
265void
266vcc_Parse(struct vcc *tl)
267{
268        struct toplev *tp;
269
270        while (tl->t->tok != EOI) {
271                ERRCHK(tl);
272                switch (tl->t->tok) {
273                case CSRC:
274                        Fc(tl, 0, "%.*s\n",
275                            tl->t->e - (tl->t->b + 4), tl->t->b + 2);
276                        vcc_NextToken(tl);
277                        break;
278                case EOI:
279                        break;
280                case ID:
281                        for (tp = toplev; tp->name != NULL; tp++) {
282                                if (!vcc_IdIs(tl->t, tp->name))
283                                        continue;
284                                tp->func(tl);
285                                break;
286                        }
287                        if (tp->name != NULL)
288                                break;
289                        /* FALLTHROUGH */
290                default:
291                        /* We deliberately do not mention inline-C */
292                        vsb_printf(tl->sb, "Expected one of\n\t");
293                        for (tp = toplev; tp->name != NULL; tp++) {
294                                if (tp[1].name == NULL)
295                                        vsb_printf(tl->sb, " or ");
296                                vsb_printf(tl->sb, "'%s'", tp->name);
297                                if (tp[1].name != NULL)
298                                        vsb_printf(tl->sb, ", ");
299                        }
300                        vsb_printf(tl->sb, "\nFound: ");
301                        vcc_ErrToken(tl, tl->t);
302                        vsb_printf(tl->sb, " at\n");
303                        vcc_ErrWhere(tl, tl->t);
304                        return;
305                }
306        }
307}
Note: See TracBrowser for help on using the repository browser.