vc4/asm/main.c
2025-10-02 22:44:00 +02:00

173 lines
4.3 KiB
C

#include "hash.h"
#include "map.h"
#include "parse.h"
#include "report.h"
#include "vec.h"
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char* input_file;
char* output_file;
} Args;
static int parse_args(Args* args, int argc, char** argv);
DEFINE_VEC(LineVec, line_vec, PLine*)
typedef struct {
size_t line_idx;
char* ident;
} Label;
DEFINE_STRINGMAP(LabelMap, label_map, Label)
static char* read_text_file(const char* filename);
int main(int argc, char** argv)
{
Args args;
if (parse_args(&args, argc, argv) != 0) {
return EXIT_FAILURE;
}
LabelMap labels = {};
char* text = read_text_file(args.input_file);
if (!text) {
return EXIT_FAILURE;
}
Parser* parser = parser_new(args.input_file, text);
LineVec lines;
line_vec_construct(&lines);
Label* super_label = nullptr;
while (!parser_done(parser)) {
if (parser_next_is_const(parser)) {
PConst* stmt = parser_parse_const(parser);
} else if (parser_next_is_include(parser)) {
PInclude* stmt = parser_parse_include(parser);
} else {
PLabel* label;
while ((label = parser_parse_label(parser)) != nullptr) {
if (label->local) {
char* ident = calloc(1,
strlen(super_label->ident) + strlen(label->ident) + 2);
strcat(ident, super_label->ident);
strcat(ident, ".");
strcat(ident, label->ident);
label_map_set(&labels,
ident,
(Label) {
.line_idx = lines.size + 1,
.ident = ident,
});
} else {
label_map_set(&labels,
label->ident,
(Label) {
.line_idx = lines.size + 1,
.ident = strdup(label->ident),
});
super_label = label_map_at(&labels, label->ident);
}
plabel_free(label);
}
PLine* line = parser_parse_line(parser);
line_vec_push(&lines, line);
printf("ident = '%s'\n", line->ident);
}
}
parser_free(parser);
free(text);
for (size_t i = 0; i < lines.size; ++i) {
pline_free(lines.data[i]);
}
line_vec_destroy(&lines);
for (size_t i = 0; i < labels.entries.size; ++i) {
free(labels.entries.data[i].value.ident);
}
label_map_destroy(&labels);
return EXIT_SUCCESS;
}
int parse_args(Args* args, int argc, char** argv)
{
*args = (Args) {
.input_file = nullptr,
.output_file = nullptr,
};
int i = 1;
while (i < argc) {
if (strcmp(argv[i], "-o") == 0) {
i += 1;
if (i >= argc) {
fprintf(stderr, FMT_ERROR("expected filename after '-o'"));
return 1;
}
args->output_file = argv[i];
i += 1;
} else if (argv[i][0] == '-') {
fprintf(stderr, FMT_ERROR("unrecognized argument '%s'"), argv[i]);
return 1;
} else {
if (args->input_file != nullptr) {
fprintf(stderr, FMT_ERROR("multiple input files"));
return 1;
}
args->input_file = argv[i];
i += 1;
}
}
if (!args->input_file) {
fprintf(stderr, FMT_ERROR("no input file"));
return 1;
}
return 0;
}
char* read_text_file(const char* filename)
{
FILE* fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr,
FMT_ERROR("could not open file '%s' for reading: %s"),
filename,
strerror(errno));
return NULL;
}
fseek(fp, 0L, SEEK_END);
size_t file_size = (size_t)ftell(fp);
rewind(fp);
char* text = calloc(file_size + 1, sizeof(char));
size_t bytes_read = fread(text, sizeof(char), file_size, fp);
fclose(fp);
if (bytes_read != file_size) {
fprintf(stderr,
FMT_ERROR("could not read input file '%s': %s"),
filename,
strerror(errno));
return NULL;
}
return text;
}