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:
parent
888395d496
commit
5d33d165a2
@ -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).
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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=$?
|
||||||
|
Loading…
Reference in New Issue
Block a user