diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 51e2b0848..71771f366 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -120,9 +120,12 @@ extern struct symtab_s *current_symtab; const char *strip_path (const char *filename); void clear_frame_macros (void); -extern FILE *yyin; -int yyparse (void); -extern int yydebug; +extern FILE *qc_yyin; +extern FILE *qp_yyin; +int qc_yyparse (void); +int qp_yyparse (void); +extern int qc_yydebug; +extern int qp_yydebug; #ifdef _WIN32 char *fix_backslash (char *path); diff --git a/tools/qfcc/include/shared.h b/tools/qfcc/include/shared.h new file mode 100644 index 000000000..81b883de9 --- /dev/null +++ b/tools/qfcc/include/shared.h @@ -0,0 +1,44 @@ +/* + shared.h + + Functions and data shared between languages. + + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/10/26 + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __shared_h +#define __shared_h + +extern struct function_s *current_func; +extern struct class_type_s *current_class; +extern struct expr_s *local_expr; +extern enum vis_e current_visibility; +extern enum storage_class_e current_storage; +extern struct symtab_s *current_symtab; + +struct symbol_s *check_redefined (struct symbol_s *sym); +extern struct symbol_s *check_undefined (struct symbol_s *sym); + +#endif//__shared_h diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 21102cf3c..aead04d0c 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -41,11 +41,11 @@ enum storage_class_e; */ //@{ -typedef enum { +typedef enum vis_e { vis_public, vis_protected, vis_private, -} vis_e; +} vis_t; typedef enum { sy_var, ///< symbol refers to a variable @@ -59,7 +59,7 @@ typedef enum { typedef struct symbol_s { struct symbol_s *next; ///< chain of symbols in symbol table struct symtab_s *table; ///< symbol table that owns this symbol - vis_e visibility; ///< symbol visiblity. defaults to public + vis_t visibility; ///< symbol visiblity. defaults to public const char *name; ///< symbol name sy_type_e sy_type; ///< symbol type (st_type) struct type_s *type; ///< type of object to which symbol refers diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index a122a3c41..4cada3791 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -35,24 +35,20 @@ QFCC_INCS=@QFCC_INCS@ INCLUDES= -I$(top_srcdir)/include $(QFCC_INCS) YFLAGS = -v -d -bin_PROGRAMS= qfcc qfpc qfprogs +bin_PROGRAMS= qfcc qfprogs bin_SCRIPTS= qfpreqcc common_src=\ class.c codespace.c constfold.c cpp.c debug.c def.c defspace.c \ diagnostic.c dot_expr.c dot_flow.c emit.c expr.c function.c grab.c \ idstuff.c linker.c method.c obj_file.c obj_type.c opcodes.c options.c \ - qfcc.c reloc.c statements.c strpool.c struct.c switch.c symtab.c type.c \ - value.c + qfcc.c reloc.c shared.c statements.c strpool.c struct.c switch.c symtab.c \ + type.c value.c -qfcc_SOURCES= qc-lex.l qc-parse.y $(common_src) +qfcc_SOURCES= qc-lex.l qc-parse.y qp-lex.l qp-parse.y $(common_src) qfcc_LDADD= $(QFCC_LIBS) qfcc_DEPENDENCIES= $(QFCC_DEPS) -qfpc_SOURCES= qp-lex.l qp-parse.y $(common_src) -qfpc_LDADD= $(QFCC_LIBS) -qfpc_DEPENDENCIES= $(QFCC_DEPS) - qfprogs_SOURCES= \ disassemble.c dump_globals.c dump_lines.c dump_modules.c obj_file.c \ stub.c qfprogs.c dump_strings.c @@ -61,5 +57,14 @@ qfprogs_DEPENDENCIES= $(QFCC_DEPS) BUILT_SOURCES=qc-parse.c qc-parse.h qc-lex.c qp-parse.c qp-parse.h qp-lex.c +qc-parse.c: qc-parse.y + $(YACC) $(YFLAGS) -Dapi.prefix=qc_yy $< -o $@ +qc-lex.c: qc-lex.l + $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqc_yy -o$@ $< +qp-parse.c: qp-parse.y + $(YACC) $(YFLAGS) -Dapi.prefix=qp_yy $< -o $@ +qp-lex.c: qp-lex.l + $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqp_yy -o$@ $< + EXTRA_DIST=qc-lex.c qc-parse.c qc-parse.h qfpreqcc \ qp-parse.c qp-parse.h qp-lex.c diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 49408499d..3c548551a 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -763,7 +763,7 @@ class_find_ivar (class_t *class, int vis, const char *name) ivar = symtab_lookup (class->ivars, name); if (ivar) { - if (ivar->visibility > (vis_e) vis) + if (ivar->visibility > (vis_t) vis) goto access_error; return ivar; } diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index f843c560c..ce00efd01 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -642,7 +642,9 @@ DecodeArgs (int argc, char **argv) linker_add_path (QFCC_LIB_PATH); } - if (options.verbosity >= 3) - yydebug = 1; + if (options.verbosity >= 3) { + qc_yydebug = 1; + qp_yydebug = 1; + } return optind; } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 9b5c0e1fa..64b1142ca 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -84,7 +84,7 @@ YY_DECL; static int keyword_or_id (char *token); -extern YYSTYPE yylval; +extern QC_YYSTYPE qc_yylval; %} @@ -123,15 +123,15 @@ STRING \"(\\.|[^"\\])*\" const char *c = yytext + yyleng - 1; int i = strtol (yytext, 0, 0); if (*c == 'u' || *c == 'U') - yylval.expr = new_integer_expr (i);//FIXME + qc_yylval.expr = new_integer_expr (i);//FIXME else - yylval.expr = new_integer_expr (i); + qc_yylval.expr = new_integer_expr (i); return CONST; } {FLOAT} { float f = strtof (yytext, 0); - yylval.expr = new_float_expr (f); + qc_yylval.expr = new_float_expr (f); return CONST; } @@ -148,7 +148,7 @@ STRING \"(\\.|[^"\\])*\" {STRING} { const char *s = make_string (yytext, 0); - yylval.expr = new_string_expr (s); + qc_yylval.expr = new_string_expr (s); return STRING; } @ return '@'; @@ -157,7 +157,7 @@ STRING \"(\\.|[^"\\])*\" vec3_t v; sscanf (yytext, "' %f %f %f '", &v[0], &v[1], &v[2]); - yylval.expr = new_vector_expr (v); + qc_yylval.expr = new_vector_expr (v); return CONST; } @@ -165,7 +165,7 @@ STRING \"(\\.|[^"\\])*\" quat_t q; sscanf (yytext, "' %f %f %f %f'", &q[0], &q[1], &q[2], &q[3]); - yylval.expr = new_quaternion_expr (q); + qc_yylval.expr = new_quaternion_expr (q); return CONST; } @@ -174,27 +174,27 @@ STRING \"(\\.|[^"\\])*\" if (str[1]) warning (0, "multibyte char constant"); - yylval.expr = new_integer_expr (*str); + qc_yylval.expr = new_integer_expr (*str); return CONST; } [+\-*/&|^%]= { - yylval.op = yytext[0]; + qc_yylval.op = yytext[0]; return ASX; } "<<=" { - yylval.op = SHL; + qc_yylval.op = SHL; return ASX; } ">>=" { - yylval.op = SHR; + qc_yylval.op = SHR; return ASX; } [!(){}.*/&|^~+\-=\[\];,#%?:] { - yylval.pointer = 0; // ensure pointer values are null + qc_yylval.pointer = 0; // ensure pointer vals are null return yytext[0]; } @@ -213,19 +213,19 @@ STRING \"(\\.|[^"\\])*\" ">" return GT; "++" { - yylval.op = '+'; + qc_yylval.op = '+'; return INCOP; } "--" { - yylval.op = '-'; + qc_yylval.op = '-'; return INCOP; } "$"{s}*{FRAMEID} { int ret = do_grab (yytext); if (ret >= 0) { - yylval.expr = new_integer_expr (ret); + qc_yylval.expr = new_integer_expr (ret); return CONST; } else { BEGIN (-ret); @@ -352,10 +352,10 @@ keyword_or_id (char *token) class_init (); if (keyword->value) { if (keyword->value == STRUCT) { - yylval.op = token[0]; + qc_yylval.op = token[0]; } else { - yylval.type = 0; - yylval.type = keyword->type; + qc_yylval.type = 0; + qc_yylval.type = keyword->type; } return keyword->value; } @@ -366,7 +366,7 @@ keyword_or_id (char *token) sym = symtab_lookup (current_symtab, token); if (!sym) sym = new_symbol (token); - yylval.symbol = sym; + qc_yylval.symbol = sym; if (sym->sy_type == sy_type) return TYPE_NAME; if (sym->sy_type == sy_class) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index b5ca156dd..f40f138bb 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -54,6 +54,7 @@ #include "options.h" #include "qfcc.h" #include "reloc.h" +#include "shared.h" #include "strpool.h" #include "struct.h" #include "switch.h" @@ -65,22 +66,22 @@ #define YYERROR_VERBOSE 1 #undef YYERROR_VERBOSE -extern char *yytext; +extern char *qc_yytext; static void yyerror (const char *s) { #ifdef YYERROR_VERBOSE - error (0, "%s %s\n", yytext, s); + error (0, "%s %s\n", qc_yytext, s); #else - error (0, "%s before %s", s, yytext); + error (0, "%s before %s", s, qc_yytext); #endif } static void parse_error (void) { - error (0, "parse error before %s", yytext); + error (0, "parse error before %s", qc_yytext); } #define PARSE_ERROR do { parse_error (); YYERROR; } while (0) @@ -205,47 +206,10 @@ int yylex (void); %{ -function_t *current_func; -class_type_t *current_class; -expr_t *local_expr; -vis_e current_visibility; -storage_class_t current_storage = st_global; -symtab_t *current_symtab; - static switch_block_t *switch_block; static expr_t *break_label; static expr_t *continue_label; -/* When defining a new symbol, already existing symbols must be in a - different scope. However, when they are in a different scope, we want a - truly new symbol. -*/ -static symbol_t * -check_redefined (symbol_t *sym) -{ - if (sym->table == current_symtab) - error (0, "%s redefined", sym->name); - if (sym->table) // truly new symbols are not in any symbol table - sym = new_symbol (sym->name); - return sym; -} - -/* Check for undefined symbols. If the symbol is undefined, default its type - to float or int, depending on compiler mode. -*/ -static symbol_t * -check_undefined (symbol_t *sym) -{ - if (!sym->table) { // truly new symbols are not in any symbol table - error (0, "%s undefined", sym->name); - if (options.code.progsversion == PROG_ID_VERSION) - sym->type = &type_float; - else - sym->type = &type_integer; - } - return sym; -} - static specifier_t make_spec (type_t *type, storage_class_t storage, int is_typedef, int is_overload) @@ -1734,28 +1698,28 @@ keywordselector selector : NAME { $$ = $1; } | CLASS_NAME { $$ = $1; } - | TYPE { $$ = new_symbol (yytext); } + | TYPE { $$ = new_symbol (qc_yytext); } | TYPE_NAME { $$ = $1; } | reserved_word ; reserved_word - : LOCAL { $$ = new_symbol (yytext); } - | RETURN { $$ = new_symbol (yytext); } - | WHILE { $$ = new_symbol (yytext); } - | DO { $$ = new_symbol (yytext); } - | IF { $$ = new_symbol (yytext); } - | ELSE { $$ = new_symbol (yytext); } - | FOR { $$ = new_symbol (yytext); } - | BREAK { $$ = new_symbol (yytext); } - | CONTINUE { $$ = new_symbol (yytext); } - | SWITCH { $$ = new_symbol (yytext); } - | CASE { $$ = new_symbol (yytext); } - | DEFAULT { $$ = new_symbol (yytext); } - | NIL { $$ = new_symbol (yytext); } - | STRUCT { $$ = new_symbol (yytext); } - | ENUM { $$ = new_symbol (yytext); } - | TYPEDEF { $$ = new_symbol (yytext); } + : LOCAL { $$ = new_symbol (qc_yytext); } + | RETURN { $$ = new_symbol (qc_yytext); } + | WHILE { $$ = new_symbol (qc_yytext); } + | DO { $$ = new_symbol (qc_yytext); } + | IF { $$ = new_symbol (qc_yytext); } + | ELSE { $$ = new_symbol (qc_yytext); } + | FOR { $$ = new_symbol (qc_yytext); } + | BREAK { $$ = new_symbol (qc_yytext); } + | CONTINUE { $$ = new_symbol (qc_yytext); } + | SWITCH { $$ = new_symbol (qc_yytext); } + | CASE { $$ = new_symbol (qc_yytext); } + | DEFAULT { $$ = new_symbol (qc_yytext); } + | NIL { $$ = new_symbol (qc_yytext); } + | STRUCT { $$ = new_symbol (qc_yytext); } + | ENUM { $$ = new_symbol (qc_yytext); } + | TYPEDEF { $$ = new_symbol (qc_yytext); } ; keyworddecl diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index fd44a330f..42f1dbf99 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,17 @@ const char *progs_src; pr_info_t pr; +typedef enum { + lang_object, + lang_ruamoko, + lang_pascal, +} lang_t; + +typedef struct ext_lang_s { + const char *ext; + lang_t lang; +} ext_lang_t; + #ifdef _WIN32 char * fix_backslash (char *path) @@ -307,12 +319,27 @@ setup_sym_file (const char *output_file) } static int -compile_to_obj (const char *file, const char *obj) +compile_to_obj (const char *file, const char *obj, lang_t lang) { int err; + FILE **yyin; + int (*yyparse) (void); - yyin = preprocess_file (file, 0); - if (!yyin) + switch (lang) { + case lang_ruamoko: + yyin = &qc_yyin; + yyparse = qc_yyparse; + break; + case lang_pascal: + yyin = &qp_yyin; + yyparse = qp_yyparse; + break; + default: + internal_error (0, "unknown language enum"); + } + + *yyin = preprocess_file (file, 0); + if (!*yyin) return !options.preprocess_only; InitData (); @@ -324,7 +351,7 @@ compile_to_obj (const char *file, const char *obj) begin_compilation (); pr.source_file = ReuseString (strip_path (file)); err = yyparse () || pr.error_count; - fclose (yyin); + fclose (*yyin); if (cpp_name && !options.save_temps) { if (unlink (tempname->str)) { perror ("unlink"); @@ -397,14 +424,35 @@ finish_link (void) return 0; } +static lang_t +file_language (const char *file, const char *ext) +{ + static ext_lang_t ext_lang[] = { + {".r", lang_ruamoko}, + {".c", lang_ruamoko}, + {".qc", lang_ruamoko}, + {".pas", lang_pascal}, + {".p", lang_pascal}, + {0, lang_object}, // unrecognized extension = object file + }; + ext_lang_t *el; + + if (strncmp (file, "-l", 2) == 0) + return lang_object; + for (el = ext_lang; el->ext; el++) + if (strcmp (ext, el->ext) == 0) + break; + return el->lang; +} + static int separate_compile (void) { - const char **file; + const char **file, *ext; const char **temp_files; + lang_t lang; dstring_t *output_file = dstring_newstr (); dstring_t *extension = dstring_newstr (); - char *f; int err = 0; int i; @@ -420,32 +468,21 @@ separate_compile (void) temp_files = calloc (i + 1, sizeof (const char*)); for (file = source_files, i = 0; *file; file++) { - dstring_clearstr (extension); - dstring_clearstr (output_file); + ext = QFS_FileExtension (*file); + dstring_copysubstr (output_file, *file, ext - *file); + dstring_copystr (extension, ext); - dstring_appendstr (output_file, *file); - f = output_file->str + strlen (output_file->str); - while (f >= output_file->str && *f != '.' && *f != '/') - f--; - if (f >= output_file->str && *f == '.') { - output_file->size -= strlen (f); - dstring_appendstr (extension, f); - *f = 0; - } if (options.compile && options.output_file) { dstring_clearstr (output_file); dstring_appendstr (output_file, options.output_file); } else { dstring_appendstr (output_file, ".qfo"); } - if (strncmp (*file, "-l", 2) - && (!strcmp (extension->str, ".r") - || !strcmp (extension->str, ".qc") - || !strcmp (extension->str, ".c"))) { + if ((lang = file_language (*file, extension->str)) != lang_object) { if (options.verbosity >= 2) printf ("%s %s\n", *file, output_file->str); temp_files[i++] = save_string (output_file->str); - err = compile_to_obj (*file, output_file->str) || err; + err = compile_to_obj (*file, output_file->str, lang) || err; free ((char *)*file); *file = strdup (output_file->str); @@ -530,16 +567,18 @@ static int compile_file (const char *filename) { int err; + FILE **yyin = &qc_yyin; + int (*yyparse) (void) = qc_yyparse; - yyin = preprocess_file (filename, 0); - if (!yyin) + *yyin = preprocess_file (filename, 0); + if (!*yyin) return !options.preprocess_only; pr.source_file = ReuseString (strip_path (filename)); pr.source_line = 1; clear_frame_macros (); err = yyparse () || pr.error_count; - fclose (yyin); + fclose (*yyin); if (cpp_name && (!options.save_temps)) { if (unlink (tempname->str)) { perror ("unlink"); diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index 03ff70fd7..0f717bbeb 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -109,13 +109,13 @@ FRAMEID {ID}(\.{ID})* {INTEGER} { int i = strtol (yytext, 0, 0); - yylval.expr = new_integer_expr (i); + qp_yylval.expr = new_integer_expr (i); return CONST; } {FLOAT} { float f = strtof (yytext, 0); - yylval.expr = new_float_expr (f); + qp_yylval.expr = new_float_expr (f); return CONST; } @@ -123,7 +123,7 @@ FRAMEID {ID}(\.{ID})* \"(\\.|[^"\\])*\" { const char *s = make_string (yytext, 0); - yylval.expr = new_string_expr (s); + qp_yylval.expr = new_string_expr (s); return CONST; } @@ -131,7 +131,7 @@ FRAMEID {ID}(\.{ID})* vec3_t v; sscanf (yytext, "' %f %f %f '", &v[0], &v[1], &v[2]); - yylval.expr = new_vector_expr (v); + qp_yylval.expr = new_vector_expr (v); return CONST; } @@ -139,20 +139,20 @@ FRAMEID {ID}(\.{ID})* quat_t q; sscanf (yytext, "' %f %f %f %f'", &q[0], &q[1], &q[2], &q[3]); - yylval.expr = new_quaternion_expr (q); + qp_yylval.expr = new_quaternion_expr (q); return CONST; } {RELOP} { - yylval.op = convert_relop (yytext); + qp_yylval.op = convert_relop (yytext); return RELOP; } {ADDOP} { - yylval.op = yytext[0]; + qp_yylval.op = yytext[0]; return ADDOP; } {MULOP} { - yylval.op = yytext[0]; + qp_yylval.op = yytext[0]; return MULOP; } @@ -166,7 +166,7 @@ FRAMEID {ID}(\.{ID})* "$"{s}*{FRAMEID} { int ret = do_grab (yytext); if (ret >= 0) { - yylval.expr = new_integer_expr (ret); + qp_yylval.expr = new_integer_expr (ret); return CONST; } else { BEGIN (-ret); @@ -251,9 +251,9 @@ keyword_or_id (const char *token) keyword = Hash_Find (keyword_tab, token); if (keyword) { if (keyword->value == ADDOP || keyword->value == MULOP) { - yylval.op = token[0]; + qp_yylval.op = token[0]; } else { - yylval.type = keyword->type; + qp_yylval.type = keyword->type; } return keyword->value; } @@ -261,10 +261,10 @@ keyword_or_id (const char *token) if (!sym) sym = new_symbol (token); if (sym->sy_type == sy_type) { - yylval.type = sym->type; + qp_yylval.type = sym->type; return TYPE_NAME; } - yylval.symbol = sym; + qp_yylval.symbol = sym; return ID; } diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 3f74e26d0..166f4b2d8 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -47,6 +47,7 @@ #include "function.h" #include "qfcc.h" #include "reloc.h" +#include "shared.h" #include "symtab.h" #include "type.h" @@ -54,22 +55,22 @@ #define YYERROR_VERBOSE 1 #undef YYERROR_VERBOSE -extern char *yytext; +extern char *qp_yytext; static void yyerror (const char *s) { #ifdef YYERROR_VERBOSE - error (0, "%s %s\n", yytext, s); + error (0, "%s %s\n", qp_yytext, s); #else - error (0, "%s before %s", s, yytext); + error (0, "%s before %s", s, qp_yytext); #endif } static void parse_error (void) { - error (0, "parse error before %s", yytext); + error (0, "parse error before %s", qp_yytext); } #define PARSE_ERROR do { parse_error (); YYERROR; } while (0) @@ -136,26 +137,6 @@ int yylex (void); %type sign %{ -symtab_t *current_symtab; -storage_class_t current_storage = st_global; -function_t *current_func; -struct class_type_s *current_class; -expr_t *local_expr; -param_t *current_params; - -/* When defining a new symbol, already existing symbols must be in a - different scope. However, when they are in a different scope, we want a - truly new symbol. -*/ -static symbol_t * -check_redefined (symbol_t *sym) -{ - if (sym->table == current_symtab) - error (0, "%s redefined", sym->name); - if (sym->table) // truly new symbols are not in any symbol table - sym = new_symbol (sym->name); - return sym; -} %} %% diff --git a/tools/qfcc/source/shared.c b/tools/qfcc/source/shared.c new file mode 100644 index 000000000..a5705e47a --- /dev/null +++ b/tools/qfcc/source/shared.c @@ -0,0 +1,78 @@ +/* + qc-parse.y + + parser for quakec + + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/10/26 + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "class.h" +#include "diagnostic.h" +#include "expr.h" +#include "function.h" +#include "options.h" +#include "shared.h" +#include "symtab.h" +#include "type.h" + +function_t *current_func; +class_type_t *current_class; +expr_t *local_expr; +vis_t current_visibility; +storage_class_t current_storage = st_global; +symtab_t *current_symtab; + +/* When defining a new symbol, already existing symbols must be in a + different scope. However, when they are in a different scope, we want a + truly new symbol. +*/ +symbol_t * +check_redefined (symbol_t *sym) +{ + if (sym->table == current_symtab) + error (0, "%s redefined", sym->name); + if (sym->table) // truly new symbols are not in any symbol table + sym = new_symbol (sym->name); + return sym; +} + +/* Check for undefined symbols. If the symbol is undefined, default its type + to float or int, depending on compiler mode. +*/ +symbol_t * +check_undefined (symbol_t *sym) +{ + if (!sym->table) { // truly new symbols are not in any symbol table + error (0, "%s undefined", sym->name); + if (options.code.progsversion == PROG_ID_VERSION) + sym->type = &type_float; + else + sym->type = &type_integer; + } + return sym; +}