Read code from a file instead of argv[1]

This commit is contained in:
Rui Ueyama 2019-08-07 08:30:06 +09:00
parent ca52c2c7fd
commit 64f2d0b8a7
4 changed files with 52 additions and 5 deletions

View File

@ -1,9 +1,11 @@
#define _GNU_SOURCE
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -47,6 +49,7 @@ char *expect_ident(void);
bool at_eof(void);
Token *tokenize(void);
extern char *filename;
extern char *user_input;
extern Token *token;

23
main.c
View File

@ -1,5 +1,25 @@
#include "chibi.h"
// Returns the contents of a given file.
static char *read_file(char *path) {
// Open and read the file.
FILE *fp = fopen(path, "r");
if (!fp)
error("cannot open %s: %s", path, strerror(errno));
int filemax = 10 * 1024 * 1024;
char *buf = malloc(filemax);
int size = fread(buf, 1, filemax - 2, fp);
if (!feof(fp))
error("%s: file too large");
// Make sure that the string ends with "\n\0".
if (size == 0 || buf[size - 1] != '\n')
buf[size++] = '\n';
buf[size] = '\0';
return buf;
}
int align_to(int n, int align) {
return (n + align - 1) & ~(align - 1);
}
@ -9,7 +29,8 @@ int main(int argc, char **argv) {
error("%s: invalid number of arguments", argv[0]);
// Tokenize and parse.
user_input = argv[1];
filename = argv[1];
user_input = read_file(argv[1]);
token = tokenize();
Program *prog = program();

View File

@ -14,7 +14,7 @@ assert() {
expected="$1"
input="$2"
./chibicc "$input" > tmp.s
./chibicc <(echo "$input") > tmp.s
gcc -static -o tmp tmp.s tmp2.o
./tmp
actual="$?"

View File

@ -1,5 +1,6 @@
#include "chibi.h"
char *filename;
char *user_input;
Token *token;
@ -12,10 +13,32 @@ void error(char *fmt, ...) {
exit(1);
}
// Reports an error location and exit.
// Reports an error message in the following format and exit.
//
// foo.c:10: x = y + 1;
// ^ <error message here>
static void verror_at(char *loc, char *fmt, va_list ap) {
int pos = loc - user_input;
fprintf(stderr, "%s\n", user_input);
// Find a line containing `loc`.
char *line = loc;
while (user_input < line && line[-1] != '\n')
line--;
char *end = loc;
while (*end != '\n')
end++;
// Get a line number.
int line_num = 1;
for (char *p = user_input; p < line; p++)
if (*p == '\n')
line_num++;
// Print out the line.
int indent = fprintf(stderr, "%s:%d: ", filename, line_num);
fprintf(stderr, "%.*s\n", (int)(end - line), line);
// Show the error message.
int pos = loc - line + indent;
fprintf(stderr, "%*s", pos, ""); // print pos spaces.
fprintf(stderr, "^ ");
vfprintf(stderr, fmt, ap);