diff --git a/tools/qfcc/include/Makefile.am b/tools/qfcc/include/Makefile.am index 75a786f6a..3c34ca1a1 100644 --- a/tools/qfcc/include/Makefile.am +++ b/tools/qfcc/include/Makefile.am @@ -2,6 +2,6 @@ AUTOMAKE_OPTIONS= foreign EXTRA_DIST= class.h codespace.h cpp.h dags.h debug.h def.h defspace.h \ diagnostic.h dot.h emit.h expr.h flow.h function.h grab.h idstuff.h \ - linker.h method.h obj_file.h obj_type.h opcodes.h options.h qfcc.h \ - qfprogs.h reloc.h set.h shared.h statements.h strpool.h struct.h \ - switch.h symtab.h type.h value.h + linker.h method.h obj_file.h obj_type.h opcodes.h options.h pragma.h \ + qfcc.h qfprogs.h reloc.h set.h shared.h statements.h strpool.h \ + struct.h switch.h symtab.h type.h value.h diff --git a/tools/qfcc/include/pragma.h b/tools/qfcc/include/pragma.h new file mode 100644 index 000000000..1f6726f28 --- /dev/null +++ b/tools/qfcc/include/pragma.h @@ -0,0 +1,42 @@ +/* + praga.h + + pragma handling + + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/11/22 + + 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 pragma_h +#define pragma_h + +/** \defgroup qfcc_pragma pragma handling + \ingroup qfcc +*/ +//@{ + +void pragma (const char *id); + +//@} + +#endif//pragma_h diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index b1ff7e639..0a0dd89c0 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -42,8 +42,8 @@ common_src=\ class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \ diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \ expr.c flow.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 set.c shared.c statements.c \ - strpool.c struct.c switch.c symtab.c type.c value.c + obj_type.c opcodes.c options.c pragma.c qfcc.c reloc.c set.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 qp-lex.l qp-parse.y $(common_src) qfcc_LDADD= $(QFCC_LIBS) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 0dee8a38d..4d8bb4678 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -122,33 +122,46 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; } +static void +opcode_free (void *_op, void *unused) +{ + free (_op); +} + void opcode_init (void) { - opcode_t *op; + opcode_t *op, *mop; - PR_Opcode_Init (); - opcode_type_table = Hash_NewTable (1021, 0, 0, 0); - Hash_SetHashCompare (opcode_type_table, get_hash, compare); - opcode_void_table = Hash_NewTable (1021, get_key, 0, 0); + if (opcode_type_table) { + Hash_FlushTable (opcode_void_table); + Hash_FlushTable (opcode_type_table); + } else { + PR_Opcode_Init (); + opcode_type_table = Hash_NewTable (1021, 0, opcode_free, 0); + Hash_SetHashCompare (opcode_type_table, get_hash, compare); + opcode_void_table = Hash_NewTable (1021, get_key, 0, 0); + } for (op = pr_opcodes; op->name; op++) { if (op->min_version > options.code.progsversion) continue; + mop = malloc (sizeof (opcode_t)); + *mop = *op; if (options.code.progsversion == PROG_ID_VERSION) { // v6 progs have no concept of integer, but the QF engine // treats the operands of certain operands as integers // irrespective the progs version, so convert the engine's // view of the operands to the prog's view. - if (op->type_a == ev_integer) - op->type_a = ev_float; - if (op->type_b == ev_integer) - op->type_b = ev_float; - if (op->type_c == ev_integer) - op->type_c = ev_float; + if (mop->type_a == ev_integer) + mop->type_a = ev_float; + if (mop->type_b == ev_integer) + mop->type_b = ev_float; + if (mop->type_c == ev_integer) + mop->type_c = ev_float; } - Hash_AddElement (opcode_type_table, op); - if (op->type_a == ev_void || op->type_b == ev_void - || op->type_c == ev_void) - Hash_Add (opcode_void_table, op); + Hash_AddElement (opcode_type_table, mop); + if (mop->type_a == ev_void || mop->type_b == ev_void + || mop->type_c == ev_void) + Hash_Add (opcode_void_table, mop); } } diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c new file mode 100644 index 000000000..c5e8e816d --- /dev/null +++ b/tools/qfcc/source/pragma.c @@ -0,0 +1,92 @@ +/* + praga.c + + pragma handling + + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/11/22 + + 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 + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/pr_comp.h" + +#include "diagnostic.h" +#include "opcodes.h" +#include "options.h" +#include "pragma.h" +#include "type.h" + +static void +set_traditional (int traditional) +{ + switch (traditional) { + case 0: + options.traditional = 0; + options.advanced = true; + options.code.progsversion = PROG_VERSION; + type_default = &type_integer; + break; + case 1: + options.traditional = 1; + options.advanced = false; + options.code.progsversion = PROG_ID_VERSION; + type_default = &type_float; + break; + case 2: + options.traditional = 2; + options.advanced = false; + options.code.progsversion = PROG_ID_VERSION; + type_default = &type_float; + break; + } + opcode_init (); // reset the opcode table +} + +void +pragma (const char *id) +{ + if (!strcmp (id, "traditional")) { + set_traditional (2); + return; + } + if (!strcmp (id, "extended")) { + set_traditional (1); + return; + } + if (!strcmp (id, "advanced")) { + set_traditional (0); + return; + } + warning (0, "unknown pragma: %s", id); +} diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index c699d0b92..feb9e7a89 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -51,6 +51,7 @@ #include "expr.h" #include "grab.h" #include "options.h" +#include "pragma.h" #include "qfcc.h" #include "strpool.h" #include "struct.h" @@ -98,9 +99,10 @@ INT ({D}+|0[xX]{X}+) RANGE \.\. ELLIPSIS \.\.\. FRAMEID {ID}(\.{ID})* +PRAGMAID {ID}(-{ID})* STRING \"(\\.|[^"\\])*\" -%x GRAB_FRAME GRAB_OTHER COMMENT +%x GRAB_FRAME GRAB_OTHER COMMENT PRAGMA %% grab_frame = GRAB_FRAME; @@ -117,7 +119,7 @@ STRING \"(\\.|[^"\\])*\" ^#{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); } ^#line{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 5); } -^{s}*#{s}*pragma.*$ /* skip */ +^{s}*#{s}*pragma{s}+ { BEGIN (PRAGMA); } {INT}+[uU]? { const char *c = yytext + yyleng - 1; @@ -234,6 +236,7 @@ STRING \"(\\.|[^"\\])*\" {FRAMEID} add_frame_macro (yytext); [^\r\n]* /* skip */ +{ID} { pragma (yytext); } <*>\r*\n { pr.source_line++;