// growable.c
#include <stdio.h>
+#include <string.h>
#include "growable.h"
v++; \
} while(0)
-int growable_grow(struct growable *g, size_t len) {
+int growable_append(struct growable *g, void *item) {
+ size_t old_len = g->len++;
void *np;
- if (len < g->allo)
- return 0;
- if (g->allo == 0)
- g->allo = 8;
- else {
- ROUND_UP_TO_POW2(len);
- g->allo = len;
+ if (g->len > g->allo) {
+ if (g->allo == 0)
+ g->allo = 8;
+ else {
+ g->allo = g->len;
+ ROUND_UP_TO_POW2(g->allo);
+ }
+ np = realloc(g->data, g->allo * g->item_size);
+ if (np == NULL) {
+ perror("realloc");
+ return -1;
+ }
+ g->data = np;
}
- np = realloc(g->data, g->allo * g->item_size);
- if (np == NULL) {
- perror("realloc");
- return -1;
- }
- g->data = np;
+ memcpy((char*)g->data + old_len * g->item_size, item, g->item_size);
return 0;
}
#define EMPTY_GROWABLE(is) \
((struct growable){ .item_size = (is), .len = 0, .allo = 0, .data = NULL })
-int growable_grow(struct growable *g, size_t len);
+int growable_append(struct growable *g, void *item);
void growable_cleanup(const struct growable g);
#define GROWABLE_AT(g, t, i) (((t*)(g).data)[i])
) {
buffer->len = 0;
do {
- if (growable_grow(buffer, buffer->len + 1) < 0)
+ if (growable_append(buffer, &c) < 0)
return -1;
- ((char*)buffer->data)[buffer->len++] = c;
c = getc(fh);
} while (isalnum(c) || c == '_');
if (c != EOF)
ungetc(c, fh);
- if (growable_grow(buffer, buffer->len + 1) < 0)
- return -1;
if (buffer->len == 4 && strncasecmp(buffer->data, "goto", 4) == 0) {
ai->type = AST_ITEM_GOTO;
return 0;
+ } else if (buffer->len == 5 && strncasecmp(buffer->data, "print", 5) == 0) {
+ ai->type = AST_ITEM_PRINT;
+ return 0;
}
ai->type = AST_ITEM_IDENT;
ai->u.s = strndup(buffer->data, buffer->len);
int c;
struct ast_item ai;
while ((c = getc(fh)) != EOF) {
- memset(&ai.u, 0, sizeof ai.u);
+ memset(&ai, 0, sizeof ai);
switch (c) {
case '+':
ai.type = AST_ITEM_PLUS;
fprintf(stderr, "Error: Identifier expected before ':'\n");
return -1;
}
- if (growable_grow(&p->markers, p->markers.len + 1) < 0)
- return -1;
p->ast_items.len--;
- GET_MARKER(*p, p->markers.len++) = (struct ast_marker){
+ if (growable_append(&p->markers, &(struct ast_marker){
GET_ITEM(*p, p->ast_items.len).u.s,
p->ast_items.len,
- };
+ }) < 0)
+ return -1;
continue;
case '*':
ai.type = AST_ITEM_MULTIPLY;
fprintf(stderr, "Error: invalid input: '%c' (0x%02x)\n", c, c & 0xff);
return -1;
add_item:
- if (growable_grow(&p->ast_items, p->ast_items.len + 1) < 0)
+ if (growable_append(&p->ast_items, &ai) < 0)
return -1;
- memcpy(&GET_ITEM(*p, p->ast_items.len++), &ai, sizeof ai);
}
if (ferror(fh)) {
fprintf(stderr, "Error: read error.\n");
return 0;
}
}
- if (growable_grow(scope, scope->len + 1) < 0)
- return -1;
- GET_SCOPE_ITEM(*scope, scope->len++) = (struct scope_item){ name, value };
- return 0;
+ return growable_append(scope, &(struct scope_item){ name, value });
}
int evaluate_statement(const struct program p, struct growable *scope, size_t *stmt) {
if (evaluate_arith(p, scope, stmt, UNTIL_SEMICOLON, &value.u.i) < 0)
return -1;
*stmt = value.u.i;
+ } else if (item->type == AST_ITEM_PRINT) {
+ (*stmt)++;
+ if (evaluate_arith(p, scope, stmt, UNTIL_SEMICOLON, &value.u.i) < 0)
+ return -1;
+ printf("%"PRIdMAX"\n", value.u.i);
+ (*stmt)++;
} else {
fprintf(stderr, "Error: canot execute: ");
ast_item_dump(stderr, *item);
case AST_ITEM_DIVIDE:
fprintf(fh, "AST_ITEM_DIVIDE");
break;
+ case AST_ITEM_GOTO:
+ fprintf(fh, "AST_ITEM_GOTO");
+ break;
+ case AST_ITEM_PRINT:
+ fprintf(fh, "AST_ITEM_PRINT");
+ break;
default:
fprintf(fh, "ast_item_type UNKNOWN(%d)", ai.type);
}
AST_ITEM_EQUALS,
AST_ITEM_IDENT,
AST_ITEM_SEMICOLON,
- AST_ITEM_GOTO,
AST_ITEM_MULTIPLY,
AST_ITEM_DIVIDE,
+ AST_ITEM_GOTO,
+ AST_ITEM_PRINT,
} type;
union {
intmax_t i;