Added include functionallity.

This commit is contained in:
2025-11-23 15:23:59 +01:00
parent 6c8a15272a
commit 0ec0590ad0
9 changed files with 394 additions and 15 deletions
+13 -13
View File
@@ -1,9 +1,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <string.h>
#include "types.h"
#include "tokenizer.h"
#include "interpreter.h"
#include "native_functions.h"
#include "preprocessor.h"
int main(int argc, char **argv) {
if (argc < 2) {
@@ -11,24 +14,21 @@ int main(int argc, char **argv) {
return 1;
}
FILE *f = fopen(argv[1], "rb");
if (!f) {
printf("Could not open file.\n");
return 1;
}
char file_path[512];
strncpy(file_path, argv[1], 511);
file_path[511] = 0;
src_code = malloc(MAX_SRC + 1);
char dir_path[512];
strncpy(dir_path, argv[1], 511);
dir_path[511] = 0;
char *dir = dirname(dir_path);
src_code = preprocess(file_path, dir);
if (!src_code) {
printf("Memory allocation failed.\n");
fclose(f);
printf("Preprocessing failed.\n");
return 1;
}
size_t n = fread(src_code, 1, MAX_SRC, f);
if (n >= MAX_SRC) n = MAX_SRC - 1;
src_code[n] = 0;
fclose(f);
register_native_functions();
tokenize(src_code);
+247
View File
@@ -0,0 +1,247 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <libgen.h>
#include <unistd.h>
#include <sys/stat.h>
#include "preprocessor.h"
static IncludedFile included_files[MAX_INCLUDED_FILES];
static int included_count = 0;
static int include_depth = 0;
static void normalize_path(const char *path, char *normalized) {
strncpy(normalized, path, 255);
normalized[255] = 0;
}
static int is_already_included(const char *path) {
char normalized[256];
normalize_path(path, normalized);
for (int i = 0; i < included_count; i++) {
if (strcmp(included_files[i].path, normalized) == 0) {
return 1;
}
}
return 0;
}
static void mark_as_included(const char *path) {
if (included_count >= MAX_INCLUDED_FILES) {
fprintf(stderr, "Error: Too many included files (max %d)\n", MAX_INCLUDED_FILES);
return;
}
char normalized[256];
normalize_path(path, normalized);
strncpy(included_files[included_count].path, normalized, 255);
included_files[included_count].path[255] = 0;
included_files[included_count].included = 1;
included_count++;
}
static char* read_file(const char *filename) {
FILE *f = fopen(filename, "rb");
if (!f) {
return NULL;
}
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
if (size <= 0 || size > MAX_PREPROCESSED_SIZE) {
fclose(f);
return NULL;
}
char *content = malloc(size + 1);
if (!content) {
fclose(f);
return NULL;
}
size_t read_size = fread(content, 1, size, f);
content[read_size] = 0;
fclose(f);
return content;
}
static void resolve_include_path(const char *current_dir, const char *include_file, char *resolved_path) {
if (include_file[0] == '/') {
strncpy(resolved_path, include_file, 511);
resolved_path[511] = 0;
return;
}
snprintf(resolved_path, 512, "%s/%s", current_dir, include_file);
}
static char* process_includes(const char *filename, const char *content, const char *current_dir);
static char* extract_include_filename(const char *line) {
const char *p = line;
while (*p && isspace(*p)) p++;
if (*p != '#') return NULL;
p++;
while (*p && isspace(*p)) p++;
if (strncmp(p, "include", 7) != 0) return NULL;
p += 7;
while (*p && isspace(*p)) p++;
if (*p != '"' && *p != '<') return NULL;
char quote = (*p == '"') ? '"' : '>';
p++;
static char filename[256];
int i = 0;
while (*p && *p != quote && i < 255) {
filename[i++] = *p++;
}
filename[i] = 0;
if (*p != quote) return NULL;
return filename;
}
static char* process_includes(const char *filename, const char *content, const char *current_dir) {
if (include_depth >= MAX_INCLUDE_DEPTH) {
fprintf(stderr, "Error: Include depth exceeded (max %d) in file: %s\n",
MAX_INCLUDE_DEPTH, filename);
exit(1);
}
include_depth++;
size_t result_size = MAX_PREPROCESSED_SIZE;
char *result = malloc(result_size);
if (!result) {
fprintf(stderr, "Error: Memory allocation failed\n");
exit(1);
}
result[0] = 0;
size_t result_len = 0;
const char *p = content;
char line[1024];
while (*p) {
int line_len = 0;
while (*p && *p != '\n' && line_len < 1023) {
line[line_len++] = *p++;
}
line[line_len] = 0;
if (*p == '\n') {
p++;
}
char *include_file = extract_include_filename(line);
if (include_file) {
char resolved_path[512];
resolve_include_path(current_dir, include_file, resolved_path);
if (is_already_included(resolved_path)) {
continue;
}
mark_as_included(resolved_path);
char *included_content = read_file(resolved_path);
if (!included_content) {
fprintf(stderr, "Error: Cannot open included file: %s\n", resolved_path);
fprintf(stderr, " Included from: %s\n", filename);
free(result);
exit(1);
}
char include_dir[512];
char temp_path[512];
strncpy(temp_path, resolved_path, 511);
temp_path[511] = 0;
char *dir = dirname(temp_path);
strncpy(include_dir, dir, 511);
include_dir[511] = 0;
char *processed = process_includes(resolved_path, included_content, include_dir);
free(included_content);
size_t processed_len = strlen(processed);
if (result_len + processed_len + 2 >= result_size) {
fprintf(stderr, "Error: Preprocessed output too large (max %d bytes)\n",
MAX_PREPROCESSED_SIZE);
free(processed);
free(result);
exit(1);
}
memcpy(result + result_len, processed, processed_len);
result_len += processed_len;
result[result_len++] = '\n';
result[result_len] = 0;
free(processed);
} else {
size_t line_total = line_len + 1;
if (result_len + line_total >= result_size) {
fprintf(stderr, "Error: Preprocessed output too large (max %d bytes)\n",
MAX_PREPROCESSED_SIZE);
free(result);
exit(1);
}
if (line_len > 0) {
memcpy(result + result_len, line, line_len);
result_len += line_len;
}
result[result_len++] = '\n';
result[result_len] = 0;
}
}
include_depth--;
return result;
}
char* preprocess(const char *filename, const char *source_dir) {
included_count = 0;
include_depth = 0;
memset(included_files, 0, sizeof(included_files));
mark_as_included(filename);
char *content = read_file(filename);
if (!content) {
fprintf(stderr, "Error: Cannot read file: %s\n", filename);
return NULL;
}
char dir_path[512];
if (source_dir) {
strncpy(dir_path, source_dir, 511);
dir_path[511] = 0;
} else {
char temp_path[512];
strncpy(temp_path, filename, 511);
temp_path[511] = 0;
char *dir = dirname(temp_path);
strncpy(dir_path, dir, 511);
dir_path[511] = 0;
}
char *result = process_includes(filename, content, dir_path);
free(content);
return result;
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef PREPROCESSOR_H
#define PREPROCESSOR_H
#define MAX_INCLUDE_DEPTH 32
#define MAX_INCLUDED_FILES 256
#define MAX_PREPROCESSED_SIZE 500000
typedef struct {
char path[256];
int included;
} IncludedFile;
char* preprocess(const char *filename, const char *source_dir);
#endif