From e360e70502ea6f21ae950086c3e822d780011a73 Mon Sep 17 00:00:00 2001 From: onelin Date: Sat, 5 Sep 2026 02:08:26 +0200 Subject: Initial commit --- main.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 main.c (limited to 'main.c') diff --git a/main.c b/main.c new file mode 100644 index 0000000..e02a9f2 --- /dev/null +++ b/main.c @@ -0,0 +1,251 @@ +#include "types.h" +#include +#include +#include +#include + +typedef struct Token { + // identifying tag + enum TokenType { + t_error, + t_size, + t_multiply, + t_divide, + t_add, + t_subtract, + t_whitespace, + t_newline, + t_number, + } type; + + // change to offset + size, or line + col -- alleviated by helper structure of + // ptrs to each newline + union Data { + i32 number; + } data; +} Token_t; + +// Should also add helper structure with pointers to each line + +static isize f_read(FILE* stream, char** dst); +static i64 f_size(FILE* stream); +static void l_print_token(Token_t token); +static Token_t* l_read(char* text, isize text_length, Token_t* dst); + +int +main(int argc, char* argv[]) { + if (argc == 2) { + FILE* f = NULL; + char* contents = NULL; + isize content_length = -1; + Token_t* tokens = NULL; + + f = fopen(argv[1], "r"); + if (f == NULL) { + fprintf(stdout, "! Failed to open file: %s\n", argv[1]); + } + + if (f != NULL) { + content_length = f_read(f, &contents); + if (content_length > 0) { + printf("%s:%ld\n%s\n", argv[1], content_length, contents); + } + fclose(f); + } + + if (content_length > 0) { + tokens = l_read(contents, strlen(contents), NULL); + free(contents); + } + + if (tokens != NULL) { + printf("%d tokens\n", tokens[0].data.number); + for (int t = 0; t < tokens[0].data.number; t++) { + l_print_token(tokens[t]); + } + } + } + return 0; +} + +/* Copies the contents of the file stream to *dst. + * @param stream An open file stream. + * @param dst** Destination buffer. If *dst is NULL allocates a buffer the size + * of stream using malloc. + * @return The number of bytes copied into dst. + * @error returns -1 on error. + */ +static isize +f_read(FILE* stream, char** dst) { + i64 file_sz = f_size(stream); + + if (dst == NULL) { + fprintf(stderr, "! Got NULL ptr\n"); + } + + if (dst != NULL && *dst == NULL && file_sz > 0) { + *dst = (char*)malloc(file_sz * sizeof(char)); + } + + if (dst != NULL && *dst == NULL && file_sz > 0) { + fprintf(stderr, "! Failed to allocate %ld bytes\n", file_sz * sizeof(char)); + } + + isize bytes_read = -1; + if (dst != NULL && *dst != NULL && file_sz > 0) { + bytes_read = fread(*dst, sizeof(char), file_sz, stream); + } + + if (bytes_read < file_sz) { + fprintf(stderr, "! Failed to read file, read %ld out of %ld bytes\n", + bytes_read, file_sz); + } + + return bytes_read; +} + +/* Returns the size in bytes and rewinds the stream. + * @param stream An open file stream. + * @return the size of the file in bytes. + * @error Returns -1 on error. + */ +static i64 +f_size(FILE* stream) { + // Could ftell and rewind to previous position, but scratch that + i64 size = -1; + i32 error = fseek(stream, 0, SEEK_END); + + if (error) { + // TODO: handle pipes (check errno == ESPIPE) + fprintf(stderr, "! Failed to seek file: %s\n", strerror(errno)); + } else { + size = ftell(stream); + rewind(stream); + } + return size; +} + +static void +l_print_token(Token_t token) { + switch (token.type) { + case t_error: + fputs(" error ", stdout); + break; + case t_size: + printf(" [%d] ", token.data.number); + break; + case t_multiply: + fputs(" * ", stdout); + break; + case t_divide: + fputs(" / ", stdout); + break; + case t_add: + fputs(" + ", stdout); + break; + case t_subtract: + fputs(" - ", stdout); + break; + case t_number: + printf("%d", token.data.number); + break; + default: + break; + } +} + +/* Reads text and parses it into an array of tokens + * @param text A buffer holding the input text + * @return a pointer to dst + * @error Returns NULL on error. + */ +static Token_t* +l_read(char* text, isize text_length, Token_t* dst) { + if (text_length > 0 && dst == NULL) { + dst = (Token_t*)malloc(text_length * sizeof(Token_t)); + } + + if (text_length > 0 && dst == NULL) { + fprintf(stderr, "! Failed to allocate %ld bytes\n", + text_length * sizeof(Token_t)); + } + + if (text_length > 0 && dst != NULL) { + isize i = 0; + isize t = 1; + i32 error = 0; + + dst[0].type = t_size; + dst[0].data.number = 0; + + // TODO: rewrite to + // if token != last-token + // dst = token,line,col + // last-token = token + // t++; + // while (last-token != error) + do { + switch (text[i]) { + // case t_size: + // break; + case '*': + dst[t].type = t_multiply; + t++; + break; + case '/': + dst[t].type = t_divide; + t++; + break; + case t_add: + dst[t].type = t_add; + t++; + break; + case '-': + dst[t].type = t_subtract; + t++; + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + dst[t].type = t_number; + dst[t].data.number = text[i] - '0'; + t++; + break; + case '+': + dst[t].type = t_add; + t++; + break; + + case ' ': + case '\t': + dst[t].type = t_whitespace; + t++; + break; + + case '\n': + dst[t].type = t_newline; + t++; + break; + + default: + dst[t].type = t_error; + t++; + error = 1; + break; + } + i++; + } while (!error && i < text_length); + + dst[0].data.number = t; + } + + return dst; +} -- cgit v1.3