mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-27 22:22:17 +00:00
Merge branch 'master' into ast-and-ir
This commit is contained in:
commit
206952b920
14 changed files with 152 additions and 158 deletions
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
#dissalow trailing whitespace
|
||||
*.c whitespace=-trailing-space
|
||||
*.h whitespace=-trailing-space
|
22
asm.c
22
asm.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
@ -90,7 +90,7 @@ static inline bool asm_parse_type(const char *skip, size_t line, asm_state *stat
|
|||
float val1;
|
||||
float val2;
|
||||
float val3;
|
||||
|
||||
|
||||
const char *find = skip + 7;
|
||||
while (*find == ' ' || *find == '\t') find++;
|
||||
|
||||
|
@ -116,7 +116,7 @@ static inline bool asm_parse_type(const char *skip, size_t line, asm_state *stat
|
|||
printf("X:[0] = %f\n", val1);
|
||||
printf("Y:[1] = %f\n", val2);
|
||||
printf("Z:[2] = %f\n", val3);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
/* ENTITY */ case 'E': {
|
||||
|
@ -132,7 +132,7 @@ static inline bool asm_parse_type(const char *skip, size_t line, asm_state *stat
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -170,11 +170,11 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
|
|||
*/
|
||||
if (strchr(name, ',')) {
|
||||
char *find = strchr(name, ',') + 1;
|
||||
|
||||
|
||||
/* skip whitespace */
|
||||
while (*find == ' ' || *find == '\t')
|
||||
find++;
|
||||
|
||||
|
||||
if (*find != '$') {
|
||||
printf("expected $ for internal function selection, got %s instead\n", find);
|
||||
mem_d(copy);
|
||||
|
@ -189,7 +189,7 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
|
|||
return false;
|
||||
}
|
||||
*strchr(name, ',')='\0';
|
||||
|
||||
|
||||
/*
|
||||
* Now add the following items to the code system:
|
||||
* function
|
||||
|
@ -209,7 +209,7 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
|
|||
.name = code_chars_elements
|
||||
});
|
||||
code_globals_add(code_chars_elements);
|
||||
|
||||
|
||||
code_chars_put(name, strlen(name));
|
||||
code_chars_add('\0');
|
||||
|
||||
|
@ -223,7 +223,7 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
|
|||
printf("found internal function %s, -%d\n", name, atoi(find));
|
||||
else
|
||||
printf("invalid internal function identifier, must be all numeric\n");
|
||||
|
||||
|
||||
} else {
|
||||
/* TODO: function bodies */
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ void asm_parse(FILE *fp) {
|
|||
line++; \
|
||||
util_debug("ASM", x); \
|
||||
} while (0); continue
|
||||
|
||||
|
||||
while ((data = asm_getline (&size, fp)) != NULL) {
|
||||
char *copy = util_strsws(data); /* skip whitespace */
|
||||
skip = util_strrnl(copy); /* delete newline */
|
||||
|
@ -263,7 +263,7 @@ void asm_parse(FILE *fp) {
|
|||
if (state == ASM_FUNCTION && (
|
||||
(strstr(skip, "DONE") == &skip[0])||
|
||||
(strstr(skip, "RETURN") == &skip[0]))) state = ASM_NULL;
|
||||
|
||||
|
||||
/* TODO: everything */
|
||||
(void)state;
|
||||
asm_end("asm_parse_end\n");
|
||||
|
|
2
ast.c
2
ast.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Wolfgang Bumiller
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
|
2
ast.h
2
ast.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Wolfgang Bumiller
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
|
40
code.c
40
code.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
@ -32,7 +32,7 @@ typedef struct {
|
|||
uint16_t flags; /* see propsal.txt */
|
||||
uint16_t crc16; /* What is this? */
|
||||
uint16_t skip; /* see propsal.txt */
|
||||
|
||||
|
||||
prog_section statements; /* prog_section_statement */
|
||||
prog_section defs; /* prog_section_def */
|
||||
prog_section fields; /* prog_section_field */
|
||||
|
@ -45,17 +45,17 @@ typedef struct {
|
|||
/*
|
||||
* The macros below expand to a typesafe vector implementation, which
|
||||
* can be viewed in gmqcc.h
|
||||
*
|
||||
*
|
||||
* code_statements_data -- raw prog_section_statement array
|
||||
* code_statements_elements -- number of elements
|
||||
* code_statements_allocated -- size of the array allocated
|
||||
* code_statements_add(T) -- add element (returns -1 on error)
|
||||
*
|
||||
*
|
||||
* code_vars_data -- raw prog_section_var array
|
||||
* code_vars_elements -- number of elements
|
||||
* code_vars_allocated -- size of the array allocated
|
||||
* code_vars_add(T) -- add element (returns -1 on error)
|
||||
*
|
||||
*
|
||||
* code_fields_data -- raw prog_section_field array
|
||||
* code_fields_elements -- number of elements
|
||||
* code_fields_allocated -- size of the array allocated
|
||||
|
@ -65,12 +65,12 @@ typedef struct {
|
|||
* code_functions_elements -- number of elements
|
||||
* code_functions_allocated -- size of the array allocated
|
||||
* code_functions_add(T) -- add element (returns -1 on error)
|
||||
*
|
||||
*
|
||||
* code_globals_data -- raw prog_section_def array
|
||||
* code_globals_elements -- number of elements
|
||||
* code_globals_allocated -- size of the array allocated
|
||||
* code_globals_add(T) -- add element (returns -1 on error)
|
||||
*
|
||||
*
|
||||
* code_chars_data -- raw char* array
|
||||
* code_chars_elements -- number of elements
|
||||
* code_chars_allocated -- size of the array allocated
|
||||
|
@ -87,7 +87,7 @@ void code_init() {
|
|||
/* omit creation of null code */
|
||||
if (opts_omit_nullcode)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* The way progs.dat is suppose to work is odd, there needs to be
|
||||
* some null (empty) statements, functions, and 28 globals
|
||||
|
@ -97,13 +97,13 @@ void code_init() {
|
|||
int i;
|
||||
for(i = 0; i < 28; i++)
|
||||
code_globals_add(0);
|
||||
|
||||
|
||||
code_chars_add ('\0');
|
||||
code_functions_add (empty_function);
|
||||
code_statements_add(empty_statement);
|
||||
}
|
||||
|
||||
void code_test() {
|
||||
void code_test() {
|
||||
code_chars_put("m_init", 0x6);
|
||||
code_chars_put("print", 0x5);
|
||||
code_chars_put("hello world\n", 0xC);
|
||||
|
@ -111,23 +111,23 @@ void code_test() {
|
|||
code_chars_put("m_draw", 0x6);
|
||||
code_chars_put("m_toggle", 0x8);
|
||||
code_chars_put("m_shutdown", 0xA);
|
||||
|
||||
|
||||
code_globals_add(1); /* m_init */
|
||||
code_globals_add(2); /* print */
|
||||
code_globals_add(14); /* hello world in string table */
|
||||
|
||||
|
||||
/* now the defs */
|
||||
code_defs_add((prog_section_def){.type=TYPE_VOID, .offset=28/*globals[28]*/, .name=1 }); /* m_init */
|
||||
code_defs_add((prog_section_def){.type=TYPE_FUNCTION,.offset=29/*globals[29]*/, .name=8 }); /* print */
|
||||
code_defs_add((prog_section_def){.type=TYPE_STRING, .offset=30/*globals[30]*/, .name=14}); /*hello_world*/
|
||||
|
||||
|
||||
code_functions_add((prog_section_function){1, 0, 0, 0, .name=1, 0, 0, {0}}); /* m_init */
|
||||
code_functions_add((prog_section_function){-4, 0, 0, 0, .name=8, 0, 0, {0}}); /* print */
|
||||
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13, 0,0, {0}}); /* m_keydown */
|
||||
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10, 0,0, {0}});
|
||||
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10+7, 0,0, {0}});
|
||||
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10+7+9, 0,0, {0}});
|
||||
|
||||
|
||||
code_statements_add((prog_section_statement){INSTR_STORE_F, {30}/*30 is hello_world */, {OFS_PARM0}, {0}});
|
||||
code_statements_add((prog_section_statement){INSTR_CALL1, {29}/*29 is print */, {0}, {0}});
|
||||
code_statements_add((prog_section_statement){INSTR_RETURN, {0}, {0}, {0}});
|
||||
|
@ -141,7 +141,7 @@ void code_write() {
|
|||
code_header.skip = 28;
|
||||
code_header.flags = 1;
|
||||
}
|
||||
|
||||
|
||||
code_header.version = 6;
|
||||
code_header.crc16 = 0; /* TODO: */
|
||||
code_header.statements = (prog_section){sizeof(prog_header), code_statements_elements };
|
||||
|
@ -160,7 +160,7 @@ void code_write() {
|
|||
code_chars_add('\0'); /* = */
|
||||
code_chars_add('\0'); /* P */
|
||||
}
|
||||
|
||||
|
||||
/* ensure all data is in LE format */
|
||||
util_endianswap(&code_header, 1, sizeof(prog_header));
|
||||
util_endianswap(code_statements_data, code_statements_elements, sizeof(prog_section_statement));
|
||||
|
@ -168,7 +168,7 @@ void code_write() {
|
|||
util_endianswap(code_fields_data, code_fields_elements, sizeof(prog_section_field));
|
||||
util_endianswap(code_functions_data, code_functions_elements, sizeof(prog_section_function));
|
||||
util_endianswap(code_globals_data, code_globals_elements, sizeof(int));
|
||||
|
||||
|
||||
FILE *fp = fopen("program.dat", "wb");
|
||||
fwrite(&code_header, 1, sizeof(prog_header), fp);
|
||||
fwrite(code_statements_data, 1, sizeof(prog_section_statement)*code_statements_elements, fp);
|
||||
|
@ -177,7 +177,7 @@ void code_write() {
|
|||
fwrite(code_functions_data, 1, sizeof(prog_section_function) *code_functions_elements, fp);
|
||||
fwrite(code_globals_data, 1, sizeof(int) *code_globals_elements, fp);
|
||||
fwrite(code_chars_data, 1, 1 *code_chars_elements, fp);
|
||||
|
||||
|
||||
util_debug("GEN","HEADER:\n");
|
||||
util_debug("GEN"," version: = %d\n", code_header.version );
|
||||
util_debug("GEN"," crc16: = %d\n", code_header.crc16 );
|
||||
|
@ -188,7 +188,7 @@ void code_write() {
|
|||
util_debug("GEN"," functions = {.offset = % 8d, .length = % 8d}\n", code_header.functions .offset, code_header.functions .length);
|
||||
util_debug("GEN"," globals = {.offset = % 8d, .length = % 8d}\n", code_header.globals .offset, code_header.globals .length);
|
||||
util_debug("GEN"," strings = {.offset = % 8d, .length = % 8d}\n", code_header.strings .offset, code_header.strings .length);
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
util_debug("GEN", "FUNCTIONS:\n");
|
||||
size_t i = 1;
|
||||
|
@ -222,7 +222,7 @@ void code_write() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mem_d(code_statements_data);
|
||||
mem_d(code_defs_data);
|
||||
mem_d(code_fields_data);
|
||||
|
|
8
error.c
8
error.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
@ -61,7 +61,7 @@ int error(lex_file *file, int status, const char *msg, ...) {
|
|||
char bu[1024*4]; /* enough? */
|
||||
char fu[1024*4]; /* enough? */
|
||||
va_list va;
|
||||
|
||||
|
||||
if (error_total + 1 > error_max) {
|
||||
fprintf(stderr, "%d errors and more following, bailing\n", error_total);
|
||||
exit (-1);
|
||||
|
@ -83,8 +83,8 @@ int error(lex_file *file, int status, const char *msg, ...) {
|
|||
# ifndef WIN32
|
||||
fputs ("\033[0m", stderr);
|
||||
# endif
|
||||
|
||||
|
||||
fflush (stderr);
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
28
gmqcc.h
28
gmqcc.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler, Wolfgang Bumiller
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
@ -91,7 +91,7 @@
|
|||
typedef int int16_t;
|
||||
typedef unsigned int uint16_t;
|
||||
#endif
|
||||
#if INT_MAX == 0x7FFFFFFF
|
||||
#if INT_MAX == 0x7FFFFFFF
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#elif LONG_MAX == 0x7FFFFFFF
|
||||
|
@ -104,7 +104,7 @@
|
|||
#else
|
||||
typedef unsigned int uintptr_t;
|
||||
typedef int intptr_t;
|
||||
#endif
|
||||
#endif
|
||||
/* Ensure type sizes are correct: */
|
||||
typedef char uint8_size_is_correct [sizeof(uint8_t) == 1?1:-1];
|
||||
typedef char uint16_size_if_correct [sizeof(uint16_t) == 2?1:-1];
|
||||
|
@ -121,9 +121,9 @@ typedef char intptr_size_is_correct [sizeof(uintptr_t)== sizeof(int*)?1:-1];
|
|||
typedef struct lex_file_t {
|
||||
FILE *file; /* file handler */
|
||||
char *name; /* name of file */
|
||||
char peek [5];
|
||||
char peek [5];
|
||||
char lastok[8192];
|
||||
|
||||
|
||||
int last; /* last token */
|
||||
int current; /* current token */
|
||||
int length; /* bytes left to parse */
|
||||
|
@ -163,7 +163,7 @@ enum {
|
|||
* and > the last type token which is TOKEN_VOID
|
||||
*/
|
||||
enum {
|
||||
LEX_COMMENT = 1128,
|
||||
LEX_COMMENT = 1128,
|
||||
LEX_CHRLIT ,
|
||||
LEX_STRLIT ,
|
||||
LEX_IDENT
|
||||
|
@ -222,7 +222,7 @@ void util_debug (const char *, const char *, ...);
|
|||
int util_getline (char **, size_t *, FILE *);
|
||||
void util_endianswap (void *, int, int);
|
||||
|
||||
uint32_t util_crc32(const char *, int, register const short);
|
||||
uint32_t util_crc32(const char *, int, register const short);
|
||||
|
||||
#ifdef NOTRACK
|
||||
# define mem_a(x) malloc(x)
|
||||
|
@ -271,8 +271,6 @@ uint32_t util_crc32(const char *, int, register const short);
|
|||
#define VECTOR_MAKE(T,N) \
|
||||
VECTOR_TYPE(T,N); \
|
||||
VECTOR_CORE(T,N)
|
||||
/* Builds a vector add function pointer for inside structures */
|
||||
#define VECTOR_IMPL(T,N) int (*N##_add)(T)
|
||||
|
||||
//===================================================================
|
||||
//=========================== code.c ================================
|
||||
|
@ -307,7 +305,7 @@ enum {
|
|||
|
||||
typedef struct {
|
||||
uint16_t opcode;
|
||||
|
||||
|
||||
/* operand 1 */
|
||||
union {
|
||||
int16_t s1; /* signed */
|
||||
|
@ -323,7 +321,7 @@ typedef struct {
|
|||
int16_t s3; /* signed */
|
||||
uint16_t u3; /* unsigned */
|
||||
} o3;
|
||||
|
||||
|
||||
/*
|
||||
* This is the same as the structure in darkplaces
|
||||
* {
|
||||
|
@ -365,8 +363,8 @@ typedef struct {
|
|||
uint8_t argsize[8]; /* size of arguments (keep 8 always?) */
|
||||
} prog_section_function;
|
||||
|
||||
/*
|
||||
* Instructions
|
||||
/*
|
||||
* Instructions
|
||||
* These are the external instructions supported by the interperter
|
||||
* this is what things compile to (from the C code).
|
||||
*/
|
||||
|
@ -449,7 +447,7 @@ enum {
|
|||
/*
|
||||
* The symbols below are created by the following
|
||||
* expanded macros:
|
||||
*
|
||||
*
|
||||
* VECTOR_MAKE(prog_section_statement, code_statements);
|
||||
* VECTOR_MAKE(prog_section_def, code_defs );
|
||||
* VECTOR_MAKE(prog_section_field, code_fields );
|
||||
|
@ -488,7 +486,7 @@ void code_init ();
|
|||
//===================================================================
|
||||
static const struct {
|
||||
const char *m; /* menomic */
|
||||
const size_t o; /* operands */
|
||||
const size_t o; /* operands */
|
||||
const size_t l; /* menomic len */
|
||||
} const asm_instr[] = {
|
||||
[INSTR_DONE] = { "DONE" , 1, 4 },
|
||||
|
|
2
ir.c
2
ir.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Wolfgang Bumiller
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
|
2
ir.h
2
ir.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Wolfgang Bumiller
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
|
115
lex.c
115
lex.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
@ -42,21 +42,21 @@ void lex_init(const char *file, lex_file **set) {
|
|||
mem_d(lex);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fseek(lex->file, 0, SEEK_END);
|
||||
lex->length = ftell(lex->file);
|
||||
lex->size = lex->length; /* copy, this is never changed */
|
||||
fseek(lex->file, 0, SEEK_SET);
|
||||
lex->last = 0;
|
||||
lex->line = 0;
|
||||
|
||||
lex->line = 1;
|
||||
|
||||
memset(lex->peek, 0, sizeof(lex->peek));
|
||||
*set = lex;
|
||||
}
|
||||
|
||||
void lex_close(lex_file *file) {
|
||||
if (!file) return;
|
||||
|
||||
|
||||
fclose(file->file); /* may already be closed */
|
||||
mem_d (file);
|
||||
}
|
||||
|
@ -77,14 +77,25 @@ static inline void lex_clear(lex_file *file) {
|
|||
* it's own internal state for this.
|
||||
*/
|
||||
static int lex_inget(lex_file *file) {
|
||||
char get;
|
||||
file->length --;
|
||||
if (file->last > 0)
|
||||
return file->peek[--file->last];
|
||||
return fgetc(file->file);
|
||||
|
||||
if (file->last > 0) {
|
||||
if ((get = file->peek[--file->last]) == '\n')
|
||||
file->line ++;
|
||||
return get;
|
||||
}
|
||||
if ((get = fgetc(file->file)) == '\n')
|
||||
file->line++;
|
||||
|
||||
return get;
|
||||
}
|
||||
static void lex_unget(int ch, lex_file *file) {
|
||||
if (file->last < sizeof(file->peek))
|
||||
if (file->last < sizeof(file->peek)) {
|
||||
if (ch == '\n')
|
||||
file->line --;
|
||||
file->peek[file->last++] = ch;
|
||||
}
|
||||
file->length ++;
|
||||
}
|
||||
|
||||
|
@ -98,7 +109,7 @@ static int lex_trigraph(lex_file *file) {
|
|||
lex_unget(ch, file);
|
||||
return '?';
|
||||
}
|
||||
|
||||
|
||||
ch = lex_inget(file);
|
||||
switch (ch) {
|
||||
case '(' : return '[' ;
|
||||
|
@ -132,29 +143,17 @@ static int lex_digraph(lex_file *file, int first) {
|
|||
if (ch == '>') return ']';
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
lex_unget(ch, file);
|
||||
return first;
|
||||
}
|
||||
|
||||
static int lex_getch(lex_file *file) {
|
||||
int ch = lex_inget(file);
|
||||
|
||||
static int str = 0;
|
||||
switch (ch) {
|
||||
case '?' :
|
||||
return lex_trigraph(file);
|
||||
case '<' :
|
||||
case ':' :
|
||||
case '%' :
|
||||
case '"' : str = !str; if (str) { file->line ++; }
|
||||
return lex_digraph(file, ch);
|
||||
|
||||
case '\n':
|
||||
if (!str)
|
||||
file->line++;
|
||||
}
|
||||
|
||||
if (ch == '?')
|
||||
return lex_trigraph(file);
|
||||
if (ch == '<' || ch == ':' || ch == '%')
|
||||
return lex_digraph(file, ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
@ -162,11 +161,11 @@ static int lex_get(lex_file *file) {
|
|||
int ch;
|
||||
if (!isspace(ch = lex_getch(file)))
|
||||
return ch;
|
||||
|
||||
|
||||
/* skip over all spaces */
|
||||
while (isspace(ch) && ch != '\n')
|
||||
ch = lex_getch(file);
|
||||
|
||||
|
||||
if (ch == '\n')
|
||||
return ch;
|
||||
lex_unget(ch, file);
|
||||
|
@ -176,13 +175,13 @@ static int lex_get(lex_file *file) {
|
|||
static int lex_skipchr(lex_file *file) {
|
||||
int ch;
|
||||
int it;
|
||||
|
||||
|
||||
lex_clear(file);
|
||||
lex_addch('\'', file);
|
||||
|
||||
|
||||
for (it = 0; it < 2 && ((ch = lex_inget(file)) != '\''); it++) {
|
||||
lex_addch(ch, file);
|
||||
|
||||
|
||||
if (ch == '\n')
|
||||
return ERROR_LEX;
|
||||
if (ch == '\\')
|
||||
|
@ -190,10 +189,10 @@ static int lex_skipchr(lex_file *file) {
|
|||
}
|
||||
lex_addch('\'', file);
|
||||
lex_addch('\0', file);
|
||||
|
||||
|
||||
if (it > 2)
|
||||
return ERROR_LEX;
|
||||
|
||||
|
||||
return LEX_CHRLIT;
|
||||
}
|
||||
|
||||
|
@ -201,30 +200,30 @@ static int lex_skipstr(lex_file *file) {
|
|||
int ch;
|
||||
lex_clear(file);
|
||||
lex_addch('"', file);
|
||||
|
||||
|
||||
while ((ch = lex_getch(file)) != '"') {
|
||||
if (ch == '\n' || ch == EOF)
|
||||
return ERROR_LEX;
|
||||
|
||||
|
||||
lex_addch(ch, file);
|
||||
if (ch == '\\')
|
||||
lex_addch(lex_inget(file), file);
|
||||
}
|
||||
|
||||
|
||||
lex_addch('"', file);
|
||||
lex_addch('\0', file);
|
||||
|
||||
|
||||
return LEX_STRLIT;
|
||||
}
|
||||
static int lex_skipcmt(lex_file *file) {
|
||||
int ch;
|
||||
lex_clear(file);
|
||||
ch = lex_getch(file);
|
||||
|
||||
|
||||
if (ch == '/') {
|
||||
lex_addch('/', file);
|
||||
lex_addch('/', file);
|
||||
|
||||
|
||||
while ((ch = lex_getch(file)) != '\n') {
|
||||
if (ch == '\\') {
|
||||
lex_addch(ch, file);
|
||||
|
@ -236,14 +235,14 @@ static int lex_skipcmt(lex_file *file) {
|
|||
lex_addch('\0', file);
|
||||
return LEX_COMMENT;
|
||||
}
|
||||
|
||||
|
||||
if (ch != '*') {
|
||||
lex_unget(ch, file);
|
||||
return '/';
|
||||
}
|
||||
|
||||
|
||||
lex_addch('/', file);
|
||||
|
||||
|
||||
/* hate this */
|
||||
do {
|
||||
lex_addch(ch, file);
|
||||
|
@ -255,16 +254,16 @@ static int lex_skipcmt(lex_file *file) {
|
|||
}
|
||||
lex_addch(ch, file);
|
||||
} while ((ch = lex_getch(file)) != '/');
|
||||
|
||||
|
||||
lex_addch('/', file);
|
||||
lex_addch('\0', file);
|
||||
|
||||
|
||||
return LEX_COMMENT;
|
||||
}
|
||||
|
||||
static int lex_getsource(lex_file *file) {
|
||||
int ch = lex_get(file);
|
||||
|
||||
|
||||
/* skip char/string/comment */
|
||||
switch (ch) {
|
||||
case '\'': return lex_skipchr(file);
|
||||
|
@ -278,29 +277,23 @@ static int lex_getsource(lex_file *file) {
|
|||
int lex_token(lex_file *file) {
|
||||
int ch = lex_getsource(file);
|
||||
int it;
|
||||
|
||||
|
||||
/* valid identifier */
|
||||
if (ch > 0 && (ch == '_' || isalpha(ch))) {
|
||||
lex_clear(file);
|
||||
|
||||
/*
|
||||
* Yes this is dirty, but there is no other _sane_ easy
|
||||
* way to do it, this is what I call defensive programming
|
||||
* if something breaks, add more defense :-)
|
||||
*/
|
||||
while (ch > 0 && ch != ' ' && ch != '(' &&
|
||||
ch != '\n' && ch != ';' && ch != ')') {
|
||||
|
||||
while (ch > 0 && (ch == '_' || isalpha(ch))) {
|
||||
lex_addch(ch, file);
|
||||
ch = lex_getsource(file);
|
||||
}
|
||||
lex_unget(ch, file);
|
||||
lex_addch('\0', file);
|
||||
|
||||
|
||||
/* look inside the table for a keyword .. */
|
||||
for (it = 0; it < sizeof(lex_keywords)/sizeof(*lex_keywords); it++)
|
||||
if (!strncmp(file->lastok, lex_keywords[it], strlen(lex_keywords[it])))
|
||||
return it;
|
||||
|
||||
|
||||
/* try a type? */
|
||||
#define TEST_TYPE(X) \
|
||||
do { \
|
||||
|
@ -315,13 +308,13 @@ int lex_token(lex_file *file) {
|
|||
if (!strncmp(X, "void" , sizeof("void"))) \
|
||||
return TOKEN_VOID; \
|
||||
} while(0)
|
||||
|
||||
|
||||
TEST_TYPE(file->lastok);
|
||||
|
||||
|
||||
/* try the hashtable for typedefs? */
|
||||
if (typedef_find(file->lastok))
|
||||
TEST_TYPE(typedef_find(file->lastok)->name);
|
||||
|
||||
|
||||
#undef TEST_TYPE
|
||||
return LEX_IDENT;
|
||||
}
|
||||
|
@ -333,7 +326,7 @@ void lex_reset(lex_file *file) {
|
|||
file->last = 0;
|
||||
file->length = file->size;
|
||||
fseek(file->file, 0, SEEK_SET);
|
||||
|
||||
|
||||
memset(file->peek, 0, sizeof(file->peek ));
|
||||
memset(file->lastok, 0, sizeof(file->lastok));
|
||||
}
|
||||
|
|
10
main.c
10
main.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
@ -133,7 +133,7 @@ int main(int argc, char **argv) {
|
|||
break;
|
||||
}
|
||||
return usage(app);
|
||||
|
||||
|
||||
}
|
||||
++argv;
|
||||
--argc;
|
||||
|
@ -143,7 +143,7 @@ int main(int argc, char **argv) {
|
|||
* options could depend on another option, this is where option
|
||||
* validity checking like that would take place.
|
||||
*/
|
||||
if (opts_memchk && !opts_debug)
|
||||
if (opts_memchk && !opts_debug)
|
||||
printf("Warning: cannot enable -memchk, without -debug.\n");
|
||||
|
||||
util_debug("COM", "starting ...\n");
|
||||
|
@ -163,12 +163,12 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
util_debug("COM", "cleaning ...\n");
|
||||
util_debug("COM", "cleaning ...\n");
|
||||
/* clean list */
|
||||
for (itr = 0; itr < items_elements; itr++)
|
||||
mem_d(items_data[itr].name);
|
||||
mem_d(items_data);
|
||||
|
||||
|
||||
util_meminfo();
|
||||
return 0;
|
||||
clean_params_usage:
|
||||
|
|
58
parse.c
58
parse.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
@ -48,34 +48,34 @@ void compile_constant_debug() {
|
|||
* Generates a parse tree out of the lexees generated by the lexer. This
|
||||
* is where the tree is built. This is where valid check is performed.
|
||||
*/
|
||||
int parse_gen(lex_file *file) {
|
||||
int parse_gen(lex_file *file) {
|
||||
int token = 0;
|
||||
while ((token = lex_token(file)) != ERROR_LEX && file->length >= 0) {
|
||||
switch (token) {
|
||||
case TOKEN_TYPEDEF: {
|
||||
char *f; /* from */
|
||||
char *t; /* to */
|
||||
|
||||
token = lex_token(file);
|
||||
|
||||
token = lex_token(file);
|
||||
token = lex_token(file); f = util_strdup(file->lastok);
|
||||
token = lex_token(file);
|
||||
token = lex_token(file);
|
||||
token = lex_token(file); t = util_strdup(file->lastok);
|
||||
|
||||
|
||||
typedef_add(file, f, t);
|
||||
mem_d(f);
|
||||
mem_d(t);
|
||||
|
||||
|
||||
token = lex_token(file);
|
||||
if (token == ' ')
|
||||
token = lex_token(file);
|
||||
|
||||
|
||||
if (token != ';')
|
||||
error(file, ERROR_PARSE, "Expected a `;` at end of typedef statement");
|
||||
|
||||
|
||||
token = lex_token(file);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case TOKEN_VOID: goto fall;
|
||||
case TOKEN_STRING: goto fall;
|
||||
case TOKEN_VECTOR: goto fall;
|
||||
|
@ -85,20 +85,20 @@ int parse_gen(lex_file *file) {
|
|||
fall:;
|
||||
char *name = NULL;
|
||||
int type = token; /* story copy */
|
||||
|
||||
|
||||
/* skip over space */
|
||||
token = lex_token(file);
|
||||
if (token == ' ')
|
||||
token = lex_token(file);
|
||||
|
||||
|
||||
/* save name */
|
||||
name = util_strdup(file->lastok);
|
||||
|
||||
|
||||
/* skip spaces */
|
||||
token = lex_token(file);
|
||||
if (token == ' ')
|
||||
token = lex_token(file);
|
||||
|
||||
|
||||
if (token == ';') {
|
||||
/*
|
||||
* Definitions go to the defs table, they don't have
|
||||
|
@ -108,12 +108,12 @@ int parse_gen(lex_file *file) {
|
|||
token = lex_token(file);
|
||||
if (token == ' ')
|
||||
token = lex_token(file);
|
||||
|
||||
|
||||
/* strings are in file->lastok */
|
||||
switch (type) {
|
||||
case TOKEN_VOID:
|
||||
error(file, ERROR_PARSE, "Cannot assign value to type void\n");
|
||||
|
||||
|
||||
/* TODO: Validate (end quote), strip quotes for constant add, name constant */
|
||||
case TOKEN_STRING:
|
||||
if (*file->lastok != '"')
|
||||
|
@ -133,13 +133,13 @@ int parse_gen(lex_file *file) {
|
|||
float compile_calc_z = 0;
|
||||
int compile_calc_d = 0; /* dot? */
|
||||
int compile_calc_s = 0; /* sign (-, +) */
|
||||
|
||||
|
||||
char compile_data[1024];
|
||||
char *compile_eval = compile_data;
|
||||
|
||||
|
||||
if (token != '{')
|
||||
error(file, ERROR_PARSE, "Expected initializer list {} for vector constant\n");
|
||||
|
||||
error(file, ERROR_PARSE, "Expected initializer list {} for vector constant\n");
|
||||
|
||||
/*
|
||||
* This parses a single vector element: x,y & z. This will handle all the
|
||||
* complicated mechanics of a vector, and can be extended as well. This
|
||||
|
@ -188,7 +188,7 @@ int parse_gen(lex_file *file) {
|
|||
compile_calc_s = 0; \
|
||||
compile_eval = &compile_data[0]; \
|
||||
memset(compile_data, 0, sizeof(compile_data))
|
||||
|
||||
|
||||
/*
|
||||
* Parse all elements using the macro above.
|
||||
* We must undef the macro afterwards.
|
||||
|
@ -197,14 +197,14 @@ int parse_gen(lex_file *file) {
|
|||
PARSE_VEC_ELEMENT('y', y);
|
||||
PARSE_VEC_ELEMENT('z', z);
|
||||
#undef PARSE_VEC_ELEMENT
|
||||
|
||||
|
||||
/* Check for the semi-colon... */
|
||||
token = lex_token(file);
|
||||
if (token == ' ')
|
||||
token = lex_token(file);
|
||||
if (token != ';')
|
||||
error(file, ERROR_PARSE, "Expected `;` on end of constant initialization for vector\n");
|
||||
|
||||
|
||||
/* add the compile-time constant */
|
||||
compile_constants_add((constant){
|
||||
.name = util_strdup(name),
|
||||
|
@ -218,7 +218,7 @@ int parse_gen(lex_file *file) {
|
|||
});
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case TOKEN_ENTITY:
|
||||
case TOKEN_FLOAT: /*TODO: validate, constant generation, name constant */
|
||||
if (!isdigit(token))
|
||||
|
@ -236,7 +236,7 @@ int parse_gen(lex_file *file) {
|
|||
}
|
||||
mem_d(name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* From here down is all language punctuation: There is no
|
||||
* need to actual create tokens from these because they're already
|
||||
|
@ -261,10 +261,10 @@ int parse_gen(lex_file *file) {
|
|||
token = lex_token(file);
|
||||
if (token == '\n')
|
||||
return error(file, ERROR_PARSE, "Invalid use of include preprocessor directive: wanted #include \"file.h\"\n");
|
||||
|
||||
|
||||
char *copy = util_strdup(file->lastok);
|
||||
lex_file *next = lex_include(file, copy);
|
||||
|
||||
|
||||
if (!next) {
|
||||
error(file, ERROR_INTERNAL, "Include subsystem failure\n");
|
||||
exit (-1);
|
||||
|
@ -283,7 +283,7 @@ int parse_gen(lex_file *file) {
|
|||
while (token != '\n')
|
||||
token = lex_token(file);
|
||||
break;
|
||||
|
||||
|
||||
case LEX_IDENT:
|
||||
token = lex_token(file);
|
||||
break;
|
||||
|
@ -301,4 +301,4 @@ int parse_gen(lex_file *file) {
|
|||
mem_d(compile_constants_data);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Copyright (C) 2012
|
||||
* Dale Weiler
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
@ -52,17 +52,17 @@ void typedef_clear() {
|
|||
int typedef_add(lex_file *file, const char *from, const char *to) {
|
||||
unsigned int hash = typedef_hash(to);
|
||||
typedef_node *find = typedef_table[hash];
|
||||
|
||||
|
||||
if (find)
|
||||
return error(file, ERROR_PARSE, "typedef for %s already exists or conflicts\n", to);
|
||||
|
||||
|
||||
/* check if the type exists first */
|
||||
if (strncmp(from, "float", sizeof("float")) == 0 ||
|
||||
strncmp(from, "vector", sizeof("vector")) == 0 ||
|
||||
strncmp(from, "string", sizeof("string")) == 0 ||
|
||||
strncmp(from, "entity", sizeof("entity")) == 0 ||
|
||||
strncmp(from, "void", sizeof("void")) == 0) {
|
||||
|
||||
|
||||
typedef_table[hash] = mem_a(sizeof(typedef_node));
|
||||
if (typedef_table[hash])
|
||||
typedef_table[hash]->name = util_strdup(from);
|
||||
|
|
10
util.c
10
util.c
|
@ -33,7 +33,7 @@ struct memblock_t {
|
|||
const char *file;
|
||||
unsigned int line;
|
||||
unsigned int byte;
|
||||
};
|
||||
};
|
||||
|
||||
void *util_memory_a(unsigned int byte, unsigned int line, const char *file) {
|
||||
struct memblock_t *info = malloc(sizeof(struct memblock_t) + byte);
|
||||
|
@ -127,10 +127,10 @@ char *util_strchp(const char *s, const char *e) {
|
|||
if (!s || !e)
|
||||
return NULL;
|
||||
|
||||
const char *c = s;
|
||||
const char *c = s;
|
||||
while (c != e)
|
||||
c++;
|
||||
|
||||
|
||||
return util_strdup(s);
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ char *util_strsws(const char *skip) {
|
|||
size_t size = 0;
|
||||
if (!skip)
|
||||
return NULL;
|
||||
|
||||
|
||||
while (*skip == ' ' || *skip == '\t')
|
||||
skip++,size++;
|
||||
return util_strdup(skip-size);
|
||||
|
@ -324,7 +324,7 @@ static const uint16_t util_crc16_table[] = {
|
|||
0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
|
||||
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Implements a CRC function for X worth bits using (uint[X]_t)
|
||||
* as type. and util_crc[X]_table.
|
||||
|
|
Loading…
Reference in a new issue