123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680 |
- /*
- * NASM-compatible parser
- *
- * Copyright (C) 2001-2007 Peter Johnson, Michael Urman
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include <util.h>
- #include <libyasm.h>
- #include <math.h>
- #include "modules/parsers/nasm/nasm-parser.h"
- #include "modules/preprocs/nasm/nasm.h"
- typedef enum {
- NORM_EXPR,
- DIR_EXPR, /* Can't have seg:off or WRT anywhere */
- DV_EXPR /* Can't have registers anywhere */
- } expr_type;
- static yasm_bytecode *parse_line(yasm_parser_nasm *parser_nasm);
- static int parse_directive_valparams(yasm_parser_nasm *parser_nasm,
- /*@out@*/ yasm_valparamhead *vps);
- static yasm_bytecode *parse_times(yasm_parser_nasm *parser_nasm);
- static yasm_bytecode *parse_exp(yasm_parser_nasm *parser_nasm);
- static yasm_bytecode *parse_instr(yasm_parser_nasm *parser_nasm);
- static yasm_insn_operand *parse_operand(yasm_parser_nasm *parser_nasm);
- static yasm_insn_operand *parse_memaddr(yasm_parser_nasm *parser_nasm);
- static yasm_expr *parse_expr(yasm_parser_nasm *parser_nasm, expr_type type);
- static yasm_expr *parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type);
- static yasm_expr *parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type);
- static yasm_expr *parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type);
- static yasm_expr *parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type);
- static yasm_expr *parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type);
- static yasm_expr *parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type);
- static yasm_expr *parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type);
- static yasm_expr *parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type);
- static void nasm_parser_directive
- (yasm_parser_nasm *parser_nasm, const char *name,
- /*@null@*/ yasm_valparamhead *valparams,
- /*@null@*/ yasm_valparamhead *objext_valparams);
- static void set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name);
- static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
- unsigned int size);
- static void yasm_ea_set_implicit_size_segment(yasm_parser_nasm *parser_nasm,
- yasm_effaddr *ea, yasm_expr *e)
- {
- if (parser_nasm->tasm) {
- const char *segment = yasm_expr_segment(e);
- ea->data_len = yasm_expr_size(e);
- if (segment) {
- const char *segreg = tasm_get_segment_register(segment);
- if (segreg)
- yasm_arch_parse_check_regtmod(p_object->arch, segreg,
- strlen(segreg), &ea->segreg);
- }
- }
- }
- #define is_eol_tok(tok) ((tok) == 0)
- #define is_eol() is_eol_tok(curtok)
- #define get_next_token() (curtok = nasm_parser_lex(&curval, parser_nasm))
- static void
- get_peek_token(yasm_parser_nasm *parser_nasm)
- {
- char savech = parser_nasm->tokch;
- if (parser_nasm->peek_token != NONE)
- yasm_internal_error(N_("only can have one token of lookahead"));
- parser_nasm->peek_token =
- nasm_parser_lex(&parser_nasm->peek_tokval, parser_nasm);
- parser_nasm->peek_tokch = parser_nasm->tokch;
- parser_nasm->tokch = savech;
- }
- static void
- destroy_curtok_(yasm_parser_nasm *parser_nasm)
- {
- if (curtok < 256)
- ;
- else switch ((enum tokentype)curtok) {
- case INTNUM:
- yasm_intnum_destroy(curval.intn);
- break;
- case FLTNUM:
- yasm_floatnum_destroy(curval.flt);
- break;
- case DIRECTIVE_NAME:
- case FILENAME:
- case ID:
- case LOCAL_ID:
- case SPECIAL_ID:
- case NONLOCAL_ID:
- yasm_xfree(curval.str_val);
- break;
- case STRING:
- yasm_xfree(curval.str.contents);
- break;
- case INSN:
- yasm_bc_destroy(curval.bc);
- break;
- default:
- break;
- }
- curtok = NONE; /* sanity */
- }
- #define destroy_curtok() destroy_curtok_(parser_nasm)
- /* Eat all remaining tokens to EOL, discarding all of them. If there's any
- * intervening tokens, generates an error (junk at end of line).
- */
- static void
- demand_eol_(yasm_parser_nasm *parser_nasm)
- {
- if (is_eol())
- return;
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("junk at end of line, first unrecognized character is `%c'"),
- parser_nasm->tokch);
- do {
- destroy_curtok();
- get_next_token();
- } while (!is_eol());
- }
- #define demand_eol() demand_eol_(parser_nasm)
- static const char *
- describe_token(int token)
- {
- static char strch[] = "` '";
- const char *str;
- switch (token) {
- case 0: str = "end of line"; break;
- case INTNUM: str = "integer"; break;
- case FLTNUM: str = "floating point value"; break;
- case DIRECTIVE_NAME: str = "directive name"; break;
- case FILENAME: str = "filename"; break;
- case STRING: str = "string"; break;
- case SIZE_OVERRIDE: str = "size override"; break;
- case DECLARE_DATA: str = "DB/DW/etc."; break;
- case RESERVE_SPACE: str = "RESB/RESW/etc."; break;
- case INCBIN: str = "INCBIN"; break;
- case EQU: str = "EQU"; break;
- case TIMES: str = "TIMES"; break;
- case SEG: str = "SEG"; break;
- case WRT: str = "WRT"; break;
- case NOSPLIT: str = "NOSPLIT"; break;
- case STRICT: str = "STRICT"; break;
- case INSN: str = "instruction"; break;
- case PREFIX: str = "instruction prefix"; break;
- case REG: str = "register"; break;
- case REGGROUP: str = "register group"; break;
- case SEGREG: str = "segment register"; break;
- case TARGETMOD: str = "target modifier"; break;
- case LEFT_OP: str = "<<"; break;
- case RIGHT_OP: str = ">>"; break;
- case SIGNDIV: str = "//"; break;
- case SIGNMOD: str = "%%"; break;
- case START_SECTION_ID: str = "$$"; break;
- case ID: str = "identifier"; break;
- case LOCAL_ID: str = ".identifier"; break;
- case SPECIAL_ID: str = "..identifier"; break;
- case NONLOCAL_ID: str = "..@identifier"; break;
- case LINE: str = "%line"; break;
- default:
- strch[1] = token;
- str = strch;
- break;
- }
- return str;
- }
- static int
- expect_(yasm_parser_nasm *parser_nasm, int token)
- {
- if (curtok == token)
- return 1;
- yasm_error_set(YASM_ERROR_PARSE, "expected %s", describe_token(token));
- destroy_curtok();
- return 0;
- }
- #define expect(token) expect_(parser_nasm, token)
- void
- nasm_parser_parse(yasm_parser_nasm *parser_nasm)
- {
- unsigned char *line;
- while ((line = (unsigned char *)
- yasm_preproc_get_line(parser_nasm->preproc)) != NULL) {
- yasm_bytecode *bc = NULL, *temp_bc;
- parser_nasm->s.bot = line;
- parser_nasm->s.tok = line;
- parser_nasm->s.ptr = line;
- parser_nasm->s.cur = line;
- parser_nasm->s.lim = line + strlen((char *)line)+1;
- parser_nasm->s.top = parser_nasm->s.lim;
- get_next_token();
- if (!is_eol()) {
- bc = parse_line(parser_nasm);
- demand_eol();
- }
- if (parser_nasm->abspos) {
- /* If we're inside an absolute section, just add to the absolute
- * position rather than appending bytecodes to a section.
- * Only RES* are allowed in an absolute section, so this is easy.
- */
- if (bc) {
- /*@null@*/ const yasm_expr *numitems, *multiple;
- unsigned int itemsize;
- numitems = yasm_bc_reserve_numitems(bc, &itemsize);
- if (numitems) {
- yasm_expr *e;
- e = yasm_expr_create(YASM_EXPR_MUL,
- yasm_expr_expr(yasm_expr_copy(numitems)),
- yasm_expr_int(yasm_intnum_create_uint(itemsize)),
- cur_line);
- multiple = yasm_bc_get_multiple_expr(bc);
- if (multiple)
- e = yasm_expr_create_tree(e, YASM_EXPR_MUL,
- yasm_expr_copy(multiple),
- cur_line);
- parser_nasm->abspos = yasm_expr_create_tree(
- parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("only RES* allowed within absolute section"));
- yasm_bc_destroy(bc);
- }
- temp_bc = NULL;
- } else if (bc) {
- temp_bc = yasm_section_bcs_append(cursect, bc);
- if (temp_bc)
- parser_nasm->prev_bc = temp_bc;
- } else
- temp_bc = NULL;
- yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
- if (parser_nasm->save_input)
- yasm_linemap_add_source(parser_nasm->linemap, temp_bc,
- (char *)line);
- yasm_linemap_goto_next(parser_nasm->linemap);
- yasm_xfree(line);
- }
- }
- /* All parse_* functions expect to be called with curtok being their first
- * token. They should return with curtok being the token *after* their
- * information.
- */
- static yasm_bytecode *
- parse_line(yasm_parser_nasm *parser_nasm)
- {
- yasm_bytecode *bc;
- bc = parse_exp(parser_nasm);
- if (bc)
- return bc;
- switch (curtok) {
- case LINE: /* LINE INTNUM '+' INTNUM FILENAME */
- {
- yasm_intnum *line, *incr;
- char *filename;
- get_next_token();
- if (!expect(INTNUM)) return NULL;
- line = INTNUM_val;
- get_next_token();
- if (!expect('+')) return NULL;
- get_next_token();
- if (!expect(INTNUM)) return NULL;
- incr = INTNUM_val;
- get_next_token();
- if (!expect(FILENAME)) return NULL;
- filename = FILENAME_val;
- get_next_token();
- /* %line indicates the line number of the *next* line, so subtract
- * out the increment when setting the line number.
- */
- yasm_linemap_set(parser_nasm->linemap, filename, 0,
- yasm_intnum_get_uint(line) - yasm_intnum_get_uint(incr),
- yasm_intnum_get_uint(incr));
- yasm_intnum_destroy(line);
- yasm_intnum_destroy(incr);
- yasm_xfree(filename);
- return NULL;
- }
- case '[': /* [ directive ] */
- {
- char *dirname;
- yasm_valparamhead dir_vps;
- int have_vps = 1;
- parser_nasm->state = DIRECTIVE;
- get_next_token();
- if (!expect(DIRECTIVE_NAME))
- return NULL;
- dirname = DIRECTIVE_NAME_val;
- get_next_token();
- /* ignore [warning]. TODO: actually implement */
- if (yasm__strcasecmp(dirname, "warning") == 0) {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("[warning] directive not supported; ignored"));
- /* throw away the rest of the directive tokens */
- while (!is_eol() && curtok != ']')
- {
- destroy_curtok();
- get_next_token();
- }
- expect(']');
- get_next_token();
- return NULL;
- }
- if (curtok == ']' || curtok == ':')
- have_vps = 0;
- else if (!parse_directive_valparams(parser_nasm, &dir_vps)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("invalid arguments to [%s]"), dirname);
- yasm_xfree(dirname);
- return NULL;
- }
- if (curtok == ':') {
- yasm_valparamhead ext_vps;
- get_next_token();
- if (!parse_directive_valparams(parser_nasm, &ext_vps)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("invalid arguments to [%s]"), dirname);
- yasm_xfree(dirname);
- return NULL;
- }
- nasm_parser_directive(parser_nasm, dirname,
- have_vps ? &dir_vps : NULL, &ext_vps);
- } else
- nasm_parser_directive(parser_nasm, dirname,
- have_vps ? &dir_vps : NULL, NULL);
- yasm_xfree(dirname);
- expect(']');
- get_next_token();
- return NULL;
- }
- case TIMES: /* TIMES expr exp */
- get_next_token();
- return parse_times(parser_nasm);
- case ID:
- case SPECIAL_ID:
- case NONLOCAL_ID:
- case LOCAL_ID:
- {
- char *name = ID_val;
- int local = parser_nasm->tasm
- ? (curtok == ID || curtok == LOCAL_ID ||
- (curtok == SPECIAL_ID && name[0] == '@'))
- : (curtok != ID);
- unsigned int size = 0;
- get_next_token();
- if (is_eol()) {
- /* label alone on the line */
- yasm_warn_set(YASM_WARN_ORPHAN_LABEL,
- N_("label alone on a line without a colon might be in error"));
- if (!local)
- set_nonlocal_label(parser_nasm, name);
- define_label(parser_nasm, name, 0);
- return NULL;
- }
- if (curtok == ':')
- get_next_token();
- if (curtok == EQU || (parser_nasm->tasm && curtok == '=')) {
- /* label EQU expr */
- yasm_expr *e;
- get_next_token();
- if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
- size = SIZE_OVERRIDE_val;
- get_next_token();
- }
- e = parse_expr(parser_nasm, NORM_EXPR);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after %s"), "EQU");
- yasm_xfree(name);
- return NULL;
- }
- yasm_symtab_define_equ(p_symtab, name, e, cur_line);
- yasm_xfree(name);
- return NULL;
- }
- if (parser_nasm->tasm && curtok == LABEL)
- get_next_token();
- if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
- size = SIZE_OVERRIDE_val;
- get_next_token();
- }
- if (!local)
- set_nonlocal_label(parser_nasm, name);
- if (is_eol()) {
- define_label(parser_nasm, name, size);
- return NULL;
- }
- if (curtok == TIMES) {
- define_label(parser_nasm, name, size);
- get_next_token();
- return parse_times(parser_nasm);
- }
- bc = parse_exp(parser_nasm);
- if (!parser_nasm->tasm && !bc)
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("instruction expected after label"));
- if (parser_nasm->tasm && bc && !size)
- size = yasm_bc_elem_size(bc);
- define_label(parser_nasm, name, size);
- return bc;
- }
- default:
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("label or instruction expected at start of line"));
- return NULL;
- }
- }
- static int
- parse_directive_valparams(yasm_parser_nasm *parser_nasm,
- /*@out@*/ yasm_valparamhead *vps)
- {
- yasm_vps_initialize(vps);
- for (;;) {
- yasm_valparam *vp;
- yasm_expr *e;
- char *id = NULL;
- /* Look for value first */
- if (curtok == ID) {
- get_peek_token(parser_nasm);
- if (parser_nasm->peek_token == '=') {
- id = ID_val;
- get_next_token(); /* id */
- get_next_token(); /* '=' */
- }
- }
- /* Look for parameter */
- switch (curtok) {
- case STRING:
- vp = yasm_vp_create_string(id, STRING_val.contents);
- get_next_token();
- break;
- case ID:
- /* We need a peek token, but avoid error if we have one
- * already; we need to work whether or not we hit the
- * "value=" if test above.
- *
- * We cheat and peek ahead to see if this is just an ID or
- * the ID is part of an expression. We assume a + or - means
- * that it's part of an expression (e.g. "x+y" is parsed as
- * the expression "x+y" and not as "x", "+y").
- */
- if (parser_nasm->peek_token == NONE)
- get_peek_token(parser_nasm);
- switch (parser_nasm->peek_token) {
- case '|': case '^': case '&': case LEFT_OP: case RIGHT_OP:
- case '+': case '-':
- case '*': case '/': case '%': case SIGNDIV: case SIGNMOD:
- break;
- default:
- /* Just an id */
- vp = yasm_vp_create_id(id, ID_val, '$');
- get_next_token();
- goto next;
- }
- /*@fallthrough@*/
- default:
- e = parse_expr(parser_nasm, DIR_EXPR);
- if (!e) {
- yasm_vps_delete(vps);
- return 0;
- }
- vp = yasm_vp_create_expr(id, e);
- break;
- }
- next:
- yasm_vps_append(vps, vp);
- if (curtok == ',')
- get_next_token();
- if (curtok == ']' || curtok == ':' || is_eol())
- return 1;
- }
- }
- static yasm_bytecode *
- parse_times(yasm_parser_nasm *parser_nasm)
- {
- yasm_expr *multiple;
- yasm_bytecode *bc;
- multiple = parse_bexpr(parser_nasm, DV_EXPR);
- if (!multiple) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("expression expected after %s"),
- "TIMES");
- return NULL;
- }
- bc = parse_exp(parser_nasm);
- if (!bc) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("instruction expected after TIMES expression"));
- yasm_expr_destroy(multiple);
- return NULL;
- }
- yasm_bc_set_multiple(bc, multiple);
- return bc;
- }
- static yasm_bytecode *
- parse_exp(yasm_parser_nasm *parser_nasm)
- {
- yasm_bytecode *bc;
- bc = parse_instr(parser_nasm);
- if (bc)
- return bc;
- switch (curtok) {
- case DECLARE_DATA:
- {
- unsigned int size = DECLARE_DATA_val/8;
- yasm_datavalhead dvs;
- yasm_dataval *dv;
- yasm_expr *e, *e2;
- get_next_token();
- yasm_dvs_initialize(&dvs);
- for (;;) {
- if (curtok == STRING) {
- /* Peek ahead to see if we're in an expr. If we're not,
- * then generate a real string dataval.
- */
- get_peek_token(parser_nasm);
- if (parser_nasm->peek_token == ','
- || is_eol_tok(parser_nasm->peek_token)) {
- dv = yasm_dv_create_string(STRING_val.contents,
- STRING_val.len);
- get_next_token();
- goto dv_done;
- }
- }
- if (curtok == '?') {
- yasm_dvs_delete(&dvs);
- get_next_token();
- if (! is_eol_tok(curtok)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("can not handle more than one '?'"));
- return NULL;
- }
- return yasm_bc_create_reserve(
- p_expr_new_ident(yasm_expr_int(
- yasm_intnum_create_uint(1))),
- size, cur_line);
- }
- if (!(e = parse_bexpr(parser_nasm, DV_EXPR))) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression or string expected"));
- yasm_dvs_delete(&dvs);
- return NULL;
- }
- if (curtok == DUP) {
- get_next_token();
- if (curtok != '(') {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected ( after DUP"));
- goto error;
- }
- get_next_token();
- if (curtok == '?') {
- get_next_token();
- if (curtok != ')') {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected ) after DUPlicated expression"));
- goto error;
- }
- get_next_token();
- if (! is_eol_tok(curtok)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("can not handle more than one '?'"));
- goto error;
- }
- yasm_dvs_delete(&dvs);
- return yasm_bc_create_reserve(e, size, cur_line);
- } else if ((e2 = parse_bexpr(parser_nasm, DV_EXPR))) {
- if (curtok != ')') {
- yasm_expr_destroy(e2);
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected ) after DUPlicated expression"));
- goto error;
- }
- get_next_token();
- dv = yasm_dv_create_expr(e2);
- yasm_dv_set_multiple(dv, e);
- } else {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression or string expected"));
- error:
- yasm_expr_destroy(e);
- yasm_dvs_delete(&dvs);
- return NULL;
- }
- } else
- dv = yasm_dv_create_expr(e);
- dv_done:
- yasm_dvs_append(&dvs, dv);
- if (is_eol())
- break;
- if (!expect(',')) {
- yasm_dvs_delete(&dvs);
- return NULL;
- }
- get_next_token();
- if (is_eol()) /* allow trailing , on list */
- break;
- }
- return yasm_bc_create_data(&dvs, size, 0, p_object->arch,
- cur_line);
- }
- case RESERVE_SPACE:
- {
- unsigned int size = RESERVE_SPACE_val/8;
- yasm_expr *e;
- get_next_token();
- e = parse_bexpr(parser_nasm, DV_EXPR);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected after %s"), "RESx");
- return NULL;
- }
- return yasm_bc_create_reserve(e, size, cur_line);
- }
- case INCBIN:
- {
- char *filename;
- yasm_expr *start = NULL, *maxlen = NULL;
- get_next_token();
- if (!expect(STRING)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("filename string expected after INCBIN"));
- return NULL;
- }
- filename = STRING_val.contents;
- get_next_token();
- /* optional start expression */
- if (curtok == ',')
- get_next_token();
- if (is_eol())
- goto incbin_done;
- start = parse_bexpr(parser_nasm, DV_EXPR);
- if (!start) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected for INCBIN start"));
- return NULL;
- }
- /* optional maxlen expression */
- if (curtok == ',')
- get_next_token();
- if (is_eol())
- goto incbin_done;
- maxlen = parse_bexpr(parser_nasm, DV_EXPR);
- if (!maxlen) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expression expected for INCBIN maximum length"));
- return NULL;
- }
- incbin_done:
- return yasm_bc_create_incbin(filename, start, maxlen,
- parser_nasm->linemap, cur_line);
- }
- default:
- return NULL;
- }
- }
- static yasm_bytecode *
- parse_instr(yasm_parser_nasm *parser_nasm)
- {
- yasm_bytecode *bc;
- switch (curtok) {
- case INSN:
- {
- yasm_insn *insn;
- bc = INSN_val;
- insn = yasm_bc_get_insn(bc);
- get_next_token();
- if (is_eol())
- return bc; /* no operands */
- /* parse operands */
- for (;;) {
- yasm_insn_operand *op = parse_operand(parser_nasm);
- if (!op) {
- if (insn->num_operands == 0)
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("unexpected %s after instruction"),
- describe_token(curtok));
- else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected operand, got %s"),
- describe_token(curtok));
- yasm_bc_destroy(bc);
- return NULL;
- }
- yasm_insn_ops_append(insn, op);
- if (is_eol())
- break;
- if (!expect(',')) {
- yasm_bc_destroy(bc);
- return NULL;
- }
- get_next_token();
- }
- return bc;
- }
- case PREFIX:
- {
- uintptr_t prefix = PREFIX_val;
- get_next_token();
- bc = parse_instr(parser_nasm);
- if (!bc)
- bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
- yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
- return bc;
- }
- case SEGREG:
- {
- uintptr_t segreg = SEGREG_val;
- get_next_token();
- bc = parse_instr(parser_nasm);
- if (!bc)
- bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
- yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), segreg);
- return bc;
- }
- default:
- return NULL;
- }
- }
- static yasm_insn_operand *
- parse_operand(yasm_parser_nasm *parser_nasm)
- {
- yasm_insn_operand *op;
- switch (curtok) {
- case '[':
- {
- get_next_token();
- op = parse_memaddr(parser_nasm);
- expect(']');
- get_next_token();
- if (!op) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("memory address expected"));
- return NULL;
- }
- if (parser_nasm->tasm && !is_eol() && curtok != ',') {
- yasm_expr *e = NULL, *f;
- yasm_effaddr *ea;
- switch (op->type) {
- case YASM_INSN__OPERAND_IMM:
- e = op->data.val;
- break;
- case YASM_INSN__OPERAND_MEMORY:
- if (op->data.ea->disp.rel) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("relative adressing not supported\n"));
- return NULL;
- }
- e = yasm_expr_copy(op->data.ea->disp.abs);
- yasm_arch_ea_destroy(p_object->arch, op->data.ea);
- break;
- case YASM_INSN__OPERAND_REG:
- case YASM_INSN__OPERAND_SEGREG:
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("register adressing not supported\n"));
- return NULL;
- }
- yasm_xfree(op);
- f = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!f) {
- yasm_expr_destroy(e);
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after ]"));
- return NULL;
- }
- e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
- ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- op = yasm_operand_create_mem(ea);
- }
- return op;
- }
- case OFFSET:
- {
- yasm_insn_operand *op2;
- get_next_token();
- if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "flat")) {
- get_next_token();
- if (curtok == ':') {
- get_next_token();
- }
- }
- op = parse_operand(parser_nasm);
- if (!op) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("memory address expected"));
- return NULL;
- }
- if (op->type == YASM_INSN__OPERAND_IMM)
- return op;
- if (op->type != YASM_INSN__OPERAND_MEMORY) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("OFFSET applied to non-memory operand"));
- return NULL;
- }
- if (op->data.ea->disp.rel) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("OFFSET applied to non-absolute memory operand"));
- return NULL;
- }
- if (op->data.ea->disp.abs)
- op2 = yasm_operand_create_imm(op->data.ea->disp.abs);
- else
- op2 = yasm_operand_create_imm(p_expr_new_ident(
- yasm_expr_int(yasm_intnum_create_uint(0))));
- yasm_xfree(op);
- return op2;
- }
- case SEGREG:
- {
- uintptr_t segreg = SEGREG_val;
- get_next_token();
- if (parser_nasm->tasm && curtok == ':') {
- get_next_token();
- op = parse_operand(parser_nasm);
- if (!op)
- return NULL;
- if (op->type == YASM_INSN__OPERAND_IMM) {
- yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch,
- op->data.val);
- yasm_insn_operand *op2;
- yasm_ea_set_implicit_size_segment(parser_nasm, ea,
- op->data.val);
- op2 = yasm_operand_create_mem(ea);
- op2->size = op->size;
- yasm_xfree(op);
- op = op2;
- }
- if (op->type != YASM_INSN__OPERAND_MEMORY) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("segment applied to non-memory operand"));
- return NULL;
- }
- yasm_ea_set_segreg(op->data.ea, segreg);
- return op;
- }
- op = yasm_operand_create_segreg(segreg);
- return op;
- }
- case REG:
- op = yasm_operand_create_reg(REG_val);
- get_next_token();
- return op;
- case REGGROUP:
- {
- unsigned long regindex;
- uintptr_t reg = REGGROUP_val;
- get_next_token(); /* REGGROUP */
- if (curtok != '(')
- return yasm_operand_create_reg(reg);
- get_next_token(); /* '(' */
- if (!expect(INTNUM)) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("integer register index expected"));
- return NULL;
- }
- regindex = yasm_intnum_get_uint(INTNUM_val);
- get_next_token(); /* INTNUM */
- if (!expect(')')) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("missing closing parenthesis for register index"));
- return NULL;
- }
- get_next_token(); /* ')' */
- reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
- if (reg == 0) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
- regindex);
- return NULL;
- }
- return yasm_operand_create_reg(reg);
- }
- case STRICT:
- get_next_token();
- op = parse_operand(parser_nasm);
- if (op)
- op->strict = 1;
- return op;
- case SIZE_OVERRIDE:
- {
- unsigned int size = SIZE_OVERRIDE_val;
- get_next_token();
- if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "ptr")) {
- get_next_token();
- }
- op = parse_operand(parser_nasm);
- if (!op)
- return NULL;
- if (op->type == YASM_INSN__OPERAND_REG &&
- yasm_arch_get_reg_size(p_object->arch, op->data.reg) != size)
- yasm_error_set(YASM_ERROR_TYPE,
- N_("cannot override register size"));
- else {
- /* Silently override others unless a warning is turned on.
- * This is to allow overrides such as:
- * %define arg1 dword [bp+4]
- * cmp word arg1, 2
- * Which expands to:
- * cmp word dword [bp+4], 2
- */
- if (op->size != 0) {
- if (op->size != size)
- yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
- N_("overriding operand size from %u-bit to %u-bit"),
- op->size, size);
- else
- yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
- N_("double operand size override"));
- }
- op->size = size;
- }
- return op;
- }
- case TARGETMOD:
- {
- uintptr_t tmod = TARGETMOD_val;
- get_next_token();
- op = parse_operand(parser_nasm);
- if (op)
- op->targetmod = tmod;
- return op;
- }
- case ID:
- case LOCAL_ID:
- case NONLOCAL_ID:
- if (parser_nasm->tasm) {
- get_peek_token(parser_nasm);
- if (parser_nasm->peek_token == '[') {
- yasm_symrec *sym = yasm_symtab_use(p_symtab, ID_val,
- cur_line);
- yasm_expr *e = p_expr_new_ident(yasm_expr_sym(sym)), *f;
- yasm_effaddr *ea;
- yasm_xfree(ID_val);
- get_next_token();
- get_next_token();
- f = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!f) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after ["));
- return NULL;
- }
- e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
- if (!expect(']')) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("missing closing bracket"));
- return NULL;
- }
- get_next_token();
- ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- op = yasm_operand_create_mem(ea);
- return op;
- }
- }
- /* Fallthrough */
- default:
- {
- yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!e)
- return NULL;
- if (curtok != ':') {
- if (parser_nasm->tasm && yasm_expr_size(e)) {
- yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- op = yasm_operand_create_mem(ea);
- return op;
- } else if (curtok == '[') {
- yasm_expr *f;
- yasm_effaddr *ea;
- yasm_insn_operand *op2;
- op = parse_operand(parser_nasm);
- if (!op)
- return NULL;
-
- f = op->data.ea->disp.abs;
- e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
- ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- op2 = yasm_operand_create_mem(ea);
- yasm_xfree(op);
- return op2;
- } else {
- return yasm_operand_create_imm(e);
- }
- } else {
- yasm_expr *off;
- get_next_token();
- off = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!off) {
- yasm_expr_destroy(e);
- return NULL;
- }
- op = yasm_operand_create_imm(off);
- op->seg = e;
- return op;
- }
- }
- }
- }
- /* memory addresses */
- static yasm_insn_operand *
- parse_memaddr(yasm_parser_nasm *parser_nasm)
- {
- yasm_insn_operand *op;
- switch (curtok) {
- case SEGREG:
- {
- uintptr_t segreg = SEGREG_val;
- get_next_token();
- if (!expect(':')) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("`:' required after segment register"));
- return NULL;
- }
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op)
- yasm_ea_set_segreg(op->data.ea, segreg);
- return op;
- }
- case SIZE_OVERRIDE:
- {
- unsigned int size = SIZE_OVERRIDE_val;
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op)
- op->data.ea->disp.size = size;
- return op;
- }
- case NOSPLIT:
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op)
- op->data.ea->nosplit = 1;
- return op;
- case REL:
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op) {
- op->data.ea->pc_rel = 1;
- op->data.ea->not_pc_rel = 0;
- }
- return op;
- case ABS:
- get_next_token();
- op = parse_memaddr(parser_nasm);
- if (op) {
- op->data.ea->pc_rel = 0;
- op->data.ea->not_pc_rel = 1;
- }
- return op;
- default:
- {
- yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!e)
- return NULL;
- if (curtok != ':') {
- yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
- return yasm_operand_create_mem(ea);
- } else {
- yasm_effaddr *ea;
- yasm_expr *off;
- get_next_token();
- off = parse_bexpr(parser_nasm, NORM_EXPR);
- if (!off) {
- yasm_expr_destroy(e);
- return NULL;
- }
- ea = yasm_arch_ea_create(p_object->arch, off);
- yasm_ea_set_implicit_size_segment(parser_nasm, ea, off);
- op = yasm_operand_create_mem(ea);
- op->seg = e;
- return op;
- }
- }
- }
- }
- /* Expression grammar parsed is:
- *
- * expr : bexpr [ : bexpr ]
- * bexpr : expr0 [ WRT expr6 ]
- * expr0 : expr1 [ {|} expr1...]
- * expr1 : expr2 [ {^} expr2...]
- * expr2 : expr3 [ {&} expr3...]
- * expr3 : expr4 [ {<<,>>} expr4...]
- * expr4 : expr5 [ {+,-} expr5...]
- * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
- * expr6 : { ~,+,-,SEG } expr6
- * | (expr)
- * | symbol
- * | $
- * | number
- */
- #define parse_expr_common(leftfunc, tok, rightfunc, op) \
- do { \
- yasm_expr *e, *f; \
- e = leftfunc(parser_nasm, type); \
- if (!e) \
- return NULL; \
- \
- while (curtok == tok) { \
- get_next_token(); \
- f = rightfunc(parser_nasm, type); \
- if (!f) { \
- yasm_error_set(YASM_ERROR_SYNTAX, \
- N_("expected expression after %s"), \
- describe_token(op)); \
- yasm_expr_destroy(e); \
- return NULL; \
- } \
- e = p_expr_new_tree(e, op, f); \
- } \
- return e; \
- } while(0)
- static yasm_expr *
- parse_expr(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- switch (type) {
- case DIR_EXPR:
- /* directive expressions can't handle seg:off or WRT */
- return parse_expr0(parser_nasm, type);
- default:
- parse_expr_common(parse_bexpr, ':', parse_bexpr, YASM_EXPR_SEGOFF);
- }
- /*@notreached@*/
- return NULL;
- }
- static yasm_expr *
- parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- parse_expr_common(parse_expr0, WRT, parse_expr6, YASM_EXPR_WRT);
- }
- static yasm_expr *
- parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- parse_expr_common(parse_expr1, '|', parse_expr1, YASM_EXPR_OR);
- }
- static yasm_expr *
- parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- parse_expr_common(parse_expr2, '^', parse_expr2, YASM_EXPR_XOR);
- }
- static yasm_expr *
- parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- parse_expr_common(parse_expr3, '&', parse_expr3, YASM_EXPR_AND);
- }
- static yasm_expr *
- parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- yasm_expr *e, *f;
- e = parse_expr4(parser_nasm, type);
- if (!e)
- return NULL;
- while (curtok == LEFT_OP || curtok == RIGHT_OP) {
- int op = curtok;
- get_next_token();
- f = parse_expr4(parser_nasm, type);
- if (!f) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"),
- describe_token(op));
- yasm_expr_destroy(e);
- return NULL;
- }
- switch (op) {
- case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
- case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
- }
- }
- return e;
- }
- static yasm_expr *
- parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- yasm_expr *e, *f;
- e = parse_expr5(parser_nasm, type);
- if (!e)
- return NULL;
- while (curtok == '+' || curtok == '-') {
- int op = curtok;
- get_next_token();
- f = parse_expr5(parser_nasm, type);
- if (!f) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"),
- describe_token(op));
- yasm_expr_destroy(e);
- return NULL;
- }
- switch (op) {
- case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
- case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
- }
- }
- return e;
- }
- static yasm_expr *
- parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- yasm_expr *e, *f;
- e = parse_expr6(parser_nasm, type);
- if (!e)
- return NULL;
- while (curtok == '*' || curtok == '/' || curtok == '%'
- || curtok == SIGNDIV || curtok == SIGNMOD) {
- int op = curtok;
- get_next_token();
- f = parse_expr6(parser_nasm, type);
- if (!f) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"),
- describe_token(op));
- yasm_expr_destroy(e);
- return NULL;
- }
- switch (op) {
- case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
- case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
- case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
- case SIGNDIV: e = p_expr_new_tree(e, YASM_EXPR_SIGNDIV, f); break;
- case SIGNMOD: e = p_expr_new_tree(e, YASM_EXPR_SIGNMOD, f); break;
- }
- }
- return e;
- }
- static yasm_expr *
- parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
- {
- yasm_expr *e;
- yasm_symrec *sym;
- switch (curtok) {
- case '+':
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "`+'");
- }
- return e;
- case '-':
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "`-'");
- return NULL;
- }
- return p_expr_new_branch(YASM_EXPR_NEG, e);
- case '~':
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "`~'");
- return NULL;
- }
- return p_expr_new_branch(YASM_EXPR_NOT, e);
- case LOW:
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "LOW");
- return NULL;
- }
- return p_expr_new_tree(e, YASM_EXPR_AND,
- p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
- case HIGH:
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "HIGH");
- return NULL;
- }
- return p_expr_new_tree(
- p_expr_new_tree(e, YASM_EXPR_SHR,
- p_expr_new_ident(yasm_expr_int(
- yasm_intnum_create_uint(8)))),
- YASM_EXPR_AND,
- p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
- case SEG:
- get_next_token();
- e = parse_expr6(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "SEG");
- return NULL;
- }
- return p_expr_new_branch(YASM_EXPR_SEG, e);
- case '(':
- get_next_token();
- e = parse_expr(parser_nasm, type);
- if (!e) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("expected expression after %s"), "`('");
- return NULL;
- }
- if (!expect(')')) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
- return NULL;
- }
- get_next_token();
- return e;
- case INTNUM:
- e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
- get_next_token();
- return e;
- case REG:
- if (type == DV_EXPR) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("data values can't have registers"));
- return NULL;
- }
- e = p_expr_new_ident(yasm_expr_reg(REG_val));
- get_next_token();
- return e;
- }
- /* directives allow very little and handle IDs specially */
- if (type == DIR_EXPR) {
- switch (curtok) {
- case ID:
- sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
- e = p_expr_new_ident(yasm_expr_sym(sym));
- yasm_xfree(ID_val);
- break;
- default:
- return NULL;
- }
- } else switch (curtok) {
- case FLTNUM:
- e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
- break;
- case STRING:
- {
- yasm_intnum *intn;
- if (parser_nasm->tasm)
- intn = yasm_intnum_create_charconst_tasm(STRING_val.contents);
- else
- intn = yasm_intnum_create_charconst_nasm(STRING_val.contents);
- e = p_expr_new_ident(yasm_expr_int(intn));
- yasm_xfree(STRING_val.contents);
- break;
- }
- case SPECIAL_ID:
- sym = yasm_objfmt_get_special_sym(p_object, ID_val+2, "nasm");
- if (sym) {
- e = p_expr_new_ident(yasm_expr_sym(sym));
- yasm_xfree(ID_val);
- break;
- }
- /*@fallthrough@*/
- case ID:
- case LOCAL_ID:
- case NONLOCAL_ID:
- sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
- e = p_expr_new_ident(yasm_expr_sym(sym));
- yasm_xfree(ID_val);
- break;
- case '$':
- /* "$" references the current assembly position */
- if (parser_nasm->abspos)
- e = yasm_expr_copy(parser_nasm->abspos);
- else {
- sym = yasm_symtab_define_curpos(p_symtab, "$",
- parser_nasm->prev_bc, cur_line);
- e = p_expr_new_ident(yasm_expr_sym(sym));
- }
- break;
- case START_SECTION_ID:
- /* "$$" references the start of the current section */
- if (parser_nasm->absstart)
- e = yasm_expr_copy(parser_nasm->absstart);
- else {
- sym = yasm_symtab_define_label(p_symtab, "$$",
- yasm_section_bcs_first(cursect), 0, cur_line);
- e = p_expr_new_ident(yasm_expr_sym(sym));
- }
- break;
- default:
- return NULL;
- }
- get_next_token();
- return e;
- }
- static void
- set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name)
- {
- if (!parser_nasm->tasm || tasm_locals) {
- if (parser_nasm->locallabel_base)
- yasm_xfree(parser_nasm->locallabel_base);
- parser_nasm->locallabel_base_len = strlen(name);
- parser_nasm->locallabel_base =
- yasm_xmalloc(parser_nasm->locallabel_base_len+1);
- strcpy(parser_nasm->locallabel_base, name);
- }
- }
- static void
- define_label(yasm_parser_nasm *parser_nasm, char *name, unsigned int size)
- {
- yasm_symrec *symrec;
- if (parser_nasm->abspos)
- symrec = yasm_symtab_define_equ(p_symtab, name,
- yasm_expr_copy(parser_nasm->abspos),
- cur_line);
- else
- symrec = yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc,
- 1, cur_line);
- yasm_symrec_set_size(symrec, size);
- yasm_symrec_set_segment(symrec, tasm_segment);
- yasm_xfree(name);
- }
- static void
- dir_align(yasm_object *object, yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams, unsigned long line)
- {
- yasm_valparam *vp = yasm_vps_first(valparams);
- yasm_expr *boundval = yasm_vp_expr(vp, object->symtab, line);
- /*@depedent@*/ yasm_intnum *boundintn;
- /* Largest .align in the section specifies section alignment.
- * Note: this doesn't match NASM behavior, but is a lot more
- * intelligent!
- */
- if (boundval && (boundintn = yasm_expr_get_intnum(&boundval, 0))) {
- unsigned long boundint = yasm_intnum_get_uint(boundintn);
- /* Alignments must be a power of two. */
- if (is_exp2(boundint)) {
- if (boundint > yasm_section_get_align(object->cur_section))
- yasm_section_set_align(object->cur_section, boundint, line);
- }
- }
- /* As this directive is called only when nop is used as fill, always
- * use arch (nop) fill.
- */
- yasm_section_bcs_append(object->cur_section,
- yasm_bc_create_align(boundval, NULL, NULL,
- /*yasm_section_is_code(object->cur_section) ?*/
- yasm_arch_get_fill(object->arch)/* : NULL*/,
- line));
- }
- static void
- nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
- yasm_valparamhead *valparams,
- yasm_valparamhead *objext_valparams)
- {
- unsigned long line = cur_line;
- yasm_valparam *vp;
- if (!yasm_object_directive(p_object, name, "nasm", valparams,
- objext_valparams, line))
- ;
- else if (yasm__strcasecmp(name, "absolute") == 0) {
- if (!valparams) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("directive `%s' requires an argument"),
- "absolute");
- } else {
- vp = yasm_vps_first(valparams);
- if (parser_nasm->absstart)
- yasm_expr_destroy(parser_nasm->absstart);
- if (parser_nasm->abspos)
- yasm_expr_destroy(parser_nasm->abspos);
- parser_nasm->absstart = yasm_vp_expr(vp, p_object->symtab, line);
- parser_nasm->abspos = yasm_expr_copy(parser_nasm->absstart);
- cursect = NULL;
- parser_nasm->prev_bc = NULL;
- }
- } else if (yasm__strcasecmp(name, "align") == 0) {
- /* Really, we shouldn't end up with an align directive in an absolute
- * section (as it's supposed to be only used for nop fill), but handle
- * it gracefully anyway.
- */
- if (parser_nasm->abspos) {
- yasm_expr *boundval, *e;
- vp = yasm_vps_first(valparams);
- boundval = yasm_vp_expr(vp, p_object->symtab, line);
- e = yasm_expr_create_tree(
- yasm_expr_create_tree(yasm_expr_copy(parser_nasm->absstart),
- YASM_EXPR_SUB,
- yasm_expr_copy(parser_nasm->abspos),
- cur_line),
- YASM_EXPR_AND,
- yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(boundval),
- yasm_expr_int(yasm_intnum_create_uint(1)),
- cur_line),
- cur_line);
- parser_nasm->abspos = yasm_expr_create_tree(
- parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
- } else if (!valparams) {
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("directive `%s' requires an argument"), "align");
- } else
- dir_align(p_object, valparams, objext_valparams, line);
- } else if (yasm__strcasecmp(name, "default") == 0) {
- if (!valparams)
- ;
- else {
- vp = yasm_vps_first(valparams);
- while (vp) {
- const char *id = yasm_vp_id(vp);
- if (id) {
- if (yasm__strcasecmp(id, "rel") == 0)
- yasm_arch_set_var(p_object->arch, "default_rel", 1);
- else if (yasm__strcasecmp(id, "abs") == 0)
- yasm_arch_set_var(p_object->arch, "default_rel", 0);
- else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("unrecognized default `%s'"), id);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("unrecognized default value"));
- vp = yasm_vps_next(vp);
- }
- }
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive `%s'"),
- name);
- if (parser_nasm->absstart && cursect) {
- /* We switched to a new section. Get out of absolute section mode. */
- yasm_expr_destroy(parser_nasm->absstart);
- parser_nasm->absstart = NULL;
- if (parser_nasm->abspos) {
- yasm_expr_destroy(parser_nasm->abspos);
- parser_nasm->abspos = NULL;
- }
- }
- if (cursect) {
- /* In case cursect changed or a bytecode was added, update prev_bc. */
- parser_nasm->prev_bc = yasm_section_bcs_last(cursect);
- }
- if (valparams)
- yasm_vps_delete(valparams);
- if (objext_valparams)
- yasm_vps_delete(objext_valparams);
- }
- yasm_bytecode *
- gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr)
- {
- yasm_bytecode *bc = NULL;
- char *sinstr = (char *) instr;
- parser_nasm->s.bot = instr;
- parser_nasm->s.tok = instr;
- parser_nasm->s.ptr = instr;
- parser_nasm->s.cur = instr;
- parser_nasm->s.lim = instr + strlen(sinstr) + 1;
- parser_nasm->s.top = parser_nasm->s.lim;
- parser_nasm->peek_token = NONE;
- get_next_token();
- if (!is_eol()) {
- bc = parse_instr(parser_nasm);
- }
- return bc;
- }
|