/* 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/alloc.h" #include "QF/progs/pr_comp.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/opcodes.h" #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/pragma.h" #include "tools/qfcc/include/strpool.h" #include "tools/qfcc/include/type.h" #include "tools/qfcc/source/qc-parse.h" typedef struct pragma_arg_s { struct pragma_arg_s *next; const char *arg; } pragma_arg_t; static pragma_arg_t *pragma_args_freelist; static pragma_arg_t *pragma_args; static pragma_arg_t **pragma_args_tail = &pragma_args; static void set_traditional (int traditional) { switch (traditional) { case -1: options.traditional = 0; options.advanced = 2; options.code.progsversion = PROG_VERSION; type_default = &type_int; type_long_int = &type_long; type_ulong_uint = &type_ulong; break; case 0: options.traditional = 0; options.advanced = 1; options.code.progsversion = PROG_V6P_VERSION; type_default = &type_int; type_long_int = &type_int; type_ulong_uint = &type_uint; break; case 1: options.traditional = 1; options.advanced = 0; options.code.progsversion = PROG_ID_VERSION; type_default = &type_float; break; case 2: options.traditional = 2; options.advanced = 0; options.code.progsversion = PROG_ID_VERSION; type_default = &type_float; break; } opcode_init (); // reset the opcode table } static void set_bug (pragma_arg_t *args) { if (!args) { warning (0, "missing bug flag"); return; } const char *flag = args->arg; if (!strcmp (flag, "none")) { options.bug.silent = true; } else if (!strcmp (flag, "!none")) { options.bug.silent = false; } else if (!strcmp (flag, "die")) { options.bug.promote = true; } else if (!strcmp (flag, "!die")) { options.bug.promote = false; } if (args->next) { warning (0, "pragma bug: ignoring extra arguments"); } } static void set_warn (pragma_arg_t *args) { if (!args) { warning (0, "missing warn flag"); return; } const char *flag = args->arg; if (!strcmp (flag, "error")) { options.warnings.promote = true; } else if (!strcmp (flag, "!error")) { options.warnings.promote = false; } if (args->next) { warning (0, "pragma warn: ignoring extra arguments"); } } static void set_optimize (pragma_arg_t *args) { if (!args) { warning (0, "missing optimize flag"); return; } const char *flag = args->arg; if (!strcmp (flag, "on") || !strcmp (flag, "!off")) { options.code.optimize = true; } else if (!strcmp (flag, "!on") || !strcmp (flag, "off")) { options.code.optimize = false; } if (args->next) { warning (0, "pragma optimize: ignoring extra arguments"); } } static pragma_arg_t * set_vector_mult (pragma_arg_t *args) { if (!args) { warning (0, "missing vector_mult arg"); return args; } const char *op = args->arg; if (!strcmp (op, "@dot")) { options.math.vector_mult = DOT; } else { warning (0, "unknown vector_mult arg: %s", op); } return args->next; } static void set_math (pragma_arg_t *args) { if (!args) { warning (0, "missing math arg"); return; } while (args) { const char *a = args->arg; if (!strcmp (a, "vector_mult")) { args = set_vector_mult (args->next); } } } void pragma_process () { if (!pragma_args) { warning (0, "empty pragma"); return; } const char *id = pragma_args->arg; if (!strcmp (id, "traditional")) { set_traditional (2); } else if (!strcmp (id, "extended")) { set_traditional (1); } else if (!strcmp (id, "advanced")) { set_traditional (0); } else if (!strcmp (id, "ruamoko") || !strcmp (id, "raumoko")) { set_traditional (-1); } else if (!strcmp (id, "bug")) { set_bug (pragma_args->next); } else if (!strcmp (id, "warn")) { set_warn (pragma_args->next); } else if (!strcmp (id, "optimize")) { set_optimize (pragma_args->next); } else if (!strcmp (id, "math")) { set_math (pragma_args->next); } else { warning (0, "unknown pragma: '%s'", id); } *pragma_args_tail = pragma_args_freelist; pragma_args_tail = &pragma_args; pragma_args = 0; } void pragma_add_arg (const char *id) { pragma_arg_t *arg; ALLOC (16, pragma_arg_t, pragma_args, arg); arg->arg = save_string (id); *pragma_args_tail = arg; pragma_args_tail = &arg->next; }