vm-translator/main.c

259 lines
5.1 KiB
C
Raw Permalink Normal View History

2020-10-29 20:22:03 -04:00
#include <stdio.h>
#include <string.h>
#include <errno.h>
2020-10-31 18:00:09 -04:00
#include <stdlib.h>
2020-11-17 12:12:39 -05:00
#include <sys/types.h>
#include <dirent.h>
2020-11-19 06:10:51 -05:00
#include <stdbool.h>
2020-11-19 06:45:31 -05:00
#include <unistd.h>
2020-10-29 20:22:03 -04:00
#include "parser.h"
2020-10-30 13:06:02 -04:00
#include "translator.h"
2020-11-17 12:12:39 -05:00
#include "bootstrap.h"
#include "util.h"
2020-10-29 20:22:03 -04:00
2020-11-19 06:45:31 -05:00
#include <limits.h>
#ifndef PATH_MAX
#ifdef __linux__
#include <linux/limits.h>
#else
#define PATH_MAX 512
#endif
#endif
2020-11-19 06:10:51 -05:00
typedef struct {
2020-11-17 12:12:39 -05:00
char** files;
char** fnames;
int filecount;
int filessz;
char* output;
2020-11-19 06:10:51 -05:00
} TRANSLATIONLIST;
2020-11-17 12:12:39 -05:00
char* getname(char* f, int len) {
int startind = 0;
int endind = len - 1;
2020-11-19 06:10:51 -05:00
bool readsmt = false;
2020-11-17 12:12:39 -05:00
for(int i = endind; i >= 0; i--) {
if(f[i] == '/') {
if(!readsmt) {
endind = i-1;
f[i] = '\0';
continue;
2020-10-31 18:00:09 -04:00
}
2020-11-17 12:12:39 -05:00
startind = i+1;
break;
2020-10-31 18:00:09 -04:00
}
2020-11-17 12:12:39 -05:00
if(f[i] == '.')
endind = i-1;
2020-11-19 06:10:51 -05:00
readsmt = true;
2020-11-17 12:12:39 -05:00
}
int size = sizeof(char)*(endind - startind + 2);
char* startstr = f + (sizeof(char)*startind);
char* retstr = (char*)malloc(size);
snprintf(retstr, size, "%s", startstr);
return retstr;
}
char* getfullname(char* f, int len) {
int endind = len - 1;
2020-11-19 06:10:51 -05:00
bool readsmt = false;
2020-11-17 12:12:39 -05:00
for(int i = endind; i >= 0; i--) {
if(f[i] == '/') {
if(!readsmt) {
endind = i-1;
continue;
}
break;
}
if(f[i] == '.')
endind = i-1;
2020-11-19 06:10:51 -05:00
readsmt = true;
2020-11-17 12:12:39 -05:00
}
int size = sizeof(char)*(endind + 2);
char* retstr = (char*)malloc(size);
snprintf(retstr, size, "%s", f);
return retstr;
}
2020-11-19 06:10:51 -05:00
bool isdotvm(char* f, int extind) {
2020-11-17 12:12:39 -05:00
char* extstr = f + (sizeof(char) * extind);
return strcmp(extstr, ".vm") == 0;
}
2020-11-19 06:10:51 -05:00
bool isdir(char* f, int len) {
bool readsmt = false;
2020-11-17 12:12:39 -05:00
for(int i = len-1; i >= 0; i--) {
if(f[i] == '.')
if(readsmt)
2020-11-19 06:10:51 -05:00
return false;
2020-11-17 12:12:39 -05:00
else
continue;
if(f[i] == '/')
return 1;
2020-11-19 06:10:51 -05:00
readsmt = true;
2020-10-31 18:00:09 -04:00
}
2020-11-19 06:10:51 -05:00
return true;
2020-10-31 18:00:09 -04:00
}
2020-11-19 06:10:51 -05:00
char* getoutname(char* input, int len, bool isdir) {
2020-11-17 12:12:39 -05:00
char* outname;
if(isdir) {
2020-11-19 06:45:31 -05:00
char olddir[PATH_MAX];
getcwd(olddir, PATH_MAX);
chdir(input);
char buf[PATH_MAX];
getcwd(buf, PATH_MAX);
chdir(olddir);
char* name = getname(buf, strlen(buf));
2020-11-17 12:12:39 -05:00
int sz = sizeof(char) * (strlen(name)+len+6);
outname = (char*)malloc(sz);
snprintf(outname, sz, "%s/%s.asm", input, name);
free(name);
}
else {
char* name = getfullname(input, len);
int sz = sizeof(char) * (strlen(name)+5);
outname = (char*)malloc(sz);
snprintf(outname, sz, "%s.asm", name);
free(name);
}
2020-11-01 17:11:11 -05:00
return outname;
}
2020-11-19 06:10:51 -05:00
void addfile(TRANSLATIONLIST* l, char* fullname, char* name) {
2020-11-17 12:12:39 -05:00
int count = l->filecount;
int targsize = (count + 1) * sizeof(char*);
if(l->filessz < targsize) {
int newsz = targsize * 2;
l->files = realloc(l->files, newsz);
l->fnames = realloc(l->fnames, newsz);
l->filessz = newsz;
}
l->files[count] = fullname;
l->fnames[count] = name;
l->filecount++;
}
2020-11-19 06:10:51 -05:00
TRANSLATIONLIST* getfiles(char* input) {
2020-11-17 12:12:39 -05:00
int filessz = sizeof(char*) * 16;
2020-11-19 06:10:51 -05:00
TRANSLATIONLIST* filelist = (TRANSLATIONLIST*)malloc(sizeof(TRANSLATIONLIST));
2020-11-17 12:12:39 -05:00
filelist->files = (char**)malloc(filessz);
filelist->fnames = (char**)malloc(filessz);
filelist->filessz = filessz;
filelist->filecount = 0;
int inplen = strlen(input);
2020-11-19 06:10:51 -05:00
bool isitdir = isdir(input, inplen);
2020-11-17 12:12:39 -05:00
if(isitdir) {
DIR* dir = opendir(input);
if(dir == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
struct dirent* thisfile;
while(thisfile = readdir(dir), thisfile != NULL) {
int len = strlen(thisfile->d_name);
if(len > 3) {
int extind = len - 3;
if(isdotvm(thisfile->d_name, extind)) {
int sz = sizeof(char)*(len+inplen+2);
char* str = (char*)malloc(sz);
snprintf(str, sz, "%s/%s", input, thisfile->d_name);
char* name = getname(thisfile->d_name, len);
addfile(filelist, str, name);
}
}
}
closedir(dir);
if(filelist->filecount <= 0) {
fprintf(stderr, "Directory doesn't have any .vm file\n");
exit(1);
}
filelist->output = getoutname(input, inplen, isitdir);
}
else {
int extind = inplen - 3;
if(isdotvm(input, extind)){
char* name = getname(input, inplen);
char* f = heapstr(input, inplen);
addfile(filelist, f, name);
}
else {
fprintf(stderr, "Input file must be named like 'Xxx.vm'\n");
exit(1);
}
filelist->output = getoutname(input, inplen, isitdir);
}
return filelist;
}
2020-11-19 06:10:51 -05:00
void freetranslationlist(TRANSLATIONLIST* ls) {
2020-11-17 12:12:39 -05:00
for(int i = 0; i < ls->filecount; i++) {
free(ls->files[i]);
free(ls->fnames[i]);
}
free(ls->files);
free(ls->fnames);
free(ls->output);
free(ls);
}
2020-10-29 20:22:03 -04:00
int main(int argc, char* argv[]) {
if(argc < 2) {
fprintf(stderr, "Usage: %s {file}\n", argv[0]);
return 1;
}
2020-11-19 06:10:51 -05:00
TRANSLATIONLIST* ls = getfiles(argv[1]);
2020-11-17 12:12:39 -05:00
FILE* output = fopen(ls->output, "w");
for(int i = 0; i < BOOTSTRAPN; i++) {
fprintf(output, "%s\n", bootstrapcode[i]);
2020-10-29 20:22:03 -04:00
}
2020-11-17 12:12:39 -05:00
for(int i = 0; i < ls->filecount; i++) {
// file name validating
char* fname = ls->fnames[i];
FILE* input = fopen(ls->files[i], "r");
2020-10-30 13:06:02 -04:00
2020-11-17 12:12:39 -05:00
if(input == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
return errno;
}
// parsing
2020-11-19 06:10:51 -05:00
PARSER* p = mkparser(input);
2020-11-17 12:12:39 -05:00
parse(p);
2020-10-29 20:22:03 -04:00
2020-11-17 12:12:39 -05:00
// translating
2020-11-19 06:10:51 -05:00
TRANSLATOR* t = mktranslator(p->lns, fname);
2020-11-17 12:12:39 -05:00
translate(t);
freeparser(p);
2020-11-21 09:25:30 -05:00
printlns(t->output, output);
2020-10-29 21:06:33 -04:00
2020-11-17 12:12:39 -05:00
// freeing rest
freetranslator(t);
}
freetranslationlist(ls);
fclose(output);
2020-10-29 20:22:03 -04:00
return 0;
}