/* @@@HEAD@@@
//
*/
#define _coldcc_
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "cdc_string.h" /* strccmp() */
#include "config.h"
#include "defs.h"
#include "y.tab.h"
#include "codegen.h"
#include "cdc_types.h"
#include "ident.h"
#include "match.h"
#include "opcodes.h"
#include "util.h"
#include "sig.h"
#include "execute.h"
#include "token.h"
#include "dump.h"
#include "modules.h"
#include "db.h"
#include "cache.h"
#include "object.h"
#include "data.h"
#include "io.h"
#if DISABLED
#include <unistd.h>
#include <time.h>
#endif
#define OPT_COMP 0
#define OPT_DECOMP 1
#define OPT_PARSE 2
int c_nowrite = 1;
int c_opt = OPT_COMP;
/* function prototypes */
internal void initialize(int argc, char **argv);
internal void usage(char * name);
internal FILE * find_text_db(void);
internal void compile_db(void);
/*
// --------------------------------------------------------------------
*/
int main(int argc, char **argv) {
initialize(argc, argv);
if (c_opt == OPT_DECOMP) {
fprintf(stderr, "Decompiling database...\n");
init_binary_db();
text_dump();
} else if (c_opt == OPT_COMP) {
fprintf(stderr, "Compiling database...\n");
compile_db();
} else if (c_opt == OPT_PARSE) {
fprintf(stderr, "This option is not yet supported, sorry\n");
return 0;
}
cache_sync();
db_close();
flush_output();
return 0;
}
/*
// --------------------------------------------------------------------
*/
internal void compile_db() {
FILE * fp;
object_t * obj;
list_t * parents;
data_t * d;
init_new_db();
fp = find_text_db();
/* create the root object */
obj = cache_retrieve(ROOT_DBREF);
if (!obj) {
parents = list_new(0);
obj = object_new(ROOT_DBREF, parents);
list_discard(parents);
}
cache_discard(obj);
/* create the system object */
obj = cache_retrieve(SYSTEM_DBREF);
if (!obj) {
parents = list_new(1);
d = list_empty_spaces(parents, 1);
d->type = DBREF;
d->u.dbref = ROOT_DBREF;
obj = object_new(SYSTEM_DBREF, parents);
list_discard(parents);
}
cache_discard(obj);
fp = fopen(c_dir_textdump, "r");
if (!fp) {
fprintf(stderr, "Couldn't open text dump file \"%s\".\n",
c_dir_textdump);
exit(1);
} else {
text_dump_read(fp);
fclose(fp);
}
fprintf(stderr, "Database compiled from \"%s\" to \"%s\".\n",
c_dir_textdump, c_dir_binary);
}
/*
// --------------------------------------------------------------------
// Finds target the database is, based off input name.
//
// If name is:
//
// "stdin", will read from stdin.
// a directory, will do directory compilation (unsupported)
// a valid file, will use that (textdump)
//
// Will output to global name "output", set by options
*/
internal FILE * find_text_db(void) {
FILE * fp = NULL;
if (strccmp(c_dir_textdump, "stdin") == F_SUCCESS) {
fputs("Reading from stdin.\n", stderr);
fp = stdin;
} else {
struct stat sbuf;
if (stat(c_dir_textdump, &sbuf) == F_FAILURE) {
fprintf(stderr, "** Unable to open target \"%s\".\n",
c_dir_textdump);
exit(1);
}
if (S_ISDIR(sbuf.st_mode)) {
fputs("** Directory based compilation is currently unsupported.\n",
stderr);
fclose(fp);
exit(0);
}
/* just let fopen deal with the other perms */
fp = fopen(c_dir_textdump, "r");
if (fp == NULL) {
fprintf(stderr, "** bad happened.\n");
exit(1);
}
fprintf(stderr, "Reading from \"%s\".\n", c_dir_textdump);
}
return fp;
}
/*
// --------------------------------------------------------------------
// Initializes tables, variables and other aspects for use
*/
#define nextarg() { \
argv++; \
argc--; \
if (!argc) { \
usage(name); \
fprintf(stderr, "** No followup argument to -%s.\n", opt); \
exit(0); \
} \
}
internal void initialize(int argc, char **argv) {
char * name = NULL,
* opt = NULL;
name = *argv;
argv++;
argc--;
while (argc) {
if (**argv == '-') {
opt = *argv;
opt++;
switch (*opt) {
case 'c':
c_opt = OPT_COMP;
break;
case 'd':
c_opt = OPT_DECOMP;
break;
case 'p':
c_opt = OPT_PARSE;
fputs("\n** Unsupported option: -p\n", stderr);
break;
case 'w':
fputs("\n** Unsupported option: -w\n", stderr);
c_nowrite = 0;
break;
case 't':
nextarg();
strcpy(c_dir_textdump, *argv);
break;
case 'o':
case 'b':
nextarg();
strcpy(c_dir_binary, *argv);
case '-':
case 'h':
usage(name);
exit(0);
default:
usage(name);
fprintf(stderr, "\n** Invalid Option: -%s\n", opt);
exit(1);
}
}
argv++;
argc--;
}
init_codegen();
init_ident();
init_op_table();
init_match();
init_util();
init_sig();
init_execute();
init_scratch_file();
init_token();
init_modules(argc, argv);
init_defs();
init_cache();
}
/*
// --------------------------------------------------------------------
// Simple usage message, rather explanatory
*/
internal void usage (char * name) {
fprintf(stderr, "\n-- %s %d.%d-%d --\n\nUsage: %s <target> [options]\n",
SERVER_NAME, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, name);
fputs("\n\
Takes input from <target>. If <target> is \"stdin\" will read from\n\
standard input instead. <target> may be a directory or file.\n\n\
Options:\n\n\
-h This message.\n\
-d Decompile.\n\
-c Compile (default).\n\
-b <binary> binary db directory name, default: \"binary\"\n\
-t <textdump> textdump filename, default: \"textdump\"\n\n\
Anticipated Options:\n\n\
-p Partial compile, compile object(s) and insert\n\
into database accordingly. Can be used with -w\n\
for a ColdC verifier.\n\
-w Compile for parse only, do not write output.\n\
This option can only be used with partial compile.\n\
\n", stderr);
}
#undef _coldcc_