From 79ce88c12c4dd378a2146eec1c90e166e0b6c0d2 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Thu, 16 Apr 2020 19:44:17 -0400 Subject: [PATCH] tools: add blkunpack and remove cfspack, which will not ever be used again. --- blk/001 | 12 ++++ blk/003 | 4 ++ blk/004 | 1 + blk/009 | 2 + blk/016 | 12 ++++ blk/018 | 7 +++ blk/030 | 5 ++ blk/032 | 6 ++ blk/035 | 13 ++++ blk/038 | 10 +++ blk/043 | 1 + blk/044 | 0 blk/046 | 5 ++ blk/048 | 9 +++ blk/052 | 6 ++ blk/054 | 2 + blk/056 | 8 +++ blk/058 | 6 ++ blk/062 | 7 +++ blk/064 | 10 +++ blk/070 | 10 +++ blk/071 | 5 ++ blk/075 | 2 + blk/078 | 4 ++ blk/084 | 10 +++ blk/087 | 10 +++ blk/091 | 9 +++ blk/101 | 14 +++++ blk/102 | 3 + blk/103 | 6 ++ blk/104 | 3 + tools/.gitignore | 1 + tools/Makefile | 4 +- tools/blkunpack.c | 44 ++++++++++++++ tools/cfspack/.gitignore | 2 - tools/cfspack/Makefile | 16 ----- tools/cfspack/README.md | 33 ---------- tools/cfspack/cfs.h | 10 --- tools/cfspack/cfspack.c | 54 ---------------- tools/cfspack/cfsunpack.c | 93 ---------------------------- tools/cfspack/libcfs.c | 152 ---------------------------------------------- 41 files changed, 250 insertions(+), 361 deletions(-) delete mode 100644 blk/044 create mode 100644 tools/blkunpack.c delete mode 100644 tools/cfspack/.gitignore delete mode 100644 tools/cfspack/Makefile delete mode 100644 tools/cfspack/README.md delete mode 100644 tools/cfspack/cfs.h delete mode 100644 tools/cfspack/cfspack.c delete mode 100644 tools/cfspack/cfsunpack.c delete mode 100644 tools/cfspack/libcfs.c diff --git a/blk/001 b/blk/001 index 3f43fae..d24305a 100644 --- a/blk/001 +++ b/blk/001 @@ -2,3 +2,15 @@ MASTER INDEX 3 Usage 30 Dictionary 70 Implementation notes 100 Block editor + + + + + + + + + + + + diff --git a/blk/003 b/blk/003 index 8b4ada6..13b3bb5 100644 --- a/blk/003 +++ b/blk/003 @@ -10,3 +10,7 @@ Contents 4 DOES> 6 Compilation vs meta-comp. 8 I/O 11 Chained comparisons 14 Addressed devices 18 Signed-ness + + + + diff --git a/blk/004 b/blk/004 index 55765dc..2be2060 100644 --- a/blk/004 +++ b/blk/004 @@ -13,3 +13,4 @@ At compile time, colon definition stops processing words when reaching the DOES>. Example: ": CONSTANT CREATE HERE @ ! DOES> @ ;" + diff --git a/blk/009 b/blk/009 index 1100574..841c445 100644 --- a/blk/009 +++ b/blk/009 @@ -12,3 +12,5 @@ new "(parse)" word. This way, we have a full-featured (and extensible) parsing with a tiny native core. + + diff --git a/blk/016 b/blk/016 index dada9c1..01a8b8e 100644 --- a/blk/016 +++ b/blk/016 @@ -2,3 +2,15 @@ kind of ad-hoc way to have some kind of mapping function, but what you'll mostly want to to is to plug device drivers into those words. + + + + + + + + + + + + diff --git a/blk/018 b/blk/018 index 0f8d53e..ea7977c 100644 --- a/blk/018 +++ b/blk/018 @@ -7,3 +7,10 @@ support the "-" prefix, but under the hood, it's all unsigned. This leads to some oddities. For example, "-1 0 <" is false. To compare whether something is negative, use the "<0" word which is the equivalent to "0x7fff >". + + + + + + + diff --git a/blk/030 b/blk/030 index 1f63268..182071e 100644 --- a/blk/030 +++ b/blk/030 @@ -9,3 +9,8 @@ Be sure to read usage guide (B3) first. 52 Addressed devices 54 Arithmetic / Bits 56 Logic 58 Strings 60 I/O 64 Disk + + + + + diff --git a/blk/032 b/blk/032 index c074364..9286672 100644 --- a/blk/032 +++ b/blk/032 @@ -8,3 +8,9 @@ Words between "()" are "support words" that aren't really meant to be used directly, but as part of another word. "*I*" in description indicates an IMMEDIATE word. + + + + + + diff --git a/blk/035 b/blk/035 index 66c0e67..78b25f2 100644 --- a/blk/035 +++ b/blk/035 @@ -1,3 +1,16 @@ (cont.) ~ - Container for native code. Usually not an executable word. ? - Is it ...? (example: IMMED?) + + + + + + + + + + + + + diff --git a/blk/038 b/blk/038 index 3320f91..9622418 100644 --- a/blk/038 +++ b/blk/038 @@ -4,3 +4,13 @@ FORGET x -- Rewind the dictionary (both CURRENT and HERE) PREV a -- a Return a wordref's previous entry. WHLEN a -- n Get word header length from wordref. That is, name length + 3. a is a wordref + + + + + + + + + + diff --git a/blk/043 b/blk/043 index 00c1c7c..ff71f97 100644 --- a/blk/043 +++ b/blk/043 @@ -13,3 +13,4 @@ INTERPRET -- Get a line from stdin, compile it in tmp memory, then execute the compiled contents. QUIT -- Return to interpreter prompt immediately EXIT! -- Exit current INTERPRET loop. + diff --git a/blk/044 b/blk/044 deleted file mode 100644 index e69de29..0000000 diff --git a/blk/046 b/blk/046 index 6a0c0c0..a1b5226 100644 --- a/blk/046 +++ b/blk/046 @@ -9,3 +9,8 @@ SWAP a b -- b a 2DUP a b -- a b a b 2OVER a b c d -- a b c d a b 2SWAP a b c d -- c d a b + + + + + diff --git a/blk/048 b/blk/048 index 31ef056..880a530 100644 --- a/blk/048 +++ b/blk/048 @@ -5,3 +5,12 @@ R> R:n -- n Pops RS and push to PS I -- n Copy RS TOS to PS I' -- n Copy RS second item to PS J -- n Copy RS third item to PS + + + + + + + + + diff --git a/blk/052 b/blk/052 index d92bf82..2bb0c2d 100644 --- a/blk/052 +++ b/blk/052 @@ -8,3 +8,9 @@ A! c a -- Indirect C! A@* -- a Address for A@ word A!* -- a Address for A! word AMOVE src dst u -- Same as MOVE, but with A@ and A! + + + + + + diff --git a/blk/054 b/blk/054 index a04f8bf..882bd5b 100644 --- a/blk/054 +++ b/blk/054 @@ -12,3 +12,5 @@ OR a b -- c a | b -> c XOR a b -- c a ^ b -> c Shortcuts: 1+ 2+ 1- 2- + + diff --git a/blk/056 b/blk/056 index c6eeddc..d2bc570 100644 --- a/blk/056 +++ b/blk/056 @@ -6,3 +6,11 @@ Logic CMP n1 n2 -- n Compare n1 and n2 and set n to -1, 0, or 1. n=0: a1=a2. n=1: a1>a2. n=-1: a1 -- a Address of the current block variable. LIST n -- Prints the contents of the block n on screen in the form of 16 lines of 64 columns. LOAD n -- Interprets Forth code from block n + + + + + + + + + + diff --git a/blk/070 b/blk/070 index c1a73b5..3575ad3 100644 --- a/blk/070 +++ b/blk/070 @@ -4,3 +4,13 @@ Implementation notes 75 Stack management 77 Dictionary 80 System variables 85 Word routines 89 Initialization sequence + + + + + + + + + + diff --git a/blk/071 b/blk/071 index 6bd9150..1ef3729 100644 --- a/blk/071 +++ b/blk/071 @@ -9,3 +9,8 @@ it. As a general rule, we go like this: 4. Is it a number? 5. If yes, push that number to PS, goto 1 6. Error: undefined word. + + + + + diff --git a/blk/075 b/blk/075 index 7cf3ec3..6093b13 100644 --- a/blk/075 +++ b/blk/075 @@ -12,3 +12,5 @@ IX always points to RS' Top Of Stack (TOS) This return stack contain "Interpreter pointers", that is a pointer to the address of a word, as seen in a compiled list of words. + + diff --git a/blk/078 b/blk/078 index 5b0f02c..4b4a58a 100644 --- a/blk/078 +++ b/blk/078 @@ -10,3 +10,7 @@ chain). There are also "special words", for example NUMBER, LIT, FBR, that have a slightly different structure. They're also a pointer to an executable, but as for the other fields, the only one they have is the "flags" field. + + + + diff --git a/blk/084 b/blk/084 index dd200ec..c645d05 100644 --- a/blk/084 +++ b/blk/084 @@ -4,3 +4,13 @@ DRIVERS section is reserved for recipe-specific drivers. Here is a list of known usages: * 0x70-0x78: ACIA buffer pointers in RC2014 recipes. + + + + + + + + + + diff --git a/blk/087 b/blk/087 index aa354d4..834b840 100644 --- a/blk/087 +++ b/blk/087 @@ -4,3 +4,13 @@ being followed by a 2 byte number, it is followed by a null-terminated string. Upon execution, the address of that null-terminated string is pushed on the PSP and IP is advanced to the address following the null. + + + + + + + + + + diff --git a/blk/091 b/blk/091 index a2a18d2..531e4fb 100644 --- a/blk/091 +++ b/blk/091 @@ -5,3 +5,12 @@ for space with HERE: New entries to the dict will overwrite that code! Also, because we're barebone, we can't have comments. This can lead to peculiar code in this area where we try to "waste" space in initialization code. + + + + + + + + + diff --git a/blk/101 b/blk/101 index 8cae18f..5878ac9 100644 --- a/blk/101 +++ b/blk/101 @@ -1,2 +1,16 @@ T ( n -- ): select line n for editing. P xxx(return): put typed line on selected line. + + + + + + + + + + + + + + diff --git a/blk/102 b/blk/102 index 1760c3a..7b9e5a4 100644 --- a/blk/102 +++ b/blk/102 @@ -11,3 +11,6 @@ ENDCASE AGAIN ; + + + diff --git a/blk/103 b/blk/103 index 4961387..d6782f9 100644 --- a/blk/103 +++ b/blk/103 @@ -8,3 +8,9 @@ VARIABLE ACC : L BLK> @ _LIST ; : B BLK> @ 1- BLK> ! L ; : N BLK> @ 1+ BLK> ! L ; + + + + + + diff --git a/blk/104 b/blk/104 index d311db5..3ef1cfe 100644 --- a/blk/104 +++ b/blk/104 @@ -11,3 +11,6 @@ VARIABLE EDPOS DUP IF DROP C< THEN LOOP ; + + + diff --git a/tools/.gitignore b/tools/.gitignore index 5834d8c..901df7b 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -9,3 +9,4 @@ /bin2c /exec /blkpack +/blkunpack diff --git a/tools/Makefile b/tools/Makefile index 8f8de0b..d1e88fc 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -9,9 +9,10 @@ STRIPFC_TGT = stripfc BIN2C_TGT = bin2c EXEC_TGT = exec BLKPACK_TGT = blkpack +BLKUNPACK_TGT = blkunpack TARGETS = $(MEMDUMP_TGT) $(BLKDUMP_TGT) $(UPLOAD_TGT) $(FONTCOMPILE_TGT) \ $(TTYSAFE_TGT) $(PINGPONG_TGT) $(SLATEST_TGT) $(STRIPFC_TGT) \ - $(BIN2C_TGT) $(EXEC_TGT) $(BLKPACK_TGT) + $(BIN2C_TGT) $(EXEC_TGT) $(BLKPACK_TGT) $(BLKUNPACK_TGT) OBJS = common.o all: $(TARGETS) @@ -31,6 +32,7 @@ $(STRIPFC_TGT): $(STRIPFC_TGT).c $(BIN2C_TGT): $(BIN2C_TGT).c $(EXEC_TGT): $(EXEC_TGT).c $(BLKPACK_TGT): $(BLKPACK_TGT).c +$(BLKUNPACK_TGT): $(BLKUNPACK_TGT).c $(TARGETS): $(OBJS) $(CC) $(CFLAGS) $@.c $(OBJS) -o $@ diff --git a/tools/blkunpack.c b/tools/blkunpack.c new file mode 100644 index 0000000..c252671 --- /dev/null +++ b/tools/blkunpack.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include + +void usage() +{ + fprintf(stderr, "Usage: blkunpack dirname\n"); +} + +int main(int argc, char *argv[]) +{ + char buf[1024]; + int blkid = 0; + if (argc != 2) { + usage(); + return 1; + } + while (fread(buf, 1024, 1, stdin) == 1) { + char fullpath[0x200]; + sprintf(fullpath, "%s/%03d", argv[1], blkid); + char c = 0; + for (int i=0; i<1024; i++) { + c |= buf[i]; + } + if (c) { + // not an empty block + printf("%s\n", fullpath); + FILE *fp = fopen(fullpath, "w"); + for (int i=0; i<16; i++) { + int len = strlen(&buf[i*64]); + fwrite(&buf[i*64], len, 1, fp); + fputc('\n', fp); + } + fclose(fp); + } else { + // empty block, delete + unlink(fullpath); + } + blkid++; + } + return 0; +} diff --git a/tools/cfspack/.gitignore b/tools/cfspack/.gitignore deleted file mode 100644 index 4c6cac5..0000000 --- a/tools/cfspack/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/cfspack -/cfsunpack diff --git a/tools/cfspack/Makefile b/tools/cfspack/Makefile deleted file mode 100644 index 106b2bd..0000000 --- a/tools/cfspack/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -TARGETS = cfspack cfsunpack - -CFSPACK_OBJS = cfspack.o libcfs.o - -.PHONY: all -all: $(TARGETS) - -cfspack: $(CFSPACK_OBJS) - $(CC) $(LDFLAGS) -o $@ $(CFSPACK_OBJS) - -cfsunpack: cfsunpack.c - $(CC) $(CFLAGS) -o $@ cfsunpack.c - -.PHONY: clean -clean: - rm -f $(TARGETS) diff --git a/tools/cfspack/README.md b/tools/cfspack/README.md deleted file mode 100644 index 20a9d6f..0000000 --- a/tools/cfspack/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# cfspack - -A tool/library to pack files into a CFS blob and unpack a CFS blob into -a directory. - -## Usage - -To pack a directory into a CFS blob, run: - - cfspack /path/to/directory - -The blob is spit to stdout. If there are subdirectories, they will be prefixes -to the filenames under it. - -`cfspack` takes optional -p pattern arguments. If specified, only files -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 -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 -(> 0x10000 - 0x20 bytes). - -To unpack a blob to a directory: - - cfsunpack /path/to/dest < blob - -If destination exists, files are created alongside existing ones. If a file to -unpack already exists, it is overwritten. diff --git a/tools/cfspack/cfs.h b/tools/cfspack/cfs.h deleted file mode 100644 index 08bb156..0000000 --- a/tools/cfspack/cfs.h +++ /dev/null @@ -1,10 +0,0 @@ -#define BLKSIZE 0x100 -#define HEADERSIZE 0x20 -#define MAX_FN_LEN 25 // 26 - null char -#define MAX_FILE_SIZE (BLKSIZE * 0x100) - HEADERSIZE - -void set_spit_stream(FILE *stream); -int is_regular_file(char *path); -void spitempty(); -int spitblock(char *fullpath, char *fn); -int spitdir(char *path, char *prefix, char **patterns); diff --git a/tools/cfspack/cfspack.c b/tools/cfspack/cfspack.c deleted file mode 100644 index 2846627..0000000 --- a/tools/cfspack/cfspack.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cfs.h" - -void usage() -{ - fprintf(stderr, "Usage: cfspack [-p pattern] [/path/to/dir...]\n"); -} - -int main(int argc, char *argv[]) -{ - int patterncount = 0; - char **patterns = malloc(sizeof(char**)); - patterns[0] = NULL; - while (1) { - int c = getopt(argc, argv, "p:"); - if (c < 0) { - break; - } - 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 -#include -#include -#include -#include - -#define BLKSIZE 0x100 -#define HEADERSIZE 0x20 -#define MAX_FN_LEN 25 // 26 - null char - -bool ensuredir(char *path) -{ - char *s = path; - while (*s != '\0') { - if (*s == '/') { - *s = '\0'; - struct stat path_stat; - if (stat(path, &path_stat) != 0) { - if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) { - return false; - } - } - *s = '/'; - } - s++; - } - return true; -} - -bool unpackblk(char *dstpath) -{ - char buf[MAX_FN_LEN+1]; - if (fgets(buf, 3+1, stdin) == NULL) { - return false; - } - if (strcmp(buf, "CFS") != 0) { - return false; - } - int c = getchar(); - uint8_t blkcnt = c; - if (blkcnt == 0) { - return false; - } - c = getchar(); - uint16_t fsize = c & 0xff; - c = getchar(); - fsize |= (c & 0xff) << 8; - - if (fgets(buf, MAX_FN_LEN+1+1, stdin) == NULL) { - return false; - } - char fullpath[0x1000]; - strcpy(fullpath, dstpath); - strcat(fullpath, "/"); - strcat(fullpath, buf); - if (!ensuredir(fullpath)) { - return false; - } - int blksize = (BLKSIZE-HEADERSIZE)+(BLKSIZE*(blkcnt-1)); - int skipcount = blksize - fsize; - FILE *fp = fopen(fullpath, "w"); - while (fsize) { - c = getchar(); - if (c == EOF) { - return false; - } - fputc(c, fp); - fsize--; - } - fclose(fp); - while (skipcount) { - getchar(); - skipcount--; - } - return true; -} - -int main(int argc, char *argv[]) -{ - if (argc != 2) { - fprintf(stderr, "Usage: cfspack /path/to/dest\n"); - return 1; - } - char *dstpath = argv[1]; - // we fail if there isn't at least one block - if (!unpackblk(dstpath)) { - return 1; - } - while (unpackblk(dstpath)); - return 0; -} - - diff --git a/tools/cfspack/libcfs.c b/tools/cfspack/libcfs.c deleted file mode 100644 index 586b20c..0000000 --- a/tools/cfspack/libcfs.c +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cfs.h" - -#define PUTC(c) putc(c, spitstream) - -static FILE *spitstream = NULL; - -void set_spit_stream(FILE *stream) -{ - spitstream = stream; -} - -int is_regular_file(char *path) -{ - struct stat path_stat; - stat(path, &path_stat); - return S_ISREG(path_stat.st_mode); -} - -void spitempty() -{ - if (spitstream == NULL) spitstream = stdout; - PUTC('C'); - PUTC('F'); - PUTC('S'); - for (int i=0; i<0x20-3; i++) { - PUTC(0); - } -} - -int spitblock(char *fullpath, char *fn) -{ - if (spitstream == NULL) spitstream = stdout; - FILE *fp = fopen(fullpath, "r"); - fseek(fp, 0, SEEK_END); - long fsize = ftell(fp); - if (fsize > MAX_FILE_SIZE) { - fclose(fp); - fprintf(stderr, "File too big: %s %ld\n", fullpath, fsize); - return 1; - } - /* Compute block count. - * We always have at least one, which contains 0x100 bytes - 0x20, which is - * metadata. The rest of the blocks have a steady 0x100. - */ - unsigned char blockcount = 1; - int fsize2 = fsize - (BLKSIZE - HEADERSIZE); - if (fsize2 > 0) { - blockcount += (fsize2 / BLKSIZE); - } - if (blockcount * BLKSIZE < fsize + HEADERSIZE) { - blockcount++; - } - PUTC('C'); - PUTC('F'); - PUTC('S'); - PUTC(blockcount); - // file size is little endian - PUTC(fsize & 0xff); - PUTC((fsize >> 8) & 0xff); - int fnlen = strlen(fn); - for (int i=0; id_name, ".") == 0) || strcmp(ep->d_name, "..") == 0) { - continue; - } - if (ep->d_type != DT_DIR && ep->d_type != DT_REG) { - fprintf(stderr, "Only regular file or directories are supported\n"); - return 1; - } - int slen = strlen(ep->d_name); - if (prefixlen + slen> MAX_FN_LEN) { - fprintf(stderr, "Filename too long: %s/%s\n", prefix, ep->d_name); - return 1; - } - char fullpath[0x1000]; - strcpy(fullpath, path); - strcat(fullpath, "/"); - strcat(fullpath, ep->d_name); - char newprefix[MAX_FN_LEN]; - strcpy(newprefix, prefix); - if (prefixlen > 0) { - strcat(newprefix, "/"); - } - strcat(newprefix, ep->d_name); - if (ep->d_type == DT_DIR) { - int r = spitdir(fullpath, newprefix, patterns); - if (r != 0) { - return r; - } - } else { - char **p = patterns; - // if we have no pattern, we match all - if (p && *p) { - int matches = 0; - while (*p) { - if (fnmatch(*p, ep->d_name, 0) == 0) { - matches = 1; - break; - } - p++; - } - if (!matches) { - continue; - } - } - - int r = spitblock(fullpath, newprefix); - if (r != 0) { - return r; - } - } - } - closedir(dp); - return 0; -}