a lower level.
To reduce code duplication, refactor several of the large if/else structures
into multiple functions with a lookup table.
Add support for registers to be used in directive expressions.
Allow directives to have underscores and numbers (still cannot start with
numbers).
svn path=/trunk/yasm/; revision=1757
* Call yasm_arch_parse_directive() instead of calling this function.
*/
int (*parse_directive) (yasm_arch *arch, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams,
yasm_object *object, unsigned long line);
* recognized, even if it wasn't valid.
*/
int yasm_arch_parse_directive(yasm_arch *arch, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams,
yasm_object *object, unsigned long line);
* Call yasm_dbgfmt_directive() instead of calling this function.
*/
int (*directive) (yasm_dbgfmt *dbgfmt, const char *name,
- yasm_section *sect, yasm_valparamhead *valparams,
+ yasm_section *sect,
+ /*@null@*/ yasm_valparamhead *valparams,
unsigned long line);
/** Module-level implementation of yasm_dbgfmt_generate().
* recognized even if it wasn't valid.
*/
int yasm_dbgfmt_directive(yasm_dbgfmt *dbgfmt, const char *name,
- yasm_section *sect, yasm_valparamhead *valparams,
+ yasm_section *sect,
+ /*@null@*/ yasm_valparamhead *valparams,
unsigned long line);
/** Generate debugging information bytecodes.
* Call yasm_objfmt_directive() instead of calling this function.
*/
int (*directive) (yasm_objfmt *objfmt, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams,
unsigned long line);
} yasm_objfmt_module;
* recognized, even if it wasn't valid.
*/
int yasm_objfmt_directive(yasm_objfmt *objfmt, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams,
unsigned long line);
static int
lc3b_parse_directive(/*@unused@*/ yasm_arch *arch,
/*@unused@*/ const char *name,
- /*@unused@*/ yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
/*@unused@*/ /*@null@*/
yasm_valparamhead *objext_valparams,
/*@unused@*/ yasm_object *object,
static int
x86_parse_directive(yasm_arch *arch, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@unused@*/ /*@null@*/
yasm_valparamhead *objext_valparams,
/*@unused@*/ yasm_object *object,
long lval;
if (yasm__strcasecmp(name, "bits") == 0) {
- if ((vp = yasm_vps_first(valparams)) && !vp->val &&
+ if (!valparams)
+ yasm_error_set(YASM_ERROR_VALUE, N_("[%s] requires an argument"),
+ "BITS");
+ else if ((vp = yasm_vps_first(valparams)) && !vp->val &&
vp->param != NULL &&
(intn = yasm_expr_get_intnum(&vp->param, 0)) != NULL &&
(lval = yasm_intnum_get_int(intn)) &&
const char *name, yasm_section *sect,
yasm_valparamhead *valparams, unsigned long line)
{
+ yasm_valparam *vp;
if (yasm__strcasecmp(name, "loc") == 0) {
/*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
dwarf2_section_data *dsd;
dwarf2_loc *loc = yasm_xmalloc(sizeof(dwarf2_loc));
/* File number (required) */
- yasm_valparam *vp = yasm_vps_first(valparams);
- if (!vp || !vp->param) {
+ if (!valparams || !(vp = yasm_vps_first(valparams)) || !vp->param) {
yasm_error_set(YASM_ERROR_SYNTAX, N_("file number required"));
yasm_xfree(loc);
return 0;
/*@dependent@*/ /*@null@*/ const yasm_intnum *file_intn;
size_t filenum;
- yasm_valparam *vp = yasm_vps_first(valparams);
+ if (!valparams) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"),
+ "FILE");
+ return 0;
+ }
+ vp = yasm_vps_first(valparams);
if (vp->val) {
/* Just a bare filename */
yasm_object_set_source_fn(dbgfmt_dwarf2->object, vp->val);
static int
bin_objfmt_directive(yasm_objfmt *objfmt, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@unused@*/ /*@null@*/
yasm_valparamhead *objext_valparams, unsigned long line)
{
if (yasm__strcasecmp(name, "org") == 0) {
/*@null@*/ yasm_expr *start = NULL;
+ if (!valparams) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"),
+ "ORG");
+ return 0;
+ }
+
/* ORG takes just a simple integer as param */
vp = yasm_vps_first(valparams);
if (vp->val)
static int
coff_objfmt_directive(/*@unused@*/ yasm_objfmt *objfmt,
/*@unused@*/ const char *name,
- /*@unused@*/ yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
/*@unused@*/ /*@null@*/
yasm_valparamhead *objext_valparams,
/*@unused@*/ unsigned long line)
static int
dbg_objfmt_directive(yasm_objfmt *objfmt, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams,
unsigned long line)
{
return sym;
}
-static int
-elf_objfmt_directive(yasm_objfmt *objfmt, const char *name,
- yasm_valparamhead *valparams,
- /*@unused@*/ /*@null@*/
- yasm_valparamhead *objext_valparams,
- unsigned long line)
+static void
+dir_type(yasm_objfmt_elf *objfmt_elf, yasm_valparam *vp, unsigned long line)
{
- yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
- yasm_symrec *sym;
- yasm_valparam *vp = yasm_vps_first(valparams);
char *symname = vp->val;
- elf_symtab_entry *entry;
+ /* Get symbol elf data */
+ yasm_symrec *sym = yasm_symtab_use(objfmt_elf->symtab, symname, line);
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
- if (!symname) {
- yasm_error_set(YASM_ERROR_SYNTAX, N_("Symbol name not specified"));
- return 0;
+ /* Create entry if necessary */
+ if (!entry) {
+ entry = elf_symtab_entry_create(
+ elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
}
- if (yasm__strcasecmp(name, "type") == 0) {
- /* Get symbol elf data */
- sym = yasm_symtab_use(objfmt_elf->symtab, symname, line);
- entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ /* Pull new type from val */
+ vp = yasm_vps_next(vp);
+ if (vp->val) {
+ if (yasm__strcasecmp(vp->val, "function") == 0)
+ elf_sym_set_type(entry, STT_FUNC);
+ else if (yasm__strcasecmp(vp->val, "object") == 0)
+ elf_sym_set_type(entry, STT_OBJECT);
+ else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized symbol type `%s'"), vp->val);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
+}
- /* Create entry if necessary */
- if (!entry) {
- entry = elf_symtab_entry_create(
- elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
- yasm_symrec_add_data(sym, &elf_symrec_data, entry);
- }
+static void
+dir_size(yasm_objfmt_elf *objfmt_elf, yasm_valparam *vp, unsigned long line)
+{
+ char *symname = vp->val;
+ /* Get symbol elf data */
+ yasm_symrec *sym = yasm_symtab_use(objfmt_elf->symtab, symname, line);
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
- /* Pull new type from val */
- vp = yasm_vps_next(vp);
- if (vp->val) {
- if (yasm__strcasecmp(vp->val, "function") == 0)
- elf_sym_set_type(entry, STT_FUNC);
- else if (yasm__strcasecmp(vp->val, "object") == 0)
- elf_sym_set_type(entry, STT_OBJECT);
- else
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("unrecognized symbol type `%s'"), vp->val);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
- } else if (yasm__strcasecmp(name, "size") == 0) {
- /* Get symbol elf data */
- sym = yasm_symtab_use(objfmt_elf->symtab, symname, line);
- entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ /* Create entry if necessary */
+ if (!entry) {
+ entry = elf_symtab_entry_create(
+ elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
- /* Create entry if necessary */
- if (!entry) {
- entry = elf_symtab_entry_create(
- elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
- yasm_symrec_add_data(sym, &elf_symrec_data, entry);
- }
+ /* Pull new size from either param (expr) or val */
+ vp = yasm_vps_next(vp);
+ if (vp->param) {
+ elf_sym_set_size(entry, vp->param);
+ vp->param = NULL;
+ } else if (vp->val)
+ elf_sym_set_size(entry, yasm_expr_create_ident(yasm_expr_sym(
+ yasm_symtab_use(objfmt_elf->symtab, vp->val, line)), line));
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
+}
- /* Pull new size from either param (expr) or val */
- vp = yasm_vps_next(vp);
- if (vp->param) {
- elf_sym_set_size(entry, vp->param);
- vp->param = NULL;
- } else if (vp->val)
- elf_sym_set_size(entry, yasm_expr_create_ident(yasm_expr_sym(
- yasm_symtab_use(objfmt_elf->symtab, vp->val, line)), line));
- else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
- } else if (yasm__strcasecmp(name, "weak") == 0) {
- sym = yasm_symtab_declare(objfmt_elf->symtab, symname, YASM_SYM_GLOBAL,
- line);
- elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK,
- 0, STV_DEFAULT, NULL, NULL);
- } else if (yasm__strcasecmp(name, "ident") == 0) {
- yasm_valparamhead sect_vps;
- yasm_datavalhead dvs;
- yasm_section *comment;
- yasm_valparam *vp2;
-
- /* Put ident data into .comment section */
- yasm_vps_initialize(§_vps);
- vp2 = yasm_vp_create(yasm__xstrdup(".comment"), NULL);
- yasm_vps_append(§_vps, vp2);
- comment = elf_objfmt_section_switch(objfmt, §_vps, NULL, line);
- yasm_vps_delete(§_vps);
-
- /* To match GAS output, if the comment section is empty, put an
- * initial 0 byte in the section.
- */
- if (yasm_section_bcs_first(comment)
- == yasm_section_bcs_last(comment)) {
- yasm_dvs_initialize(&dvs);
- yasm_dvs_append(&dvs, yasm_dv_create_expr(
- yasm_expr_create_ident(
- yasm_expr_int(yasm_intnum_create_uint(0)), line)));
- yasm_section_bcs_append(comment,
- yasm_bc_create_data(&dvs, 1, 0, objfmt_elf->arch, line));
- }
+static void
+dir_weak(yasm_objfmt_elf *objfmt_elf, yasm_valparam *vp, unsigned long line)
+{
+ char *symname = vp->val;
+ yasm_symrec *sym = yasm_symtab_declare(objfmt_elf->symtab, symname,
+ YASM_SYM_GLOBAL, line);
+ elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, 0,
+ STV_DEFAULT, NULL, NULL);
+}
+static void
+dir_ident(yasm_objfmt_elf *objfmt_elf, yasm_valparam *vp, unsigned long line)
+{
+ char *symname = vp->val;
+ yasm_valparamhead sect_vps;
+ yasm_datavalhead dvs;
+ yasm_section *comment;
+ yasm_valparam *vp2;
+
+ /* Put ident data into .comment section */
+ yasm_vps_initialize(§_vps);
+ vp2 = yasm_vp_create(yasm__xstrdup(".comment"), NULL);
+ yasm_vps_append(§_vps, vp2);
+ comment = elf_objfmt_section_switch((yasm_objfmt *)objfmt_elf, §_vps,
+ NULL, line);
+ yasm_vps_delete(§_vps);
+
+ /* To match GAS output, if the comment section is empty, put an
+ * initial 0 byte in the section.
+ */
+ if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) {
yasm_dvs_initialize(&dvs);
- do {
- yasm_dvs_append(&dvs, yasm_dv_create_string(vp->val,
- strlen(vp->val)));
- vp->val = NULL;
- } while ((vp = yasm_vps_next(vp)));
-
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ yasm_expr_create_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0)), line)));
yasm_section_bcs_append(comment,
- yasm_bc_create_data(&dvs, 1, 1, objfmt_elf->arch, line));
- } else
- return 1; /* unrecognized */
+ yasm_bc_create_data(&dvs, 1, 0, objfmt_elf->arch, line));
+ }
- return 0;
+ yasm_dvs_initialize(&dvs);
+ do {
+ yasm_dvs_append(&dvs, yasm_dv_create_string(vp->val, strlen(vp->val)));
+ vp->val = NULL;
+ } while ((vp = yasm_vps_next(vp)));
+
+ yasm_section_bcs_append(comment,
+ yasm_bc_create_data(&dvs, 1, 1, objfmt_elf->arch, line));
+}
+
+static int
+elf_objfmt_directive(yasm_objfmt *objfmt, const char *name,
+ /*@null@*/ yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
+ static const struct {
+ const char *name;
+ void (*func) (yasm_objfmt_elf *, yasm_valparam *, unsigned long);
+ } dirs[] = {
+ {"TYPE", dir_type},
+ {"SIZE", dir_size},
+ {"WEAK", dir_weak},
+ {"IDENT", dir_ident}
+ };
+ size_t i;
+
+ for (i=0; i<NELEMS(dirs); i++) {
+ if (yasm__strcasecmp(name, dirs[i].name) == 0) {
+ yasm_valparam *vp;
+ if (!valparams || !(vp = yasm_vps_first(valparams)) || !vp->val) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("Symbol name not specified"));
+ return 0;
+ }
+ dirs[i].func(objfmt_elf, vp, line);
+ return 0;
+ }
+ }
+ return 1; /* unrecognized */
}
static int
macho_objfmt_directive(/*@unused@*/ yasm_objfmt *objfmt,
/*@unused@*/ const char *name,
- /*@unused@*/ yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
/*@unused@*/ /*@null@*/
yasm_valparamhead *objext_valparams,
/*@unused@*/ unsigned long line)
static int
rdf_objfmt_directive(yasm_objfmt *objfmt, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@unused@*/ /*@null@*/
yasm_valparamhead *objext_valparams, unsigned long line)
{
else
return 1;
+ if (!valparams) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"),
+ name);
+ return 0;
+ }
vp = yasm_vps_first(valparams);
if (!vp->val) {
yasm_error_set(YASM_ERROR_SYNTAX, N_("argument to [%s] must be name"),
static int
xdf_objfmt_directive(/*@unused@*/ yasm_objfmt *objfmt,
/*@unused@*/ const char *name,
- /*@unused@*/ yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/ yasm_valparamhead *valparams,
/*@unused@*/ /*@null@*/
yasm_valparamhead *objext_valparams,
/*@unused@*/ unsigned long line)
static void nasm_parser_directive
(yasm_parser_nasm *parser_nasm, const char *name,
- yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams);
static int fix_directive_symrec(/*@null@*/ yasm_expr__item *ei,
/*@null@*/ void *d);
{
char *dirname;
yasm_valparamhead dir_vps;
+ int have_vps = 1;
parser_nasm->state = DIRECTIVE;
get_next_token();
dirname = DIRECTIVE_NAME_val;
get_next_token();
- if (!parse_directive_valparams(parser_nasm, &dir_vps)) {
+ 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);
yasm_xfree(dirname);
return NULL;
}
- nasm_parser_directive(parser_nasm, dirname, &dir_vps,
- &ext_vps);
+ nasm_parser_directive(parser_nasm, dirname,
+ have_vps ? &dir_vps : NULL, &ext_vps);
} else
- nasm_parser_directive(parser_nasm, dirname, &dir_vps, NULL);
+ nasm_parser_directive(parser_nasm, dirname,
+ have_vps ? &dir_vps : NULL, NULL);
yasm_xfree(dirname);
expect(']');
get_next_token();
case INTNUM:
e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
break;
+ case REG:
+ e = p_expr_new_ident(yasm_expr_reg(REG_val[0]));
+ break;
case ID:
e = p_expr_new_ident(yasm_expr_sym(
yasm_symtab_define_label(p_symtab, ID_val,
return 0;
}
+static void
+dir_extern(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_objfmt_extern_declare(parser_nasm->objfmt, vp->val, objext_valparams,
+ cur_line);
+}
+
+static void
+dir_global(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_objfmt_global_declare(parser_nasm->objfmt, vp->val, objext_valparams,
+ cur_line);
+}
+
+static void
+dir_common(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_valparam *vp2 = yasm_vps_next(vp);
+ unsigned long line = cur_line;
+
+ if (!vp2 || (!vp2->val && !vp2->param)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("no size specified in %s declaration"), "COMMON");
+ return;
+ }
+ if (vp2->val) {
+ yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
+ p_expr_new_ident(yasm_expr_sym(
+ yasm_symtab_use(p_symtab, vp2->val, line))),
+ objext_valparams, line);
+ } else if (vp2->param) {
+ yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val, vp2->param,
+ objext_valparams, line);
+ vp2->param = NULL;
+ }
+}
+
+static void
+dir_section(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_section *new_section =
+ yasm_objfmt_section_switch(parser_nasm->objfmt, valparams,
+ objext_valparams, cur_line);
+ if (new_section) {
+ parser_nasm->cur_section = new_section;
+ parser_nasm->prev_bc = yasm_section_bcs_last(new_section);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
+ "SECTION");
+}
+
+static void
+dir_absolute(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ unsigned long line = cur_line;
+ /* it can be just an ID or a complete expression, so handle both. */
+ if (vp->val)
+ parser_nasm->cur_section =
+ yasm_object_create_absolute(parser_nasm->object,
+ p_expr_new_ident(yasm_expr_sym(
+ yasm_symtab_use(p_symtab, vp->val, line))), line);
+ else if (vp->param) {
+ parser_nasm->cur_section =
+ yasm_object_create_absolute(parser_nasm->object, vp->param, line);
+ vp->param = NULL;
+ }
+ parser_nasm->prev_bc = yasm_section_bcs_last(parser_nasm->cur_section);
+}
+
+static void
+dir_align(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ /*@only@*/ yasm_expr *boundval;
+ /*@depedent@*/ yasm_intnum *boundintn;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+
+ /* it can be just an ID or a complete expression, so handle both. */
+ vp = yasm_vps_first(valparams);
+ if (vp->val)
+ boundval = p_expr_new_ident(yasm_expr_sym(
+ yasm_symtab_use(p_symtab, vp->val, cur_line)));
+ else if (vp->param) {
+ boundval = vp->param;
+ vp->param = NULL;
+ }
+
+ /* Largest .align in the section specifies section alignment.
+ * Note: this doesn't match NASM behavior, but is a lot more
+ * intelligent!
+ */
+ boundintn = yasm_expr_get_intnum(&boundval, 0);
+ if (boundintn) {
+ 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(parser_nasm->cur_section))
+ yasm_section_set_align(parser_nasm->cur_section, boundint,
+ cur_line);
+ }
+ }
+
+ /* As this directive is called only when nop is used as fill, always
+ * use arch (nop) fill.
+ */
+ parser_nasm->prev_bc =
+ yasm_section_bcs_append(parser_nasm->cur_section,
+ yasm_bc_create_align(boundval, NULL, NULL,
+ /*yasm_section_is_code(parser_nasm->cur_section) ?*/
+ yasm_arch_get_fill(parser_nasm->arch)/* : NULL*/,
+ cur_line));
+}
+
+static void
+dir_cpu(yasm_parser_nasm *parser_nasm, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ yasm_valparam *vp;
+ yasm_vps_foreach(vp, valparams) {
+ if (vp->val)
+ yasm_arch_parse_cpu(parser_nasm->arch, vp->val, strlen(vp->val));
+ else if (vp->param) {
+ const yasm_intnum *intcpu;
+ intcpu = yasm_expr_get_intnum(&vp->param, 0);
+ if (!intcpu)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid argument to [%s]"), "CPU");
+ else {
+ char strcpu[16];
+ sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
+ yasm_arch_parse_cpu(parser_nasm->arch, strcpu, strlen(strcpu));
+ }
+ }
+ }
+}
+
static void
nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
yasm_valparamhead *valparams,
{
yasm_valparam *vp, *vp2;
unsigned long line = cur_line;
+ static const struct {
+ const char *name;
+ int required_arg:1;
+ int id_only:1;
+ void (*func) (yasm_parser_nasm *, yasm_valparamhead *,
+ yasm_valparamhead *);
+ } dirs[] = {
+ {"EXTERN", 1, 1, dir_extern},
+ {"GLOBAL", 1, 1, dir_global},
+ {"COMMON", 1, 1, dir_common},
+ {"SECTION", 1, 0, dir_section},
+ {"SEGMENT", 1, 0, dir_section},
+ {"ABSOLUTE", 1, 0, dir_absolute},
+ {"ALIGN", 1, 0, dir_align},
+ {"CPU", 1, 0, dir_cpu}
+ };
+ size_t i;
/* Handle (mostly) output-format independent directives here */
- if (yasm__strcasecmp(name, "extern") == 0) {
- vp = yasm_vps_first(valparams);
- if (vp->val) {
- yasm_objfmt_extern_declare(parser_nasm->objfmt, vp->val,
- objext_valparams, line);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
- "EXTERN");
- } else if (yasm__strcasecmp(name, "global") == 0) {
- vp = yasm_vps_first(valparams);
- if (vp->val) {
- yasm_objfmt_global_declare(parser_nasm->objfmt, vp->val,
- objext_valparams, line);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
- "GLOBAL");
- } else if (yasm__strcasecmp(name, "common") == 0) {
- vp = yasm_vps_first(valparams);
- if (vp->val) {
- vp2 = yasm_vps_next(vp);
- if (!vp2 || (!vp2->val && !vp2->param))
+ for (i=0; i<NELEMS(dirs); i++) {
+ if (yasm__strcasecmp(name, dirs[i].name) == 0) {
+ if (dirs[i].required_arg && !valparams) {
yasm_error_set(YASM_ERROR_SYNTAX,
- N_("no size specified in %s declaration"),
- "COMMON");
- else {
- if (vp2->val) {
- yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
- p_expr_new_ident(yasm_expr_sym(
- yasm_symtab_use(p_symtab, vp2->val, line))),
- objext_valparams, line);
- } else if (vp2->param) {
- yasm_objfmt_common_declare(parser_nasm->objfmt, vp->val,
- vp2->param, objext_valparams,
- line);
- vp2->param = NULL;
- }
+ N_("[%s] requires an argument"), dirs[i].name);
+ break;
}
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
- "COMMON");
- } else if (yasm__strcasecmp(name, "section") == 0 ||
- yasm__strcasecmp(name, "segment") == 0) {
- yasm_section *new_section =
- yasm_objfmt_section_switch(parser_nasm->objfmt, valparams,
- objext_valparams, line);
- if (new_section) {
- parser_nasm->cur_section = new_section;
- parser_nasm->prev_bc = yasm_section_bcs_last(new_section);
- } else
- yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
- "SECTION");
- } else if (yasm__strcasecmp(name, "absolute") == 0) {
- /* it can be just an ID or a complete expression, so handle both. */
- vp = yasm_vps_first(valparams);
- if (vp->val)
- parser_nasm->cur_section =
- yasm_object_create_absolute(parser_nasm->object,
- p_expr_new_ident(yasm_expr_sym(
- yasm_symtab_use(p_symtab, vp->val, line))), line);
- else if (vp->param) {
- parser_nasm->cur_section =
- yasm_object_create_absolute(parser_nasm->object, vp->param,
- line);
- vp->param = NULL;
- }
- parser_nasm->prev_bc = yasm_section_bcs_last(parser_nasm->cur_section);
- } else if (yasm__strcasecmp(name, "align") == 0) {
- /*@only@*/ yasm_expr *boundval;
- /*@depedent@*/ yasm_intnum *boundintn;
-
- /* it can be just an ID or a complete expression, so handle both. */
- vp = yasm_vps_first(valparams);
- if (vp->val)
- boundval = p_expr_new_ident(yasm_expr_sym(
- yasm_symtab_use(p_symtab, vp->val, line)));
- else if (vp->param) {
- boundval = vp->param;
- vp->param = NULL;
- }
-
- /* Largest .align in the section specifies section alignment.
- * Note: this doesn't match NASM behavior, but is a lot more
- * intelligent!
- */
- boundintn = yasm_expr_get_intnum(&boundval, 0);
- if (boundintn) {
- 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(parser_nasm->cur_section))
- yasm_section_set_align(parser_nasm->cur_section, boundint,
- cur_line);
+ if (dirs[i].id_only && (vp = yasm_vps_first(valparams))
+ && !vp->val) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid argument to [%s]"), dirs[i].name);
+ break;
}
+ dirs[i].func(parser_nasm, valparams, objext_valparams);
+ break;
}
+ }
- /* As this directive is called only when nop is used as fill, always
- * use arch (nop) fill.
- */
- parser_nasm->prev_bc =
- yasm_section_bcs_append(parser_nasm->cur_section,
- yasm_bc_create_align(boundval, NULL, NULL,
- /*yasm_section_is_code(parser_nasm->cur_section) ?*/
- yasm_arch_get_fill(parser_nasm->arch)/* : NULL*/,
- cur_line));
- } else if (yasm__strcasecmp(name, "cpu") == 0) {
- yasm_vps_foreach(vp, valparams) {
- if (vp->val)
- yasm_arch_parse_cpu(parser_nasm->arch, vp->val,
- strlen(vp->val));
- else if (vp->param) {
- const yasm_intnum *intcpu;
- intcpu = yasm_expr_get_intnum(&vp->param, 0);
- if (!intcpu)
- yasm_error_set(YASM_ERROR_SYNTAX,
- N_("invalid argument to [%s]"), "CPU");
- else {
- char strcpu[16];
- sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
- yasm_arch_parse_cpu(parser_nasm->arch, strcpu,
- strlen(strcpu));
- }
- }
- }
+ if (i != NELEMS(dirs)) {
+ ;
} else if (!yasm_arch_parse_directive(parser_nasm->arch, name, valparams,
objext_valparams, parser_nasm->object, line)) {
;
name);
}
- yasm_vps_delete(valparams);
+done:
+ if (valparams)
+ yasm_vps_delete(valparams);
if (objext_valparams)
yasm_vps_delete(objext_valparams);
}
RETURN(s->tok[0]);
}
- iletter+ {
+ [a-zA-Z_][a-zA-Z_0-9]* {
lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
if (yasm__strcasecmp(lvalp->str_val, "section") == 0 ||
yasm__strcasecmp(lvalp->str_val, "segment") == 0)