mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
Merge qfpc into qfcc.
Since gnu bison and flex are required anyway, no harm in using their api prefix options. Now, qfcc can compile both QC/Ruamoko and Pascal files (Pascal is (currently?) NOT supported in progs.src mode), selecting the language based on the extension: .r, .qc and .c select QC/Ruamoko, .pas and .p select Pascal, while anything else is treated as an object file (as before).
This commit is contained in:
parent
6e04fd5ff6
commit
f14d8060e0
12 changed files with 272 additions and 156 deletions
|
@ -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);
|
||||
|
|
44
tools/qfcc/include/shared.h
Normal file
44
tools/qfcc/include/shared.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
shared.h
|
||||
|
||||
Functions and data shared between languages.
|
||||
|
||||
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include <QF/dstring.h>
|
||||
#include <QF/hash.h>
|
||||
#include <QF/qendian.h>
|
||||
#include <QF/quakefs.h>
|
||||
#include <QF/script.h>
|
||||
#include <QF/sys.h>
|
||||
#include <QF/va.h>
|
||||
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <op> 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;
|
||||
}
|
||||
%}
|
||||
|
||||
%%
|
||||
|
|
78
tools/qfcc/source/shared.c
Normal file
78
tools/qfcc/source/shared.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
qc-parse.y
|
||||
|
||||
parser for quakec
|
||||
|
||||
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
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;
|
||||
}
|
Loading…
Reference in a new issue