Skip to content

Commit

Permalink
feat: Include directive (#61)
Browse files Browse the repository at this point in the history
* fix: Fix castings

* feat: Implement include directive
  • Loading branch information
keyvank authored Nov 28, 2024
1 parent 9b59c8a commit d849085
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 93 deletions.
35 changes: 35 additions & 0 deletions lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "lexer.h"

char is_num(char c)
Expand Down Expand Up @@ -569,3 +570,37 @@ typed_token *tokenize(char *inp)
}
return first;
}

typed_token *tokenize_file(char *path)
{
FILE *fp = NULL;

fp = fopen(path, "rb");
if (fp == NULL)
{
fprintf(stderr, "Error opening file: %s\n", path);
exit(1);
}

char *data = NULL;
struct stat st;

if (fstat(fileno(fp), &st) == -1)
goto ret;

data = calloc(st.st_size + 1, sizeof(char));
if (!data)
goto ret;

int rd = fread(data, sizeof(char), st.st_size, fp);
if (rd != st.st_size)
{
data = NULL;
goto ret;
}
data[st.st_size] = '\0';

return tokenize(data);
ret:
return NULL;
}
1 change: 1 addition & 0 deletions lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ typedef struct typed_token_

typed_token *new_tkn(int tkn_id, void *data, void (*debug)(typed_token *));
void str_tkn_debug(typed_token *tkn);
typed_token *tokenize_file(char *path);
typed_token *tokenize(char *inp);

#define TKN_EOF 0
Expand Down
87 changes: 13 additions & 74 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,73 +7,35 @@
#include "linked_list.h"
#include "preprocess/preprocess.h"

char *read_source_file(FILE *fp);

#define MAX_INCLUDE_DEPTH 8
/**
* free() ignores NULL pointer by default. set each pointer to NULL
* after calling free() to avoid double free error.
*/
#define xfree(p) \
do \
{ \
free((p)); \
(p) = NULL; \
} while (0)

typed_token *process(const char *filename, int depth, int log_lex, int log_prep)
typed_token *process(const char *filename, int log_lex, int log_prep)
{
typed_token *tkn = NULL;
char *content = NULL;
FILE *fp = NULL;

if (depth > MAX_INCLUDE_DEPTH)
{
fprintf(stderr, "exceeded maximum include depth (%d)\n", MAX_INCLUDE_DEPTH);
goto cleanup;
}

fp = fopen(filename, "rb");
if (fp == NULL)
{
fprintf(stderr, "Error opening file: %s\n", filename);
goto cleanup;
}
content = read_source_file(fp);

if (!content)
{
fprintf(stderr, "failed to read source file: read_source_file returned NULL\n");
goto cleanup;
}
prep_ctx *ctx = (prep_ctx *)malloc(sizeof(prep_ctx));
ctx->curr_path = NULL;
ctx->defs = new_linked_list();

tkn = tokenize(content);
typed_token *lexed = tokenize_file(filename);
typed_token *prep = preprocess(ctx, filename);
if (log_lex)
{
typed_token *t = tkn;
typed_token *t = lexed;
while (t)
{
t->debug(t);
t = t->next;
}
}
tkn = preprocess(tkn);

if (log_prep)
{
typed_token *t = tkn;
typed_token *t = prep;
while (t)
{
t->debug(t);
t = t->next;
}
}

cleanup:
if (fp)
fclose(fp);
if (content)
xfree(content);
return tkn;
return prep;
}

int main(int argc, char *argv[])
Expand All @@ -84,15 +46,16 @@ int main(int argc, char *argv[])
return 1;
}

if (strcmp(argv[2], "--lex") != 0 && strcmp(argv[2], "--asm") != 0 && strcmp(argv[2], "--tree") != 0&& strcmp(argv[2], "--prep") != 0) {
if (strcmp(argv[2], "--lex") != 0 && strcmp(argv[2], "--asm") != 0 && strcmp(argv[2], "--tree") != 0 && strcmp(argv[2], "--prep") != 0)
{
fprintf(stderr, "Unknown argument %s", argv[2]);
return 1;
}

int log_lex = !strcmp(argv[2], "--lex");
int log_prep = !strcmp(argv[2], "--prep");

typed_token *tkn = process(argv[1], 0, log_lex, log_prep);
typed_token *tkn = process(argv[1], log_lex, log_prep);
if (tkn == NULL)
{
return 1;
Expand Down Expand Up @@ -135,27 +98,3 @@ int main(int argc, char *argv[])

return 0;
}

char *read_source_file(FILE *fp)
{
char *data = NULL;
struct stat st;

if (fstat(fileno(fp), &st) == -1)
goto ret;

data = calloc(st.st_size + 1, sizeof(char));
if (!data)
goto ret;

int rd = fread(data, sizeof(char), st.st_size, fp);
if (rd != st.st_size)
{
data = NULL;
goto ret;
}
data[st.st_size] = '\0';

ret:
return data;
}
76 changes: 76 additions & 0 deletions preprocess/macro_include.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <stdlib.h>
#include <stdio.h>
#include "macro_include.h"
#include "preprocess.h"
#include <string.h>

char *get_path(char *curr_path, char *header_path)
{
char *new_path = (char *)malloc(128);
strcpy(new_path, curr_path);

char *last_slash = new_path;
char *ptr = new_path;
while (*ptr)
{
if (*ptr == '/')
{
last_slash = ptr + 1;
}
ptr++;
}
strcpy(last_slash, header_path);
return new_path;
}

linked_list *seg_include_gen(seg *self, prep_ctx *ctx)
{
seg_include *inc = (seg_include *)self->data;
linked_list *ret = new_linked_list();

typed_token *t = preprocess(ctx, get_path(ctx->curr_path, inc->path));
while (t->type_id != TKN_EOF)
{
add_to_list(ret, t);
t = t->next;
}
return ret;
}

seg *parse_include(prep_ctx *ctx, typed_token **tkns_ptr)
{
typed_token *tkn = *tkns_ptr;
if (tkn->type_id == TKN_DIRECTIVE)
{
typed_token *inner_tkn = (typed_token *)tkn->data;
tkn = tkn->next;
if (inner_tkn->type_id == TKN_ID)
{
if (strcmp((char *)inner_tkn->data, "include") == 0)
{
inner_tkn = inner_tkn->next;
if (inner_tkn->type_id == TKN_LIT_STR)
{
char *path = (char *)inner_tkn->data;
inner_tkn = inner_tkn->next;

if (inner_tkn->type_id == TKN_EOF)
{
*tkns_ptr = tkn;
seg *ret = (seg *)malloc(sizeof(seg));
ret->data = malloc(sizeof(seg_include));
ret->to_code = seg_include_gen;
ret->stringified = NULL;
((seg_include *)ret->data)->path = path;
return ret;
}
else
{
return NULL;
}
}
}
}
}
return NULL;
}
14 changes: 14 additions & 0 deletions preprocess/macro_include.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef MACRO_INCLUDE_H
#define MACRO_INCLUDE_H

#include "../linked_list.h"
#include "preprocess.h"

typedef struct
{
char *path;
} seg_include;

seg *parse_include(prep_ctx *ctx, typed_token **tkns_ptr);

#endif
13 changes: 10 additions & 3 deletions preprocess/preprocess.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "preprocess.h"
#include "macro_define.h"
#include "macro_call.h"
#include "macro_include.h"
#include "token.h"

typed_token *chain_tokens(linked_list *tkns)
Expand All @@ -27,18 +28,22 @@ typed_token *chain_tokens(linked_list *tkns)
return res_first;
}

typed_token *preprocess(typed_token *tkn)
typed_token *preprocess(prep_ctx *ctx, char *path)
{
char *prev_path = ctx->curr_path;
ctx->curr_path = path;
typed_token *tkn = tokenize_file(path);
linked_list *ret = new_linked_list();
prep_ctx *ctx = (prep_ctx *)malloc(sizeof(prep_ctx));
ctx->defs = new_linked_list();

while (tkn->type_id != TKN_EOF)
{
seg *s = NULL;
if (!s)
s = parse_token(ctx, &tkn);
if (!s)
s = parse_define(ctx, &tkn);
if (!s)
s = parse_include(ctx, &tkn);
if (!s)
s = parse_macro_call(ctx, &tkn);

Expand All @@ -55,5 +60,7 @@ typed_token *preprocess(typed_token *tkn)
}
}

ctx->curr_path = prev_path;

return chain_tokens(ret);
}
3 changes: 2 additions & 1 deletion preprocess/preprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

typedef struct
{
char *curr_path;
linked_list *defs;
} prep_ctx;

Expand All @@ -15,6 +16,6 @@ typedef struct seg_
linked_list *(*to_code)(struct seg_ *self, prep_ctx *ctx);
} seg;

typed_token *preprocess(typed_token *tkn);
typed_token *preprocess(prep_ctx *ctx, char *path);

#endif
19 changes: 4 additions & 15 deletions tests/output/inp_include.c_asm_output.asm
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
TKN_INT
TKN_ID(function2)
TKN_L_PAREN
TKN_R_PAREN
TKN_L_BRACE
TKN_RETURN
TKN_LIT_INT(13)
TKN_SEMICOLON
TKN_R_BRACE
TKN_EOF
section .data
__function2_size: equ 16
__function_size: equ 16
__printf_size: equ 16
__temp_str_3 db `function: %d\n`, 0
__temp_str_4 db `function2: %d\n`, 0
__temp_str_2 db `function: %d\n`, 0
__temp_str_3 db `function2: %d\n`, 0
__main_size: equ 96
section .text
global function2
Expand Down Expand Up @@ -46,7 +35,7 @@ main:
push rbp
mov rbp, rsp
sub rsp, __main_size
mov rax, __temp_str_3
mov rax, __temp_str_2
mov [rsp+0], rax
mov rax, rsp
add rax, 0
Expand All @@ -61,7 +50,7 @@ mov rax, rsp
add rax, 0
mov [rsp+32], rax
call printf
mov rax, __temp_str_4
mov rax, __temp_str_3
mov [rsp+40], rax
mov rax, rsp
add rax, 0
Expand Down
4 changes: 4 additions & 0 deletions tests/output/inp_include.c_lex_output.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
TKN_DIRECTIVE:
TKN_ID(include)
TKN_LIT_STR(header1.h)
TKN_EOF
TKN_VOID
TKN_ID(printf)
TKN_L_PAREN
Expand Down
Loading

0 comments on commit d849085

Please sign in to comment.