replaced getline with util_getline

This commit is contained in:
Dale Weiler 2012-04-17 16:14:00 -04:00
parent f8f0cdf95d
commit 7501444add
4 changed files with 182 additions and 55 deletions

View file

@ -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
View file

@ -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);

View file

@ -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
View file

@ -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);
}