cfspack: allow multiple patterns and multiple paths in args

Also, always end the CFS chain with a stop block.

fixes #55 #56 #57
This commit is contained in:
Virgil Dupras 2019-12-11 20:57:23 -05:00
parent 888395d496
commit 5d33d165a2
3 changed files with 72 additions and 28 deletions

View File

@ -12,12 +12,16 @@ To pack a directory into a CFS blob, run:
The blob is spit to stdout. If there are subdirectories, they will be prefixes The blob is spit to stdout. If there are subdirectories, they will be prefixes
to the filenames under it. to the filenames under it.
`cfspack` takes an optional second argument, a "fnmatch" pattern. If specified, `cfspack` takes optional -p pattern arguments. If specified, only files
only files patching the pattern will be included. matching at least one of the patterns ("fnmatch" style") will be included.
If path is a file, a CFS with a single file will be spit and its name will If path is a file, a CFS with a single file will be spit and its name will
exclude the directory part of that filename. exclude the directory part of that filename.
The chain being spitted is always ended with a "stop block" (a zero-allocation
block that stops the CFS chain). You can call `cfspack` with no argument to get
only a stop block.
The program errors out if a file name is too long (> 26 bytes) or too big The program errors out if a file name is too long (> 26 bytes) or too big
(> 0x10000 - 0x20 bytes). (> 0x10000 - 0x20 bytes).

View File

@ -1,4 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h> #include <dirent.h>
#include <string.h> #include <string.h>
#include <fnmatch.h> #include <fnmatch.h>
@ -17,6 +19,16 @@ int is_regular_file(char *path)
return S_ISREG(path_stat.st_mode); return S_ISREG(path_stat.st_mode);
} }
void spitempty()
{
putchar('C');
putchar('F');
putchar('S');
for (int i=0; i<0x20-3; i++) {
putchar(0);
}
}
int spitblock(char *fullpath, char *fn) int spitblock(char *fullpath, char *fn)
{ {
FILE *fp = fopen(fullpath, "r"); FILE *fp = fopen(fullpath, "r");
@ -65,7 +77,7 @@ int spitblock(char *fullpath, char *fn)
return 0; return 0;
} }
int spitdir(char *path, char *prefix, char *pattern) int spitdir(char *path, char *prefix, char **patterns)
{ {
DIR *dp; DIR *dp;
struct dirent *ep; struct dirent *ep;
@ -100,15 +112,23 @@ int spitdir(char *path, char *prefix, char *pattern)
} }
strcat(newprefix, ep->d_name); strcat(newprefix, ep->d_name);
if (ep->d_type == DT_DIR) { if (ep->d_type == DT_DIR) {
int r = spitdir(fullpath, newprefix, pattern); int r = spitdir(fullpath, newprefix, patterns);
if (r != 0) { if (r != 0) {
return r; return r;
} }
} else { } else {
if (pattern) { char **p = patterns;
if (fnmatch(pattern, ep->d_name, 0) != 0) { // if we have no pattern, we match all
continue; int matches = (*p) == NULL ? 1 : 0;
while (*p) {
if (fnmatch(*p, ep->d_name, 0) == 0) {
matches = 1;
break;
} }
p++;
}
if (!matches) {
continue;
} }
int r = spitblock(fullpath, newprefix); int r = spitblock(fullpath, newprefix);
@ -121,22 +141,46 @@ int spitdir(char *path, char *prefix, char *pattern)
return 0; return 0;
} }
int main(int argc, char *argv[]) void usage()
{ {
if ((argc > 3) || (argc < 2)) { fprintf(stderr, "Usage: cfspack [-p pattern] [/path/to/dir...]\n");
fprintf(stderr, "Usage: cfspack /path/to/dir [pattern] \n"); }
return 1;
} int main(int argc, char *argv[])
char *srcpath = argv[1]; {
char *pattern = NULL; int patterncount = 0;
if (argc == 3) { char **patterns = malloc(sizeof(char**));
pattern = argv[2]; patterns[0] = NULL;
} while (1) {
if (is_regular_file(srcpath)) { int c = getopt(argc, argv, "p:");
// special case: just one file if (c < 0) {
return spitblock(srcpath, basename(srcpath)); break;
} else { }
return spitdir(srcpath, "", pattern); switch (c) {
} case 'p':
patterns[patterncount] = optarg;
patterncount++;
patterns = realloc(patterns, sizeof(char**)*(patterncount+1));
patterns[patterncount] = NULL;
break;
default:
usage();
return 1;
}
}
int res = 0;
for (int i=optind; i<argc; i++) {
if (is_regular_file(argv[i])) {
// special case: just one file
res = spitblock(argv[i], basename(argv[i]));
} else {
res = spitdir(argv[i], "", patterns);
}
}
if (res == 0) {
spitempty();
}
free(patterns);
return res;
} }

View File

@ -31,11 +31,7 @@ ZASMBIN="${DIR}/emul/zasm/zasm"
CFSPACK="${DIR}/cfspack/cfspack" CFSPACK="${DIR}/cfspack/cfspack"
INCCFS=$(mktemp) INCCFS=$(mktemp)
for p in "$@"; do "${CFSPACK}" -p "*.h" -p "*.asm" -p "*.bin" "$@" > "${INCCFS}"
"${CFSPACK}" "${p}" "*.h" >> "${INCCFS}"
"${CFSPACK}" "${p}" "*.asm" >> "${INCCFS}"
"${CFSPACK}" "${p}" "*.bin" >> "${INCCFS}"
done
"${ZASMBIN}" "${org}" "${INCCFS}" "${ZASMBIN}" "${org}" "${INCCFS}"
RES=$? RES=$?