mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-23 20:33:05 +00:00
preliminary segregated console subsystem
This commit is contained in:
parent
e7d558dbd8
commit
f0750209b7
6 changed files with 391 additions and 80 deletions
3
Makefile
3
Makefile
|
@ -24,7 +24,8 @@ OBJ = \
|
|||
code.o \
|
||||
ast.o \
|
||||
ir.o \
|
||||
error.o
|
||||
error.o \
|
||||
con.o
|
||||
OBJ_A = test/ast-test.o
|
||||
OBJ_I = test/ir-test.o
|
||||
OBJ_C = main.o lexer.o parser.o
|
||||
|
|
309
con.c
Normal file
309
con.c
Normal file
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include "gmqcc.h"
|
||||
|
||||
/*
|
||||
* isatty/STDERR_FILENO/STDOUT_FILNO
|
||||
* + some other things likewise.
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define GMQCC_IS_STDOUT(X) ((X) == stdout)
|
||||
#define GMQCC_IS_STDERR(X) ((X) == stderr)
|
||||
#define GMQCC_IS_DEFINE(X) (GMQCC_IS_STDERR(X) || GMQCC_IS_STDOUT(X))
|
||||
|
||||
typedef struct {
|
||||
FILE *handle_err;
|
||||
FILE *handle_out;
|
||||
|
||||
int color_err;
|
||||
int color_out;
|
||||
} con_t;
|
||||
|
||||
/*
|
||||
* Doing colored output on windows is fucking stupid. The linux way is
|
||||
* the real way. So we emulate it on windows :)
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
/*
|
||||
* Windows doesn't have constants for FILENO, sadly but the docs tell
|
||||
* use the constant values.
|
||||
*/
|
||||
#undef STDERR_FILENO
|
||||
#undef STDOUT_FILENO
|
||||
#define STDERR_FILENO 2
|
||||
#define STDOUT_FILENO 1
|
||||
|
||||
/*
|
||||
* Windows and it's posix underscore bullshit. We simply fix this
|
||||
* with yay, another macro :P
|
||||
*/
|
||||
#define isatty _isatty
|
||||
|
||||
enum {
|
||||
RESET = 0,
|
||||
BOLD = 1,
|
||||
BLACK = 30,
|
||||
RED,
|
||||
GREEN,
|
||||
YELLOW,
|
||||
BLUE,
|
||||
MAGENTA,
|
||||
CYAN,
|
||||
GRAY,
|
||||
WHITE
|
||||
};
|
||||
|
||||
enum {
|
||||
WBLACK,
|
||||
WBLUE,
|
||||
WGREEN = 2,
|
||||
WRED = 4,
|
||||
WINTENSE = 8,
|
||||
WCYAN = WBLUE | WGREEN,
|
||||
WMAGENTA = WBLUE | WRED,
|
||||
WYELLOW = WGREEN | WRED,
|
||||
WWHITE = WBLUE | WGREEN | WRED
|
||||
}
|
||||
|
||||
static const ansi2win[] = {
|
||||
WBLACK,
|
||||
WRED,
|
||||
WGREEN,
|
||||
WYELLOW,
|
||||
WBLUE,
|
||||
WMAGENTA,
|
||||
WCYAN,
|
||||
WWHITE
|
||||
};
|
||||
|
||||
static void win_fputs(char *str, FILE *f) {
|
||||
/* state for translate */
|
||||
int acolor;
|
||||
int wcolor;
|
||||
int icolor;
|
||||
|
||||
int state;
|
||||
int place;
|
||||
|
||||
/* attributes */
|
||||
int intense = -1;
|
||||
int colors[] = {-1, -1 };
|
||||
int colorpos = 1;
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO cinfo;
|
||||
GetConsoleScreenBufferInfo(
|
||||
(h == stdout) ?
|
||||
GetStdHandle(STD_OUTPUT_HANDLE) :
|
||||
GetStdHandle(STD_ERROR_HANDLE), &cinfo
|
||||
);
|
||||
icolor = cinfo.wAttributes;
|
||||
|
||||
while (*str) {
|
||||
if (*str == '\e')
|
||||
state = '\e';
|
||||
else if (state == '\e' && *str == '[')
|
||||
state = '[';
|
||||
else if (state == '[') {
|
||||
if (*str != 'm') {
|
||||
colors[colorpos] = *str;
|
||||
colorpos--;
|
||||
} else {
|
||||
int find;
|
||||
int mult;
|
||||
for (find = colorpos + 1, acolor = 0, mult = 1; find < 2; find++) {
|
||||
acolor += (colors[find] - 48) * mult;
|
||||
mult *= 10;
|
||||
}
|
||||
|
||||
/* convert to windows color */
|
||||
if (acolor == BOLD)
|
||||
intense = WINTENSE;
|
||||
else if (acolor == RESET) {
|
||||
intense = WBLACK;
|
||||
wcolor = icolor;
|
||||
}
|
||||
else if (BLACK < acolor && acolor <= WHITE)
|
||||
wcolor = ansi2win[acolor - 30];
|
||||
else if (acolor == 90) {
|
||||
/* special gray really white man */
|
||||
wcolor = WWHITE;
|
||||
intense = WBLACK;
|
||||
}
|
||||
|
||||
SetConsoleTextattribute(
|
||||
(h == stdout) ?
|
||||
GetStdHandle(STD_OUTPUT_HANDLE) :
|
||||
GetStdHandle(STD_ERROR_HANDLE),
|
||||
|
||||
wcolor | intense | (icolor & 0xF0)
|
||||
);
|
||||
colorpos = 1;
|
||||
state = -1;
|
||||
}
|
||||
} else {
|
||||
fputc(*str, h);
|
||||
}
|
||||
}
|
||||
/* restore */
|
||||
SetConsoleTextAttribute(
|
||||
(h == stdout) ?
|
||||
GetStdHandle(STD_OUTPUT_HANDLE) :
|
||||
GetStdHandle(STD_ERROR_HANDLE),
|
||||
icolor
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We use standard files as default. These can be changed at any time
|
||||
* with con_change(F, F)
|
||||
*/
|
||||
static con_t console;
|
||||
|
||||
/*
|
||||
* Enables color on output if supported.
|
||||
* NOTE: The support for checking colors is NULL. On windows this will
|
||||
* always work, on *nix it depends if the term has colors.
|
||||
*
|
||||
* NOTE: This prevents colored output to piped stdout/err via isatty
|
||||
* checks.
|
||||
*/
|
||||
static void con_enablecolor() {
|
||||
if (console.handle_err == stderr || console.handle_err == stdout)
|
||||
console.color_err = !!(isatty(STDERR_FILENO));
|
||||
if (console.handle_out == stderr || console.handle_out == stdout)
|
||||
console.color_out = !!(isatty(STDOUT_FILENO));
|
||||
}
|
||||
|
||||
/*
|
||||
* Does a write to the handle with the format string and list of
|
||||
* arguments. This colorizes for windows as well via translate
|
||||
* step.
|
||||
*/
|
||||
static int con_write(FILE *handle, const char *fmt, va_list va) {
|
||||
int ln;
|
||||
#ifndef _WIN32
|
||||
ln = vfprintf(handle, fmt, va);
|
||||
#else
|
||||
{
|
||||
char *data = NULL;
|
||||
ln = _vscprintf(fmt, va);
|
||||
data = malloc(ln + 1);
|
||||
data[ln] = 0;
|
||||
vsprintf(data, fmt, va);
|
||||
if (GMQCC_IS_DEFINE(handle))
|
||||
ln = win_fputs(data, handle);
|
||||
else
|
||||
ln = fputs(data, handle);
|
||||
free(data);
|
||||
}
|
||||
#endif
|
||||
return ln;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* EXPOSED INTERFACE BEGINS
|
||||
*********************************************************************/
|
||||
|
||||
void con_close() {
|
||||
if (!GMQCC_IS_DEFINE(console.handle_err))
|
||||
fclose(console.handle_err);
|
||||
if (!GMQCC_IS_DEFINE(console.handle_out))
|
||||
fclose(console.handle_out);
|
||||
}
|
||||
|
||||
void con_color(int state) {
|
||||
if (state)
|
||||
con_enablecolor();
|
||||
else {
|
||||
console.color_err = 0;
|
||||
console.color_out = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void con_init() {
|
||||
console.handle_err = stderr;
|
||||
console.handle_out = stdout;
|
||||
con_enablecolor();
|
||||
}
|
||||
|
||||
void con_reset() {
|
||||
con_close();
|
||||
con_init ();
|
||||
}
|
||||
|
||||
/*
|
||||
* This is clever, say you want to change the console to use two
|
||||
* files for out/err. You pass in two strings, it will properly
|
||||
* close the existing handles (if they're not std* handles) and
|
||||
* open them. Now say you want TO use stdout and stderr, this
|
||||
* allows you to do that so long as you cast them to (char*).
|
||||
* Say you need stdout for out, but want a file for error, you can
|
||||
* do this too, just cast the stdout for (char*) and stick to a
|
||||
* string for the error file.
|
||||
*/
|
||||
int con_change(const char *out, const char *err) {
|
||||
con_close();
|
||||
|
||||
if (GMQCC_IS_DEFINE((FILE*)out)) {
|
||||
console.handle_out = (((FILE*)err) == stdout) ? stdout : stderr;
|
||||
con_enablecolor();
|
||||
} else if (!(console.handle_out = fopen(out, "w"))) return 0;
|
||||
|
||||
if (GMQCC_IS_DEFINE((FILE*)err)) {
|
||||
console.handle_err = (((FILE*)err) == stdout) ? stdout : stderr;
|
||||
con_enablecolor();
|
||||
} else if (!(console.handle_err = fopen(err, "w"))) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int con_verr(const char *fmt, va_list va) {
|
||||
return con_write(console.handle_err, fmt, va);
|
||||
}
|
||||
int con_vout(const char *fmt, va_list va) {
|
||||
return con_write(console.handle_out, fmt, va);
|
||||
}
|
||||
|
||||
int con_err(const char *fmt, ...) {
|
||||
va_list va;
|
||||
int ln = 0;
|
||||
va_start(va, fmt);
|
||||
con_verr(fmt, va);
|
||||
va_end (va);
|
||||
return ln;
|
||||
}
|
||||
int con_out(const char *fmt, ...) {
|
||||
va_list va;
|
||||
int ln = 0;
|
||||
va_start(va, fmt);
|
||||
con_vout(fmt, va);
|
||||
va_end (va);
|
||||
return ln;
|
||||
}
|
17
gmqcc.h
17
gmqcc.h
|
@ -528,6 +528,19 @@ uint32_t code_genstring (const char *string);
|
|||
uint32_t code_cachedstring(const char *string);
|
||||
qcint code_alloc_field (size_t qcsize);
|
||||
|
||||
/*===================================================================*/
|
||||
/*============================ con.c ================================*/
|
||||
/*===================================================================*/
|
||||
void con_close();
|
||||
void con_color(int state);
|
||||
void con_init ();
|
||||
void con_reset();
|
||||
int con_change(const char *out, const char *err);
|
||||
int con_verr (const char *fmt, va_list va);
|
||||
int con_vout (const char *fmt, va_list va);
|
||||
int con_err (const char *fmt, ...);
|
||||
int con_out (const char *fmt, ...);
|
||||
|
||||
/*===================================================================*/
|
||||
/*========================= assembler.c =============================*/
|
||||
/*===================================================================*/
|
||||
|
@ -605,10 +618,6 @@ static const struct {
|
|||
|
||||
{ "END" , 0, 3 } /* virtual assembler instruction */
|
||||
};
|
||||
|
||||
void asm_init (const char *, FILE **);
|
||||
void asm_close(FILE *);
|
||||
void asm_parse(FILE *);
|
||||
/*===================================================================*/
|
||||
/*============================= ast.c ===============================*/
|
||||
/*===================================================================*/
|
||||
|
|
81
main.c
81
main.c
|
@ -54,28 +54,28 @@ VECTOR_MAKE(argitem, items);
|
|||
static const char *app_name;
|
||||
|
||||
static int usage() {
|
||||
printf("usage: %s [options] [files...]", app_name);
|
||||
printf("options:\n"
|
||||
con_out("usage: %s [options] [files...]", app_name);
|
||||
con_out("options:\n"
|
||||
" -h, --help show this help message\n"
|
||||
" -debug turns on compiler debug messages\n"
|
||||
" -memchk turns on compiler memory leak check\n");
|
||||
printf(" -o, --output=file output file, defaults to progs.dat\n"
|
||||
con_out(" -o, --output=file output file, defaults to progs.dat\n"
|
||||
" -a filename add an asm file to be assembled\n"
|
||||
" -s filename add a progs.src file to be used\n");
|
||||
printf(" -E stop after preprocessing\n");
|
||||
printf(" -f<flag> enable a flag\n"
|
||||
con_out(" -E stop after preprocessing\n");
|
||||
con_out(" -f<flag> enable a flag\n"
|
||||
" -fno-<flag> disable a flag\n"
|
||||
" -std standard select one of the following standards\n"
|
||||
" -std=qcc original QuakeC\n"
|
||||
" -std=fteqcc fteqcc QuakeC\n"
|
||||
" -std=gmqcc this compiler (default)\n");
|
||||
printf(" -W<warning> enable a warning\n"
|
||||
con_out(" -W<warning> enable a warning\n"
|
||||
" -Wno-<warning> disable a warning\n"
|
||||
" -Wall enable all warnings\n"
|
||||
" -Werror treat warnings as errors\n");
|
||||
printf(" -force-crc=num force a specific checksum into the header\n");
|
||||
printf("\n");
|
||||
printf("flags:\n"
|
||||
con_out(" -force-crc=num force a specific checksum into the header\n");
|
||||
con_out("\n");
|
||||
con_out("flags:\n"
|
||||
" -fadjust-vector-fields\n"
|
||||
" when assigning a vector field, its _y and _z fields also get assigned\n"
|
||||
);
|
||||
|
@ -184,7 +184,7 @@ static bool options_parse(int argc, char **argv) {
|
|||
else if (!strcmp(argarg, "qccx"))
|
||||
opts_standard = COMPILER_QCCX;
|
||||
else {
|
||||
printf("Unknown standard: %s\n", argarg);
|
||||
con_out("Unknown standard: %s\n", argarg);
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
|
@ -222,31 +222,31 @@ static bool options_parse(int argc, char **argv) {
|
|||
case 'f':
|
||||
util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
|
||||
if (!strcmp(argv[0]+2, "HELP")) {
|
||||
printf("Possible flags:\n");
|
||||
con_out("Possible flags:\n");
|
||||
for (itr = 0; itr < COUNT_FLAGS; ++itr) {
|
||||
util_strtononcmd(opts_flag_list[itr].name, buffer, sizeof(buffer));
|
||||
printf(" -f%s\n", buffer);
|
||||
con_out(" -f%s\n", buffer);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
else if (!strncmp(argv[0]+2, "NO_", 3)) {
|
||||
if (!options_setflag(argv[0]+5, false)) {
|
||||
printf("unknown flag: %s\n", argv[0]+2);
|
||||
con_out("unknown flag: %s\n", argv[0]+2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!options_setflag(argv[0]+2, true)) {
|
||||
printf("unknown flag: %s\n", argv[0]+2);
|
||||
con_out("unknown flag: %s\n", argv[0]+2);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'W':
|
||||
util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
|
||||
if (!strcmp(argv[0]+2, "HELP")) {
|
||||
printf("Possible warnings:\n");
|
||||
con_out("Possible warnings:\n");
|
||||
for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
|
||||
util_strtononcmd(opts_warn_list[itr].name, buffer, sizeof(buffer));
|
||||
printf(" -W%s\n", buffer);
|
||||
con_out(" -W%s\n", buffer);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
@ -270,19 +270,19 @@ static bool options_parse(int argc, char **argv) {
|
|||
}
|
||||
if (!strncmp(argv[0]+2, "NO_", 3)) {
|
||||
if (!options_setwarn(argv[0]+5, false)) {
|
||||
printf("unknown warning: %s\n", argv[0]+2);
|
||||
con_out("unknown warning: %s\n", argv[0]+2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!options_setwarn(argv[0]+2, true)) {
|
||||
printf("unknown warning: %s\n", argv[0]+2);
|
||||
con_out("unknown warning: %s\n", argv[0]+2);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
if (!options_witharg(&argc, &argv, &argarg)) {
|
||||
printf("option -O requires a numerical argument\n");
|
||||
con_out("option -O requires a numerical argument\n");
|
||||
return false;
|
||||
}
|
||||
opts_O = atoi(argarg);
|
||||
|
@ -290,7 +290,7 @@ static bool options_parse(int argc, char **argv) {
|
|||
|
||||
case 'o':
|
||||
if (!options_witharg(&argc, &argv, &argarg)) {
|
||||
printf("option -o requires an argument: the output file name\n");
|
||||
con_out("option -o requires an argument: the output file name\n");
|
||||
return false;
|
||||
}
|
||||
opts_output = argarg;
|
||||
|
@ -301,7 +301,7 @@ static bool options_parse(int argc, char **argv) {
|
|||
case 's':
|
||||
item.type = argv[0][1] == 'a' ? TYPE_ASM : TYPE_SRC;
|
||||
if (!options_witharg(&argc, &argv, &argarg)) {
|
||||
printf("option -a requires a filename %s\n",
|
||||
con_out("option -a requires a filename %s\n",
|
||||
(argv[0][1] == 'a' ? "containing QC-asm" : "containing a progs.src formatted list"));
|
||||
return false;
|
||||
}
|
||||
|
@ -326,14 +326,14 @@ static bool options_parse(int argc, char **argv) {
|
|||
opts_output = argarg;
|
||||
opts_output_wasset = true;
|
||||
} else {
|
||||
printf("Unknown parameter: %s\n", argv[0]);
|
||||
con_out("Unknown parameter: %s\n", argv[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown parameter: %s\n", argv[0]);
|
||||
con_out("Unknown parameter: %s\n", argv[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -398,6 +398,7 @@ int main(int argc, char **argv) {
|
|||
bool opts_output_free = false;
|
||||
|
||||
app_name = argv[0];
|
||||
con_init();
|
||||
|
||||
/* default options / warn flags */
|
||||
options_set(opts_warn, WARN_UNKNOWN_CONTROL_SEQUENCE, true);
|
||||
|
@ -431,18 +432,18 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (opts_dump) {
|
||||
for (itr = 0; itr < COUNT_FLAGS; ++itr) {
|
||||
printf("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr));
|
||||
con_out("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr));
|
||||
}
|
||||
for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
|
||||
printf("Warning %s = %i\n", opts_warn_list[itr].name, OPTS_WARN(itr));
|
||||
con_out("Warning %s = %i\n", opts_warn_list[itr].name, OPTS_WARN(itr));
|
||||
}
|
||||
printf("output = %s\n", opts_output);
|
||||
printf("optimization level = %i\n", (int)opts_O);
|
||||
printf("standard = %i\n", opts_standard);
|
||||
con_out("output = %s\n", opts_output);
|
||||
con_out("optimization level = %i\n", (int)opts_O);
|
||||
con_out("standard = %i\n", opts_standard);
|
||||
}
|
||||
|
||||
if (!parser_init()) {
|
||||
printf("failed to initialize parser\n");
|
||||
con_out("failed to initialize parser\n");
|
||||
retval = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -450,23 +451,17 @@ int main(int argc, char **argv) {
|
|||
util_debug("COM", "starting ...\n");
|
||||
|
||||
if (items_elements) {
|
||||
printf("Mode: manual\n");
|
||||
printf("There are %lu items to compile:\n", (unsigned long)items_elements);
|
||||
con_out("Mode: manual\n");
|
||||
con_out("There are %lu items to compile:\n", (unsigned long)items_elements);
|
||||
for (itr = 0; itr < items_elements; ++itr) {
|
||||
#ifndef JS
|
||||
printf(" item: %s (%s)\n",
|
||||
con_out(" item: %s (%s)\n",
|
||||
items_data[itr].filename,
|
||||
( (items_data[itr].type == TYPE_QC ? "qc" :
|
||||
(items_data[itr].type == TYPE_ASM ? "asm" :
|
||||
(items_data[itr].type == TYPE_SRC ? "progs.src" :
|
||||
("unknown"))))));
|
||||
#endif
|
||||
|
||||
#ifdef JS
|
||||
if (!parser_compile_string("js.qc", items_data[itr].filename))
|
||||
#else
|
||||
if (!parser_compile_file(items_data[itr].filename))
|
||||
#endif
|
||||
if (!parser_compile_file(items_data[itr].filename))
|
||||
{
|
||||
retval = 1;
|
||||
goto cleanup;
|
||||
|
@ -483,17 +478,17 @@ int main(int argc, char **argv) {
|
|||
char *line;
|
||||
size_t linelen = 0;
|
||||
|
||||
printf("Mode: progs.src\n");
|
||||
con_out("Mode: progs.src\n");
|
||||
src = util_fopen("progs.src", "rb");
|
||||
if (!src) {
|
||||
printf("failed to open `progs.src` for reading\n");
|
||||
con_out("failed to open `progs.src` for reading\n");
|
||||
retval = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
line = NULL;
|
||||
if (!progs_nextline(&line, &linelen, src) || !line[0]) {
|
||||
printf("illformatted progs.src file: expected output filename in first line\n");
|
||||
con_out("illformatted progs.src file: expected output filename in first line\n");
|
||||
retval = 1;
|
||||
goto srcdone;
|
||||
}
|
||||
|
@ -506,7 +501,7 @@ int main(int argc, char **argv) {
|
|||
while (progs_nextline(&line, &linelen, src)) {
|
||||
if (!line[0] || (line[0] == '/' && line[1] == '/'))
|
||||
continue;
|
||||
printf(" src: %s\n", line);
|
||||
con_out(" src: %s\n", line);
|
||||
if (!parser_compile_file(line)) {
|
||||
retval = 1;
|
||||
goto srcdone;
|
||||
|
|
54
parser.c
54
parser.c
|
@ -522,7 +522,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
op = &operators[sy->ops[sy->ops_count-1].etype - 1];
|
||||
ctx = sy->ops[sy->ops_count-1].ctx;
|
||||
|
||||
DEBUGSHUNTDO(printf("apply %s\n", op->op));
|
||||
DEBUGSHUNTDO(con_out("apply %s\n", op->op));
|
||||
|
||||
if (sy->out_count < op->operands) {
|
||||
parseerror(parser, "internal error: not enough operands: %i (operator %s (%i))", sy->out_count,
|
||||
|
@ -826,7 +826,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
return false;
|
||||
}
|
||||
if (opts_standard == COMPILER_GMQCC)
|
||||
printf("TODO: early out logic\n");
|
||||
con_out("TODO: early out logic\n");
|
||||
if (CanConstFold(exprs[0], exprs[1]))
|
||||
out = (ast_expression*)parser_const_float(parser,
|
||||
(generated_op == INSTR_OR ? (ConstF(0) || ConstF(1)) : (ConstF(0) && ConstF(1))));
|
||||
|
@ -956,7 +956,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
return false;
|
||||
}
|
||||
|
||||
DEBUGSHUNTDO(printf("applied %s\n", op->op));
|
||||
DEBUGSHUNTDO(con_out("applied %s\n", op->op));
|
||||
sy->out[sy->out_count++] = syexp(ctx, out);
|
||||
return true;
|
||||
}
|
||||
|
@ -1183,7 +1183,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
DEBUGSHUNTDO(printf("push %s\n", parser_tokval(parser)));
|
||||
DEBUGSHUNTDO(con_out("push %s\n", parser_tokval(parser)));
|
||||
}
|
||||
else if (parser->tok == TOKEN_FLOATCONST) {
|
||||
ast_value *val;
|
||||
|
@ -1199,7 +1199,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
DEBUGSHUNTDO(printf("push %g\n", parser_token(parser)->constval.f));
|
||||
DEBUGSHUNTDO(con_out("push %g\n", parser_token(parser)->constval.f));
|
||||
}
|
||||
else if (parser->tok == TOKEN_INTCONST) {
|
||||
ast_value *val;
|
||||
|
@ -1215,7 +1215,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
DEBUGSHUNTDO(printf("push %i\n", parser_token(parser)->constval.i));
|
||||
DEBUGSHUNTDO(con_out("push %i\n", parser_token(parser)->constval.i));
|
||||
}
|
||||
else if (parser->tok == TOKEN_STRINGCONST) {
|
||||
ast_value *val;
|
||||
|
@ -1231,7 +1231,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
DEBUGSHUNTDO(printf("push string\n"));
|
||||
DEBUGSHUNTDO(con_out("push string\n"));
|
||||
}
|
||||
else if (parser->tok == TOKEN_VECTORCONST) {
|
||||
ast_value *val;
|
||||
|
@ -1247,7 +1247,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
DEBUGSHUNTDO(printf("push '%g %g %g'\n",
|
||||
DEBUGSHUNTDO(con_out("push '%g %g %g'\n",
|
||||
parser_token(parser)->constval.v.x,
|
||||
parser_token(parser)->constval.v.y,
|
||||
parser_token(parser)->constval.v.z));
|
||||
|
@ -1258,7 +1258,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
}
|
||||
else if (parser->tok == ')') {
|
||||
if (wantop) {
|
||||
DEBUGSHUNTDO(printf("do[op] )\n"));
|
||||
DEBUGSHUNTDO(con_out("do[op] )\n"));
|
||||
--parens;
|
||||
if (parens < 0)
|
||||
break;
|
||||
|
@ -1267,7 +1267,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
if (!parser_close_paren(parser, &sy, false))
|
||||
goto onerr;
|
||||
} else {
|
||||
DEBUGSHUNTDO(printf("do[nop] )\n"));
|
||||
DEBUGSHUNTDO(con_out("do[nop] )\n"));
|
||||
--parens;
|
||||
if (parens < 0)
|
||||
break;
|
||||
|
@ -1348,7 +1348,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
|
||||
if (op->id == opid1('(')) {
|
||||
if (wantop) {
|
||||
DEBUGSHUNTDO(printf("push [op] (\n"));
|
||||
DEBUGSHUNTDO(con_out("push [op] (\n"));
|
||||
++parens;
|
||||
/* we expected an operator, this is the function-call operator */
|
||||
if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), 'f', sy.out_count-1))) {
|
||||
|
@ -1361,11 +1361,11 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
DEBUGSHUNTDO(printf("push [nop] (\n"));
|
||||
DEBUGSHUNTDO(con_out("push [nop] (\n"));
|
||||
}
|
||||
wantop = false;
|
||||
} else {
|
||||
DEBUGSHUNTDO(printf("push operator %s\n", op->op));
|
||||
DEBUGSHUNTDO(con_out("push operator %s\n", op->op));
|
||||
if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))
|
||||
goto onerr;
|
||||
wantop = false;
|
||||
|
@ -1392,7 +1392,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
expr = sy.out[0].out;
|
||||
MEM_VECTOR_CLEAR(&sy, out);
|
||||
MEM_VECTOR_CLEAR(&sy, ops);
|
||||
DEBUGSHUNTDO(printf("shunt done\n"));
|
||||
DEBUGSHUNTDO(con_out("shunt done\n"));
|
||||
return expr;
|
||||
|
||||
onerr:
|
||||
|
@ -2891,7 +2891,7 @@ bool parser_compile_file(const char *filename)
|
|||
{
|
||||
parser->lex = lex_open(filename);
|
||||
if (!parser->lex) {
|
||||
printf("failed to open file \"%s\"\n", filename);
|
||||
con_out("failed to open file \"%s\"\n", filename);
|
||||
return false;
|
||||
}
|
||||
return parser_compile();
|
||||
|
@ -2901,7 +2901,7 @@ bool parser_compile_string(const char *name, const char *str)
|
|||
{
|
||||
parser->lex = lex_open_string(str, strlen(str), name);
|
||||
if (!parser->lex) {
|
||||
printf("failed to create lexer for string \"%s\"\n", name);
|
||||
con_out("failed to create lexer for string \"%s\"\n", name);
|
||||
return false;
|
||||
}
|
||||
return parser_compile();
|
||||
|
@ -3023,7 +3023,7 @@ bool parser_finish(const char *output)
|
|||
{
|
||||
ir = ir_builder_new("gmqcc_out");
|
||||
if (!ir) {
|
||||
printf("failed to allocate builder\n");
|
||||
con_out("failed to allocate builder\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3036,7 +3036,7 @@ bool parser_finish(const char *output)
|
|||
isconst = field->isconst;
|
||||
field->isconst = false;
|
||||
if (!ast_global_codegen((ast_value*)field, ir)) {
|
||||
printf("failed to generate field %s\n", field->name);
|
||||
con_out("failed to generate field %s\n", field->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
|
@ -3067,40 +3067,40 @@ bool parser_finish(const char *output)
|
|||
}
|
||||
}
|
||||
if (!ast_global_codegen(asvalue, ir)) {
|
||||
printf("failed to generate global %s\n", parser->globals[i].name);
|
||||
con_out("failed to generate global %s\n", parser->globals[i].name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < parser->imm_float_count; ++i) {
|
||||
if (!ast_global_codegen(parser->imm_float[i], ir)) {
|
||||
printf("failed to generate global %s\n", parser->imm_float[i]->name);
|
||||
con_out("failed to generate global %s\n", parser->imm_float[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < parser->imm_string_count; ++i) {
|
||||
if (!ast_global_codegen(parser->imm_string[i], ir)) {
|
||||
printf("failed to generate global %s\n", parser->imm_string[i]->name);
|
||||
con_out("failed to generate global %s\n", parser->imm_string[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < parser->imm_vector_count; ++i) {
|
||||
if (!ast_global_codegen(parser->imm_vector[i], ir)) {
|
||||
printf("failed to generate global %s\n", parser->imm_vector[i]->name);
|
||||
con_out("failed to generate global %s\n", parser->imm_vector[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < parser->functions_count; ++i) {
|
||||
if (!ast_function_codegen(parser->functions[i], ir)) {
|
||||
printf("failed to generate function %s\n", parser->functions[i]->name);
|
||||
con_out("failed to generate function %s\n", parser->functions[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
if (!ir_function_finalize(parser->functions[i]->ir_func)) {
|
||||
printf("failed to finalize function %s\n", parser->functions[i]->name);
|
||||
con_out("failed to finalize function %s\n", parser->functions[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
|
@ -3108,12 +3108,12 @@ bool parser_finish(const char *output)
|
|||
|
||||
if (retval) {
|
||||
if (opts_dump)
|
||||
ir_builder_dump(ir, printf);
|
||||
ir_builder_dump(ir, con_out);
|
||||
|
||||
generate_checksum(parser);
|
||||
|
||||
if (!ir_builder_generate(ir, output)) {
|
||||
printf("*** failed to generate output file\n");
|
||||
con_out("*** failed to generate output file\n");
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
|
@ -3123,6 +3123,6 @@ bool parser_finish(const char *output)
|
|||
return retval;
|
||||
}
|
||||
|
||||
printf("*** there were compile errors\n");
|
||||
con_out("*** there were compile errors\n");
|
||||
return false;
|
||||
}
|
||||
|
|
7
util.c
7
util.c
|
@ -242,11 +242,8 @@ void util_debug(const char *area, const char *ms, ...) {
|
|||
return;
|
||||
|
||||
va_start(va, ms);
|
||||
fprintf (stdout, "DEBUG: ");
|
||||
fputc ('[', stdout);
|
||||
fprintf(stdout, "%s", area);
|
||||
fputs ("] ", stdout);
|
||||
vfprintf(stdout, ms, va);
|
||||
con_out ("[%s] ", area);
|
||||
con_vout(ms, va);
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue