mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-11 03:13:06 +00:00
replaced getline with util_getline
This commit is contained in:
parent
f8f0cdf95d
commit
7501444add
4 changed files with 182 additions and 55 deletions
111
assembler.c
111
assembler.c
|
@ -31,16 +31,16 @@ static const struct {
|
|||
const size_t o; /* operands */
|
||||
const size_t l; /* menomic len */
|
||||
} const asm_instr[] = {
|
||||
[INSTR_DONE] = { "DONE" , 0, 4 },
|
||||
[INSTR_MUL_F] = { "MUL_F" , 0, 5 },
|
||||
[INSTR_MUL_V] = { "MUL_V" , 0, 5 },
|
||||
[INSTR_MUL_FV] = { "MUL_FV" , 0, 6 },
|
||||
[INSTR_MUL_VF] = { "MUL_VF" , 0, 6 },
|
||||
[INSTR_DONE] = { "DONE" , 1, 4 },
|
||||
[INSTR_MUL_F] = { "MUL_F" , 3, 5 },
|
||||
[INSTR_MUL_V] = { "MUL_V" , 3, 5 },
|
||||
[INSTR_MUL_FV] = { "MUL_FV" , 3, 6 },
|
||||
[INSTR_MUL_VF] = { "MUL_VF" , 3, 6 },
|
||||
[INSTR_DIV_F] = { "DIV" , 0, 3 },
|
||||
[INSTR_ADD_F] = { "ADD_F" , 0, 5 },
|
||||
[INSTR_ADD_V] = { "ADD_V" , 0, 5 },
|
||||
[INSTR_SUB_F] = { "SUB_F" , 0, 5 },
|
||||
[INSTR_SUB_V] = { "DUB_V" , 0, 5 },
|
||||
[INSTR_ADD_F] = { "ADD_F" , 3, 5 },
|
||||
[INSTR_ADD_V] = { "ADD_V" , 3, 5 },
|
||||
[INSTR_SUB_F] = { "SUB_F" , 3, 5 },
|
||||
[INSTR_SUB_V] = { "DUB_V" , 3, 5 },
|
||||
[INSTR_EQ_F] = { "EQ_F" , 0, 4 },
|
||||
[INSTR_EQ_V] = { "EQ_V" , 0, 4 },
|
||||
[INSTR_EQ_S] = { "EQ_S" , 0, 4 },
|
||||
|
@ -114,10 +114,10 @@ const char *const asm_keys[] = {
|
|||
|
||||
static char *const asm_getline(size_t *byte, FILE *fp) {
|
||||
char *line = NULL;
|
||||
ssize_t read = getline(&line, byte, fp);
|
||||
ssize_t read = util_getline(&line, byte, fp);
|
||||
*byte = read;
|
||||
if (read == -1) {
|
||||
free (line);
|
||||
mem_d (line);
|
||||
return NULL;
|
||||
}
|
||||
return line;
|
||||
|
@ -138,12 +138,29 @@ void asm_close(FILE *fp) {
|
|||
fclose(fp);
|
||||
code_write();
|
||||
}
|
||||
|
||||
/*
|
||||
* Following parse states:
|
||||
* ASM_FUNCTION -- in a function accepting input statements
|
||||
* ....
|
||||
*/
|
||||
typedef enum {
|
||||
ASM_NULL,
|
||||
ASM_FUNCTION
|
||||
} asm_state;
|
||||
|
||||
typedef struct {
|
||||
char *name; /* name of constant */
|
||||
int offset; /* location in globals */
|
||||
} globals;
|
||||
VECTOR_MAKE(globals, assembly_constants);
|
||||
|
||||
void asm_parse(FILE *fp) {
|
||||
char *data = NULL;
|
||||
char *skip = NULL;
|
||||
long line = 1; /* current line */
|
||||
size_t size = 0; /* size of line */
|
||||
char *data = NULL;
|
||||
char *skip = NULL;
|
||||
long line = 1; /* current line */
|
||||
size_t size = 0; /* size of line */
|
||||
asm_state state = ASM_NULL;
|
||||
|
||||
while ((data = asm_getline(&size, fp)) != NULL) {
|
||||
skip = data;
|
||||
|
@ -176,6 +193,10 @@ void asm_parse(FILE *fp) {
|
|||
(void)offset_functions; \
|
||||
(void)offset_fields; \
|
||||
(void)offset_defs; \
|
||||
assembly_constants_add((globals){ \
|
||||
.name = util_strdup(skip), \
|
||||
.offset = offset_globals \
|
||||
}); \
|
||||
} \
|
||||
goto end; \
|
||||
}
|
||||
|
@ -213,10 +234,17 @@ void asm_parse(FILE *fp) {
|
|||
.offset = offset_globals, /* offset to offset in string table (for data)*/
|
||||
.name = offset_chars /* location of name in string table (for name)*/
|
||||
});
|
||||
code_strings_add('h');
|
||||
});
|
||||
/* FUNCTION */
|
||||
DECLTYPE(asm_keys[5], {
|
||||
/* TODO: parse */
|
||||
if (state != ASM_NULL) {
|
||||
printf("%li: Error unfinished function block, expected DONE or RETURN\n", line);
|
||||
goto end;
|
||||
}
|
||||
|
||||
state = ASM_FUNCTION;
|
||||
code_defs_add((prog_section_def){
|
||||
.type = TYPE_VOID,
|
||||
.offset = offset_globals,
|
||||
|
@ -237,19 +265,64 @@ void asm_parse(FILE *fp) {
|
|||
|
||||
/* if we make it this far then we have statements */
|
||||
{
|
||||
size_t i = 0;
|
||||
size_t i = 0; /* counter */
|
||||
size_t o = 0; /* operands */
|
||||
char *t = NULL; /* token */
|
||||
|
||||
/*
|
||||
* Most ops a single statement can have is three.
|
||||
* lets allocate some space for all of those here.
|
||||
*/
|
||||
char op[3][32768] = {{0},{0},{0}};
|
||||
for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) {
|
||||
if (!strncmp(skip, asm_instr[i].m, asm_instr[i].l)) {
|
||||
/* TODO */
|
||||
if (state != ASM_FUNCTION) {
|
||||
printf("%li: Statement not inside function block\n", line);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* update parser state */
|
||||
if (i == INSTR_DONE || i == INSTR_RETURN) {
|
||||
goto end;
|
||||
state = ASM_NULL;
|
||||
}
|
||||
|
||||
/* parse the statement */
|
||||
o = asm_instr[i].o; /* operands */
|
||||
skip += asm_instr[i].l; /* skip instruction */
|
||||
t = strtok(skip, " ,");
|
||||
i = 0;
|
||||
while (t != NULL && i < 3) {
|
||||
strcpy(op[i], t);
|
||||
t = strtok(NULL, " ,");
|
||||
i ++;
|
||||
}
|
||||
|
||||
util_debug("ASM", "Operand 1: %s\n", util_strrnl(op[0]));
|
||||
util_debug("ASM", "Operand 2: %s\n", util_strrnl(op[1]));
|
||||
util_debug("ASM", "Operand 3: %s\n", util_strrnl(op[2]));
|
||||
|
||||
/* check */
|
||||
if (i != o) {
|
||||
printf("not enough operands, expected: %li, got %li\n", o, i);
|
||||
}
|
||||
|
||||
/* TODO: hashtable value LOAD .... etc */
|
||||
code_statements_add((prog_section_statement){
|
||||
i, {0}, {0}, {0}
|
||||
});
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if we made it this far something is wrong */
|
||||
printf("ERROR");
|
||||
if (*skip != '\0')
|
||||
printf("%li: Invalid statement, expression, or decleration\n", line);
|
||||
|
||||
end:
|
||||
free(data);
|
||||
//free(data);
|
||||
mem_d(data);
|
||||
line ++;
|
||||
}
|
||||
}
|
||||
|
|
50
code.c
50
code.c
|
@ -158,43 +158,26 @@ void code_write() {
|
|||
fwrite(code_globals_data, 1, sizeof(int) *code_globals_elements, fp);
|
||||
fwrite(code_strings_data, 1, 1 *code_strings_elements, fp);
|
||||
|
||||
free(code_statements_data);
|
||||
free(code_defs_data);
|
||||
free(code_fields_data);
|
||||
free(code_functions_data);
|
||||
free(code_globals_data);
|
||||
free(code_strings_data);
|
||||
mem_d(code_statements_data);
|
||||
mem_d(code_defs_data);
|
||||
mem_d(code_fields_data);
|
||||
mem_d(code_functions_data);
|
||||
mem_d(code_globals_data);
|
||||
mem_d(code_strings_data);
|
||||
|
||||
util_debug("CODE","wrote program.dat\n\
|
||||
util_debug("GEN","wrote program.dat:\n\
|
||||
version: = %d\n\
|
||||
crc16: = %d\n\
|
||||
statements {\n\
|
||||
.offset = %d\n\
|
||||
.length = %d\n\
|
||||
}\n\
|
||||
defs {\n\
|
||||
.offset = %d\n\
|
||||
.length = %d\n\
|
||||
}\n\
|
||||
fields {\n\
|
||||
.offset = %d\n\
|
||||
.length = %d\n\
|
||||
}\n\
|
||||
functions {\n\
|
||||
.offset = %d\n\
|
||||
.length = %d\n\
|
||||
}\n\
|
||||
globals {\n\
|
||||
.offset = %d\n\
|
||||
.length = %d\n\
|
||||
}\n\
|
||||
strings {\n\
|
||||
.offset = %d\n\
|
||||
.length = %d\n\
|
||||
}\n\
|
||||
entfield: = %d\n",
|
||||
entfield: = %d\n\
|
||||
statements {.offset = % 8d, .length = % 8d}\n\
|
||||
defs {.offset = % 8d, .length = % 8d}\n\
|
||||
fields {.offset = % 8d, .length = % 8d}\n\
|
||||
functions {.offset = % 8d, .length = % 8d}\n\
|
||||
globals {.offset = % 8d, .length = % 8d}\n\
|
||||
strings {.offset = % 8d, .length = % 8d}\n",
|
||||
code_header.version,
|
||||
code_header.crc16,
|
||||
code_header.entfield,
|
||||
code_header.statements.offset,
|
||||
code_header.statements.length,
|
||||
code_header.defs.offset,
|
||||
|
@ -206,8 +189,7 @@ void code_write() {
|
|||
code_header.strings.offset,
|
||||
code_header.strings.length,
|
||||
code_header.globals.offset,
|
||||
code_header.globals.length,
|
||||
code_header.entfield
|
||||
code_header.globals.length
|
||||
);
|
||||
|
||||
fclose(fp);
|
||||
|
|
5
gmqcc.h
5
gmqcc.h
|
@ -160,7 +160,9 @@ void *util_memory_a(unsigned int, unsigned int, const char *);
|
|||
void util_memory_d(void *, unsigned int, const char *);
|
||||
char *util_strdup (const char *);
|
||||
char *util_strrq (char *);
|
||||
char *util_strrnl (char *);
|
||||
void util_debug (const char *, const char *, ...);
|
||||
int util_getline (char **, size_t *, FILE *);
|
||||
|
||||
#ifdef NOTRACK
|
||||
# define mem_a(x) malloc(x)
|
||||
|
@ -181,11 +183,12 @@ void util_debug (const char *, const char *, ...);
|
|||
} else { \
|
||||
N##_allocated *= 2; \
|
||||
} \
|
||||
void *temp = realloc(N##_data, (N##_allocated * sizeof(T))); \
|
||||
void *temp = mem_a(N##_allocated * sizeof(T)); \
|
||||
if (!temp) { \
|
||||
free(temp); \
|
||||
return -1; \
|
||||
} \
|
||||
memcpy(temp, N##_data, (N##_elements * sizeof(T))); \
|
||||
N##_data = (T*)temp; \
|
||||
} \
|
||||
N##_data[N##_elements] = element; \
|
||||
|
|
71
util.c
71
util.c
|
@ -21,6 +21,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include "gmqcc.h"
|
||||
|
||||
struct memblock_t {
|
||||
|
@ -79,7 +80,7 @@ char *util_strdup(const char *s) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Removed quotes from a string, escapes from \ in string
|
||||
* Remove quotes from a string, escapes from \ in string
|
||||
* as well. This function shouldn't be used to create a
|
||||
* char array that is later freed (it uses pointer arith)
|
||||
*/
|
||||
|
@ -100,6 +101,20 @@ char *util_strrq(char *s) {
|
|||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove newline from a string (if it exists). This is
|
||||
* done pointer wise instead of strlen(), and an array
|
||||
* access.
|
||||
*/
|
||||
char *util_strrnl(char *s) {
|
||||
char *cpy = s;
|
||||
while (cpy && *cpy && *cpy != '\n')
|
||||
cpy++;
|
||||
|
||||
*cpy = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
void util_debug(const char *area, const char *ms, ...) {
|
||||
va_list va;
|
||||
va_start(va, ms);
|
||||
|
@ -110,3 +125,57 @@ void util_debug(const char *area, const char *ms, ...) {
|
|||
vfprintf(stdout, ms, va);
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements libc getline for systems that don't have it, which is
|
||||
* assmed all. This works the same as getline().
|
||||
*/
|
||||
int util_getline(char **lineptr, size_t *n, FILE *stream) {
|
||||
int chr;
|
||||
int ret;
|
||||
char *pos;
|
||||
|
||||
if (!lineptr || !n || !stream)
|
||||
return -1;
|
||||
if (!*lineptr) {
|
||||
if (!(*lineptr = mem_a((*n = 64))))
|
||||
return -1;
|
||||
}
|
||||
|
||||
chr = *n;
|
||||
pos = *lineptr;
|
||||
|
||||
for (;;) {
|
||||
int c = getc(stream);
|
||||
|
||||
if (chr < 2) {
|
||||
char *tmp = mem_a((*n+=(*n>16)?*n:64));
|
||||
if (!tmp)
|
||||
return -1;
|
||||
|
||||
chr = *n + *lineptr - pos;
|
||||
strcpy(tmp,*lineptr);
|
||||
|
||||
if (!(*lineptr = tmp))
|
||||
return -1;
|
||||
|
||||
pos = *n - chr + *lineptr;
|
||||
}
|
||||
|
||||
if (ferror(stream))
|
||||
return -1;
|
||||
if (c == EOF) {
|
||||
if (pos == *lineptr)
|
||||
return -1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*pos++ = c;
|
||||
chr--;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
*pos = '\0';
|
||||
return (ret = pos - *lineptr);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue