summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/ast.h3
-rw-r--r--src/codegen/codegen_decl.c17
-rw-r--r--src/parser/parser_expr.c2
-rw-r--r--std/io.zc62
4 files changed, 63 insertions, 21 deletions
diff --git a/src/ast/ast.h b/src/ast/ast.h
index cf082a7..a5d3d0a 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -54,7 +54,8 @@ typedef struct Type
struct Type **args; // For GENERIC args.
int arg_count;
int is_const;
- union {
+ union
+ {
int array_size; // For fixed-size arrays [T; N].
int is_varargs; // For function types (...).
int is_restrict; // For restrict pointers.
diff --git a/src/codegen/codegen_decl.c b/src/codegen/codegen_decl.c
index 4979236..42e0ba9 100644
--- a/src/codegen/codegen_decl.c
+++ b/src/codegen/codegen_decl.c
@@ -93,11 +93,18 @@ void emit_preamble(ParserContext *ctx, FILE *out)
"\"Assertion failed: \" "
"__VA_ARGS__); exit(1); }\n",
out);
- fputs("string _z_readln_raw() { char *line = NULL; size_t len = 0; "
- "if(getline(&line, &len, "
- "stdin) == -1) return NULL; if(strlen(line) > 0 && "
- "line[strlen(line)-1] == '\\n') "
- "line[strlen(line)-1] = 0; return line; }\n",
+ fputs("string _z_readln_raw() { "
+ "size_t cap = 64; size_t len = 0; "
+ "char *line = z_malloc(cap); "
+ "if(!line) return NULL; "
+ "int c; "
+ "while((c = fgetc(stdin)) != EOF) { "
+ "if(c == '\\n') break; "
+ "if(len + 1 >= cap) { cap *= 2; char *n = z_realloc(line, cap); "
+ "if(!n) { z_free(line); return NULL; } line = n; } "
+ "line[len++] = c; } "
+ "if(len == 0 && c == EOF) { z_free(line); return NULL; } "
+ "line[len] = 0; return line; }\n",
out);
fputs("int _z_scan_helper(const char *fmt, ...) { char *l = "
"_z_readln_raw(); if(!l) return "
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index 9861de6..b9a1c35 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -2335,7 +2335,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
call->type_info = type_new(TYPE_INT);
ASTNode *fmt_node = ast_create(NODE_EXPR_LITERAL);
- fmt_node->literal.type_kind = 2;
+ fmt_node->literal.type_kind = TOK_STRING;
fmt_node->literal.string_val = xstrdup(fmt);
ASTNode *head = fmt_node, *tail = fmt_node;
diff --git a/std/io.zc b/std/io.zc
index e7b6300..02018a8 100644
--- a/std/io.zc
+++ b/std/io.zc
@@ -19,25 +19,59 @@ raw {
va_end(args);
return buffer;
}
+
+ void* _z_get_stdin()
+ {
+ return stdin;
+ }
+
+ int _z_get_eof()
+ {
+ return EOF;
+ }
+
+ int _z_fgetc(void* stream)
+ {
+ return fgetc((FILE*)stream);
+ }
}
-raw {
- char* readln() {
- char* line = NULL;
- size_t len = 0;
- ssize_t read;
-
- read = getline(&line, &len, stdin);
-
- if (read != -1) {
- // Remove newline if present
- if (line[read - 1] == '\n') {
- line[read - 1] = '\0';
+
+
+fn readln() -> char* {
+ var cap: usize = 64;
+ var len: usize = 0;
+ var line: char* = malloc(cap);
+ if (line == NULL) return NULL;
+
+ var c: int;
+ var std_in = _z_get_stdin();
+ var eof_val = _z_get_eof();
+
+ while (true) {
+ c = _z_fgetc(std_in);
+ if (c == eof_val) break;
+ if (c == 10) break; // '\n'
+
+ if (len + 1 >= cap) {
+ cap = cap * 2;
+ var n = realloc(line, cap);
+ if (n == NULL) {
+ free(line);
+ return NULL;
}
- return line;
+ line = n;
}
- if (line) free(line);
+ line[len] = c;
+ len = len + 1;
+ }
+
+ if (len == 0 && c == eof_val) {
+ free(line);
return NULL;
}
+
+ line[len] = 0;
+ return line;
}