From 0f4d0a93434aa7586c9f66c6a48707b561ebf00a Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Fri, 14 Nov 2025 06:27:22 -0500 Subject: Generate usage message from comments in the .rst. --- src/Makefile | 7 +++++- src/mkusage.pl | 18 +++++++++++++++ src/unalf.1 | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/unalf.c | 24 +++++++++++++++----- src/unalf.rst | 36 ++++++++++++++++++++++++++++++ src/usage.c | 16 ++++++++++++++ 6 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 src/mkusage.pl create mode 100644 src/usage.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index f8b73cf..2c8a31d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,7 +3,12 @@ CFLAGS=-Wall -Wno-unused-label -I../f65 $(COPT) all: unalf unalf.1 alfsum alfsum.1 -unalf: unalf.o io.o listalf.o extract.o ../f65/f65.o glob.o opts.o +unalf: unalf.o io.o listalf.o extract.o ../f65/f65.o glob.o opts.o usage.o + +usage.o: usage.c + +usage.c: mkusage.pl unalf.rst + perl mkusage.pl unalf.rst > usage.c unalf.o: unalf.c unalf.h ../f65/f65.h diff --git a/src/mkusage.pl b/src/mkusage.pl new file mode 100644 index 0000000..d8a5c77 --- /dev/null +++ b/src/mkusage.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl -w + +print "const char *usage_msg[] = {\n"; + +while(<>) { + chomp; + next if /^---/; + if(/^-[-a-zA-Z\d]/) { + $opt = $_; + next; + } + if($opt && (/^\.\. (.*)$/)) { + print "\t\" $opt: $1\",\n"; + undef $opt; + } +} + +print "\t(const char*)0\n};\n"; diff --git a/src/unalf.1 b/src/unalf.1 index 7cc8aab..99ed684 100644 --- a/src/unalf.1 +++ b/src/unalf.1 @@ -62,50 +62,100 @@ are considered text. .sp Note that \fIonly\fP line\-endings are converted. Other ATASCII characters are left alone. If you need anything more in\-depth, use \fBa8cat\fP(1). +.UNINDENT +.\" convert EOLs in text files. +. +.INDENT 0.0 .TP .BI \-a\fB a Convert line endings in all extracted files. This will corrupt any executables or non\-text data files, so use with caution. +.UNINDENT +.\" convert EOLs in ALL files. +. +.INDENT 0.0 .TP .BI \-d \ output\-dir Write extracted files to this directory, which will be created if it does not exist. The default is the current directory. +.UNINDENT +.\" set output directory (created if needed). +. +.INDENT 0.0 .TP .B \-e Extract files. This is actually a no\-op, as extraction is the default action. +.UNINDENT +.\" extract files (redundant; this is the default action). +. +.INDENT 0.0 .TP .B \-k Keep trailing periods. In most (all?) ALF files, filenames that have no extension are stored with a trailing period, e.g. \(aq\fBFOO\fP\(aq would be stored as \(aq\fBFOO.\fP\(aq. By default, \fBunalf\fP removes the trailing period; use \fB\-k\fP to keep it. +.UNINDENT +.\" keep trailing periods (dots) in filenames. +. +.INDENT 0.0 .TP .B \-l List filenames in archive, one per line, but do not extract. Use \fB\-v\fP for more information (file size, etc). +.UNINDENT +.\" list files in archive (filenames only). +. +.INDENT 0.0 .TP .B \-L Lowercase filesnames. Example: \fBFOO.TXT\fP will extract to \fBfoo.txt\fP\&. +.UNINDENT +.\" use lowercase filenames. +. +.INDENT 0.0 .TP .B \-o Overwrite files, if they already exist. The default is to rename existing files, adding a \fB~\fP suffix. Note that renaming \fBfile\fP to \fBfile~\fP \fIwill\fP overwrite \fBfile~\fP if it already exists. +.UNINDENT +.\" overwrite files (do not create file~ backups). +. +.INDENT 0.0 .TP .B \-p Extract to standard output. All the files that get extracted will be printed to stdout with no delimiters, so this is most useful when only extracting one file. \fB\-q\fP is automatically enabled by this option. +.sp +\fIWarning:\fP No checking is done to see whether stdout is a terminal. +Printing binary files to a terminal is a good way to make a mess. +Even text files with the EOLs translated can still contain ATASCII +formatting/graphics codes that can confuse your terminal. You have +been warned. +.UNINDENT +.\" extract to stdout (enables -q). +. +.INDENT 0.0 .TP .B \-q Quiet extraction: do not print "Uncrunching \fIfile\fP" messages. Errors and warnings will still be printed. This is the default when \fB\-p\fP is used. +.UNINDENT +.\" quiet: don't print filenames during extraction. +. +.INDENT 0.0 .TP .B \-t Test archive. Same as extraction, except the files are not written anywhere. +.UNINDENT +.\" test archive. +. +.INDENT 0.0 .TP .B \-v Verbose listing of archive contents, with compressed and original @@ -114,12 +164,18 @@ output format is similar to that of \fBarc \-v\fP, minus the \fIStowage\fP column, since \fIALF\fP doesn\(aqt support multiple compression types. The date and time are displayed, but in most .alf files these are the default values of "8 Jan 82 12:24a". +.UNINDENT +.\" verbose listing of archive contents. +. +.INDENT 0.0 .TP .BI \-x \ wildcard Exclude (do not list or extract) files matching \fIwildcard\fP\&. See \fBWILDCARDS\fP below. This option can be given multiple times to exclude multiple patterns. .UNINDENT +.\" exclude . may be given multiple times. +. .SH WILDCARDS .sp Wildcard (aka glob) matching works like it does on the Atari: \fI*.*\fP @@ -135,6 +191,19 @@ ignored: \fBFOO*BAR.TXT\fP is equivalent to \fBFOO*.TXT\fP, and equivalent to \fBFOO*\fP, and \fIwill not\fP match the file \fBFOO.TXT\fP\&. .sp Unlike the Atari, matching is case\-insensitive. +.sp +To avoid your shell trying to expand the wildcards, always quote them! +Example: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +unalf filename.alf \(aq*.txt\(aq +.ft P +.fi +.UNINDENT +.UNINDENT .SH EXIT STATUS .sp \fB0\fP for success, \fB1\fP for failure. diff --git a/src/unalf.c b/src/unalf.c index 9a722f8..d4b5aa0 100644 --- a/src/unalf.c +++ b/src/unalf.c @@ -7,6 +7,10 @@ #include #include "unalf.h" +#ifndef VERSION +#define VERSION "0.0.0" +#endif + FILE *in_file, *out_file; char *in_filename, *self; opts_t opts; @@ -15,11 +19,6 @@ int exclude_count; char * const *include_globs; static void create_outdir(void); -static void usage(void) { - printf("usage: %s [-l] file.alf\n", self); - exit(1); -} - static void set_self(char *argv0) { char *p; @@ -48,6 +47,21 @@ static void create_outdir(void) { } } +void usage(void) { + extern char *usage_msg[]; + char **line; + + puts("unalf (ALF extractor) v" VERSION " by B. Watson. WTFPL."); + printf("Usage: %s -[options] [wildcard ...]\n", self); + puts("Options:"); + puts(" wildcards: extract only matching files."); + + for(line = usage_msg; *line; line++) + puts(*line); + + exit(0); +} + int main(int argc, char **argv) { set_self(argv[0]); diff --git a/src/unalf.rst b/src/unalf.rst index a1cfb7e..64a0be5 100644 --- a/src/unalf.rst +++ b/src/unalf.rst @@ -50,50 +50,78 @@ OPTIONS Note that *only* line-endings are converted. Other ATASCII characters are left alone. If you need anything more in-depth, use **a8cat**\(1). +.. convert EOLs in text files. + -aa Convert line endings in all extracted files. This will corrupt any executables or non-text data files, so use with caution. +.. convert EOLs in ALL files. + -d output-dir Write extracted files to this directory, which will be created if it does not exist. The default is the current directory. +.. set output directory (created if needed). + -e Extract files. This is actually a no-op, as extraction is the default action. +.. extract files (redundant; this is the default action). + -k Keep trailing periods. In most (all?) ALF files, filenames that have no extension are stored with a trailing period, e.g. '**FOO**' would be stored as '**FOO.**'. By default, **unalf** removes the trailing period; use **-k** to keep it. +.. keep trailing periods (dots) in filenames. + -l List filenames in archive, one per line, but do not extract. Use **-v** for more information (file size, etc). +.. list files in archive (filenames only). + -L Lowercase filesnames. Example: **FOO.TXT** will extract to **foo.txt**. +.. use lowercase filenames. + -o Overwrite files, if they already exist. The default is to rename existing files, adding a **~** suffix. Note that renaming **file** to **file~** *will* overwrite **file~** if it already exists. +.. overwrite files (do not create file~ backups). + -p Extract to standard output. All the files that get extracted will be printed to stdout with no delimiters, so this is most useful when only extracting one file. **-q** is automatically enabled by this option. + *Warning:* No checking is done to see whether stdout is a terminal. + Printing binary files to a terminal is a good way to make a mess. + Even text files with the EOLs translated can still contain ATASCII + formatting/graphics codes that can confuse your terminal. You have + been warned. + +.. extract to stdout (enables -q). + -q Quiet extraction: do not print "Uncrunching *file*" messages. Errors and warnings will still be printed. This is the default when **-p** is used. +.. quiet: don't print filenames during extraction. + -t Test archive. Same as extraction, except the files are not written anywhere. +.. test archive. + -v Verbose listing of archive contents, with compressed and original sizes, compression ration, date/time stamps, and checksum. The @@ -102,12 +130,15 @@ OPTIONS date and time are displayed, but in most .alf files these are the default values of "8 Jan 82 12:24a". +.. verbose listing of archive contents. -x wildcard Exclude (do not list or extract) files matching *wildcard*. See **WILDCARDS** below. This option can be given multiple times to exclude multiple patterns. +.. exclude . may be given multiple times. + WILDCARDS ========= @@ -125,6 +156,11 @@ equivalent to **FOO\***, and *will not* match the file **FOO.TXT**. Unlike the Atari, matching is case-insensitive. +To avoid your shell trying to expand the wildcards, always quote them! +Example:: + + unalf filename.alf '*.txt' + EXIT STATUS =========== diff --git a/src/usage.c b/src/usage.c new file mode 100644 index 0000000..d3d1e25 --- /dev/null +++ b/src/usage.c @@ -0,0 +1,16 @@ +const char *usage_msg[] = { + " -a: convert EOLs in text files.", + " -aa: convert EOLs in ALL files.", + " -d output-dir: set output directory (created if needed).", + " -e: extract files (redundant; this is the default action).", + " -k: keep trailing periods (dots) in filenames.", + " -l: list files in archive (filenames only).", + " -L: use lowercase filenames.", + " -o: overwrite files (do not create file~ backups).", + " -p: extract to stdout (enables -q).", + " -q: quiet: don't print filenames during extraction.", + " -t: test archive.", + " -v: verbose listing of archive contents.", + " -x wildcard: exclude . may be given multiple times.", + (const char*)0 +}; -- cgit v1.2.3