173 lines
4.3 KiB
C
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;
|
|
}
|