vinyl-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 756
vcc_ErrToken(const struct vcc *tl, const struct token *t)
45
{
46
47 756
        if (t->tok == EOI)
48 0
                VSB_cat(tl->sb, "end of input");
49 756
        else if (t->tok == CSRC)
50 0
                VSB_cat(tl->sb, "C{ ... }C");
51
        else
52 756
                VSB_printf(tl->sb, "'%.*s'", PF(t));
53 756
}
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 15014
vcc_iline(const struct token *t, const char **ll, int tail)
70
{
71
        const char *p, *b, *x;
72
73 15014
        b = t->src->b;
74 15014
        if (ll != NULL)
75 15014
                *ll = b;
76 15014
        x = tail ? t->e - 1 : t->b;
77 5821410
        for (p = b; p < x; p++) {
78 5806396
                if (*p == '\n') {
79 179567
                        if (ll != NULL)
80 179567
                                *ll = p + 1;
81 179567
                }
82 5806396
        }
83 15014
}
84
85
/*--------------------------------------------------------------------
86
 * Find and print src+line+pos of this token
87
 */
88
89
static void
90 2828423
vcc_icoord(struct vsb *vsb, const struct token *t, int tail)
91
{
92
        unsigned lin, pos;
93
        const char *p, *b, *x;
94
95 2828423
        lin = 1;
96 2828423
        pos = 0;
97 2828423
        b = t->src->b;
98 2828423
        x = tail ? t->e - 1 : t->b;
99 15253320263
        for (p = b; p < x; p++) {
100 15250491840
                if (*p == '\n') {
101 591732609
                        lin++;
102 591732609
                        pos = 0;
103 15250491840
                } else if (*p == '\t') {
104 281324415
                        pos &= ~7;
105 281324415
                        pos += 8;
106 281324415
                } else
107 14377434816
                        pos++;
108 15250491840
        }
109 2828423
        VSB_cat(vsb, "(");
110 2828423
        if (tail < 2)
111 2825756
                VSB_printf(vsb, "'%s' Line %u ", t->src->name, lin);
112 2828423
        VSB_printf(vsb, "Pos %u)", pos + 1);
113 2828423
}
114
115
/*--------------------------------------------------------------------*/
116
117
void
118 2813409
vcc_Coord(const struct vcc *tl, struct vsb *vsb, const struct token *t)
119
{
120
121 2813409
        if (t == NULL)
122 2813409
                t = tl->t;
123 2813409
        vcc_icoord(vsb, t, 0);
124 2813409
}
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 12347
vcc_quoteline(const struct vcc *tl, const char *l, const char *le)
133
{
134
        const char *p;
135
        unsigned x, y;
136
137 12347
        x = y = 0;
138 392439
        for (p = l; p < le && *p != '\n'; p++) {
139 380092
                if (*p == '\t') {
140 16483
                        y &= ~7;
141 16483
                        y += 8;
142 148179
                        while (x < y) {
143 131696
                                VSB_putc(tl->sb, ' ');
144 131696
                                x++;
145
                        }
146 16483
                } else {
147 363609
                        x++;
148 363609
                        y++;
149 363609
                        VSB_putc(tl->sb, *p);
150
                }
151 380092
        }
152 12347
        VSB_putc(tl->sb, '\n');
153 12347
}
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 12347
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 12347
        x = y = 0;
169 392439
        for (p = l; p < le && *p != '\n'; p++) {
170 380092
                if (p >= b && p < e)
171 98411
                        c = '#';
172
                else
173 281681
                        c = '-';
174
175 380092
                if (*p == '\t') {
176 16483
                        y &= ~7;
177 16483
                        y += 8;
178 16483
                } else
179 363609
                        y++;
180 875397
                while (x < y) {
181 495305
                        VSB_putc(tl->sb, c);
182 495305
                        x++;
183
                }
184 380092
        }
185 12347
        VSB_putc(tl->sb, '\n');
186 12347
}
187
188
void
189 3339
vcc_Warn(struct vcc *tl)
190
{
191
192 3339
        AN(tl);
193 3339
        AN(tl->err);
194 3339
        VSB_cat(tl->sb, "(That was just a warning)\n");
195 3339
        tl->err = 0;
196 3339
}
197
198
/*--------------------------------------------------------------------*/
199
/* XXX: should take first+last token */
200
201
void
202 2772
vcc_ErrWhere2(struct vcc *tl, const struct token *t, const struct token *t2)
203
{
204
        const char  *l1, *l2, *l3;
205
206 2772
        if (t == NULL) {
207 21
                vcc_ErrWhere(tl, t2);
208 21
                return;
209
        }
210 2751
        if (t->src != t2->src) {
211 84
                vcc_ErrWhere(tl, t);
212 84
                return;
213
        }
214 2667
        vcc_iline(t, &l1, 0);
215 2667
        t2 = VTAILQ_PREV(t2, tokenhead, list);
216 2667
        vcc_iline(t2, &l2, 1);
217
218
219 2667
        if (l1 == l2) {
220 2667
                vcc_icoord(tl->sb, t, 0);
221 2667
                VSB_cat(tl->sb, " -- ");
222 2667
                vcc_icoord(tl->sb, t2, 2);
223 2667
                VSB_putc(tl->sb, '\n');
224
                /* Two tokens on same line */
225 2667
                vcc_quoteline(tl, l1, t->src->e);
226 2667
                vcc_markline(tl, l1, t->src->e, t->b, t2->e);
227 2667
        } else {
228
                /* Two tokens different lines */
229 0
                l3 = strchr(l1, '\n');
230 0
                AN(l3);
231
                /* XXX: t had better be before t2 */
232 0
                vcc_icoord(tl->sb, t, 0);
233 0
                if (l3 + 1 == l2) {
234 0
                        VSB_cat(tl->sb, " -- ");
235 0
                        vcc_icoord(tl->sb, t2, 1);
236 0
                }
237 0
                VSB_putc(tl->sb, '\n');
238 0
                vcc_quoteline(tl, l1, t->src->e);
239 0
                vcc_markline(tl, l1, t->src->e, t->b, t2->e);
240 0
                if (l3 + 1 != l2) {
241 0
                        VSB_cat(tl->sb, "[...]\n");
242 0
                        vcc_icoord(tl->sb, t2, 1);
243 0
                        VSB_putc(tl->sb, '\n');
244 0
                }
245 0
                vcc_quoteline(tl, l2, t->src->e);
246 0
                vcc_markline(tl, l2, t->src->e, t->b, t2->e);
247
        }
248 2667
        VSB_putc(tl->sb, '\n');
249 2667
        tl->err = 1;
250 2772
}
251
252
void
253 9680
vcc_ErrWhere(struct vcc *tl, const struct token *t)
254
{
255
        const char  *l1;
256
257 9680
        vcc_iline(t, &l1, 0);
258 9680
        vcc_icoord(tl->sb, t, 0);
259 9680
        VSB_putc(tl->sb, '\n');
260 9680
        vcc_quoteline(tl, l1, t->src->e);
261 9680
        vcc_markline(tl, l1, t->src->e, t->b, t->e);
262 9680
        VSB_putc(tl->sb, '\n');
263 9680
        tl->err = 1;
264 9680
}
265
266
/*--------------------------------------------------------------------*/
267
268
struct token *
269 95300038
vcc_PeekTokenFrom(const struct vcc *tl, const struct token *t)
270
{
271
        struct token *t2;
272
273 95300038
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
274 95300038
        AN(t);
275 95300038
        assert(t->tok != EOI);
276 95300038
        t2 = VTAILQ_NEXT(t, list);
277 95300038
        AN(t2);
278 95300038
        return (t2);
279
}
280
281
struct token *
282 6882305
vcc_PeekToken(const struct vcc *tl)
283
{
284
285 6882305
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
286 6882305
        return (vcc_PeekTokenFrom(tl, tl->t));
287
}
288
289
void
290 36245437
vcc_NextToken(struct vcc *tl)
291
{
292
293 36245437
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
294 36245437
        tl->t = vcc_PeekTokenFrom(tl, tl->t);
295 36245437
}
296
297
void
298 25205681
vcc__Expect(struct vcc *tl, unsigned tok, unsigned line)
299
{
300 25205681
        if (tl->t->tok == tok)
301 25205345
                return;
302 336
        VSB_printf(tl->sb, "Expected %s got ", vcl_tnames[tok]);
303 336
        vcc_ErrToken(tl, tl->t);
304 336
        VSB_printf(tl->sb, "\n(program line %u), at\n", line);
305 336
        vcc_ErrWhere(tl, tl->t);
306 25205681
}
307
308
/*--------------------------------------------------------------------
309
 * Compare ID token to string, return true of match
310
 */
311
312
int
313 67257390
vcc_IdIs(const struct token *t, const char *p)
314
{
315
        const char *q;
316
317 67257390
        assert(t->tok == ID);
318 89397994
        for (q = t->b; q < t->e && *p != '\0'; p++, q++)
319 84357968
                if (*q != *p)
320 62217364
                        return (0);
321 5040026
        if (q != t->e || *p != '\0')
322 4431
                return (0);
323 5035595
        return (1);
324 67257390
}
325
326
/*--------------------------------------------------------------------
327
 * Check that we have a Vinyl identifier
328
 */
329
330
void
331 735
vcc_PrintTokens(const struct vcc *tl,
332
    const struct token *tb, const struct token *te)
333
{
334
335 735
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
336 735
        AN(tb);
337 735
        AN(te);
338 2478
        while (tb != te) {
339 1743
                VSB_printf(tl->sb, "%.*s", PF(tb));
340 1743
                tb = vcc_PeekTokenFrom(tl, tb);
341 1743
                AN(tb);
342
        }
343 735
}
344
345
void
346 2856521
vcc_ExpectVid(struct vcc *tl, const char *what)
347
{
348 2856521
        const char *bad = NULL;
349
        struct token *t2;
350
351 2856521
        ExpectErr(tl, ID);
352 2856500
        ERRCHK(tl);
353
354 2856500
        t2 = vcc_PeekToken(tl);
355 2856500
        AN(t2);
356 2856626
        while (t2->tok == '.') {
357 126
                bad = ".";
358 126
                t2 = vcc_PeekTokenFrom(tl, t2);
359 126
                AN(t2);
360 126
                if (t2->tok != ID)
361 0
                        break;
362 126
                t2 = vcc_PeekTokenFrom(tl, t2);
363 126
                AN(t2);
364
        }
365 2856500
        if (bad == NULL)
366 2856374
                bad = VCT_invalid_name(tl->t->b, tl->t->e);
367 2856500
        if (bad != NULL) {
368 126
                VSB_printf(tl->sb, "Name of %s, '", what);
369 126
                vcc_PrintTokens(tl, tl->t, t2);
370 252
                VSB_printf(tl->sb,
371 126
                    "', contains illegal character '%c'\n", *bad);
372 126
                vcc_ErrWhere2(tl, tl->t, t2);
373 126
                return;
374
        }
375 2856521
}
376
377
/*--------------------------------------------------------------------
378
 * Decode a string
379
 */
380
381
static void
382 3220887
vcc_decstr(struct vcc *tl, unsigned sep)
383
{
384
        char *q;
385
        unsigned int l;
386
387 3220887
        assert(tl->t->tok == CSTR);
388 3220887
        l = pdiff(tl->t->b + sep, tl->t->e - sep);
389 3220887
        tl->t->dec = TlAlloc(tl, l + 1);
390 3220887
        AN(tl->t->dec);
391 3220887
        q = tl->t->dec;
392 3220887
        vmemcpy(q, tl->t->b + sep, l);
393 3220887
        q[l] = '\0';
394 3220887
}
395
396
/*--------------------------------------------------------------------
397
 * Add a token to the token list.
398
 */
399
400
static void
401 68600396
vcc_addtoken(struct vcc *tl, unsigned tok,
402
    struct source *sp, const char *b, const char *e)
403
{
404
        struct token *t;
405
406 68600396
        t = TlAlloc(tl, sizeof *t);
407 68600396
        assert(t != NULL);
408 68600396
        t->tok = tok;
409 68600396
        t->b = b;
410 68600396
        t->e = e;
411 68600396
        t->src = sp;
412 68600396
        VTAILQ_INSERT_TAIL(&sp->src_tokens, t, src_list);
413 68600396
        tl->t = t;
414 68600396
}
415
416
/*--------------------------------------------------------------------
417
 * Find a delimited token
418
 */
419
420
static const struct delim_def {
421
        const char      *name;
422
        const char      *b;
423
        const char      *e;
424
        unsigned        len;    /* NB: must be the same for both delimiters */
425
        unsigned        crlf;
426
        unsigned        tok;
427
} delim_defs[] = {
428
#define DELIM_DEF(nm, l, r, c, t)               \
429
        { nm, l, r, sizeof (l) - 1, c, t }
430
        DELIM_DEF("long-string", "\"\"\"", "\"\"\"", 1, CSTR),  /* """...""" */
431
        DELIM_DEF("long-string", "{\"", "\"}", 1, CSTR),        /*  {"..."}  */
432
        DELIM_DEF("string", "\"", "\"", 0, CSTR),               /*   "..."   */
433
        DELIM_DEF("inline C source", "C{", "}C", 1, CSRC),      /*  C{...}C  */
434
#undef DELIM_DEF
435
        { NULL }
436
};
437
438
static unsigned
439 68497898
vcc_delim_token(struct vcc *tl, struct source *sp, const char *p,
440
    const char **qp)
441
{
442
        const struct delim_def *dd;
443
        const char *q, *r;
444
445 335369898
        for (dd = delim_defs; dd->name != NULL; dd++)
446 270093475
                if (!vstrncmp(p, dd->b, dd->len))
447 3221475
                        break;
448
449 68497898
        if (dd->name == NULL)
450 65276423
                return (0);
451
452 3221475
        q = strstr(p + dd->len, dd->e);
453 3221475
        if (q != NULL && !dd->crlf) {
454 2543867
                r = strpbrk(p + dd->len, "\r\n");
455 2543867
                if (r != NULL && r < q)
456 0
                        q = NULL;
457 2543867
        }
458
459 3221475
        if (q == NULL) {
460 84
                vcc_addtoken(tl, EOI, sp, p, p + dd->len);
461 84
                VSB_printf(tl->sb, "Unterminated %s, starting at\n", dd->name);
462 84
                vcc_ErrWhere(tl, tl->t);
463 84
                return (0);
464
        }
465
466 3221391
        assert(q < sp->e);
467 3221391
        vcc_addtoken(tl, dd->tok, sp, p, q + dd->len);
468 3221391
        if (dd->tok == CSTR)
469 3220887
                vcc_decstr(tl, dd->len);
470 3221391
        *qp = q + dd->len;
471 3221391
        return (1);
472 68497898
}
473
474
/*--------------------------------------------------------------------
475
 * Lex a number, either CNUM or FNUM.
476
 * We enforce the RFC8941 restrictions on number of digits here.
477
 */
478
479
static int
480 948207
vcc_lex_number_token_valid(struct vcc *tl)
481
{
482 948207
        if (*tl->t->e == 'e' || *tl->t->e == 'E') {
483 42
                VSB_printf(tl->sb, "Unexpected character '%c'.\n", *tl->t->e);
484 42
                tl->t->e++;
485 42
                vcc_ErrWhere(tl, tl->t);
486 42
                return (0);
487
        }
488 948165
        return (1);
489 948207
}
490
491
static const char *
492 948291
vcc_lex_number(struct vcc *tl, struct source *sp, const char *p)
493
{
494
        const char *q, *r;
495
        char *s;
496
497 3284663
        for (q = p; q < sp->e; q++)
498 3284663
                if (!vct_isdigit(*q))
499 948291
                        break;
500 948291
        if (*q != '.') {
501 843147
                vcc_addtoken(tl, CNUM, sp, p, q);
502 843147
                if (q - p > 15) {
503 21
                        VSB_cat(tl->sb, "Too many digits for integer.\n");
504 21
                        vcc_ErrWhere(tl, tl->t);
505 21
                        return (NULL);
506
                }
507 843126
                if (! vcc_lex_number_token_valid(tl))
508 21
                        return (NULL);
509 843105
                tl->t->num = strtod(p, &s);
510 843105
                assert(s == tl->t->e);
511 843105
                return (q);
512
        }
513 105144
        r = ++q;
514 211422
        for (; r < sp->e; r++)
515 211422
                if (!vct_isdigit(*r))
516 105144
                        break;
517 105144
        vcc_addtoken(tl, FNUM, sp, p, r);
518 105144
        if (q - p > 13 || r - q > 3) {
519 63
                VSB_cat(tl->sb, "Too many digits for real.\n");
520 63
                vcc_ErrWhere(tl, tl->t);
521 63
                return (NULL);
522
        }
523 105081
        if (! vcc_lex_number_token_valid(tl))
524 21
                return (NULL);
525 105060
        tl->t->num = strtod(p, &s);
526 105060
        assert(s == tl->t->e);
527 105060
        return (r);
528 948291
}
529
530
/*--------------------------------------------------------------------
531
 * Lexical analysis and token generation
532
 */
533
534
void
535 102624
vcc_Lexer(struct vcc *tl, struct source *sp)
536
{
537
        const char *p, *q, *r;
538
        unsigned u;
539
        struct vsb *vsb;
540
        char namebuf[40];
541
542 139788892
        for (p = sp->b; p < sp->e; ) {
543
544
                /* Skip any whitespace */
545 139686772
                if (vct_isspace(*p)) {
546 65774520
                        p++;
547 65774520
                        continue;
548
                }
549
550
                /* Skip '#.*\n' comments */
551 73912252
                if (*p == '#') {
552 254101077
                        while (p < sp->e && *p != '\n')
553 248687479
                                p++;
554 5413598
                        continue;
555
                }
556
557
                /* Skip C-style comments */
558 68498654
                if (*p == '/' && p[1] == '*') {
559 1386
                        for (q = p + 2; q < sp->e; q++) {
560 1365
                                if (*q == '/' && q[1] == '*') {
561 21
                                        VSB_cat(tl->sb,
562
                                            "/* ... */ comment contains /*\n");
563 21
                                        vcc_addtoken(tl, EOI, sp, p, p + 2);
564 21
                                        vcc_ErrWhere(tl, tl->t);
565 21
                                        vcc_addtoken(tl, EOI, sp, q, q + 2);
566 21
                                        vcc_ErrWhere(tl, tl->t);
567 21
                                        return;
568
                                }
569 1344
                                if (*q == '*' && q[1] == '/') {
570 42
                                        p = q + 2;
571 42
                                        break;
572
                                }
573 1302
                        }
574 63
                        if (q < sp->e)
575 42
                                continue;
576 21
                        vcc_addtoken(tl, EOI, sp, p, p + 2);
577 21
                        VSB_cat(tl->sb,
578
                            "Unterminated /* ... */ comment, starting at\n");
579 21
                        vcc_ErrWhere(tl, tl->t);
580 21
                        return;
581
                }
582
583
                /* Skip C++-style comments */
584 68498570
                if (*p == '/' && p[1] == '/') {
585 10563
                        while (p < sp->e && *p != '\n')
586 10206
                                p++;
587 357
                        continue;
588
                }
589
590
                /* Recognize BLOB (= SF-binary) */
591 68498213
                if (*p == ':') {
592 315
                        vsb = VSB_new_auto();
593 315
                        AN(vsb);
594 315
                        q = sp->e;
595 315
                        q -= (q - (p + 1)) % 4;
596 315
                        assert(q > p);
597 315
                        r = VENC_Decode_Base64(vsb, p + 1, q);
598 315
                        if (r == NULL && *q == ':')
599 21
                                r = q;
600 315
                        if (r == NULL) {
601 42
                                vcc_addtoken(tl, CBLOB, sp, p, q + 1);
602 42
                                VSB_cat(tl->sb,
603
                                    "Missing colon at end of BLOB:\n");
604 42
                                vcc_ErrWhere(tl, tl->t);
605 42
                                VSB_destroy(&vsb);
606 42
                                return;
607
                        }
608 273
                        vcc_addtoken(tl, CBLOB, sp, p, r + 1);
609 273
                        if (*r == ':' && ((r - p) % 4) != 1) {
610 63
                                VSB_cat(tl->sb,
611
                                    "BLOB must have n*4 base64 characters\n");
612 63
                                vcc_ErrWhere(tl, tl->t);
613 63
                                VSB_destroy(&vsb);
614 63
                                return;
615
                        }
616 210
                        if (*r == '=') {
617 63
                                VSB_cat(tl->sb,
618
                                    "Wrong padding ('=') in BLOB:\n");
619 63
                                vcc_ErrWhere(tl, tl->t);
620 63
                                VSB_destroy(&vsb);
621 63
                                return;
622
                        }
623 147
                        if (*r != ':') {
624 42
                                VSB_cat(tl->sb, "Illegal BLOB character:\n");
625 42
                                vcc_ErrWhere(tl, tl->t);
626 42
                                VSB_destroy(&vsb);
627 42
                                return;
628
                        }
629 105
                        r++;
630 105
                        AZ(VSB_finish(vsb));
631
632 105
                        bprintf(namebuf, "blob_%u", tl->unique++);
633 210
                        Fh(tl, 0,
634
                            "\nstatic const unsigned char %s_data[%zd] = {\n",
635 105
                            namebuf, VSB_len(vsb));
636 3675
                        for (u = 0; u < VSB_len(vsb); u++) {
637 3570
                                Fh(tl, 0, "\t0x%02x,", VSB_data(vsb)[u] & 0xff);
638 3570
                                if ((u & 7) == 7)
639 420
                                        Fh(tl, 0, "\n");
640 3570
                        }
641 105
                        if ((u & 7) != 7)
642 105
                                Fh(tl, 0, "\n");
643 105
                        Fh(tl, 0, "};\n");
644 210
                        Fh(tl, 0,
645
                            "\nstatic const struct vrt_blob %s[1] = {{\n",
646 105
                            namebuf);
647 105
                        Fh(tl, 0, "\t.magic =\tVRT_BLOB_MAGIC,\n");
648 105
                        Fh(tl, 0, "\t.len =\t%zd,\n", VSB_len(vsb));
649 105
                        Fh(tl, 0, "\t.blob =\t%s_data,\n", namebuf);
650 105
                        Fh(tl, 0, "}};\n");
651 105
                        REPLACE(tl->t->dec, namebuf);
652 105
                        VSB_destroy(&vsb);
653 105
                        p = r;
654 105
                        continue;
655
                }
656
657
                /* Match delimited tokens */
658 68497898
                if (vcc_delim_token(tl, sp, p, &q) != 0) {
659 3221391
                        p = q;
660 3221391
                        continue;
661
                }
662 65276507
                ERRCHK(tl);
663
664
                /* Match for the fixed tokens (see generate.py) */
665 65276423
                u = vcl_fixed_token(p, &q);
666 65276423
                if (u != 0) {
667 35698380
                        vcc_addtoken(tl, u, sp, p, q);
668 35698380
                        p = q;
669 35698380
                        continue;
670
                }
671
672
                /* Match Identifiers */
673 29578043
                if (vct_isident1(*p)) {
674 224689120
                        for (q = p; q < sp->e; q++)
675 224689120
                                if (!vct_isident(*q))
676 28629710
                                        break;
677 28629710
                        vcc_addtoken(tl, ID, sp, p, q);
678 28629710
                        p = q;
679 28629710
                        continue;
680
                }
681
682
                /* Match numbers { [0-9]+ } */
683 948333
                if (vct_isdigit(*p)) {
684 948291
                        p = vcc_lex_number(tl, sp, p);
685 948291
                        if (p == NULL)
686 126
                                return;
687 948165
                        continue;
688
                }
689 42
                vcc_addtoken(tl, EOI, sp, p, p + 1);
690 42
                VSB_cat(tl->sb, "Syntax error at\n");
691 42
                vcc_ErrWhere(tl, tl->t);
692 42
                return;
693
        }
694 102120
        vcc_addtoken(tl, EOI, sp, sp->e, sp->e);
695 102624
}