diff options
Diffstat (limited to 'mixlib')
-rw-r--r-- | mixlib/mix_parser.c | 87 | ||||
-rw-r--r-- | mixlib/mix_parser.h | 19 | ||||
-rw-r--r-- | mixlib/mix_scanner.l | 104 |
3 files changed, 110 insertions, 100 deletions
diff --git a/mixlib/mix_parser.c b/mixlib/mix_parser.c index 2087f15..e2c7e3f 100644 --- a/mixlib/mix_parser.c +++ b/mixlib/mix_parser.c @@ -1,23 +1,23 @@ /* -*-c-*- -------------- mix_parser.c : - * Implementation of the functions declared in mix_parser.h and + * Implementation of the functions declared in mix_parser.h and * xmix_parser.h * ------------------------------------------------------------------ - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * + * Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * + * */ #include <string.h> @@ -57,7 +57,8 @@ static const gchar * const ERR_MESSAGE_[] = { N_("symbol is an instruction name"), N_("failed write access to code file"), N_("operand of ALF pseudo instruction has less than 5 chars"), - N_("operand of ALF pseudo instruction has more than 5 chars") + N_("operand of ALF pseudo instruction has more than 5 chars"), + N_("operand of ALF pseudo instruction must be quoted") }; static const guint NO_OF_MESSAGES_ = sizeof(ERR_MESSAGE_)/sizeof (gchar*); @@ -68,13 +69,13 @@ mix_parser_err_string (mix_parser_err_t error) return (error < NO_OF_MESSAGES_) ? _(ERR_MESSAGE_[error]) : NULL; } -guint +guint mix_parser_err_count (const mix_parser_t *parser) { return (parser) ? parser->err_count : 0; } -guint +guint mix_parser_warning_count (const mix_parser_t *parser) { return (parser) ? parser->warn_count : 0; @@ -104,7 +105,7 @@ compare_shorts_ (gconstpointer s1, gconstpointer s2) return mix_short_magnitude (a) - mix_short_magnitude (b); else if ( mix_short_magnitude (a) == 0 && mix_short_magnitude (b) == 0 ) return 0; - else if ( mix_short_is_positive (a) ) + else if ( mix_short_is_positive (a) ) return 1; return -1; } @@ -113,9 +114,9 @@ mix_parser_t * mix_parser_new (const gchar *in_file) { mix_parser_t *result; - mix_file_t *f = mix_file_new_with_def_ext (in_file, mix_io_READ, + mix_file_t *f = mix_file_new_with_def_ext (in_file, mix_io_READ, MIX_SRC_DEFEXT); - + if ( f == NULL ) return NULL; result = g_new (mix_parser_t, 1); result->symbol_table = mix_symbol_table_new (); @@ -193,16 +194,16 @@ update_future_refs_value_ (mix_parser_t *parser, const gchar *name, { GSList *list = NULL; gpointer key; - + g_assert (parser != NULL && name != NULL); - if ( g_hash_table_lookup_extended (parser->future_refs, name, &key, + if ( g_hash_table_lookup_extended (parser->future_refs, name, &key, (gpointer *)&list) ) { GSList *tmp = list; ins_node_ *node; while ( tmp != NULL ) { - node = + node = (ins_node_ *)g_tree_lookup (parser->ins_table,tmp->data); g_assert (node); if (mix_get_ins_address (node->ins) == 1) { @@ -230,7 +231,7 @@ update_ls_ (gpointer symbol, gpointer value, gpointer parser) mix_ins_t ins; mix_word_t w = (mix_word_t) GPOINTER_TO_UINT (value); mix_parser_t *par = (mix_parser_t *) parser; - + mix_word_to_ins_uncheck (w, ins); mix_parser_add_ins (par, &ins, 0); update_future_refs_ (par, (const gchar *)symbol); @@ -245,16 +246,16 @@ mix_parser_compile (mix_parser_t *parser) g_return_val_if_fail (parser->symbol_table != NULL, MIX_PERR_INTERNAL); g_return_val_if_fail (parser->future_refs != NULL, MIX_PERR_INTERNAL); g_return_val_if_fail (parser->ins_table != NULL, MIX_PERR_INTERNAL); - + parser->status = mix_flex_scan (parser); if ( parser->status == MIX_PERR_OK ) { - mix_symbol_table_foreach (parser->ls_table, update_ls_, + mix_symbol_table_foreach (parser->ls_table, update_ls_, (gpointer)parser); - g_hash_table_foreach_remove (parser->future_refs, + g_hash_table_foreach_remove (parser->future_refs, undef_warning_, (gpointer)parser); } - + return parser->status; } @@ -275,7 +276,7 @@ write_code_ (gpointer address, gpointer ins_node, gpointer context) desc.address = (mix_address_t)GPOINTER_TO_UINT (address); if ( mix_code_file_write_ins (cntx->file, &desc) ) return FALSE; - else + else { cntx->parser->status = MIX_PERR_NOWRITE; return TRUE; @@ -283,14 +284,14 @@ write_code_ (gpointer address, gpointer ins_node, gpointer context) } mix_parser_err_t -mix_parser_write_code (mix_parser_t *parser, const gchar *code_file, +mix_parser_write_code (mix_parser_t *parser, const gchar *code_file, gboolean debug) { struct write_code_context_ context; const gchar *cfname = (code_file) ? code_file : mix_file_base_name (parser->in_file); gchar *source_path; - + g_return_val_if_fail (parser != NULL, MIX_PERR_INTERNAL); if (parser->status != MIX_PERR_OK ) return parser->status; context.parser = parser; @@ -303,13 +304,13 @@ mix_parser_write_code (mix_parser_t *parser, const gchar *code_file, } else source_path = g_strdup (mix_file_base_name (parser->in_file)); - + context.file = mix_code_file_new_write (cfname, parser->start, source_path, debug, parser->symbol_table); g_free (source_path); if (context.file == NULL) return MIX_PERR_NOOUT; - g_tree_traverse (parser->ins_table, write_code_, + g_tree_traverse (parser->ins_table, write_code_, G_IN_ORDER, (gpointer)&context); mix_code_file_delete (context.file); return parser->status; @@ -344,21 +345,21 @@ mix_parser_write_listing (mix_parser_t *parser, const gchar *list_file) FILE *file; mix_file_t *mfile; const gchar *name; - + g_return_val_if_fail (parser != NULL, MIX_PERR_INTERNAL); if (parser->status != MIX_PERR_OK ) return parser->status; name = (list_file) ? list_file : mix_file_base_name (parser->in_file); mfile = mix_file_new_with_def_ext (name, mix_io_WRITE, MIX_LIST_DEFEXT); if ( mfile == NULL ) return MIX_PERR_NOOUT; file = mix_file_to_FILE (mfile); - fprintf (file, _("*** %s%s: compilation summary ***\n\n"), - mix_file_base_name (parser->in_file), + fprintf (file, _("*** %s%s: compilation summary ***\n\n"), + mix_file_base_name (parser->in_file), mix_file_extension (parser->in_file)); fputs ( _("*** Address / Compiled word / Symbolic rep / Source file line\n"), file); - g_tree_traverse (parser->ins_table, write_listing_, + g_tree_traverse (parser->ins_table, write_listing_, G_IN_ORDER, (gpointer)file); - fprintf (file, _("\n*** Start address: %d\n"), + fprintf (file, _("\n*** Start address: %d\n"), mix_short_magnitude (parser->start)); fprintf (file, _("\n*** Symbol table\n")); mix_symbol_table_print (parser->symbol_table, MIX_SYM_ROWS, file, TRUE); @@ -372,7 +373,7 @@ static gint load_vm_ (gpointer address, gpointer ins, gpointer vm) { mix_vm_set_addr_contents ((mix_vm_t*)vm, - (mix_address_t)GPOINTER_TO_UINT (address), + (mix_address_t)GPOINTER_TO_UINT (address), ((ins_node_ *)ins)->ins); return FALSE; } @@ -410,12 +411,12 @@ mix_parser_err_t mix_parser_define_symbol_value (mix_parser_t *parser, const gchar *name, mix_word_t value) { - g_assert (parser != NULL && name != NULL); - + g_assert (parser != NULL && name != NULL); + switch (mix_symbol_table_add (parser->symbol_table, name, value)) { - case MIX_SYM_OK: - if ( parser->status == MIX_PERR_NOCOMP ) + case MIX_SYM_OK: + if ( parser->status == MIX_PERR_NOCOMP ) update_future_refs_value_ (parser, name, value); return MIX_PERR_OK; case MIX_SYM_LONG: return MIX_PERR_LONG_SYMBOL; @@ -449,10 +450,10 @@ mix_parser_manage_local_symbol (mix_parser_t *parser, const gchar *name, { gchar ref[3]; ref[2] = 0; - + g_assert (parser != NULL && name != NULL); g_assert (strlen(name) == 2); - + switch (name[1]) { case 'f': case 'F': @@ -461,10 +462,10 @@ mix_parser_manage_local_symbol (mix_parser_t *parser, const gchar *name, case 'h': case 'H': ref[0] = name[0]; ref[1] = 'F'; - if ( parser->status == MIX_PERR_NOCOMP ) + if ( parser->status == MIX_PERR_NOCOMP ) update_future_refs_value_ (parser, ref, value); ref[1] = 'B'; - mix_symbol_table_insert (parser->symbol_table, ref, + mix_symbol_table_insert (parser->symbol_table, ref, mix_short_to_word_fast (value)); break; default: @@ -484,7 +485,7 @@ mix_parser_define_ls (mix_parser_t *parser, mix_word_t value) /* Compilation */ void -mix_parser_add_ins (mix_parser_t *parser, const mix_ins_t *new_ins, +mix_parser_add_ins (mix_parser_t *parser, const mix_ins_t *new_ins, guint lineno) { g_assert (parser != NULL && new_ins != NULL); @@ -506,7 +507,7 @@ mix_parser_add_raw (mix_parser_t *parser, mix_word_t word, guint lineno) } /* Error handling */ -void +void mix_parser_log_error (mix_parser_t *parser, mix_parser_err_t error, gint lineno, const gchar *comment, gboolean warn) { @@ -519,9 +520,9 @@ mix_parser_log_error (mix_parser_t *parser, mix_parser_err_t error, parser->err_line = lineno; parser->status = error; } - + fprintf (stderr, "%s%s:%d: %s: %s", - mix_file_base_name (parser->in_file), + mix_file_base_name (parser->in_file), mix_file_extension (parser->in_file), lineno, warn ? _("warning"):_("error"), _(ERR_MESSAGE_[error])); diff --git a/mixlib/mix_parser.h b/mixlib/mix_parser.h index f371430..a18442c 100644 --- a/mixlib/mix_parser.h +++ b/mixlib/mix_parser.h @@ -2,22 +2,22 @@ * Declarations for mix_parser_t, which compiles a source file into * a mix code file. * ------------------------------------------------------------------ - * Copyright (C) 2000 Free Software Foundation, Inc. - * + * Copyright (C) 2000, 2003 Free Software Foundation, Inc. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * + * */ @@ -46,7 +46,7 @@ mix_parser_src_file_extension(const mix_parser_t *parser); /* Compile a mix source file */ /* compilation errors */ -typedef enum { +typedef enum { MIX_PERR_OK, /* no error */ MIX_PERR_NOCOMP, /* file not yet compiled */ MIX_PERR_INTERNAL, /* internal error */ @@ -70,7 +70,8 @@ typedef enum { MIX_PERR_SYM_INS, /* symbol has the same name as instruction */ MIX_PERR_NOWRITE, /* failed code write */ MIX_PERR_SHORT_ALF, /* short ALF operand */ - MIX_PERR_LONG_ALF /* too long ALF operand */ + MIX_PERR_LONG_ALF, /* too long ALF operand */ + MIX_PERR_UNQUOTED_ALF /* unquoted ALF operand */ } mix_parser_err_t; extern const gchar * @@ -79,10 +80,10 @@ mix_parser_err_string(mix_parser_err_t error); extern mix_parser_err_t mix_parser_compile(mix_parser_t *parser); -extern guint +extern guint mix_parser_warning_count(const mix_parser_t *parser); -extern guint +extern guint mix_parser_err_count(const mix_parser_t *parser); /* Write the compilation result to a code file with the given name. diff --git a/mixlib/mix_scanner.l b/mixlib/mix_scanner.l index 8c6a186..6e4cb71 100644 --- a/mixlib/mix_scanner.l +++ b/mixlib/mix_scanner.l @@ -1,25 +1,26 @@ /* -*-c-*- -------------- mix_scanner.l : * Lexical scanner used by mix_parser_t * ------------------------------------------------------------------ - * Copyright (C) 2000 Free Software Foundation, Inc. - * + * Copyright (C) 2000, 2003 Free Software Foundation, Inc. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * + * */ %{ +#include <ctype.h> #include <string.h> #include "mix.h" @@ -104,13 +105,25 @@ BEGIN (INITIAL); \ } while (FALSE) - + static mix_word_t - eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y); - +eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y); + +static void yyunput(int, char*); + static void - unput_word_ (mix_word_t word); - +unput_word_ (mix_word_t word) + { + gchar *value; + gint k; + value = g_strdup_printf ("%s%ld", + mix_word_is_negative (word)? "-":"+", + mix_word_magnitude (word)); + for (k = strlen (value) - 1; k >= 0; --k) + unput (value[k]); + g_free (value); + } + %} %option nomain @@ -148,7 +161,7 @@ atexpr {digit}+|{symbol}|\* expr [+-]?{atexpr}({binop}{1}{atexpr})* fpart \({expr}\) wexpr {expr}({fpart})?(,{expr}({fpart})?)* - + %% @@ -161,14 +174,14 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* gchar *symbol = NULL, *lsymbol = NULL; mix_address_t loc = MIX_SHORT_ZERO; guint lineno = 1; - mix_ins_fill_from_id (ins, mix_NOP); - ins.address = 0; - ins.index = 0; + mix_ins_fill_from_id (ins, mix_NOP); + ins.address = 0; + ins.index = 0; parser->err_line = 0; yyin = mix_file_to_FILE (parser->in_file); - + %} - + <*><<EOF>> { mix_parser_log_error (parser, MIX_PERR_UNEX_EOF, lineno, NULL, FALSE); @@ -182,11 +195,11 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* yyless (0); BEGIN (LOC); } - \n { + \n { ++lineno; - if ( end ) return parser->status; + if ( end ) return parser->status; } -} +} <LOC>{ {ws}+ BEGIN (OP); /* LOC field is empty */ @@ -209,7 +222,7 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* } symbol[1] = 'B'; /* this will be referred as nB afterwards */ BEGIN (OP); - } + } {flocsymbol}|{blocsymbol} RETURN_ERROR (MIX_PERR_UNEX_LOC, yytext); {symbol}/({ws}+EQU) { /* store symbol name for future definition */ symbol = g_strdup (yytext); @@ -253,10 +266,18 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* mix_parser_log_error (parser, MIX_PERR_LONG_ALF, lineno, NULL, TRUE); value = mix_bytes_to_word (bytes, 5); - + ADD_RAW (value); } - [A-Z0-9]+{ws}*/\n | + ALF{ws}+.*\n { + gchar* msg; + guint k = 4; + while ( isspace(yytext[k]) ) k++; + msg = g_strdup_printf("\"%5s\"", g_strchomp (yytext + k)); + mix_parser_log_error (parser, MIX_PERR_UNQUOTED_ALF, lineno, msg, FALSE); + g_free (msg); + } + [A-Z0-9]+{ws}*/\n | [A-Z0-9]+{ws}+ { mix_ins_id_t id = mix_get_id_from_string (g_strchomp (yytext)); if ( id == mix_INVALID_INS ) @@ -268,7 +289,7 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* BEGIN (ADDRESS); } {expr} RETURN_ERROR (MIX_PERR_INV_OP, yytext); - . RETURN_ERROR (MIX_PERR_INV_OP, yytext); + . RETURN_ERROR (MIX_PERR_INV_OP, yytext); } @@ -336,7 +357,7 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* [+-]?{number}[(,\n] { ins.address = mix_short_new (atol (yytext)); switch ( yytext[yyleng-1] ) { - case '(' : BEGIN (FSPEC); break; + case '(' : BEGIN (FSPEC); break; case ',' : BEGIN (INDEX); break; case '\n' : ADD_INS (); break; default: g_assert_not_reached (); @@ -363,7 +384,7 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* \n ADD_INS (); . RETURN_ERROR (MIX_PERR_INV_ADDRESS, yytext); } - + <INDEX>{ {number}[\n(\t ] { @@ -383,7 +404,7 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* {expr}/[\n(\t ] ENTER_EVAL (); \n { mix_parser_log_error (parser, MIX_PERR_INV_IDX, lineno++, NULL, FALSE); - RESET (); + RESET (); BEGIN (INITIAL); } . RETURN_ERROR (MIX_PERR_INV_IDX, yytext); @@ -392,13 +413,13 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* <FSPEC>{ {number}")"(({ws}+.*\n)|\n) { glong val = atol (yytext); - if ( val < 0 || val > MIX_BYTE_MAX ) + if ( val < 0 || val > MIX_BYTE_MAX ) RETURN_ERROR (MIX_PERR_INV_FSPEC, NULL); - if ( ins.opcode != mix_opMOVE + if ( ins.opcode != mix_opMOVE && ( ins.opcode < mix_opJBUS || ins.opcode > mix_opJXx ) && !mix_fspec_is_valid (mix_byte_new (val)) ) RETURN_ERROR (MIX_PERR_INV_FSPEC, NULL); - if ( nof ) + if ( nof ) mix_parser_log_error (parser, MIX_PERR_INV_FSPEC, lineno, _("ignored"), TRUE); else @@ -426,11 +447,11 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* mix_parser_log_error (parser, MIX_PERR_UNDEF_SYM, lineno, s, FALSE); yy_pop_state (); } - expr_val = eval_binop_ (yytext, expr_val, + expr_val = eval_binop_ (yytext, expr_val, mix_symbol_table_value (parser->symbol_table, s)); } {binop}"*" { - expr_val = eval_binop_ (yytext, expr_val, + expr_val = eval_binop_ (yytext, expr_val, mix_short_to_word_fast (parser->loc_count)); } "*" unput_word_ (mix_short_to_word_fast (parser->loc_count)); @@ -457,13 +478,13 @@ wexpr {expr}({fpart})?(,{expr}({fpart})?)* mix_parser_log_error (parser, MIX_PERR_MIS_PAREN, lineno, NULL, FALSE); yy_pop_state (); } - if ( val < 0 || val > MIX_BYTE_MAX + if ( val < 0 || val > MIX_BYTE_MAX || !mix_fspec_is_valid (mix_byte_new (val)) ) { mix_parser_log_error (parser, MIX_PERR_INV_FSPEC, lineno, NULL, FALSE); yy_pop_state (); } is_fp = FALSE; - wexpr_val = mix_word_store_field (mix_byte_new (val), wexpr_val_tmp, + wexpr_val = mix_word_store_field (mix_byte_new (val), wexpr_val_tmp, wexpr_val); } {number}/[,()\n\t ] wexpr_val = mix_word_new (atol (yytext)); @@ -489,8 +510,8 @@ eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y) mix_word_t result = MIX_WORD_ZERO; switch (op[0]) { - case '+': - result = mix_word_add (x,y); + case '+': + result = mix_word_add (x,y); break; case '-': result = mix_word_sub (x,y); @@ -518,16 +539,3 @@ eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y) return result; } - -static void -unput_word_ (mix_word_t word) -{ - gchar *value; - gint k; - value = g_strdup_printf ("%s%ld", - mix_word_is_negative (word)? "-":"+", - mix_word_magnitude (word)); - for (k = strlen (value) - 1; k >= 0; --k) - unput (value[k]); - g_free (value); -} |