#define ULAS_TOK_PREPROC_BEGIN '#'
#define ULASINFO() fprintf(ulaserr, "%s:%ld ", ulas.filename, ulas.line);
+#define ULASDBG(...) \
+ if (ulascfg.verbose) { \
+ fprintf(ulaserr, __VA_ARGS__); \
+ }
#define ULASERR(...) ULASINFO() fprintf(ulaserr, __VA_ARGS__);
#define ULASWARN(...) ULASINFO() fprintf(ulaserr, __VA_ARGS__);
#define ULASPANIC(...) \
fprintf((f), "%s", (fmt)); \
}
+/**
+ * Output target files
+ */
+
+// input file for source reader
extern FILE *ulasin;
+// source code output target
extern FILE *ulasout;
+// error output target
extern FILE *ulaserr;
+// assembly listing output
+extern FILE *ulaslstout;
+// symbol list output
+extern FILE *ulassymout;
struct ulas_expr;
struct ulas_tok;
// internal counter
// used whenever a new unique number might be needed
int icntr;
-
- FILE *lstout;
- FILE *symout;
};
extern struct ulas ulas;
FILE *ulasin = NULL;
FILE *ulasout = NULL;
FILE *ulaserr = NULL;
+FILE *ulaslstout = NULL;
+FILE *ulassymout = NULL;
struct ulas_config ulascfg;
struct ulas ulas;
if (ulaserr == NULL) {
ulaserr = stderr;
}
+
ulascfg = cfg;
// init assembly context
ulas.toks = ulas_tokbuf();
ulas.exprs = ulas_exprbuf();
- ulas.lstout = stdout;
}
void ulas_free(void) {
return cfg;
}
+FILE *ulas_fopen(const char *path, const char *mode, FILE *stdfile) {
+ if (!path || strncmp(path, "-", 1) == 0) {
+ return stdfile;
+ }
+ FILE *f = fopen(path, mode);
+
+ if (!f) {
+ ULASPANIC("%s: %s\n", path, strerror(errno));
+ return NULL;
+ }
+ return f;
+}
+
+void ulas_fclose(FILE *f) {
+ if (!f || f == stdin || f == stdout || f == stderr) {
+ return;
+ }
+
+ fclose(f);
+}
+
int ulas_main(struct ulas_config cfg) {
int rc = 0;
+ ulas_init(cfg);
if (cfg.output_path) {
- ulasout = fopen(cfg.output_path, "we");
- if (!ulasout) {
- fprintf(ulaserr, "%s: %s\n", cfg.output_path, strerror(errno));
- return -1;
- }
+ ULASDBG("output: %s\n", cfg.output_path);
+ ulasout = ulas_fopen(cfg.output_path, "we", stdout);
}
- if (cfg.argc > 0) {
- ulasin = fopen(cfg.argv[0], "re");
- if (!ulasin) {
- fprintf(ulaserr, "%s: %s\n", cfg.argv[0], strerror(errno));
- return -1;
- }
+ if (cfg.sym_path) {
+ ULASDBG("symbols: %s\n", cfg.sym_path);
+ ulassymout = ulas_fopen(cfg.sym_path, "we", stdout);
}
- ulas_init(cfg);
+ if (cfg.lst_path) {
+ ULASDBG("list: %s\n", cfg.lst_path);
+ ulaslstout = ulas_fopen(cfg.lst_path, "we", stdout);
+ }
+
+ if (cfg.argc > 0) {
+ ULASDBG("input: %s\n", cfg.argv[0]);
+ ulasin = ulas_fopen(cfg.argv[0], "re", stdin);
+ }
FILE *preprocdst = NULL;
cleanup:
if (!cfg.preproc_only) {
- fclose(preprocdst);
+ ulas_fclose(preprocdst);
}
if (cfg.output_path) {
- fclose(ulasout);
+ ulas_fclose(ulasout);
}
if (cfg.sym_path) {
- fclose(ulas.symout);
- ulas.symout = NULL;
+ ulas_fclose(ulassymout);
}
if (cfg.lst_path) {
- fclose(ulas.lstout);
- ulas.lstout = NULL;
+ ulas_fclose(ulaslstout);
}
if (cfg.argc > 0) {
- fclose(ulasin);
+ ulas_fclose(ulasin);
}
ulas_free();
fwrite(outbuf, 1, towrite, dst);
- if (ulas.lstout) {
+ if (ulaslstout) {
// TODO: verbose output <address> <bytes>\tline
- fprintf(ulas.lstout, "%08X\t%s", ulas.address, start);
+ fprintf(ulaslstout, "%08X\t%s", ulas.address, start);
}
fail: