Support use of NASM preprocessor with GAS parser.

Note: this combination is obviously not supported by any other assembler.

Requested by: Brian Gladman <brg@gladman.plus.com>

svn path=/trunk/yasm/; revision=2076
0.7.2
Peter Johnson 17 years ago
parent ca23bda1cf
commit 7b190b80fb
  1. 115
      modules/parsers/gas/gas-parse.c
  2. 6
      modules/parsers/gas/gas-parser.c
  3. 9
      modules/parsers/gas/gas-parser.h
  4. 45
      modules/parsers/gas/gas-token.re

@ -44,7 +44,8 @@ typedef struct dir_lookup {
enum gas_parser_state newstate;
} dir_lookup;
static yasm_bytecode * cpp_line_marker(yasm_parser_gas *parser_gas);
static void cpp_line_marker(yasm_parser_gas *parser_gas);
static void nasm_line_marker(yasm_parser_gas *parser_gas);
static yasm_bytecode *parse_instr(yasm_parser_gas *parser_gas);
static int parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps);
static int parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
@ -248,9 +249,14 @@ parse_line(yasm_parser_gas *parser_gas)
define_label(parser_gas, LABEL_val, 0);
get_next_token(); /* LABEL */
return parse_line(parser_gas);
case LINE_MARKER:
case CPP_LINE_MARKER:
get_next_token();
return cpp_line_marker(parser_gas);
cpp_line_marker(parser_gas);
return NULL;
case NASM_LINE_MARKER:
get_next_token();
nasm_line_marker(parser_gas);
return NULL;
default:
yasm_error_set(YASM_ERROR_SYNTAX,
N_("label or instruction expected at start of line"));
@ -268,10 +274,10 @@ parse_line(yasm_parser_gas *parser_gas)
without adding a filter to the input before passing it to cpp.
This function is only called if the preprocessor was 'cpp', since the
LINE_MARKER token isn't generated for any other preprocessor. With any other
preprocessor, anything after a '#' is always treated as a comment.
CPP_LINE_MARKER token isn't generated for any other preprocessor. With any
other preprocessor, anything after a '#' is always treated as a comment.
*/
static yasm_bytecode *
static void
cpp_line_marker(yasm_parser_gas *parser_gas)
{
yasm_valparamhead vps;
@ -285,14 +291,14 @@ cpp_line_marker(yasm_parser_gas *parser_gas)
while (curtok != '\n')
get_next_token();
return NULL;
return;
}
if (yasm_intnum_sign(INTNUM_val) < 0) {
get_next_token(); /* INTNUM */
yasm_error_set(YASM_ERROR_SYNTAX,
N_("line number is negative"));
return NULL;
return;
}
line = yasm_intnum_get_uint(INTNUM_val);
@ -315,7 +321,7 @@ cpp_line_marker(yasm_parser_gas *parser_gas)
while (curtok != '\n')
get_next_token();
return NULL;
return;
}
filename = STRING_val.contents;
@ -339,7 +345,8 @@ cpp_line_marker(yasm_parser_gas *parser_gas)
yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
yasm_vps_delete(&vps);
}
} else
yasm_xfree(filename);
/* Skip flags. */
while (1) {
@ -348,18 +355,98 @@ cpp_line_marker(yasm_parser_gas *parser_gas)
break;
case '\n':
return NULL;
return;
default:
yasm_error_set(YASM_ERROR_SYNTAX,
N_("junk at end of cpp line marker"));
return NULL;
return;
}
get_next_token();
}
}
/* Never reached. */
return NULL;
/*
Handle line markers generated by the nasm preproc.
We expect a positive integer (line) followed by a plus sign, followed by
another positive integer, followed by a string (filename).
This function is only called if the preprocessor was 'nasm', since the
NASM_LINE_MARKER token isn't generated for any other preprocessor.
*/
static void
nasm_line_marker(yasm_parser_gas *parser_gas)
{
yasm_valparamhead vps;
yasm_valparam *vp;
unsigned long line, incr;
char *filename;
/* Line number. */
if (!expect(INTNUM)) return;
if (yasm_intnum_sign(INTNUM_val) < 0) {
get_next_token(); /* INTNUM */
yasm_error_set(YASM_ERROR_SYNTAX,
N_("line number is negative"));
return;
}
line = yasm_intnum_get_uint(INTNUM_val);
yasm_intnum_destroy(INTNUM_val);
get_next_token(); /* INTNUM */
if (!expect('+')) return;
get_next_token(); /* + */
/* Line number increment. */
if (!expect(INTNUM)) return;
if (yasm_intnum_sign(INTNUM_val) < 0) {
get_next_token(); /* INTNUM */
yasm_error_set(YASM_ERROR_SYNTAX,
N_("line increment is negative"));
return;
}
incr = yasm_intnum_get_uint(INTNUM_val);
yasm_intnum_destroy(INTNUM_val);
/* File name is not in quotes, so need to switch to a different tokenizer
* state.
*/
parser_gas->state = NASM_FILENAME;
get_next_token(); /* INTNUM */
if (!expect(STRING)) {
parser_gas->state = INITIAL;
return;
}
filename = STRING_val.contents;
get_next_token(); /* STRING */
/* Set linemap. */
yasm_linemap_set(parser_gas->linemap, filename, line, incr);
/*
The first line marker in the file (which should be on the first line
of the file) will give us the name of the source file. This information
needs to be passed on to the debug format module.
*/
if (parser_gas->seen_line_marker == 0) {
parser_gas->seen_line_marker = 1;
yasm_vps_initialize(&vps);
vp = yasm_vp_create_string(NULL, filename);
yasm_vps_append(&vps, vp);
yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
yasm_vps_delete(&vps);
} else
yasm_xfree(filename);
}
/* Line directive */

@ -76,6 +76,11 @@ gas_parser_do_parse(yasm_object *object, yasm_preproc *pp,
for (i=0; i<10; i++)
parser_gas.local[i] = 0;
parser_gas.is_cpp_preproc =
yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "cpp") == 0;
parser_gas.is_nasm_preproc =
yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "nasm") == 0;
/* yacc debugging, needs YYDEBUG set in bison.y.in to work */
parser_gas.debug = 1;
@ -114,6 +119,7 @@ gas_parser_do_parse(yasm_object *object, yasm_preproc *pp,
static const char *gas_parser_preproc_keywords[] = {
"raw",
"cpp",
"nasm",
NULL
};

@ -48,7 +48,8 @@ enum tokentype {
RIGHT_OP,
ID,
LABEL,
LINE_MARKER,
CPP_LINE_MARKER,
NASM_LINE_MARKER,
NONE
};
@ -90,7 +91,8 @@ enum gas_parser_state {
INITIAL,
COMMENT,
SECTION_DIRECTIVE,
INSTDIR
INSTDIR,
NASM_FILENAME
};
typedef struct yasm_parser_gas {
@ -147,6 +149,9 @@ typedef struct yasm_parser_gas {
/* Parser-handled directives HAMT lookup */
HAMT *dirs;
int is_nasm_preproc;
int is_cpp_preproc;
} yasm_parser_gas;
/* shorter access names to commonly used parser_gas fields */

@ -302,6 +302,8 @@ gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas)
goto comment;
case SECTION_DIRECTIVE:
goto section_directive;
case NASM_FILENAME:
goto nasm_filename;
default:
break;
}
@ -387,6 +389,11 @@ scan:
[%][a-zA-Z0-9]+ {
savech = s->tok[TOKLEN];
s->tok[TOKLEN] = '\0';
if (parser_gas->is_nasm_preproc && strcmp(TOK+1, "line") == 0) {
s->tok[TOKLEN] = savech;
RETURN(NASM_LINE_MARKER);
}
switch (yasm_arch_parse_check_regtmod
(p_object->arch, TOK+1, TOKLEN-1, &lvalp->arch_data)) {
case YASM_ARCH_REG:
@ -482,10 +489,9 @@ scan:
"/*" { parser_gas->state = COMMENT; goto comment; }
"#" {
if (strcmp(((yasm_preproc_base*)parser_gas->preproc)->module->keyword,
"cpp") == 0)
if (parser_gas->is_cpp_preproc)
{
RETURN(LINE_MARKER);
RETURN(CPP_LINE_MARKER);
} else
goto line_comment;
}
@ -569,6 +575,39 @@ section_directive:
}
*/
/* filename portion of nasm preproc %line */
nasm_filename:
strbuf = yasm_xmalloc(STRBUF_ALLOC_SIZE);
strbuf_size = STRBUF_ALLOC_SIZE;
count = 0;
nasm_filename_scan:
SCANINIT();
/*!re2c
"\n" {
strbuf_append(count++, cursor, s, '\0');
lvalp->str.contents = (char *)strbuf;
lvalp->str.len = count;
parser_gas->state = INITIAL;
RETURN(STRING);
}
ws+ { goto nasm_filename_scan; }
any {
if (cursor == s->eof) {
strbuf_append(count++, cursor, s, '\0');
lvalp->str.contents = (char *)strbuf;
lvalp->str.len = count;
parser_gas->state = INITIAL;
RETURN(STRING);
}
strbuf_append(count++, cursor, s, s->tok[0]);
goto nasm_filename_scan;
}
*/
/* character constant values */
charconst:
/*TODO*/

Loading…
Cancel
Save