varnish-cache/lib/libvcc/vcc_token.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2011 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
#include "config.h"
32
33
#include <stdlib.h>
34
#include <string.h>
35
36
#include "vcc_compile.h"
37
38
#include "venc.h"
39
#include "vct.h"
40
41
/*--------------------------------------------------------------------*/
42
43
void
44 1320
vcc_ErrToken(const struct vcc *tl, const struct token *t)
45
{
46
47 1320
        if (t->tok == EOI)
48 0
                VSB_cat(tl->sb, "end of input");
49 1320
        else if (t->tok == CSRC)
50 0
                VSB_cat(tl->sb, "C{ ... }C");
51
        else
52 1320
                VSB_printf(tl->sb, "'%.*s'", PF(t));
53 1320
}
54
55
void
56 0
vcc__ErrInternal(struct vcc *tl, const char *func, unsigned line)
57
{
58
59 0
        VSB_printf(tl->sb, "VCL compiler internal error at %s():%u\n",
60 0
            func, line);
61 0
        tl->err = 1;
62 0
}
63
64
/*--------------------------------------------------------------------
65
 * Find start of source-line of token
66
 */
67
68
static void
69 27480
vcc_iline(const struct token *t, const char **ll, int tail)
70
{
71
        const char *p, *b, *x;
72
73 27480
        b = t->src->b;
74 27480
        if (ll != NULL)
75 27480
                *ll = b;
76 27480
        x = tail ? t->e - 1 : t->b;
77 12035240
        for (p = b; p < x; p++) {
78 12007760
                if (*p == '\n') {
79 338000
                        if (ll != NULL)
80 338000
                                *ll = p + 1;
81 338000
                }
82 12007760
        }
83 27480
}
84
85
/*--------------------------------------------------------------------
86
 * Find and print src+line+pos of this token
87
 */
88
89
static void
90 4787320
vcc_icoord(struct vsb *vsb, const struct token *t, int tail)
91
{
92
        unsigned lin, pos;
93
        const char *p, *b, *x;
94
95 4787320
        lin = 1;
96 4787320
        pos = 0;
97 4787320
        b = t->src->b;
98 4787320
        x = tail ? t->e - 1 : t->b;
99 20122470238
        for (p = b; p < x; p++) {
100 20117682918
                if (*p == '\n') {
101 837572160
                        lin++;
102 837572160
                        pos = 0;
103 20117682918
                } else if (*p == '\t') {
104 403623440
                        pos &= ~7;
105 403623440
                        pos += 8;
106 403623440
                } else
107 18876487318
                        pos++;
108 20117682918
        }
109 4787320
        VSB_cat(vsb, "(");
110 4787320
        if (tail < 2)
111 4782320
                VSB_printf(vsb, "'%s' Line %u ", t->src->name, lin);
112 4787320
        VSB_printf(vsb, "Pos %u)", pos + 1);
113 4787320
}
114
115
/*--------------------------------------------------------------------*/
116
117
void
118 4759840
vcc_Coord(const struct vcc *tl, struct vsb *vsb, const struct token *t)
119
{
120
121 4759840
        if (t == NULL)
122 4759840
                t = tl->t;
123 4759840
        vcc_icoord(vsb, t, 0);
124 4759840
}
125
126
/*--------------------------------------------------------------------
127
 * Output one line of source code, starting at 'l' and ending at the
128
 * first NL or 'le'.
129
 */
130
131
static void
132 22480
vcc_quoteline(const struct vcc *tl, const char *l, const char *le)
133
{
134
        const char *p;
135
        unsigned x, y;
136
137 22480
        x = y = 0;
138 743498
        for (p = l; p < le && *p != '\n'; p++) {
139 721018
                if (*p == '\t') {
140 30520
                        y &= ~7;
141 30520
                        y += 8;
142 274680
                        while (x < y) {
143 244160
                                VSB_putc(tl->sb, ' ');
144 244160
                                x++;
145
                        }
146 30520
                } else {
147 690498
                        x++;
148 690498
                        y++;
149 690498
                        VSB_putc(tl->sb, *p);
150
                }
151 721018
        }
152 22480
        VSB_putc(tl->sb, '\n');
153 22480
}
154
155
/*--------------------------------------------------------------------
156
 * Output a marker line for a sourceline starting at 'l' and ending at
157
 * the first NL or 'le'.  Characters between 'b' and 'e' are marked.
158
 */
159
160
static void
161 22480
vcc_markline(const struct vcc *tl, const char *l, const char *le,
162
    const char *b, const char *e)
163
{
164
        const char *p;
165
        unsigned x, y;
166
        char c;
167
168 22480
        x = y = 0;
169 743498
        for (p = l; p < le && *p != '\n'; p++) {
170 721018
                if (p >= b && p < e)
171 178352
                        c = '#';
172
                else
173 542666
                        c = '-';
174
175 721018
                if (*p == '\t') {
176 30520
                        y &= ~7;
177 30520
                        y += 8;
178 30520
                } else
179 690498
                        y++;
180 1655676
                while (x < y) {
181 934658
                        VSB_putc(tl->sb, c);
182 934658
                        x++;
183
                }
184 721018
        }
185 22480
        VSB_putc(tl->sb, '\n');
186 22480
}
187
188
void
189 6200
vcc_Warn(struct vcc *tl)
190
{
191
192 6200
        AN(tl);
193 6200
        AN(tl->err);
194 6200
        VSB_cat(tl->sb, "(That was just a warning)\n");
195 6200
        tl->err = 0;
196 6200
}
197
198
/*--------------------------------------------------------------------*/
199
/* XXX: should take first+last token */
200
201
void
202 5080
vcc_ErrWhere2(struct vcc *tl, const struct token *t, const struct token *t2)
203
{
204
        const char  *l1, *l2, *l3;
205
206 5080
        if (t == NULL) {
207 40
                vcc_ErrWhere(tl, t2);
208 40
                return;
209
        }
210 5040
        vcc_iline(t, &l1, 0);
211 5040
        t2 = VTAILQ_PREV(t2, tokenhead, list);
212 5040
        vcc_iline(t2, &l2, 1);
213
214
215 5040
        if (l1 == l2) {
216 5000
                vcc_icoord(tl->sb, t, 0);
217 5000
                VSB_cat(tl->sb, " -- ");
218 5000
                vcc_icoord(tl->sb, t2, 2);
219 5000
                VSB_putc(tl->sb, '\n');
220
                /* Two tokens on same line */
221 5000
                vcc_quoteline(tl, l1, t->src->e);
222 5000
                vcc_markline(tl, l1, t->src->e, t->b, t2->e);
223 5000
        } else {
224
                /* Two tokens different lines */
225 40
                l3 = strchr(l1, '\n');
226 40
                AN(l3);
227
                /* XXX: t had better be before t2 */
228 40
                vcc_icoord(tl->sb, t, 0);
229 40
                if (l3 + 1 == l2) {
230 0
                        VSB_cat(tl->sb, " -- ");
231 0
                        vcc_icoord(tl->sb, t2, 1);
232 0
                }
233 40
                VSB_putc(tl->sb, '\n');
234 40
                vcc_quoteline(tl, l1, t->src->e);
235 40
                vcc_markline(tl, l1, t->src->e, t->b, t2->e);
236 40
                if (l3 + 1 != l2) {
237 40
                        VSB_cat(tl->sb, "[...]\n");
238 40
                        vcc_icoord(tl->sb, t2, 1);
239 40
                        VSB_putc(tl->sb, '\n');
240 40
                }
241 40
                vcc_quoteline(tl, l2, t->src->e);
242 40
                vcc_markline(tl, l2, t->src->e, t->b, t2->e);
243
        }
244 5040
        VSB_putc(tl->sb, '\n');
245 5040
        tl->err = 1;
246 5080
}
247
248
void
249 17400
vcc_ErrWhere(struct vcc *tl, const struct token *t)
250
{
251
        const char  *l1;
252
253 17400
        vcc_iline(t, &l1, 0);
254 17400
        vcc_icoord(tl->sb, t, 0);
255 17400
        VSB_putc(tl->sb, '\n');
256 17400
        vcc_quoteline(tl, l1, t->src->e);
257 17400
        vcc_markline(tl, l1, t->src->e, t->b, t->e);
258 17400
        VSB_putc(tl->sb, '\n');
259 17400
        tl->err = 1;
260 17400
}
261
262
/*--------------------------------------------------------------------*/
263
264
struct token *
265 154645160
vcc_PeekTokenFrom(const struct vcc *tl, const struct token *t)
266
{
267
        struct token *t2;
268
269 154645160
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
270 154645160
        AN(t);
271 154645160
        assert(t->tok != EOI);
272 154645160
        t2 = VTAILQ_NEXT(t, list);
273 154645160
        AN(t2);
274 154645160
        return (t2);
275
}
276
277
struct token *
278 10998040
vcc_PeekToken(const struct vcc *tl)
279
{
280
281 10998040
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
282 10998040
        return (vcc_PeekTokenFrom(tl, tl->t));
283
}
284
285
void
286 59017000
vcc_NextToken(struct vcc *tl)
287
{
288
289 59017000
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
290 59017000
        tl->t = vcc_PeekTokenFrom(tl, tl->t);
291 59017000
}
292
293
void
294 41513400
vcc__Expect(struct vcc *tl, unsigned tok, unsigned line)
295
{
296 41513400
        if (tl->t->tok == tok)
297 41512840
                return;
298 560
        VSB_printf(tl->sb, "Expected %s got ", vcl_tnames[tok]);
299 560
        vcc_ErrToken(tl, tl->t);
300 560
        VSB_printf(tl->sb, "\n(program line %u), at\n", line);
301 560
        vcc_ErrWhere(tl, tl->t);
302 41513400
}
303
304
/*--------------------------------------------------------------------
305
 * Compare ID token to string, return true of match
306
 */
307
308
int
309 111553360
vcc_IdIs(const struct token *t, const char *p)
310
{
311
        const char *q;
312
313 111553360
        assert(t->tok == ID);
314 148840800
        for (q = t->b; q < t->e && *p != '\0'; p++, q++)
315 140266320
                if (*q != *p)
316 102978880
                        return (0);
317 8574480
        if (q != t->e || *p != '\0')
318 8400
                return (0);
319 8566080
        return (1);
320 111553360
}
321
322
/*--------------------------------------------------------------------
323
 * Check that we have a Varnish identifier
324
 */
325
326
void
327 1280
vcc_PrintTokens(const struct vcc *tl,
328
    const struct token *tb, const struct token *te)
329
{
330
331 1280
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
332 1280
        AN(tb);
333 1280
        AN(te);
334 4320
        while (tb != te) {
335 3040
                VSB_printf(tl->sb, "%.*s", PF(tb));
336 3040
                tb = vcc_PeekTokenFrom(tl, tb);
337 3040
                AN(tb);
338
        }
339 1280
}
340
341
void
342 4838200
vcc_ExpectVid(struct vcc *tl, const char *what)
343
{
344 4838200
        const char *bad = NULL;
345
        struct token *t2;
346
347 4838200
        ExpectErr(tl, ID);
348 4838160
        ERRCHK(tl);
349
350 4838160
        t2 = vcc_PeekToken(tl);
351 4838160
        AN(t2);
352 4838280
        while (t2->tok == '.') {
353 120
                bad = ".";
354 120
                t2 = vcc_PeekTokenFrom(tl, t2);
355 120
                AN(t2);
356 120
                if (t2->tok != ID)
357 0
                        break;
358 120
                t2 = vcc_PeekTokenFrom(tl, t2);
359 120
                AN(t2);
360
        }
361 4838160
        if (bad == NULL)
362 4838040
                bad = VCT_invalid_name(tl->t->b, tl->t->e);
363 4838160
        if (bad != NULL) {
364 120
                VSB_printf(tl->sb, "Name of %s, '", what);
365 120
                vcc_PrintTokens(tl, tl->t, t2);
366 240
                VSB_printf(tl->sb,
367 120
                    "', contains illegal character '%c'\n", *bad);
368 120
                vcc_ErrWhere2(tl, tl->t, t2);
369 120
                return;
370
        }
371 4838200
}
372
373
/*--------------------------------------------------------------------
374
 * Decode a string
375
 */
376
377
static void
378 4983240
vcc_decstr(struct vcc *tl, unsigned sep)
379
{
380
        char *q;
381
        unsigned int l;
382
383 4983240
        assert(tl->t->tok == CSTR);
384 4983240
        l = pdiff(tl->t->b + sep, tl->t->e - sep);
385 4983240
        tl->t->dec = TlAlloc(tl, l + 1);
386 4983240
        AN(tl->t->dec);
387 4983240
        q = tl->t->dec;
388 4983240
        memcpy(q, tl->t->b + sep, l);
389 4983240
        q[l] = '\0';
390 4983240
}
391
392
/*--------------------------------------------------------------------
393
 * Add a token to the token list.
394
 */
395
396
static void
397 111249280
vcc_addtoken(struct vcc *tl, unsigned tok,
398
    struct source *sp, const char *b, const char *e)
399
{
400
        struct token *t;
401
402 111249280
        t = TlAlloc(tl, sizeof *t);
403 111249280
        assert(t != NULL);
404 111249280
        t->tok = tok;
405 111249280
        t->b = b;
406 111249280
        t->e = e;
407 111249280
        t->src = sp;
408 111249280
        VTAILQ_INSERT_TAIL(&sp->src_tokens, t, src_list);
409 111249280
        tl->t = t;
410 111249280
}
411
412
/*--------------------------------------------------------------------
413
 * Find a delimited token
414
 */
415
416
static const struct delim_def {
417
        const char      *name;
418
        const char      *b;
419
        const char      *e;
420
        unsigned        len;    /* NB: must be the same for both delimiters */
421
        unsigned        crlf;
422
        unsigned        tok;
423
} delim_defs[] = {
424
#define DELIM_DEF(nm, l, r, c, t)               \
425
        { nm, l, r, sizeof (l) - 1, c, t }
426
        DELIM_DEF("long-string", "\"\"\"", "\"\"\"", 1, CSTR),  /* """...""" */
427
        DELIM_DEF("long-string", "{\"", "\"}", 1, CSTR),        /*  {"..."}  */
428
        DELIM_DEF("string", "\"", "\"", 0, CSTR),               /*   "..."   */
429
        DELIM_DEF("inline C source", "C{", "}C", 1, CSRC),      /*  C{...}C  */
430
#undef DELIM_DEF
431
        { NULL }
432
};
433
434
static unsigned
435 111063680
vcc_delim_token(struct vcc *tl, struct source *sp, const char *p,
436
    const char **qp)
437
{
438
        const struct delim_def *dd;
439
        const char *q, *r;
440
441 544123200
        for (dd = delim_defs; dd->name != NULL; dd++)
442 438043880
                if (!strncmp(p, dd->b, dd->len))
443 4984360
                        break;
444
445 111063680
        if (dd->name == NULL)
446 106079320
                return (0);
447
448 4984360
        q = strstr(p + dd->len, dd->e);
449 4984360
        if (q != NULL && !dd->crlf) {
450 3756040
                r = strpbrk(p + dd->len, "\r\n");
451 3756040
                if (r != NULL && r < q)
452 0
                        q = NULL;
453 3756040
        }
454
455 4984360
        if (q == NULL) {
456 160
                vcc_addtoken(tl, EOI, sp, p, p + dd->len);
457 160
                VSB_printf(tl->sb, "Unterminated %s, starting at\n", dd->name);
458 160
                vcc_ErrWhere(tl, tl->t);
459 160
                return (0);
460
        }
461
462 4984200
        assert(q < sp->e);
463 4984200
        vcc_addtoken(tl, dd->tok, sp, p, q + dd->len);
464 4984200
        if (dd->tok == CSTR)
465 4983240
                vcc_decstr(tl, dd->len);
466 4984200
        *qp = q + dd->len;
467 4984200
        return (1);
468 111063680
}
469
470
/*--------------------------------------------------------------------
471
 * Lex a number, either CNUM or FNUM.
472
 * We enforce the RFC8941 restrictions on number of digits here.
473
 */
474
475
static int
476 1594440
vcc_lex_number_token_valid(struct vcc *tl)
477
{
478 1594440
        if (*tl->t->e == 'e' || *tl->t->e == 'E') {
479 80
                VSB_printf(tl->sb, "Unexpected character '%c'.\n", *tl->t->e);
480 80
                tl->t->e++;
481 80
                vcc_ErrWhere(tl, tl->t);
482 80
                return (0);
483
        }
484 1594360
        return (1);
485 1594440
}
486
487
static const char *
488 1594600
vcc_lex_number(struct vcc *tl, struct source *sp, const char *p)
489
{
490
        const char *q, *r;
491
        char *s;
492
493 5455440
        for (q = p; q < sp->e; q++)
494 5455440
                if (!vct_isdigit(*q))
495 1594600
                        break;
496 1594600
        if (*q != '.') {
497 1404520
                vcc_addtoken(tl, CNUM, sp, p, q);
498 1404520
                if (q - p > 15) {
499 40
                        VSB_cat(tl->sb, "Too many digits for integer.\n");
500 40
                        vcc_ErrWhere(tl, tl->t);
501 40
                        return (NULL);
502
                }
503 1404480
                if (! vcc_lex_number_token_valid(tl))
504 40
                        return (NULL);
505 1404440
                tl->t->num = strtod(p, &s);
506 1404440
                assert(s == tl->t->e);
507 1404440
                return (q);
508
        }
509 190080
        r = ++q;
510 381560
        for (; r < sp->e; r++)
511 381560
                if (!vct_isdigit(*r))
512 190080
                        break;
513 190080
        vcc_addtoken(tl, FNUM, sp, p, r);
514 190080
        if (q - p > 13 || r - q > 3) {
515 120
                VSB_cat(tl->sb, "Too many digits for real.\n");
516 120
                vcc_ErrWhere(tl, tl->t);
517 120
                return (NULL);
518
        }
519 189960
        if (! vcc_lex_number_token_valid(tl))
520 40
                return (NULL);
521 189920
        tl->t->num = strtod(p, &s);
522 189920
        assert(s == tl->t->e);
523 189920
        return (r);
524 1594600
}
525
526
/*--------------------------------------------------------------------
527
 * Lexical analysis and token generation
528
 */
529
530
void
531 185920
vcc_Lexer(struct vcc *tl, struct source *sp)
532
{
533
        const char *p, *q, *r;
534
        unsigned u;
535
        struct vsb *vsb;
536
        char namebuf[40];
537
538 223140320
        for (p = sp->b; p < sp->e; ) {
539
540
                /* Skip any whitespace */
541 222955360
                if (vct_isspace(*p)) {
542 104773680
                        p++;
543 104773680
                        continue;
544
                }
545
546
                /* Skip '#.*\n' comments */
547 118181680
                if (*p == '#') {
548 331666160
                        while (p < sp->e && *p != '\n')
549 324549440
                                p++;
550 7116720
                        continue;
551
                }
552
553
                /* Skip C-style comments */
554 111064960
                if (*p == '/' && p[1] == '*') {
555 2640
                        for (q = p + 2; q < sp->e; q++) {
556 2600
                                if (*q == '/' && q[1] == '*') {
557 40
                                        VSB_cat(tl->sb,
558
                                            "/* ... */ comment contains /*\n");
559 40
                                        vcc_addtoken(tl, EOI, sp, p, p + 2);
560 40
                                        vcc_ErrWhere(tl, tl->t);
561 40
                                        vcc_addtoken(tl, EOI, sp, q, q + 2);
562 40
                                        vcc_ErrWhere(tl, tl->t);
563 40
                                        return;
564
                                }
565 2560
                                if (*q == '*' && q[1] == '/') {
566 80
                                        p = q + 2;
567 80
                                        break;
568
                                }
569 2480
                        }
570 120
                        if (q < sp->e)
571 80
                                continue;
572 40
                        vcc_addtoken(tl, EOI, sp, p, p + 2);
573 40
                        VSB_cat(tl->sb,
574
                            "Unterminated /* ... */ comment, starting at\n");
575 40
                        vcc_ErrWhere(tl, tl->t);
576 40
                        return;
577
                }
578
579
                /* Skip C++-style comments */
580 111064800
                if (*p == '/' && p[1] == '/') {
581 15080
                        while (p < sp->e && *p != '\n')
582 14480
                                p++;
583 600
                        continue;
584
                }
585
586
                /* Recognize BLOB (= SF-binary) */
587 111064200
                if (*p == ':') {
588 520
                        vsb = VSB_new_auto();
589 520
                        AN(vsb);
590 520
                        q = sp->e;
591 520
                        q -= (q - (p + 1)) % 4;
592 520
                        assert(q > p);
593 520
                        r = VENC_Decode_Base64(vsb, p + 1, q);
594 520
                        if (r == NULL) {
595 80
                                vcc_addtoken(tl, CBLOB, sp, p, q + 1);
596 80
                                VSB_cat(tl->sb,
597
                                    "Missing colon at end of BLOB:\n");
598 80
                                vcc_ErrWhere(tl, tl->t);
599 80
                                VSB_destroy(&vsb);
600 80
                                return;
601
                        }
602 440
                        vcc_addtoken(tl, CBLOB, sp, p, r + 1);
603 440
                        if (*r == ':' && ((r - p) % 4) != 1) {
604 120
                                VSB_cat(tl->sb,
605
                                    "BLOB must have n*4 base64 characters\n");
606 120
                                vcc_ErrWhere(tl, tl->t);
607 120
                                VSB_destroy(&vsb);
608 120
                                return;
609
                        }
610 320
                        if (*r == '=') {
611 120
                                VSB_cat(tl->sb,
612
                                    "Wrong padding ('=') in BLOB:\n");
613 120
                                vcc_ErrWhere(tl, tl->t);
614 120
                                VSB_destroy(&vsb);
615 120
                                return;
616
                        }
617 200
                        if (*r != ':') {
618 80
                                VSB_cat(tl->sb, "Illegal BLOB character:\n");
619 80
                                vcc_ErrWhere(tl, tl->t);
620 80
                                VSB_destroy(&vsb);
621 80
                                return;
622
                        }
623 120
                        r++;
624 120
                        AZ(VSB_finish(vsb));
625
626 120
                        bprintf(namebuf, "blob_%u", tl->unique++);
627 240
                        Fh(tl, 0,
628
                            "\nstatic const unsigned char %s_data[%zd] = {\n",
629 120
                            namebuf, VSB_len(vsb));
630 3280
                        for (u = 0; u < VSB_len(vsb); u++) {
631 3160
                                Fh(tl, 0, "\t0x%02x,", VSB_data(vsb)[u] & 0xff);
632 3160
                                if ((u & 7) == 7)
633 360
                                        Fh(tl, 0, "\n");
634 3160
                        }
635 120
                        if ((u & 7) != 7)
636 120
                                Fh(tl, 0, "\n");
637 120
                        Fh(tl, 0, "};\n");
638 240
                        Fh(tl, 0,
639
                            "\nstatic const struct vrt_blob %s[1] = {{\n",
640 120
                            namebuf);
641 120
                        Fh(tl, 0, "\t.magic =\tVRT_BLOB_MAGIC,\n");
642 120
                        Fh(tl, 0, "\t.len =\t%zd,\n", VSB_len(vsb));
643 120
                        Fh(tl, 0, "\t.blob =\t%s_data,\n", namebuf);
644 120
                        Fh(tl, 0, "}};\n");
645 120
                        REPLACE(tl->t->dec, namebuf);
646 120
                        VSB_destroy(&vsb);
647 120
                        p = r;
648 120
                        continue;
649
                }
650
651
                /* Match delimited tokens */
652 111063680
                if (vcc_delim_token(tl, sp, p, &q) != 0) {
653 4984200
                        p = q;
654 4984200
                        continue;
655
                }
656 106079480
                ERRCHK(tl);
657
658
                /* Match for the fixed tokens (see generate.py) */
659 106079320
                u = vcl_fixed_token(p, &q);
660 106079320
                if (u != 0) {
661 57732360
                        vcc_addtoken(tl, u, sp, p, q);
662 57732360
                        p = q;
663 57732360
                        continue;
664
                }
665
666
                /* Match Identifiers */
667 48346960
                if (vct_isident1(*p)) {
668 372254000
                        for (q = p; q < sp->e; q++)
669 372254000
                                if (!vct_isident(*q))
670 46752280
                                        break;
671 46752280
                        vcc_addtoken(tl, ID, sp, p, q);
672 46752280
                        p = q;
673 46752280
                        continue;
674
                }
675
676
                /* Match numbers { [0-9]+ } */
677 1594680
                if (vct_isdigit(*p)) {
678 1594600
                        p = vcc_lex_number(tl, sp, p);
679 1594600
                        if (p == NULL)
680 240
                                return;
681 1594360
                        continue;
682
                }
683 80
                vcc_addtoken(tl, EOI, sp, p, p + 1);
684 80
                VSB_cat(tl->sb, "Syntax error at\n");
685 80
                vcc_ErrWhere(tl, tl->t);
686 80
                return;
687
        }
688 184960
        vcc_addtoken(tl, EOI, sp, sp->e, sp->e);
689 185920
}