mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-18 17:41:47 +00:00
A command line interface for the PAK utility, made it a seperate build target too.
This commit is contained in:
parent
a568d43487
commit
eabb92f7b4
2 changed files with 149 additions and 5 deletions
15
Makefile
15
Makefile
|
@ -9,14 +9,14 @@ CYGWIN = $(findstring CYGWIN, $(UNAME))
|
||||||
MINGW = $(findstring MINGW32, $(UNAME))
|
MINGW = $(findstring MINGW32, $(UNAME))
|
||||||
|
|
||||||
CC ?= clang
|
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),)
|
ifneq ($(shell git describe --always 2>/dev/null),)
|
||||||
CFLAGS += -DGMQCC_GITINFO="\"$(shell git describe --always)\""
|
CFLAGS += -DGMQCC_GITINFO="\"$(shell git describe --always)\""
|
||||||
endif
|
endif
|
||||||
#turn on tons of warnings if clang is present
|
#turn on tons of warnings if clang is present
|
||||||
# but also turn off the STUPID ONES
|
# but also turn off the STUPID ONES
|
||||||
ifeq ($(CC), clang)
|
ifeq ($(CC), clang)
|
||||||
CFLAGS += \
|
CFLAGS += \
|
||||||
-Weverything \
|
-Weverything \
|
||||||
-Wno-padded \
|
-Wno-padded \
|
||||||
-Wno-format-nonliteral \
|
-Wno-format-nonliteral \
|
||||||
|
@ -41,7 +41,8 @@ ifeq ($(track), no)
|
||||||
CFLAGS += -DNOTRACK
|
CFLAGS += -DNOTRACK
|
||||||
endif
|
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_T = test.o util.o conout.o fs.o
|
||||||
OBJ_C = main.o lexer.o parser.o fs.o
|
OBJ_C = main.o lexer.o parser.o fs.o
|
||||||
OBJ_X = exec-standalone.o util.o conout.o fs.o
|
OBJ_X = exec-standalone.o util.o conout.o fs.o
|
||||||
|
@ -56,6 +57,7 @@ ifneq ("$(CYGWIN)", "")
|
||||||
QCVM = qcvm.exe
|
QCVM = qcvm.exe
|
||||||
GMQCC = gmqcc.exe
|
GMQCC = gmqcc.exe
|
||||||
TESTSUITE = testsuite.exe
|
TESTSUITE = testsuite.exe
|
||||||
|
PAK = pak.exe
|
||||||
else
|
else
|
||||||
ifneq ("$(MINGW)", "")
|
ifneq ("$(MINGW)", "")
|
||||||
#nullify the common variables that
|
#nullify the common variables that
|
||||||
|
@ -67,6 +69,7 @@ ifneq ("$(MINGW)", "")
|
||||||
QCVM = qcvm.exe
|
QCVM = qcvm.exe
|
||||||
GMQCC = gmqcc.exe
|
GMQCC = gmqcc.exe
|
||||||
TESTSUITE = testsuite.exe
|
TESTSUITE = testsuite.exe
|
||||||
|
PAK = pak.exe
|
||||||
else
|
else
|
||||||
#arm support for linux .. we need to allow unaligned accesses
|
#arm support for linux .. we need to allow unaligned accesses
|
||||||
#to memory otherwise we just segfault everywhere
|
#to memory otherwise we just segfault everywhere
|
||||||
|
@ -77,6 +80,7 @@ else
|
||||||
QCVM = qcvm
|
QCVM = qcvm
|
||||||
GMQCC = gmqcc
|
GMQCC = gmqcc
|
||||||
TESTSUITE = testsuite
|
TESTSUITE = testsuite
|
||||||
|
PAK = pak
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -148,7 +152,10 @@ $(GMQCC): $(OBJ_C) $(OBJ_D)
|
||||||
$(TESTSUITE): $(OBJ_T)
|
$(TESTSUITE): $(OBJ_T)
|
||||||
$(CC) -o $@ $^ $(CFLAGS)
|
$(CC) -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
all: $(GMQCC) $(QCVM) $(TESTSUITE)
|
$(PAK): $(OBJ_P)
|
||||||
|
$(CC) -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
all: $(GMQCC) $(QCVM) $(TESTSUITE) $(PAK)
|
||||||
|
|
||||||
check: all
|
check: all
|
||||||
@ ./$(TESTSUITE)
|
@ ./$(TESTSUITE)
|
||||||
|
|
139
pak.c
139
pak.c
|
@ -28,7 +28,7 @@
|
||||||
* The PAK format uses a FOURCC concept for storing the magic ident within
|
* The PAK format uses a FOURCC concept for storing the magic ident within
|
||||||
* the header as a uint32_t.
|
* 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 {
|
typedef struct {
|
||||||
uint32_t magic; /* "PACK" */
|
uint32_t magic; /* "PACK" */
|
||||||
|
@ -441,3 +441,140 @@ bool pak_close(pak_file_t *pak) {
|
||||||
|
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue