A command line interface for the PAK utility, made it a seperate build target too.

This commit is contained in:
Dale Weiler 2013-02-08 16:32:15 +00:00
parent a568d43487
commit eabb92f7b4
2 changed files with 149 additions and 5 deletions

View file

@ -9,7 +9,7 @@ CYGWIN = $(findstring CYGWIN, $(UNAME))
MINGW = $(findstring MINGW32, $(UNAME))
CC ?= clang
CFLAGS += -Wall -Wextra -I. -fno-strict-aliasing -fsigned-char
CFLAGS += -Wall -Wextra -Werror -I. -fno-strict-aliasing -fsigned-char
ifneq ($(shell git describe --always 2>/dev/null),)
CFLAGS += -DGMQCC_GITINFO="\"$(shell git describe --always)\""
endif
@ -41,7 +41,8 @@ ifeq ($(track), no)
CFLAGS += -DNOTRACK
endif
OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o fs.o utf8.o correct.o pak.o
OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o fs.o utf8.o correct.o
OBJ_P = util.o fs.o conout.o opts.o pak.o
OBJ_T = test.o util.o conout.o fs.o
OBJ_C = main.o lexer.o parser.o fs.o
OBJ_X = exec-standalone.o util.o conout.o fs.o
@ -56,6 +57,7 @@ ifneq ("$(CYGWIN)", "")
QCVM = qcvm.exe
GMQCC = gmqcc.exe
TESTSUITE = testsuite.exe
PAK = pak.exe
else
ifneq ("$(MINGW)", "")
#nullify the common variables that
@ -67,6 +69,7 @@ ifneq ("$(MINGW)", "")
QCVM = qcvm.exe
GMQCC = gmqcc.exe
TESTSUITE = testsuite.exe
PAK = pak.exe
else
#arm support for linux .. we need to allow unaligned accesses
#to memory otherwise we just segfault everywhere
@ -77,6 +80,7 @@ else
QCVM = qcvm
GMQCC = gmqcc
TESTSUITE = testsuite
PAK = pak
endif
endif
@ -148,7 +152,10 @@ $(GMQCC): $(OBJ_C) $(OBJ_D)
$(TESTSUITE): $(OBJ_T)
$(CC) -o $@ $^ $(CFLAGS)
all: $(GMQCC) $(QCVM) $(TESTSUITE)
$(PAK): $(OBJ_P)
$(CC) -o $@ $^ $(CFLAGS)
all: $(GMQCC) $(QCVM) $(TESTSUITE) $(PAK)
check: all
@ ./$(TESTSUITE)

139
pak.c
View file

@ -28,7 +28,7 @@
* The PAK format uses a FOURCC concept for storing the magic ident within
* the header as a uint32_t.
*/
#define PAK_FOURCC ((uint32_t)(('P' << 24) | ('A' << 16) | ('C' << 8) | 'K'))
#define PAK_FOURCC ((uint32_t)(('P' | ('A' << 8) | ('C' << 16) | ('K' << 24))))
typedef struct {
uint32_t magic; /* "PACK" */
@ -441,3 +441,140 @@ bool pak_close(pak_file_t *pak) {
return true;
}
/*
* Fancy GCC-like LONG parsing allows things like --opt=param with
* assignment operator. This is used for redirecting stdout/stderr
* console to specific files of your choice.
*/
static bool parsecmd(const char *optname, int *argc_, char ***argv_, char **out, int ds, bool split) {
int argc = *argc_;
char **argv = *argv_;
size_t len = strlen(optname);
if (strncmp(argv[0]+ds, optname, len))
return false;
/* it's --optname, check how the parameter is supplied */
if (argv[0][ds+len] == '=') {
*out = argv[0]+ds+len+1;
return true;
}
if (!split || argc < ds) /* no parameter was provided, or only single-arg form accepted */
return false;
/* using --opt param */
*out = argv[1];
--*argc_;
++*argv_;
return true;
}
int main(int argc, char **argv) {
bool extract = true;
char *redirout = (char*)stdout;
char *redirerr = (char*)stderr;
char *directory = NULL;
char *file = NULL;
char **files = NULL;
pak_file_t *pak = NULL;
size_t iter = 0;
con_init();
/*
* Command line option parsing commences now We only need to support
* a few things in the test suite.
*/
while (argc > 1) {
++argv;
--argc;
if (argv[0][0] == '-') {
if (parsecmd("redirout", &argc, &argv, &redirout, 1, false))
continue;
if (parsecmd("redirerr", &argc, &argv, &redirerr, 1, false))
continue;
if (parsecmd("directory", &argc, &argv, &directory, 1, false))
continue;
if (parsecmd("file", &argc, &argv, &file, 1, false))
continue;
con_change(redirout, redirerr);
switch (argv[0][1]) {
case 'e': extract = true; continue;
case 'c': extract = false; continue;
}
if (!strcmp(argv[0]+1, "debug")) {
OPTS_OPTION_BOOL(OPTION_DEBUG) = true;
continue;
}
if (!strcmp(argv[0]+1, "memchk")) {
OPTS_OPTION_BOOL(OPTION_MEMCHK) = true;
continue;
}
if (!strcmp(argv[0]+1, "nocolor")) {
con_color(0);
continue;
}
}
vec_push(files, argv[0]);
}
con_change(redirout, redirerr);
if (!file) {
con_err("-file must be specified for output/input PAK file\n");
return EXIT_FAILURE;
}
if (extract) {
if (!(pak = pak_open(file, "r"))) {
con_err("failed to open PAK file %s\n", file);
return EXIT_FAILURE;
}
if (!pak_extract_all(pak, (directory) ? directory : "./")) {
con_err("failed to extract PAK %s (files may be missing)\n", file);
pak_close(pak);
return EXIT_FAILURE;
}
/* not possible */
if (!pak_close(pak))
abort();
util_meminfo();
return EXIT_SUCCESS;
}
if (!(pak = pak_open(file, "w"))) {
con_err("failed to open PAK %s for writing\n", file);
return EXIT_FAILURE;
}
if (directory && !fs_dir_change(directory)) {
con_err("failed to change directory %s\n", directory);
pak_close(pak);
return EXIT_FAILURE;
}
for (iter = 0; iter < vec_size(files); iter++) {
if (!(pak_insert_one(pak, files[iter]))) {
con_err("failed inserting %s for PAK %s\n", files[iter], file);
pak_close(pak);
return EXIT_FAILURE;
}
}
/* not possible */
if (!pak_close(pak))
abort();
return EXIT_SUCCESS;
}