1/*
2 * NASM-compatible re2c lexer
3 *
4 *  Copyright (C) 2001-2007  Peter Johnson
5 *
6 *  Portions based on re2c's example code.
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 OTHER CONTRIBUTORS ``AS IS''
18 * AND 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 THE AUTHOR OR OTHER CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29#include <util.h>
30
31#include <libyasm.h>
32
33#include "modules/parsers/nasm/nasm-parser.h"
34#include "modules/preprocs/nasm/nasm.h"
35
36
37#define YYCURSOR        cursor
38#define YYLIMIT         (s->lim)
39#define YYMARKER        (s->ptr)
40#define YYFILL(n)       {}
41
42#define RETURN(i)       {s->cur = cursor; parser_nasm->tokch = s->tok[0]; \
43                         return i;}
44
45#define SCANINIT()      {s->tok = cursor;}
46
47#define TOK             ((char *)s->tok)
48#define TOKLEN          (size_t)(cursor-s->tok)
49
50
51/* starting size of string buffer */
52#define STRBUF_ALLOC_SIZE       128
53
54/* string buffer used when parsing strings/character constants */
55static YYCTYPE *strbuf = NULL;
56
57/* length of strbuf (including terminating NULL character) */
58static size_t strbuf_size = 0;
59
60static int linechg_numcount;
61
62/*!re2c
63  any = [\001-\377];
64  digit = [0-9];
65  iletter = [a-zA-Z];
66  bindigit = [01_];
67  octdigit = [0-7_];
68  hexdigit = [0-9a-fA-F_];
69  ws = [ \t\r];
70  quot = ["'];
71*/
72
73static int
74handle_dot_label(YYSTYPE *lvalp, char *tok, size_t toklen, size_t zeropos,
75                 yasm_parser_nasm *parser_nasm)
76{
77    /* check for special non-local labels like ..start */
78    if (tok[zeropos+1] == '.') {
79        lvalp->str_val = yasm__xstrndup(tok+zeropos+(parser_nasm->tasm?2:0),
80            toklen-zeropos-(parser_nasm->tasm?2:0));
81        /* check for special non-local ..@label */
82        if (lvalp->str_val[zeropos+2] == '@')
83            return NONLOCAL_ID;
84        return SPECIAL_ID;
85    }
86    if (parser_nasm->masm && tok[zeropos] == '.') {
87        lvalp->str_val = yasm__xstrndup(tok + zeropos, toklen - zeropos);
88        return SPECIAL_ID;
89    }
90    if (parser_nasm->tasm && (!tasm_locals ||
91                (tok[zeropos] == '.' &&
92                 tok[zeropos+1] != '@' && tok[zeropos+2] != '@'))) {
93        /* no locals on Tasm without the 'locals' directive */
94        /* .foo is never local either, but .@@foo may be (local structure
95         * members) */
96        lvalp->str_val = yasm__xstrndup(tok + zeropos, toklen - zeropos);
97        return SPECIAL_ID;
98    }
99    if (!parser_nasm->locallabel_base) {
100        lvalp->str_val = yasm__xstrndup(tok+zeropos, toklen-zeropos);
101        yasm_warn_set(YASM_WARN_GENERAL,
102                      N_("no non-local label before `%s'"),
103                      lvalp->str_val);
104    } else {
105        size_t len = toklen - zeropos + parser_nasm->locallabel_base_len;
106        lvalp->str_val = yasm_xmalloc(len + 1);
107        strcpy(lvalp->str_val, parser_nasm->locallabel_base);
108        strncat(lvalp->str_val, tok+zeropos, toklen-zeropos);
109        lvalp->str_val[len] = '\0';
110    }
111
112    return LOCAL_ID;
113}
114
115int
116nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm)
117{
118    yasm_scanner *s = &parser_nasm->s;
119    YYCTYPE *cursor = s->cur;
120    YYCTYPE endch;
121    size_t count;
122    YYCTYPE savech;
123
124    /* Handle one token of lookahead */
125    if (parser_nasm->peek_token != NONE) {
126        int tok = parser_nasm->peek_token;
127        *lvalp = parser_nasm->peek_tokval;  /* structure copy */
128        parser_nasm->tokch = parser_nasm->peek_tokch;
129        parser_nasm->peek_token = NONE;
130        return tok;
131    }
132
133    /* Catch EOL (EOF from the scanner perspective) */
134    if (s->eof && cursor == s->eof)
135        return 0;
136
137    /* Jump to proper "exclusive" states */
138    switch (parser_nasm->state) {
139        case DIRECTIVE:
140            goto directive;
141        case SECTION_DIRECTIVE:
142            goto section_directive;
143        case DIRECTIVE2:
144            goto directive2;
145        case LINECHG:
146            goto linechg;
147        case LINECHG2:
148            goto linechg2;
149        default:
150            break;
151    }
152
153scan:
154    SCANINIT();
155    if (*cursor == '\0')
156        goto endofinput;
157
158    /*!re2c
159        /* standard decimal integer */
160        digit+ {
161            savech = s->tok[TOKLEN];
162            s->tok[TOKLEN] = '\0';
163            lvalp->intn = yasm_intnum_create_dec(TOK);
164            s->tok[TOKLEN] = savech;
165            RETURN(INTNUM);
166        }
167        /* 10010011b - binary number */
168
169        [01] bindigit* 'b' {
170            s->tok[TOKLEN-1] = '\0'; /* strip off 'b' */
171            lvalp->intn = yasm_intnum_create_bin(TOK);
172            RETURN(INTNUM);
173        }
174
175        /* 777q or 777o - octal number */
176        [0-7] octdigit* [qQoO] {
177            s->tok[TOKLEN-1] = '\0'; /* strip off 'q' or 'o' */
178            lvalp->intn = yasm_intnum_create_oct(TOK);
179            RETURN(INTNUM);
180        }
181
182        /* 0AAh form of hexidecimal number */
183        digit hexdigit* 'h' {
184            s->tok[TOKLEN-1] = '\0'; /* strip off 'h' */
185            lvalp->intn = yasm_intnum_create_hex(TOK);
186            RETURN(INTNUM);
187        }
188
189        /* $0AA and 0xAA forms of hexidecimal number */
190        (("$" digit) | '0x') hexdigit+ {
191            savech = s->tok[TOKLEN];
192            s->tok[TOKLEN] = '\0';
193            if (s->tok[1] == 'x' || s->tok[1] == 'X')
194                /* skip 0 and x */
195                lvalp->intn = yasm_intnum_create_hex(TOK+2);
196            else
197                /* don't skip 0 */
198                lvalp->intn = yasm_intnum_create_hex(TOK+1);
199            s->tok[TOKLEN] = savech;
200            RETURN(INTNUM);
201        }
202
203        /* floating point value */
204        digit+ "." digit* ('e' [-+]? digit+)? {
205            savech = s->tok[TOKLEN];
206            s->tok[TOKLEN] = '\0';
207            lvalp->flt = yasm_floatnum_create(TOK);
208            s->tok[TOKLEN] = savech;
209            RETURN(FLTNUM);
210        }
211
212        /* string/character constant values */
213        quot {
214            endch = s->tok[0];
215            goto stringconst;
216        }
217
218        /* %line linenum+lineinc filename */
219        "%line" {
220            parser_nasm->state = LINECHG;
221            linechg_numcount = 0;
222            RETURN(LINE);
223        }
224
225        /* size specifiers */
226        'byte'          { lvalp->int_info = 8; RETURN(SIZE_OVERRIDE); }
227        'hword'         {
228            lvalp->int_info = yasm_arch_wordsize(p_object->arch)/2;
229            RETURN(SIZE_OVERRIDE);
230        }
231        'word'          {
232            lvalp->int_info = yasm_arch_wordsize(p_object->arch);
233            RETURN(SIZE_OVERRIDE);
234        }
235        'dword' | 'long'        {
236            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
237            RETURN(SIZE_OVERRIDE);
238        }
239        'qword'         {
240            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*4;
241            RETURN(SIZE_OVERRIDE);
242        }
243        'tword'         { lvalp->int_info = 80; RETURN(SIZE_OVERRIDE); }
244        'dqword'        {
245            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
246            RETURN(SIZE_OVERRIDE);
247        }
248        'oword'        {
249            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
250            RETURN(SIZE_OVERRIDE);
251        }
252        'yword'        {
253            lvalp->int_info = 256;
254            RETURN(SIZE_OVERRIDE);
255        }
256
257        /* pseudo-instructions */
258        'db'            {
259            lvalp->int_info = 8;
260            parser_nasm->state = INSTRUCTION;
261            RETURN(DECLARE_DATA);
262        }
263        'dhw'           {
264            lvalp->int_info = yasm_arch_wordsize(p_object->arch)/2;
265            parser_nasm->state = INSTRUCTION;
266            RETURN(DECLARE_DATA);
267        }
268        'dw'            {
269            lvalp->int_info = yasm_arch_wordsize(p_object->arch);
270            parser_nasm->state = INSTRUCTION;
271            RETURN(DECLARE_DATA);
272        }
273        'dd'            {
274            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
275            parser_nasm->state = INSTRUCTION;
276            RETURN(DECLARE_DATA);
277        }
278        'dq'            {
279            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*4;
280            parser_nasm->state = INSTRUCTION;
281            RETURN(DECLARE_DATA);
282        }
283        'dt'            {
284            lvalp->int_info = 80;
285            parser_nasm->state = INSTRUCTION;
286            RETURN(DECLARE_DATA);
287        }
288        'ddq'           {
289            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
290            parser_nasm->state = INSTRUCTION;
291            RETURN(DECLARE_DATA);
292        }
293        'do'           {
294            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
295            parser_nasm->state = INSTRUCTION;
296            RETURN(DECLARE_DATA);
297        }
298        'dy'           {
299            lvalp->int_info = 256;
300            parser_nasm->state = INSTRUCTION;
301            RETURN(DECLARE_DATA);
302        }
303
304        'resb'          {
305            lvalp->int_info = 8;
306            parser_nasm->state = INSTRUCTION;
307            RETURN(RESERVE_SPACE);
308        }
309        'reshw'         {
310            lvalp->int_info = yasm_arch_wordsize(p_object->arch)/2;
311            parser_nasm->state = INSTRUCTION;
312            RETURN(RESERVE_SPACE);
313        }
314        'resw'          {
315            lvalp->int_info = yasm_arch_wordsize(p_object->arch);
316            parser_nasm->state = INSTRUCTION;
317            RETURN(RESERVE_SPACE);
318        }
319        'resd'          {
320            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
321            parser_nasm->state = INSTRUCTION;
322            RETURN(RESERVE_SPACE);
323        }
324        'resq'          {
325            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*4;
326            parser_nasm->state = INSTRUCTION;
327            RETURN(RESERVE_SPACE);
328        }
329        'rest'          {
330            lvalp->int_info = 80;
331            parser_nasm->state = INSTRUCTION;
332            RETURN(RESERVE_SPACE);
333        }
334        'resdq'         {
335            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
336            parser_nasm->state = INSTRUCTION;
337            RETURN(RESERVE_SPACE);
338        }
339        'reso'         {
340            lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
341            parser_nasm->state = INSTRUCTION;
342            RETURN(RESERVE_SPACE);
343        }
344        'resy'         {
345            lvalp->int_info = 256;
346            parser_nasm->state = INSTRUCTION;
347            RETURN(RESERVE_SPACE);
348        }
349
350        'incbin'        { RETURN(INCBIN); }
351
352        'equ'           { RETURN(EQU); }
353
354        'times'         { RETURN(TIMES); }
355
356        'seg'           { RETURN(SEG); }
357        'wrt'           { RETURN(WRT); }
358
359        'abs'           { RETURN(ABS); }
360        'rel'           { RETURN(REL); }
361
362        'nosplit'       { RETURN(NOSPLIT); }
363        'strict'        { RETURN(STRICT); }
364
365        /* operators */
366        "<<"                    { RETURN(LEFT_OP); }
367        ">>"                    { RETURN(RIGHT_OP); }
368        "//"                    { RETURN(SIGNDIV); }
369        "%%"                    { RETURN(SIGNMOD); }
370        "$$"                    { RETURN(START_SECTION_ID); }
371        [-+|^*&/%~$():=,\[?]    { RETURN(s->tok[0]); }
372        "]"                     { RETURN(s->tok[0]); }
373
374        /* local label (.label) */
375        ("." | "@@") [a-zA-Z0-9_$#@~.?]+ {
376            RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 0, parser_nasm));
377        }
378
379        /* forced identifier */
380        "$" [a-zA-Z0-9_$#@~.?]+ {
381            if (TOK[1] == '.' ||
382                    (parser_nasm->tasm && TOK[1] == '@' && TOK[2] == '@')) {
383                /* handle like .label */
384                RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 1, parser_nasm));
385            }
386            lvalp->str_val = yasm__xstrndup(TOK+1, TOKLEN-1);
387            RETURN(ID);
388        }
389
390        /* identifier that may be a register, instruction, etc. */
391        [a-zA-Z_?@][a-zA-Z0-9_$#@~.?]* {
392            savech = s->tok[TOKLEN];
393            s->tok[TOKLEN] = '\0';
394            if (parser_nasm->state != INSTRUCTION) {
395                uintptr_t prefix;
396                switch (yasm_arch_parse_check_insnprefix
397                        (p_object->arch, TOK, TOKLEN, cur_line, &lvalp->bc,
398                         &prefix)) {
399                    case YASM_ARCH_INSN:
400                        parser_nasm->state = INSTRUCTION;
401                        s->tok[TOKLEN] = savech;
402                        RETURN(INSN);
403                    case YASM_ARCH_PREFIX:
404                        lvalp->arch_data = prefix;
405                        s->tok[TOKLEN] = savech;
406                        RETURN(PREFIX);
407                    default:
408                        break;
409                }
410            }
411            switch (yasm_arch_parse_check_regtmod
412                    (p_object->arch, TOK, TOKLEN, &lvalp->arch_data)) {
413                case YASM_ARCH_REG:
414                    s->tok[TOKLEN] = savech;
415                    RETURN(REG);
416                case YASM_ARCH_SEGREG:
417                    s->tok[TOKLEN] = savech;
418                    RETURN(SEGREG);
419                case YASM_ARCH_TARGETMOD:
420                    s->tok[TOKLEN] = savech;
421                    RETURN(TARGETMOD);
422                case YASM_ARCH_REGGROUP:
423                    if (parser_nasm->masm) {
424                        s->tok[TOKLEN] = savech;
425                        RETURN(REGGROUP);
426                    }
427                default:
428                    break;
429            }
430            if (parser_nasm->masm) {
431               if (!yasm__strcasecmp(TOK, "offset")) {
432                    s->tok[TOKLEN] = savech;
433                    RETURN(OFFSET);
434                }
435            } else if (parser_nasm->tasm) {
436                if (!yasm__strcasecmp(TOK, "shl")) {
437                    s->tok[TOKLEN] = savech;
438                    RETURN(LEFT_OP);
439                }
440                if (!yasm__strcasecmp(TOK, "shr")) {
441                    s->tok[TOKLEN] = savech;
442                    RETURN(RIGHT_OP);
443                }
444                if (!yasm__strcasecmp(TOK, "and")) {
445                    s->tok[TOKLEN] = savech;
446                    RETURN('&');
447                }
448                if (!yasm__strcasecmp(TOK, "or")) {
449                    s->tok[TOKLEN] = savech;
450                    RETURN('|');
451                }
452                if (!yasm__strcasecmp(TOK, "not")) {
453                    s->tok[TOKLEN] = savech;
454                    RETURN('~');
455                }
456                if (!yasm__strcasecmp(TOK, "low")) {
457                    s->tok[TOKLEN] = savech;
458                    RETURN(LOW);
459                }
460                if (!yasm__strcasecmp(TOK, "high")) {
461                    s->tok[TOKLEN] = savech;
462                    RETURN(HIGH);
463                }
464                if (!yasm__strcasecmp(TOK, "offset")) {
465                    s->tok[TOKLEN] = savech;
466                    RETURN(OFFSET);
467                }
468                if (!yasm__strcasecmp(TOK, "fword")) {
469                    s->tok[TOKLEN] = savech;
470                    lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
471                    RETURN(SIZE_OVERRIDE);
472                }
473                if (!yasm__strcasecmp(TOK, "df")) {
474                    s->tok[TOKLEN] = savech;
475                    lvalp->int_info = yasm_arch_wordsize(p_object->arch)*3;
476                    parser_nasm->state = INSTRUCTION;
477                    RETURN(DECLARE_DATA);
478                }
479                if (!yasm__strcasecmp(TOK, "label")) {
480                    s->tok[TOKLEN] = savech;
481                    RETURN(LABEL);
482                }
483                if (!yasm__strcasecmp(TOK, "dup")) {
484                    s->tok[TOKLEN] = savech;
485                    RETURN(DUP);
486                }
487            }
488            /* Propagate errors in case we got a warning from the arch */
489            yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
490            /* Just an identifier, return as such. */
491            s->tok[TOKLEN] = savech;
492            lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
493            RETURN(ID);
494        }
495
496        ";" (any \ [\000])*     { goto scan; }
497
498        ws+                     { goto scan; }
499
500        [\000]                  { goto endofinput; }
501
502        any {
503            yasm_warn_set(YASM_WARN_UNREC_CHAR,
504                          N_("ignoring unrecognized character `%s'"),
505                          yasm__conv_unprint(s->tok[0]));
506            goto scan;
507        }
508    */
509
510    /* %line linenum+lineinc filename */
511linechg:
512    SCANINIT();
513    if (*cursor == '\0')
514        goto endofinput;
515
516    /*!re2c
517        digit+ {
518            linechg_numcount++;
519            savech = s->tok[TOKLEN];
520            s->tok[TOKLEN] = '\0';
521            lvalp->intn = yasm_intnum_create_dec(TOK);
522            s->tok[TOKLEN] = savech;
523            RETURN(INTNUM);
524        }
525
526        [\000] { goto endofinput; }
527
528        "+" {
529            RETURN(s->tok[0]);
530        }
531
532        ws+ {
533            if (linechg_numcount == 2) {
534                parser_nasm->state = LINECHG2;
535                goto linechg2;
536            }
537            goto linechg;
538        }
539
540        any {
541            yasm_warn_set(YASM_WARN_UNREC_CHAR,
542                          N_("ignoring unrecognized character `%s'"),
543                          yasm__conv_unprint(s->tok[0]));
544            goto linechg;
545        }
546    */
547
548linechg2:
549    SCANINIT();
550    if (*cursor == '\0')
551        goto endofinput;
552
553    /*!re2c
554        [\000] { goto endofinput; }
555
556        "\r" { goto linechg2; }
557
558        (any \ [\000])+ {
559            parser_nasm->state = LINECHG;
560            lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
561            RETURN(FILENAME);
562        }
563    */
564
565    /* directive: [name value] */
566directive:
567    SCANINIT();
568    if (*cursor == '\0')
569        goto endofinput;
570
571    /*!re2c
572        [\]\000] { goto endofinput; }
573
574        [a-zA-Z_][a-zA-Z_0-9]* {
575            lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
576            if (yasm__strcasecmp(lvalp->str_val, "section") == 0 ||
577                yasm__strcasecmp(lvalp->str_val, "segment") == 0)
578                parser_nasm->state = SECTION_DIRECTIVE;
579            else
580                parser_nasm->state = DIRECTIVE2;
581            RETURN(DIRECTIVE_NAME);
582        }
583
584        any {
585            yasm_warn_set(YASM_WARN_UNREC_CHAR,
586                          N_("ignoring unrecognized character `%s'"),
587                          yasm__conv_unprint(s->tok[0]));
588            goto directive;
589        }
590    */
591
592    /* section directive (the section name portion thereof) */
593section_directive:
594    SCANINIT();
595    if (*cursor == '\0')
596        goto endofinput;
597
598    /*!re2c
599        [a-zA-Z0-9_$#@~.?-]+ {
600            lvalp->str.contents = yasm__xstrndup(TOK, TOKLEN);
601            lvalp->str.len = TOKLEN;
602            parser_nasm->state = DIRECTIVE2;
603            RETURN(STRING);
604        }
605
606        quot            {
607            parser_nasm->state = DIRECTIVE2;
608            endch = s->tok[0];
609            goto stringconst;
610        }
611
612        ws+             {
613            parser_nasm->state = DIRECTIVE2;
614            goto section_directive;
615        }
616
617        [\]\000]        { goto endofinput; }
618
619        any {
620            yasm_warn_set(YASM_WARN_UNREC_CHAR,
621                          N_("ignoring unrecognized character `%s'"),
622                          yasm__conv_unprint(s->tok[0]));
623            goto section_directive;
624        }
625    */
626
627    /* inner part of directive */
628directive2:
629    SCANINIT();
630    if (*cursor == '\0')
631        goto endofinput;
632
633    /*!re2c
634        /* standard decimal integer */
635        digit+ {
636            savech = s->tok[TOKLEN];
637            s->tok[TOKLEN] = '\0';
638            lvalp->intn = yasm_intnum_create_dec(TOK);
639            s->tok[TOKLEN] = savech;
640            RETURN(INTNUM);
641        }
642        /* 10010011b - binary number */
643
644        [01] bindigit* 'b' {
645            s->tok[TOKLEN-1] = '\0'; /* strip off 'b' */
646            lvalp->intn = yasm_intnum_create_bin(TOK);
647            RETURN(INTNUM);
648        }
649
650        /* 777q or 777o - octal number */
651        [0-7] octdigit* [qQoO] {
652            s->tok[TOKLEN-1] = '\0'; /* strip off 'q' or 'o' */
653            lvalp->intn = yasm_intnum_create_oct(TOK);
654            RETURN(INTNUM);
655        }
656
657        /* 0AAh form of hexidecimal number */
658        digit hexdigit* 'h' {
659            s->tok[TOKLEN-1] = '\0'; /* strip off 'h' */
660            lvalp->intn = yasm_intnum_create_hex(TOK);
661            RETURN(INTNUM);
662        }
663
664        /* $0AA and 0xAA forms of hexidecimal number */
665        (("$" digit) | '0x') hexdigit+ {
666            savech = s->tok[TOKLEN];
667            s->tok[TOKLEN] = '\0';
668            if (s->tok[1] == 'x' || s->tok[1] == 'X')
669                /* skip 0 and x */
670                lvalp->intn = yasm_intnum_create_hex(TOK+2);
671            else
672                /* don't skip 0 */
673                lvalp->intn = yasm_intnum_create_hex(TOK+1);
674            s->tok[TOKLEN] = savech;
675            RETURN(INTNUM);
676        }
677
678        /* string/character constant values */
679        quot {
680            endch = s->tok[0];
681            goto stringconst;
682        }
683
684        /* operators */
685        "<<"                    { RETURN(LEFT_OP); }
686        ">>"                    { RETURN(RIGHT_OP); }
687        "//"                    { RETURN(SIGNDIV); }
688        "%%"                    { RETURN(SIGNMOD); }
689        [-+|^*&/%~$():=,\[]     { RETURN(s->tok[0]); }
690
691        /* handle ] for directives */
692        "]"                     { goto endofinput; }
693
694        /* forced identifier; within directive, don't strip '$', this is
695         * handled later.
696         */
697        "$" [a-zA-Z0-9_$#@~.?]+ {
698            lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
699            RETURN(ID);
700        }
701
702        /* identifier; within directive, no local label mechanism */
703        [a-zA-Z_.?][a-zA-Z0-9_$#@~.?]* {
704            savech = s->tok[TOKLEN];
705            s->tok[TOKLEN] = '\0';
706            switch (yasm_arch_parse_check_regtmod
707                    (p_object->arch, TOK, TOKLEN, &lvalp->arch_data)) {
708                case YASM_ARCH_REG:
709                    s->tok[TOKLEN] = savech;
710                    RETURN(REG);
711                default:
712                    s->tok[TOKLEN] = savech;
713            }
714            /* Propagate errors in case we got a warning from the arch */
715            yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
716            /* Just an identifier, return as such. */
717            lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
718            RETURN(ID);
719        }
720
721        ";" (any \ [\000])*     { goto directive2; }
722
723        ws+                     { goto directive2; }
724
725        [\000]                  { goto endofinput; }
726
727        any {
728            yasm_warn_set(YASM_WARN_UNREC_CHAR,
729                          N_("ignoring unrecognized character `%s'"),
730                          yasm__conv_unprint(s->tok[0]));
731            goto scan;
732        }
733     */
734
735    /* string/character constant values */
736stringconst:
737    strbuf = yasm_xmalloc(STRBUF_ALLOC_SIZE);
738    strbuf_size = STRBUF_ALLOC_SIZE;
739    count = 0;
740
741stringconst_scan:
742    SCANINIT();
743    if (*cursor == '\0')
744        goto stringconst_error;
745
746    /*!re2c
747        [\000]  { goto stringconst_error; }
748
749        "''" | '""'     {
750            if (endch != s->tok[0]) {
751                strbuf[count++] = s->tok[0];
752                if (count >= strbuf_size) {
753                    strbuf = yasm_xrealloc(strbuf,
754                                           strbuf_size + STRBUF_ALLOC_SIZE);
755                    strbuf_size += STRBUF_ALLOC_SIZE;
756                }
757            } else if (!parser_nasm->tasm) {
758                YYCURSOR--;
759                goto stringconst_end;
760            }
761            strbuf[count++] = s->tok[0];
762            if (count >= strbuf_size) {
763                strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE);
764                strbuf_size += STRBUF_ALLOC_SIZE;
765            }
766            goto stringconst_scan;
767        }
768
769        any     {
770            if (s->tok[0] == endch)
771                goto stringconst_end;
772
773            strbuf[count++] = s->tok[0];
774            if (count >= strbuf_size) {
775                strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE);
776                strbuf_size += STRBUF_ALLOC_SIZE;
777            }
778
779            goto stringconst_scan;
780        }
781    */
782
783stringconst_error:
784    yasm_error_set(YASM_ERROR_SYNTAX, N_("unterminated string"));
785
786stringconst_end:
787    strbuf[count] = '\0';
788    lvalp->str.contents = (char *)strbuf;
789    lvalp->str.len = count;
790    RETURN(STRING);
791
792endofinput:
793    parser_nasm->state = INITIAL;
794    RETURN(s->tok[0]);
795}
796