mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-17 09:02:25 +00:00
assembler can parse internal functions. Wrote all internal functions (that are not extensions) to test.qs
This commit is contained in:
parent
403901d6ee
commit
07c6aea7dc
5 changed files with 181 additions and 57 deletions
105
asm.c
105
asm.c
|
@ -21,40 +21,6 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
#include "gmqcc.h"
|
||||
/*
|
||||
* Some assembler keywords not part of the opcodes above: these are
|
||||
* for creating functions, or constants.
|
||||
*/
|
||||
const char *const asm_keys[] = {
|
||||
"FLOAT" , /* define float */
|
||||
"VECTOR" , /* define vector */
|
||||
"ENTITY" , /* define ent */
|
||||
"FIELD" , /* define field */
|
||||
"STRING" , /* define string */
|
||||
"FUNCTION"
|
||||
};
|
||||
|
||||
static char *const asm_getline(size_t *byte, FILE *fp) {
|
||||
char *line = NULL;
|
||||
ssize_t read = util_getline(&line, byte, fp);
|
||||
*byte = read;
|
||||
if (read == -1) {
|
||||
mem_d (line);
|
||||
return NULL;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
void asm_init(const char *file, FILE **fp) {
|
||||
*fp = fopen(file, "r");
|
||||
code_init();
|
||||
}
|
||||
|
||||
void asm_close(FILE *fp) {
|
||||
fclose(fp);
|
||||
code_write();
|
||||
}
|
||||
|
||||
/*
|
||||
* Following parse states:
|
||||
* ASM_FUNCTION -- in a function accepting input statements
|
||||
|
@ -71,6 +37,33 @@ typedef struct {
|
|||
} globals;
|
||||
VECTOR_MAKE(globals, assembly_constants);
|
||||
|
||||
/*
|
||||
* Assembly text processing: this handles the internal collection
|
||||
* of text to allow parsing and assemblation.
|
||||
*/
|
||||
static char *const asm_getline(size_t *byte, FILE *fp) {
|
||||
char *line = NULL;
|
||||
ssize_t read = util_getline(&line, byte, fp);
|
||||
*byte = read;
|
||||
if (read == -1) {
|
||||
mem_d (line);
|
||||
return NULL;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
/*
|
||||
* Entire external interface for main.c - to perform actual assemblation
|
||||
* of assembly files.
|
||||
*/
|
||||
void asm_init(const char *file, FILE **fp) {
|
||||
*fp = fopen(file, "r");
|
||||
code_init();
|
||||
}
|
||||
void asm_close(FILE *fp) {
|
||||
fclose(fp);
|
||||
code_write();
|
||||
}
|
||||
void asm_clear() {
|
||||
size_t i = 0;
|
||||
for (; i < assembly_constants_elements; i++)
|
||||
|
@ -114,14 +107,54 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
|
|||
return false;
|
||||
}
|
||||
/* TODO: failure system, invalid name */
|
||||
if (!isalpha(*name) || isupper(*name)) {
|
||||
if (!isalpha(*name) || util_strupper(name)) {
|
||||
printf("invalid identifer for function name\n");
|
||||
mem_d(copy);
|
||||
mem_d(name);
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("NAME: %s\n", name);
|
||||
/*
|
||||
* Function could be internal function, look for $
|
||||
* to determine this.
|
||||
*/
|
||||
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);
|
||||
mem_d(name);
|
||||
return false;
|
||||
}
|
||||
find ++;
|
||||
if (!isdigit(*find)) {
|
||||
printf("invalid internal identifier, expected valid number\n");
|
||||
mem_d(copy);
|
||||
mem_d(name);
|
||||
return false;
|
||||
}
|
||||
/* reassign name */
|
||||
mem_d(name);
|
||||
name = util_strchp(name, strchr(name, ','));
|
||||
|
||||
/* add internal function */
|
||||
code_functions_add((prog_section_function){
|
||||
-atoi(find), /* needs to be negated */
|
||||
0, 0, 0,
|
||||
.name = code_chars_elements,
|
||||
0, 0,{0}
|
||||
});
|
||||
/* add name to string table */
|
||||
code_chars_put(name, strlen(name));
|
||||
code_chars_add('\0');
|
||||
|
||||
printf("found internal function %s, -%d\n", name, atoi(find));
|
||||
}
|
||||
|
||||
mem_d(copy);
|
||||
mem_d(name);
|
||||
|
|
27
code.c
27
code.c
|
@ -205,18 +205,21 @@ void code_write() {
|
|||
*((int32_t*)&code_functions_data[i].argsize)
|
||||
);
|
||||
util_debug("GEN", " NAME: %s\n", &code_chars_data[code_functions_data[i].name]);
|
||||
util_debug("GEN", " CODE:\n");
|
||||
for (;;) {
|
||||
if (code_statements_data[j].opcode != INSTR_DONE &&
|
||||
code_statements_data[j].opcode != INSTR_RETURN)
|
||||
util_debug("GEN", " %s {0x%05d,0x%05d,0x%05d}\n",
|
||||
asm_instr[code_statements_data[j].opcode].m,
|
||||
code_statements_data[j].s1,
|
||||
code_statements_data[j].s2,
|
||||
code_statements_data[j].s3
|
||||
);
|
||||
else break;
|
||||
j++;
|
||||
/* Internal functions have no code */
|
||||
if (code_functions_data[i].entry >= 0) {
|
||||
util_debug("GEN", " CODE:\n");
|
||||
for (;;) {
|
||||
if (code_statements_data[j].opcode != INSTR_DONE &&
|
||||
code_statements_data[j].opcode != INSTR_RETURN)
|
||||
util_debug("GEN", " %s {0x%05d,0x%05d,0x%05d}\n",
|
||||
asm_instr[code_statements_data[j].opcode].m,
|
||||
code_statements_data[j].s1,
|
||||
code_statements_data[j].s2,
|
||||
code_statements_data[j].s3
|
||||
);
|
||||
else break;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
92
data/test.qs
92
data/test.qs
|
@ -1,11 +1,85 @@
|
|||
FLOAT: f 1;
|
||||
FLOAT: f 2;
|
||||
FLOAT: f 3;
|
||||
STRING: bar "hello world"
|
||||
|
||||
; these are builtin functions
|
||||
FUNCTION: foo
|
||||
FUNCTION: makevectors, $1
|
||||
FUNCTION: setorigin, $2
|
||||
FUNCTION: setmodel, $3
|
||||
FUNCTION: setsize, $4
|
||||
|
||||
FUNCTION: foo
|
||||
ADD_F 200.4f, 300.3, OFS_RETURN
|
||||
DONE
|
||||
FUNCTION: break, $6
|
||||
FUNCTION: random, $7
|
||||
FUNCTION: sound, $8
|
||||
FUNCTION: normalize, $9
|
||||
FUNCTION: error, $10
|
||||
FUNCTION: objerror, $11
|
||||
FUNCTION: vlen, $12
|
||||
FUNCTION: vectoyaw, $13
|
||||
FUNCTION: spawn, $14
|
||||
FUNCTION: remove, $15
|
||||
FUNCTION: traceline, $16
|
||||
|
||||
FUNCTION: find, $18
|
||||
FUNCTION: precache_sound, $19
|
||||
FUNCTION: precache_model, $20
|
||||
|
||||
FUNCTION: findradius, $22
|
||||
|
||||
FUNCTION: dprint, $25
|
||||
FUNCTION: ftos, $26
|
||||
FUNCTION: vtos, $27
|
||||
FUNCTION: coredump, $28
|
||||
FUNCTION: traceon, $29
|
||||
FUNCTION: traceoff, $30
|
||||
FUNCTION: eprint, $31
|
||||
FUNCTION: walkmove, $32
|
||||
|
||||
FUNCTION: droptofloor, $34
|
||||
FUNCTION: lightstyle, $35
|
||||
FUNCTION: rint, $36
|
||||
FUNCTION: floor, $37
|
||||
FUNCTION: ceil, $38
|
||||
|
||||
FUNCTION: checkbottom, $40
|
||||
FUNCTION: pointcontents, $41
|
||||
|
||||
FUNCTION: fabs, $43
|
||||
|
||||
FUNCTION: cvar, $45
|
||||
FUNCTION: localcmd, $46
|
||||
FUNCTION: nextent, $47
|
||||
FUNCTION: particle, $48
|
||||
FUNCTION: ChangeYaw, $49
|
||||
|
||||
FUNCTION: vectoangles, $51
|
||||
FUNCTION: vectoangles2, $51
|
||||
|
||||
FUNCTION: sin, $60
|
||||
FUNCTION: cos, $61
|
||||
FUNCTION: sqrt, $62
|
||||
FUNCTION: changepitch, $63
|
||||
FUNCTION: tracetoss, $64
|
||||
FUNCTION: etos, $65
|
||||
|
||||
FUNCTION: precache_file, $68
|
||||
FUNCTION: makestatic, $69
|
||||
|
||||
FUNCTION: cvar_set, $72
|
||||
|
||||
FUNCTION: ambientsound, $74
|
||||
FUNCTION: precache_model2,$75
|
||||
FUNCTION: precache_sound2,$76
|
||||
FUNCTION: precache_file2, $77
|
||||
|
||||
FUNCTION: stof, $81
|
||||
|
||||
FUNCTION: tracebox, $90
|
||||
FUNCTION: randomvec, $91
|
||||
FUNCTION: getlight, $92
|
||||
FUNCTION: getlight2, $92
|
||||
FUNCTION: registercvar, $93
|
||||
FUNCTION: min, $94
|
||||
FUNCTION: max, $95
|
||||
FUNCTION: bound, $96
|
||||
FUNCTION: pow, $97
|
||||
FUNCTION: findfloat, $98
|
||||
FUNCTION: checkextension, $99
|
||||
|
||||
; todo support other crap
|
||||
|
|
1
gmqcc.h
1
gmqcc.h
|
@ -194,6 +194,7 @@ void *util_memory_a (unsigned int, unsigned int, const char *);
|
|||
void util_memory_d (void *, unsigned int, const char *);
|
||||
void util_meminfo ();
|
||||
|
||||
bool util_strupper (const char *);
|
||||
char *util_strdup (const char *);
|
||||
char *util_strrq (char *);
|
||||
char *util_strrnl (char *);
|
||||
|
|
13
util.c
13
util.c
|
@ -166,6 +166,19 @@ char *util_strsws(const char *skip) {
|
|||
return util_strdup(skip-size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if string is all uppercase, otherwise
|
||||
* it returns false.
|
||||
*/
|
||||
bool util_strupper(const char *str) {
|
||||
while (*str) {
|
||||
if(!isupper(*str))
|
||||
return false;
|
||||
str++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void util_debug(const char *area, const char *ms, ...) {
|
||||
if (!opts_debug)
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue