From 0ec0ca749598c53a17a3b63b3699515f89a01614 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 20 Aug 2025 21:19:34 +0200 Subject: [PATCH 1/5] Config files are now specified with -c, rather than via filename arguments, because otherwise you get really unhelpful error messages when you get things wrong. --- build.py | 18 +++++++++--------- lib/config/flags.cc | 23 ++++++++++++++--------- lib/config/flags.h | 23 +++++++++++++++++++---- scripts/encodedecodetest.sh | 8 ++++---- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/build.py b/build.py index 71f5274d..9e61d692 100644 --- a/build.py +++ b/build.py @@ -28,7 +28,7 @@ else: ("acorndfs", "", "--200"), ("agat", "", ""), ("amiga", "", ""), - ("apple2", "", "--140 40track_drive"), + ("apple2", "", "--140 -c 40track_drive"), ("atarist", "", "--360"), ("atarist", "", "--370"), ("atarist", "", "--400"), @@ -38,17 +38,17 @@ else: ("atarist", "", "--800"), ("atarist", "", "--820"), ("bk", "", ""), - ("brother", "", "--120 40track_drive"), + ("brother", "", "--120 -c 40track_drive"), ("brother", "", "--240"), ( "commodore", "scripts/commodore1541_test.textpb", - "--171 40track_drive", + "--171 -c 40track_drive", ), ( "commodore", "scripts/commodore1541_test.textpb", - "--192 40track_drive", + "--192 -c 40track_drive", ), ("commodore", "", "--800"), ("commodore", "", "--1620"), @@ -60,17 +60,17 @@ else: ("ibm", "", "--1232"), ("ibm", "", "--1440"), ("ibm", "", "--1680"), - ("ibm", "", "--180 40track_drive"), - ("ibm", "", "--160 40track_drive"), - ("ibm", "", "--320 40track_drive"), - ("ibm", "", "--360 40track_drive"), + ("ibm", "", "--180 -c 40track_drive"), + ("ibm", "", "--160 -c 40track_drive"), + ("ibm", "", "--320 -c 40track_drive"), + ("ibm", "", "--360 -c 40track_drive"), ("ibm", "", "--720_96"), ("ibm", "", "--720_135"), ("mac", "scripts/mac400_test.textpb", "--400"), ("mac", "scripts/mac800_test.textpb", "--800"), ("n88basic", "", ""), ("rx50", "", ""), - ("tartu", "", "--390 40track_drive"), + ("tartu", "", "--390 -c 40track_drive"), ("tartu", "", "--780"), ("tids990", "", ""), ("victor9k", "", "--612"), diff --git a/lib/config/flags.cc b/lib/config/flags.cc index bc54262a..f474673b 100644 --- a/lib/config/flags.cc +++ b/lib/config/flags.cc @@ -13,17 +13,23 @@ static std::vector all_flags; static std::map flags_by_name; static void doHelp(); +static void doLoadConfig(const std::string& filename); static void doShowConfig(); static void doDoc(); static FlagGroup helpGroup; static ActionFlag helpFlag = ActionFlag({"--help"}, "Shows the help.", doHelp); -static ActionFlag showConfigFlag = ActionFlag({"--config", "-C"}, +static FlagGroup configGroup; +static ActionFlag loadConfigFlag({"--config", "-c"}, + "Reads an internal or external configuration file.", + doLoadConfig); + +static ActionFlag showConfigFlag({"--show-config", "-C"}, "Shows the currently set configuration and halts.", doShowConfig); -static ActionFlag docFlag = ActionFlag( +static ActionFlag docFlag( {"--doc"}, "Shows the available configuration options and halts.", doDoc); FlagGroup::FlagGroup() @@ -182,17 +188,16 @@ void FlagGroup::parseFlags(int argc, "non-option parameter '{}' seen (try --help)", *filenames.begin()); } +static void doLoadConfig(const std::string& filename) +{ + globalConfig().readBaseConfigFile(filename); +} + void FlagGroup::parseFlagsWithConfigFiles(int argc, const char* argv[], const std::map& configFiles) { - parseFlags(argc, - argv, - [&](const auto& filename) - { - globalConfig().readBaseConfigFile(filename); - return true; - }); + FlagGroup({this, &configGroup}).parseFlags(argc, argv); } void FlagGroup::checkInitialised() const diff --git a/lib/config/flags.h b/lib/config/flags.h index 67be675f..d8b96af4 100644 --- a/lib/config/flags.h +++ b/lib/config/flags.h @@ -83,13 +83,23 @@ public: const std::string helptext, std::function callback): Flag(names, helptext), - _callback(callback) + _voidCallback(callback), + _hasArgument(false) + { + } + + ActionFlag(const std::vector& names, + const std::string helptext, + std::function callback): + Flag(names, helptext), + _callback(callback), + _hasArgument(true) { } bool hasArgument() const override { - return false; + return _hasArgument; } const std::string defaultValueAsString() const override @@ -99,11 +109,16 @@ public: void set(const std::string& value) override { - _callback(); + if (_hasArgument) + _callback(value); + else + _voidCallback(); } private: - const std::function _callback; + const std::function _callback; + const std::function _voidCallback; + bool _hasArgument; }; class SettableFlag : public Flag diff --git a/scripts/encodedecodetest.sh b/scripts/encodedecodetest.sh index 80842e24..d8cbf5b9 100755 --- a/scripts/encodedecodetest.sh +++ b/scripts/encodedecodetest.sh @@ -14,10 +14,10 @@ destfile=$dir/dest.img dd if=/dev/urandom of=$srcfile bs=1048576 count=2 2>&1 -echo $fluxengine write $format -i $srcfile -d $fluxfile --drive.rotational_period_ms=200 $flags -$fluxengine write $format -i $srcfile -d $fluxfile --drive.rotational_period_ms=200 $flags -echo $fluxengine read $format -s $fluxfile -o $destfile --drive.rotational_period_ms=200 $flags -$fluxengine read $format -s $fluxfile -o $destfile --drive.rotational_period_ms=200 $flags +echo $fluxengine write -c $format -i $srcfile -d $fluxfile --drive.rotational_period_ms=200 $flags +$fluxengine write -c $format -i $srcfile -d $fluxfile --drive.rotational_period_ms=200 $flags +echo $fluxengine read -c $format -s $fluxfile -o $destfile --drive.rotational_period_ms=200 $flags +$fluxengine read -c $format -s $fluxfile -o $destfile --drive.rotational_period_ms=200 $flags if [ ! -s $destfile ]; then echo "Zero length output file!" >&2 exit 1 From ec16931f3a76e11003d3a06f2a2dc6d3d25eba65 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 20 Aug 2025 21:23:02 +0200 Subject: [PATCH 2/5] Update documentation for -c. --- doc/disk-40track_drive.md | 2 +- doc/disk-acornadfs.md | 10 +++++----- doc/disk-acorndfs.md | 8 ++++---- doc/disk-aeslanier.md | 2 +- doc/disk-agat.md | 4 ++-- doc/disk-amiga.md | 4 ++-- doc/disk-ampro.md | 4 ++-- doc/disk-apple2.md | 8 ++++---- doc/disk-apple2_drive.md | 2 +- doc/disk-atarist.md | 32 ++++++++++++++--------------- doc/disk-bk.md | 4 ++-- doc/disk-brother.md | 8 ++++---- doc/disk-commodore.md | 18 ++++++++--------- doc/disk-eco1.md | 2 +- doc/disk-epsonpf10.md | 2 +- doc/disk-f85.md | 2 +- doc/disk-fb100.md | 2 +- doc/disk-hplif.md | 16 +++++++-------- doc/disk-ibm.md | 42 +++++++++++++++++++-------------------- doc/disk-icl30.md | 2 +- doc/disk-mac.md | 8 ++++---- doc/disk-micropolis.md | 4 ++-- doc/disk-mx.md | 8 ++++---- doc/disk-n88basic.md | 4 ++-- doc/disk-northstar.md | 12 +++++------ doc/disk-psos.md | 4 ++-- doc/disk-rolandd20.md | 4 ++-- doc/disk-rx50.md | 4 ++-- doc/disk-shugart_drive.md | 2 +- doc/disk-smaky6.md | 2 +- doc/disk-tartu.md | 8 ++++---- doc/disk-tids990.md | 4 ++-- doc/disk-tiki.md | 8 ++++---- doc/disk-victor9k.md | 8 ++++---- doc/disk-zilogmcz.md | 2 +- doc/using.md | 16 +++++++-------- scripts/mkdoc.cc | 2 +- 37 files changed, 137 insertions(+), 137 deletions(-) diff --git a/doc/disk-40track_drive.md b/doc/disk-40track_drive.md index 203628f8..39b65558 100644 --- a/doc/disk-40track_drive.md +++ b/doc/disk-40track_drive.md @@ -10,6 +10,6 @@ no way to detect this automatically. For example: ``` -fluxengine read ibm --180 40track_drive +fluxengine read -c ibm --180 40track_drive ``` diff --git a/doc/disk-acornadfs.md b/doc/disk-acornadfs.md index 2e63eff3..2b969bcc 100644 --- a/doc/disk-acornadfs.md +++ b/doc/disk-acornadfs.md @@ -31,9 +31,9 @@ they might require nudging as the side order can't be reliably autodetected. To read: - - `fluxengine read acornadfs --160 -s drive:0 -o acornadfs.img` - - `fluxengine read acornadfs --320 -s drive:0 -o acornadfs.img` - - `fluxengine read acornadfs --640 -s drive:0 -o acornadfs.img` - - `fluxengine read acornadfs --800 -s drive:0 -o acornadfs.img` - - `fluxengine read acornadfs --1600 -s drive:0 -o acornadfs.img` + - `fluxengine read -c acornadfs --160 -s drive:0 -o acornadfs.img` + - `fluxengine read -c acornadfs --320 -s drive:0 -o acornadfs.img` + - `fluxengine read -c acornadfs --640 -s drive:0 -o acornadfs.img` + - `fluxengine read -c acornadfs --800 -s drive:0 -o acornadfs.img` + - `fluxengine read -c acornadfs --1600 -s drive:0 -o acornadfs.img` diff --git a/doc/disk-acorndfs.md b/doc/disk-acorndfs.md index a36b0ddc..6f9e42db 100644 --- a/doc/disk-acorndfs.md +++ b/doc/disk-acorndfs.md @@ -24,13 +24,13 @@ requires a bit of fiddling as they have the same tracks on twice. To read: - - `fluxengine read acorndfs --100 -s drive:0 -o acorndfs.img` - - `fluxengine read acorndfs --200 -s drive:0 -o acorndfs.img` + - `fluxengine read -c acorndfs --100 -s drive:0 -o acorndfs.img` + - `fluxengine read -c acorndfs --200 -s drive:0 -o acorndfs.img` To write: - - `fluxengine write acorndfs --100 -d drive:0 -i acorndfs.img` - - `fluxengine write acorndfs --200 -d drive:0 -i acorndfs.img` + - `fluxengine write -c acorndfs --100 -d drive:0 -i acorndfs.img` + - `fluxengine write -c acorndfs --200 -d drive:0 -i acorndfs.img` ## References diff --git a/doc/disk-aeslanier.md b/doc/disk-aeslanier.md index 73073fc3..7cfe2411 100644 --- a/doc/disk-aeslanier.md +++ b/doc/disk-aeslanier.md @@ -37,7 +37,7 @@ based on what looks right. If anyone knows _anything_ about these disks, To read: - - `fluxengine read aeslanier -s drive:0 -o aeslanier.img` + - `fluxengine read -c aeslanier -s drive:0 -o aeslanier.img` ## References diff --git a/doc/disk-agat.md b/doc/disk-agat.md index dc2b579d..57cf416e 100644 --- a/doc/disk-agat.md +++ b/doc/disk-agat.md @@ -20,11 +20,11 @@ profile. To read: - - `fluxengine read agat -s drive:0 -o agat.img` + - `fluxengine read -c agat -s drive:0 -o agat.img` To write: - - `fluxengine write agat -d drive:0 -i agat.img` + - `fluxengine write -c agat -d drive:0 -i agat.img` ## References diff --git a/doc/disk-amiga.md b/doc/disk-amiga.md index fe40ed94..5ab77d78 100644 --- a/doc/disk-amiga.md +++ b/doc/disk-amiga.md @@ -26,11 +26,11 @@ distinctly subpar and not particularly good at detecting errors. To read: - - `fluxengine read amiga -s drive:0 -o amiga.adf` + - `fluxengine read -c amiga -s drive:0 -o amiga.adf` To write: - - `fluxengine write amiga -d drive:0 -i amiga.adf` + - `fluxengine write -c amiga -d drive:0 -i amiga.adf` ## References diff --git a/doc/disk-ampro.md b/doc/disk-ampro.md index f1b51f32..e55076f5 100644 --- a/doc/disk-ampro.md +++ b/doc/disk-ampro.md @@ -43,8 +43,8 @@ kayinfo.lbr To read: - - `fluxengine read ampro --400 -s drive:0 -o ampro.img` - - `fluxengine read ampro --800 -s drive:0 -o ampro.img` + - `fluxengine read -c ampro --400 -s drive:0 -o ampro.img` + - `fluxengine read -c ampro --800 -s drive:0 -o ampro.img` ## References diff --git a/doc/disk-apple2.md b/doc/disk-apple2.md index d866a497..fd1eee32 100644 --- a/doc/disk-apple2.md +++ b/doc/disk-apple2.md @@ -58,13 +58,13 @@ volume. To read: - - `fluxengine read apple2 --140 -s drive:0 -o apple2.img` - - `fluxengine read apple2 --640 -s drive:0 -o apple2.img` + - `fluxengine read -c apple2 --140 -s drive:0 -o apple2.img` + - `fluxengine read -c apple2 --640 -s drive:0 -o apple2.img` To write: - - `fluxengine write apple2 --140 -d drive:0 -i apple2.img` - - `fluxengine write apple2 --640 -d drive:0 -i apple2.img` + - `fluxengine write -c apple2 --140 -d drive:0 -i apple2.img` + - `fluxengine write -c apple2 --640 -d drive:0 -i apple2.img` ## References diff --git a/doc/disk-apple2_drive.md b/doc/disk-apple2_drive.md index e631d138..6fa952e4 100644 --- a/doc/disk-apple2_drive.md +++ b/doc/disk-apple2_drive.md @@ -11,6 +11,6 @@ connector. For example: ``` -fluxengine read apple2 --160 apple2_drive +fluxengine read -c apple2 --160 apple2_drive ``` diff --git a/doc/disk-atarist.md b/doc/disk-atarist.md index 25f3e11e..76aa1ef2 100644 --- a/doc/disk-atarist.md +++ b/doc/disk-atarist.md @@ -29,25 +29,25 @@ Be aware that many PC drives (including mine) won't do the 82 track formats. To read: - - `fluxengine read atarist --360 -s drive:0 -o atarist.img` - - `fluxengine read atarist --370 -s drive:0 -o atarist.img` - - `fluxengine read atarist --400 -s drive:0 -o atarist.img` - - `fluxengine read atarist --410 -s drive:0 -o atarist.img` - - `fluxengine read atarist --720 -s drive:0 -o atarist.img` - - `fluxengine read atarist --740 -s drive:0 -o atarist.img` - - `fluxengine read atarist --800 -s drive:0 -o atarist.img` - - `fluxengine read atarist --820 -s drive:0 -o atarist.img` + - `fluxengine read -c atarist --360 -s drive:0 -o atarist.img` + - `fluxengine read -c atarist --370 -s drive:0 -o atarist.img` + - `fluxengine read -c atarist --400 -s drive:0 -o atarist.img` + - `fluxengine read -c atarist --410 -s drive:0 -o atarist.img` + - `fluxengine read -c atarist --720 -s drive:0 -o atarist.img` + - `fluxengine read -c atarist --740 -s drive:0 -o atarist.img` + - `fluxengine read -c atarist --800 -s drive:0 -o atarist.img` + - `fluxengine read -c atarist --820 -s drive:0 -o atarist.img` To write: - - `fluxengine write atarist --360 -d drive:0 -i atarist.img` - - `fluxengine write atarist --370 -d drive:0 -i atarist.img` - - `fluxengine write atarist --400 -d drive:0 -i atarist.img` - - `fluxengine write atarist --410 -d drive:0 -i atarist.img` - - `fluxengine write atarist --720 -d drive:0 -i atarist.img` - - `fluxengine write atarist --740 -d drive:0 -i atarist.img` - - `fluxengine write atarist --800 -d drive:0 -i atarist.img` - - `fluxengine write atarist --820 -d drive:0 -i atarist.img` + - `fluxengine write -c atarist --360 -d drive:0 -i atarist.img` + - `fluxengine write -c atarist --370 -d drive:0 -i atarist.img` + - `fluxengine write -c atarist --400 -d drive:0 -i atarist.img` + - `fluxengine write -c atarist --410 -d drive:0 -i atarist.img` + - `fluxengine write -c atarist --720 -d drive:0 -i atarist.img` + - `fluxengine write -c atarist --740 -d drive:0 -i atarist.img` + - `fluxengine write -c atarist --800 -d drive:0 -i atarist.img` + - `fluxengine write -c atarist --820 -d drive:0 -i atarist.img` ## References diff --git a/doc/disk-bk.md b/doc/disk-bk.md index fa18d96a..e26bfd12 100644 --- a/doc/disk-bk.md +++ b/doc/disk-bk.md @@ -22,9 +22,9 @@ on what was available at the time, with the same format on both. To read: - - `fluxengine read bk -s drive:0 -o bk800.img` + - `fluxengine read -c bk -s drive:0 -o bk800.img` To write: - - `fluxengine write bk -d drive:0 -i bk800.img` + - `fluxengine write -c bk -d drive:0 -i bk800.img` diff --git a/doc/disk-brother.md b/doc/disk-brother.md index 6e12dced..ba041e56 100644 --- a/doc/disk-brother.md +++ b/doc/disk-brother.md @@ -44,13 +44,13 @@ investigate. To read: - - `fluxengine read brother --120 -s drive:0 -o brother.img` - - `fluxengine read brother --240 -s drive:0 -o brother.img` + - `fluxengine read -c brother --120 -s drive:0 -o brother.img` + - `fluxengine read -c brother --240 -s drive:0 -o brother.img` To write: - - `fluxengine write brother --120 -d drive:0 -i brother.img` - - `fluxengine write brother --240 -d drive:0 -i brother.img` + - `fluxengine write -c brother --120 -d drive:0 -i brother.img` + - `fluxengine write -c brother --240 -d drive:0 -i brother.img` Dealing with misaligned disks ----------------------------- diff --git a/doc/disk-commodore.md b/doc/disk-commodore.md index c2ad45f9..98021111 100644 --- a/doc/disk-commodore.md +++ b/doc/disk-commodore.md @@ -54,18 +54,18 @@ A CMD FD2000 disk (a popular third-party Commodore disk drive) To read: - - `fluxengine read commodore --171 -s drive:0 -o commodore.d64` - - `fluxengine read commodore --192 -s drive:0 -o commodore.d64` - - `fluxengine read commodore --800 -s drive:0 -o commodore.d64` - - `fluxengine read commodore --1042 -s drive:0 -o commodore.d64` - - `fluxengine read commodore --1620 -s drive:0 -o commodore.d64` + - `fluxengine read -c commodore --171 -s drive:0 -o commodore.d64` + - `fluxengine read -c commodore --192 -s drive:0 -o commodore.d64` + - `fluxengine read -c commodore --800 -s drive:0 -o commodore.d64` + - `fluxengine read -c commodore --1042 -s drive:0 -o commodore.d64` + - `fluxengine read -c commodore --1620 -s drive:0 -o commodore.d64` To write: - - `fluxengine write commodore --171 -d drive:0 -i commodore.d64` - - `fluxengine write commodore --192 -d drive:0 -i commodore.d64` - - `fluxengine write commodore --800 -d drive:0 -i commodore.d64` - - `fluxengine write commodore --1620 -d drive:0 -i commodore.d64` + - `fluxengine write -c commodore --171 -d drive:0 -i commodore.d64` + - `fluxengine write -c commodore --192 -d drive:0 -i commodore.d64` + - `fluxengine write -c commodore --800 -d drive:0 -i commodore.d64` + - `fluxengine write -c commodore --1620 -d drive:0 -i commodore.d64` ## References diff --git a/doc/disk-eco1.md b/doc/disk-eco1.md index f31ca3a1..8159611a 100644 --- a/doc/disk-eco1.md +++ b/doc/disk-eco1.md @@ -33,7 +33,7 @@ images. To read: - - `fluxengine read eco1 -s drive:0 -o eco1.img` + - `fluxengine read -c eco1 -s drive:0 -o eco1.img` ## References diff --git a/doc/disk-epsonpf10.md b/doc/disk-epsonpf10.md index 4f272f09..772001ab 100644 --- a/doc/disk-epsonpf10.md +++ b/doc/disk-epsonpf10.md @@ -15,5 +15,5 @@ format itself is yet another IBM scheme variant. To read: - - `fluxengine read epsonpf10 -s drive:0 -o epsonpf10.img` + - `fluxengine read -c epsonpf10 -s drive:0 -o epsonpf10.img` diff --git a/doc/disk-f85.md b/doc/disk-f85.md index 3f99b343..b4041f86 100644 --- a/doc/disk-f85.md +++ b/doc/disk-f85.md @@ -36,7 +36,7 @@ touch](https://github.com/davidgiven/fluxengine/issues/new). To read: - - `fluxengine read f85 -s drive:0 -o f85.img` + - `fluxengine read -c f85 -s drive:0 -o f85.img` ## References diff --git a/doc/disk-fb100.md b/doc/disk-fb100.md index 2ba81422..8d788758 100644 --- a/doc/disk-fb100.md +++ b/doc/disk-fb100.md @@ -30,7 +30,7 @@ I don't have access to one of those disks. To read: - - `fluxengine read fb100 -s drive:0 -o fb100.img` + - `fluxengine read -c fb100 -s drive:0 -o fb100.img` ## References diff --git a/doc/disk-hplif.md b/doc/disk-hplif.md index f5cf22f6..c59720d1 100644 --- a/doc/disk-hplif.md +++ b/doc/disk-hplif.md @@ -23,17 +23,17 @@ encoding scheme. To read: - - `fluxengine read hplif --264 -s drive:0 -o hplif.img` - - `fluxengine read hplif --608 -s drive:0 -o hplif.img` - - `fluxengine read hplif --616 -s drive:0 -o hplif.img` - - `fluxengine read hplif --770 -s drive:0 -o hplif.img` + - `fluxengine read -c hplif --264 -s drive:0 -o hplif.img` + - `fluxengine read -c hplif --608 -s drive:0 -o hplif.img` + - `fluxengine read -c hplif --616 -s drive:0 -o hplif.img` + - `fluxengine read -c hplif --770 -s drive:0 -o hplif.img` To write: - - `fluxengine write hplif --264 -d drive:0 -i hplif.img` - - `fluxengine write hplif --608 -d drive:0 -i hplif.img` - - `fluxengine write hplif --616 -d drive:0 -i hplif.img` - - `fluxengine write hplif --770 -d drive:0 -i hplif.img` + - `fluxengine write -c hplif --264 -d drive:0 -i hplif.img` + - `fluxengine write -c hplif --608 -d drive:0 -i hplif.img` + - `fluxengine write -c hplif --616 -d drive:0 -i hplif.img` + - `fluxengine write -c hplif --770 -d drive:0 -i hplif.img` ## References diff --git a/doc/disk-ibm.md b/doc/disk-ibm.md index 742be528..bd83f6cd 100644 --- a/doc/disk-ibm.md +++ b/doc/disk-ibm.md @@ -55,30 +55,30 @@ image format. FluxEngine will use these parameters. To read: - - `fluxengine read ibm --auto -s drive:0 -o ibm.img` - - `fluxengine read ibm --160 -s drive:0 -o ibm.img` - - `fluxengine read ibm --180 -s drive:0 -o ibm.img` - - `fluxengine read ibm --320 -s drive:0 -o ibm.img` - - `fluxengine read ibm --360 -s drive:0 -o ibm.img` - - `fluxengine read ibm --720_96 -s drive:0 -o ibm.img` - - `fluxengine read ibm --720_135 -s drive:0 -o ibm.img` - - `fluxengine read ibm --1200 -s drive:0 -o ibm.img` - - `fluxengine read ibm --1232 -s drive:0 -o ibm.img` - - `fluxengine read ibm --1440 -s drive:0 -o ibm.img` - - `fluxengine read ibm --1680 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --auto -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --160 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --180 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --320 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --360 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --720_96 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --720_135 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --1200 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --1232 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --1440 -s drive:0 -o ibm.img` + - `fluxengine read -c ibm --1680 -s drive:0 -o ibm.img` To write: - - `fluxengine write ibm --160 -d drive:0 -i ibm.img` - - `fluxengine write ibm --180 -d drive:0 -i ibm.img` - - `fluxengine write ibm --320 -d drive:0 -i ibm.img` - - `fluxengine write ibm --360 -d drive:0 -i ibm.img` - - `fluxengine write ibm --720_96 -d drive:0 -i ibm.img` - - `fluxengine write ibm --720_135 -d drive:0 -i ibm.img` - - `fluxengine write ibm --1200 -d drive:0 -i ibm.img` - - `fluxengine write ibm --1232 -d drive:0 -i ibm.img` - - `fluxengine write ibm --1440 -d drive:0 -i ibm.img` - - `fluxengine write ibm --1680 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --160 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --180 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --320 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --360 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --720_96 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --720_135 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --1200 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --1232 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --1440 -d drive:0 -i ibm.img` + - `fluxengine write -c ibm --1680 -d drive:0 -i ibm.img` Mixed-format disks ------------------ diff --git a/doc/disk-icl30.md b/doc/disk-icl30.md index a5333a8d..237fb1f5 100644 --- a/doc/disk-icl30.md +++ b/doc/disk-icl30.md @@ -15,5 +15,5 @@ track! Other than that it's another IBM scheme variation. To read: - - `fluxengine read icl30 -s drive:0 -o icl30.img` + - `fluxengine read -c icl30 -s drive:0 -o icl30.img` diff --git a/doc/disk-mac.md b/doc/disk-mac.md index 655c5175..459aadb4 100644 --- a/doc/disk-mac.md +++ b/doc/disk-mac.md @@ -47,13 +47,13 @@ standard for disk images is to omit it. If you want them, specify that you want To read: - - `fluxengine read mac --400 -s drive:0 -o mac.dsk` - - `fluxengine read mac --800 -s drive:0 -o mac.dsk` + - `fluxengine read -c mac --400 -s drive:0 -o mac.dsk` + - `fluxengine read -c mac --800 -s drive:0 -o mac.dsk` To write: - - `fluxengine write mac --400 -d drive:0 -i mac.dsk` - - `fluxengine write mac --800 -d drive:0 -i mac.dsk` + - `fluxengine write -c mac --400 -d drive:0 -i mac.dsk` + - `fluxengine write -c mac --800 -d drive:0 -i mac.dsk` ## References diff --git a/doc/disk-micropolis.md b/doc/disk-micropolis.md index a5c2576f..f7e59151 100644 --- a/doc/disk-micropolis.md +++ b/doc/disk-micropolis.md @@ -63,11 +63,11 @@ need to apply extra options to change the format if desired. To read: - - `fluxengine read micropolis -s drive:0 -o micropolis.img` + - `fluxengine read -c micropolis -s drive:0 -o micropolis.img` To write: - - `fluxengine write micropolis -d drive:0 -i micropolis.img` + - `fluxengine write -c micropolis -d drive:0 -i micropolis.img` ## References diff --git a/doc/disk-mx.md b/doc/disk-mx.md index 0e3102e9..d881f370 100644 --- a/doc/disk-mx.md +++ b/doc/disk-mx.md @@ -52,10 +52,10 @@ Words are all stored little-endian. To read: - - `fluxengine read mx --110 -s drive:0 -o mx.img` - - `fluxengine read mx --220ds -s drive:0 -o mx.img` - - `fluxengine read mx --220ss -s drive:0 -o mx.img` - - `fluxengine read mx --440 -s drive:0 -o mx.img` + - `fluxengine read -c mx --110 -s drive:0 -o mx.img` + - `fluxengine read -c mx --220ds -s drive:0 -o mx.img` + - `fluxengine read -c mx --220ss -s drive:0 -o mx.img` + - `fluxengine read -c mx --440 -s drive:0 -o mx.img` ## References diff --git a/doc/disk-n88basic.md b/doc/disk-n88basic.md index 749b256c..5538f368 100644 --- a/doc/disk-n88basic.md +++ b/doc/disk-n88basic.md @@ -18,9 +18,9 @@ boot ROM could only read single density data.) To read: - - `fluxengine read n88basic -s drive:0 -o n88basic.img` + - `fluxengine read -c n88basic -s drive:0 -o n88basic.img` To write: - - `fluxengine write n88basic -d drive:0 -i n88basic.img` + - `fluxengine write -c n88basic -d drive:0 -i n88basic.img` diff --git a/doc/disk-northstar.md b/doc/disk-northstar.md index 26386574..dfc4d471 100644 --- a/doc/disk-northstar.md +++ b/doc/disk-northstar.md @@ -31,15 +31,15 @@ equivalent to .img images. To read: - - `fluxengine read northstar --87 -s drive:0 -o northstar.nsi` - - `fluxengine read northstar --175 -s drive:0 -o northstar.nsi` - - `fluxengine read northstar --350 -s drive:0 -o northstar.nsi` + - `fluxengine read -c northstar --87 -s drive:0 -o northstar.nsi` + - `fluxengine read -c northstar --175 -s drive:0 -o northstar.nsi` + - `fluxengine read -c northstar --350 -s drive:0 -o northstar.nsi` To write: - - `fluxengine write northstar --87 -d drive:0 -i northstar.nsi` - - `fluxengine write northstar --175 -d drive:0 -i northstar.nsi` - - `fluxengine write northstar --350 -d drive:0 -i northstar.nsi` + - `fluxengine write -c northstar --87 -d drive:0 -i northstar.nsi` + - `fluxengine write -c northstar --175 -d drive:0 -i northstar.nsi` + - `fluxengine write -c northstar --350 -d drive:0 -i northstar.nsi` ## References diff --git a/doc/disk-psos.md b/doc/disk-psos.md index 27df0224..66933130 100644 --- a/doc/disk-psos.md +++ b/doc/disk-psos.md @@ -24,9 +24,9 @@ and, oddly, swapped sides. To read: - - `fluxengine read psos -s drive:0 -o pme.img` + - `fluxengine read -c psos -s drive:0 -o pme.img` To write: - - `fluxengine write psos -d drive:0 -i pme.img` + - `fluxengine write -c psos -d drive:0 -i pme.img` diff --git a/doc/disk-rolandd20.md b/doc/disk-rolandd20.md index 92eaa1dc..b8ad4040 100644 --- a/doc/disk-rolandd20.md +++ b/doc/disk-rolandd20.md @@ -40,9 +40,9 @@ for assistance with this! To read: - - `fluxengine read rolandd20 -s drive:0 -o rolandd20.img` + - `fluxengine read -c rolandd20 -s drive:0 -o rolandd20.img` To write: - - `fluxengine write rolandd20 -d drive:0 -i rolandd20.img` + - `fluxengine write -c rolandd20 -d drive:0 -i rolandd20.img` diff --git a/doc/disk-rx50.md b/doc/disk-rx50.md index d39a5ca2..888feaec 100644 --- a/doc/disk-rx50.md +++ b/doc/disk-rx50.md @@ -15,9 +15,9 @@ vanilla single-sided IBM scheme variation. To read: - - `fluxengine read rx50 -s drive:0 -o rx50.img` + - `fluxengine read -c rx50 -s drive:0 -o rx50.img` To write: - - `fluxengine write rx50 -d drive:0 -i rx50.img` + - `fluxengine write -c rx50 -d drive:0 -i rx50.img` diff --git a/doc/disk-shugart_drive.md b/doc/disk-shugart_drive.md index 086e1d39..a1f8685a 100644 --- a/doc/disk-shugart_drive.md +++ b/doc/disk-shugart_drive.md @@ -10,6 +10,6 @@ on Greaseweazle hardware. For example: ``` -fluxengine read ibm --720 shugart_drive +fluxengine read -c ibm --720 shugart_drive ``` diff --git a/doc/disk-smaky6.md b/doc/disk-smaky6.md index 03dec9f8..4f3ccfc6 100644 --- a/doc/disk-smaky6.md +++ b/doc/disk-smaky6.md @@ -26,7 +26,7 @@ this is completely correct, so don't trust it! To read: - - `fluxengine read smaky6 -s drive:0 -o smaky6.img` + - `fluxengine read -c smaky6 -s drive:0 -o smaky6.img` ## References diff --git a/doc/disk-tartu.md b/doc/disk-tartu.md index 4831d4db..5fb0d049 100644 --- a/doc/disk-tartu.md +++ b/doc/disk-tartu.md @@ -34,13 +34,13 @@ FluxEngine supports reading and writing Tartu disks with CP/M filesystem access. To read: - - `fluxengine read tartu --390 -s drive:0 -o tartu.img` - - `fluxengine read tartu --780 -s drive:0 -o tartu.img` + - `fluxengine read -c tartu --390 -s drive:0 -o tartu.img` + - `fluxengine read -c tartu --780 -s drive:0 -o tartu.img` To write: - - `fluxengine write tartu --390 -d drive:0 -i tartu.img` - - `fluxengine write tartu --780 -d drive:0 -i tartu.img` + - `fluxengine write -c tartu --390 -d drive:0 -i tartu.img` + - `fluxengine write -c tartu --780 -d drive:0 -i tartu.img` ## References diff --git a/doc/disk-tids990.md b/doc/disk-tids990.md index e25dea48..c429b674 100644 --- a/doc/disk-tids990.md +++ b/doc/disk-tids990.md @@ -26,11 +26,11 @@ FluxEngine will read and write these (but only the DSDD MFM variant). To read: - - `fluxengine read tids990 -s drive:0 -o tids990.img` + - `fluxengine read -c tids990 -s drive:0 -o tids990.img` To write: - - `fluxengine write tids990 -d drive:0 -i tids990.img` + - `fluxengine write -c tids990 -d drive:0 -i tids990.img` ## References diff --git a/doc/disk-tiki.md b/doc/disk-tiki.md index bcf4cf89..6f92e19e 100644 --- a/doc/disk-tiki.md +++ b/doc/disk-tiki.md @@ -20,8 +20,8 @@ on the precise format. To read: - - `fluxengine read tiki --90 -s drive:0 -o tiki.img` - - `fluxengine read tiki --200 -s drive:0 -o tiki.img` - - `fluxengine read tiki --400 -s drive:0 -o tiki.img` - - `fluxengine read tiki --800 -s drive:0 -o tiki.img` + - `fluxengine read -c tiki --90 -s drive:0 -o tiki.img` + - `fluxengine read -c tiki --200 -s drive:0 -o tiki.img` + - `fluxengine read -c tiki --400 -s drive:0 -o tiki.img` + - `fluxengine read -c tiki --800 -s drive:0 -o tiki.img` diff --git a/doc/disk-victor9k.md b/doc/disk-victor9k.md index 82e69814..47e98e15 100644 --- a/doc/disk-victor9k.md +++ b/doc/disk-victor9k.md @@ -46,13 +46,13 @@ FluxEngine can read and write both the single-sided and double-sided variants. To read: - - `fluxengine read victor9k --612 -s drive:0 -o victor9k.img` - - `fluxengine read victor9k --1224 -s drive:0 -o victor9k.img` + - `fluxengine read -c victor9k --612 -s drive:0 -o victor9k.img` + - `fluxengine read -c victor9k --1224 -s drive:0 -o victor9k.img` To write: - - `fluxengine write victor9k --612 -d drive:0 -i victor9k.img` - - `fluxengine write victor9k --1224 -d drive:0 -i victor9k.img` + - `fluxengine write -c victor9k --612 -d drive:0 -i victor9k.img` + - `fluxengine write -c victor9k --1224 -d drive:0 -i victor9k.img` ## References diff --git a/doc/disk-zilogmcz.md b/doc/disk-zilogmcz.md index 7d2cb218..7f530f74 100644 --- a/doc/disk-zilogmcz.md +++ b/doc/disk-zilogmcz.md @@ -31,7 +31,7 @@ system. To read: - - `fluxengine read zilogmcz -s drive:0 -o zilogmcz.img` + - `fluxengine read -c zilogmcz -s drive:0 -o zilogmcz.img` ## References diff --git a/doc/using.md b/doc/using.md index 9b83828b..3fd5ee73 100644 --- a/doc/using.md +++ b/doc/using.md @@ -82,16 +82,16 @@ Here are some sample invocations: ``` # Read an PC 1440kB disk, producing a disk image with the default name # (ibm.img) -$ fluxengine read ibm --1440 +$ fluxengine read -c ibm --1440 # Write a PC 1440kB disk to drive 1 -$ fluxengine write ibm --1440 -i image.img -d drive:1 +$ fluxengine write -c ibm --1440 -i image.img -d drive:1 # Read a Eco1 CP/M disk, making a copy of the flux into a file -$ fluxengine read eco1 --copy-flux-to copy.flux -o eco1.ldbs +$ fluxengine read -c eco1 --copy-flux-to copy.flux -o eco1.ldbs # Rerun the decode from the flux file, tweaking the parameters -$ fluxengine read eco1 -s copy.flux -o eco1.ldbs --cylinders=1 +$ fluxengine read -c eco1 -s copy.flux -o eco1.ldbs --cylinders=1 ``` ### Configuration @@ -146,14 +146,14 @@ different task. Run each one with `--help` to get a full list of (non-configuration-setting) options; this describes only basic usage of the more common tools. - - `fluxengine read -s -o ` + - `fluxengine read -c -s -o ` Reads flux (possibly from a disk) and decodes it into a file system image. `` is a reference to an internal input configuration file describing the format. `` may be any combination of options defined by the profile. - - `fluxengine write -i -d ` + - `fluxengine write -c -i -d ` Reads a filesystem image and encodes it into flux (possibly writing to a disk). `` is a reference to an internal output configuration file @@ -489,7 +489,7 @@ containing valuable historical data, and you want to read them. Typically I do this: ``` -$ fluxengine read brother240 -s drive:0 -o brother.img --copy-flux-to=brother.flux --decoder.write_csv_to=brother.csv +$ fluxengine read -c brother240 -s drive:0 -o brother.img --copy-flux-to=brother.flux --decoder.write_csv_to=brother.csv ``` This will read the disk in drive 0 and write out an information CSV file. It'll @@ -499,7 +499,7 @@ settings, I can rerun the decode without having to physically touch the disk like this: ``` -$ fluxengine read brother -s brother.flux -o brother.img --decoder.write_csv_to=brother.csv +$ fluxengine read -c brother -s brother.flux -o brother.img --decoder.write_csv_to=brother.csv ``` Apart from being drastically faster, this avoids touching the (potentially diff --git a/scripts/mkdoc.cc b/scripts/mkdoc.cc index a116134e..9f98d7c2 100644 --- a/scripts/mkdoc.cc +++ b/scripts/mkdoc.cc @@ -28,7 +28,7 @@ static void addExample(std::vector& examples, else return; - r += fmt::format(" {}", name); + r += fmt::format(" -c {}", name); if (format) r += fmt::format(" --{}", format->name()); From e2a6fbcf3cc1c99bf6d672d8b83c7abb80be7d6b Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 20 Aug 2025 21:30:06 +0200 Subject: [PATCH 3/5] Update a few places which used -c for other purposes. --- src/fe-analysedriveresponse.cc | 13 +++++++------ src/fe-inspect.cc | 9 +++++---- src/fe-seek.cc | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/fe-analysedriveresponse.cc b/src/fe-analysedriveresponse.cc index 6b1f2c19..52dd14ea 100644 --- a/src/fe-analysedriveresponse.cc +++ b/src/fe-analysedriveresponse.cc @@ -22,9 +22,7 @@ static StringFlag destFlux({"--dest", "-d"}, globalConfig().setFluxSink(value); }); -static IntFlag destTrack({"--cylinder", "-c"}, "track to write to", 0); - -static IntFlag destHead({"--head", "-h"}, "head to write to", 0); +static StringFlag destTracks({"--tracks", "-t"}, "tracks to write to", "c0h0"); static DoubleFlag minInterval( {"--min-interval-us"}, "Minimum pulse interval", 2.0); @@ -251,11 +249,14 @@ int mainAnalyseDriveResponse(int argc, const char* argv[]) if (globalConfig()->flux_sink().type() != FLUXTYPE_DRIVE) error("this only makes sense with a real disk drive"); + auto tracks = parseCylinderHeadsString(destTracks); + if (tracks.size() != 1) + error("you must specify exactly one track"); usbSetDrive(globalConfig()->drive().drive(), globalConfig()->drive().high_density(), globalConfig()->drive().index_mode()); - usbSeek(destTrack); + usbSeek(tracks[0].cylinder); std::cout << "Measuring rotational speed...\n"; nanoseconds_t period = usbGetRotationalPeriod(0); @@ -291,12 +292,12 @@ int mainAnalyseDriveResponse(int argc, const char* argv[]) outFluxmap.appendPulse(); } - usbWrite(destHead, outFluxmap.rawBytes(), 0); + usbWrite(tracks[0].head, outFluxmap.rawBytes(), 0); /* Read the test pattern in again. */ Fluxmap inFluxmap; - inFluxmap.appendBytes(usbRead(destHead, true, period, 0)); + inFluxmap.appendBytes(usbRead(tracks[0].head, true, period, 0)); /* Compute histogram. */ diff --git a/src/fe-inspect.cc b/src/fe-inspect.cc index d66cddc4..9bb78123 100644 --- a/src/fe-inspect.cc +++ b/src/fe-inspect.cc @@ -21,9 +21,7 @@ static StringFlag sourceFlux({"--source", "-s"}, globalConfig().setFluxSource(value); }); -static IntFlag trackFlag({"--cylinder", "-c"}, "Track to read.", 0); - -static IntFlag headFlag({"--head", "-h"}, "Head to read.", 0); +static StringFlag destTracks({"--tracks", "-t"}, "tracks to write to", "c0h0"); static SettableFlag dumpFluxFlag( {"--dump-flux", "-F"}, "Dump raw magnetic disk flux."); @@ -135,7 +133,10 @@ int mainInspect(int argc, const char* argv[]) flags.parseFlagsWithConfigFiles(argc, argv, {}); auto fluxSource = FluxSource::create(globalConfig()); - const auto fluxmap = fluxSource->readFlux(trackFlag, headFlag)->next(); + auto tracks = parseCylinderHeadsString(destTracks); + if (tracks.size() != 1) + error("you must specify exactly one track"); + const auto fluxmap = fluxSource->readFlux(tracks[0])->next(); std::cout << fmt::format("0x{:x} bytes of data in {:.3f}ms\n", fluxmap->bytes(), diff --git a/src/fe-seek.cc b/src/fe-seek.cc index 8f933716..038f6169 100644 --- a/src/fe-seek.cc +++ b/src/fe-seek.cc @@ -16,7 +16,7 @@ static StringFlag sourceFlux({"-s", "--source"}, globalConfig().setFluxSource(value); }); -static IntFlag track({"--cylinder", "-c"}, "track to seek to", 0); +static IntFlag track({"--cylinder", "-t"}, "track to seek to", 0); extern const std::map readables; From 9062a531f32124f0fd9b171402347308fcfcf3e4 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 21 Aug 2025 00:53:50 +0200 Subject: [PATCH 4/5] Migrate the 40track etc extension configs to actual options. Add the ability to have --group=value options to make this cleaner. --- build.py | 18 ++-- doc/disk-40track_drive.md | 2 +- doc/disk-apple2_drive.md | 2 +- doc/disk-shugart_drive.md | 2 +- lib/config/config.cc | 145 ++++++++++++----------------- lib/config/config.h | 22 ++++- lib/config/config.proto | 3 +- lib/config/flags.cc | 3 +- src/formats/40track_drive.textpb | 22 ----- src/formats/_global_options.textpb | 77 +++++++++++++++ src/formats/apple2_drive.textpb | 29 ------ src/formats/build.py | 4 +- src/formats/shugart_drive.textpb | 22 ----- tests/options.cc | 12 +-- 14 files changed, 175 insertions(+), 188 deletions(-) delete mode 100644 src/formats/40track_drive.textpb create mode 100644 src/formats/_global_options.textpb delete mode 100644 src/formats/apple2_drive.textpb delete mode 100644 src/formats/shugart_drive.textpb diff --git a/build.py b/build.py index 9e61d692..38b0c9cb 100644 --- a/build.py +++ b/build.py @@ -28,7 +28,7 @@ else: ("acorndfs", "", "--200"), ("agat", "", ""), ("amiga", "", ""), - ("apple2", "", "--140 -c 40track_drive"), + ("apple2", "", "--140 --drivetype=40"), ("atarist", "", "--360"), ("atarist", "", "--370"), ("atarist", "", "--400"), @@ -38,17 +38,17 @@ else: ("atarist", "", "--800"), ("atarist", "", "--820"), ("bk", "", ""), - ("brother", "", "--120 -c 40track_drive"), + ("brother", "", "--120 --drivetype=40"), ("brother", "", "--240"), ( "commodore", "scripts/commodore1541_test.textpb", - "--171 -c 40track_drive", + "--171 --drivetype=40", ), ( "commodore", "scripts/commodore1541_test.textpb", - "--192 -c 40track_drive", + "--192 --drivetype=40", ), ("commodore", "", "--800"), ("commodore", "", "--1620"), @@ -60,17 +60,17 @@ else: ("ibm", "", "--1232"), ("ibm", "", "--1440"), ("ibm", "", "--1680"), - ("ibm", "", "--180 -c 40track_drive"), - ("ibm", "", "--160 -c 40track_drive"), - ("ibm", "", "--320 -c 40track_drive"), - ("ibm", "", "--360 -c 40track_drive"), + ("ibm", "", "--180 --drivetype=40"), + ("ibm", "", "--160 --drivetype=40"), + ("ibm", "", "--320 --drivetype=40"), + ("ibm", "", "--360 --drivetype=40"), ("ibm", "", "--720_96"), ("ibm", "", "--720_135"), ("mac", "scripts/mac400_test.textpb", "--400"), ("mac", "scripts/mac800_test.textpb", "--800"), ("n88basic", "", ""), ("rx50", "", ""), - ("tartu", "", "--390 -c 40track_drive"), + ("tartu", "", "--390 --drivetype=40"), ("tartu", "", "--780"), ("tids990", "", ""), ("victor9k", "", "--612"), diff --git a/doc/disk-40track_drive.md b/doc/disk-40track_drive.md index 39b65558..203628f8 100644 --- a/doc/disk-40track_drive.md +++ b/doc/disk-40track_drive.md @@ -10,6 +10,6 @@ no way to detect this automatically. For example: ``` -fluxengine read -c ibm --180 40track_drive +fluxengine read ibm --180 40track_drive ``` diff --git a/doc/disk-apple2_drive.md b/doc/disk-apple2_drive.md index 6fa952e4..e631d138 100644 --- a/doc/disk-apple2_drive.md +++ b/doc/disk-apple2_drive.md @@ -11,6 +11,6 @@ connector. For example: ``` -fluxengine read -c apple2 --160 apple2_drive +fluxengine read apple2 --160 apple2_drive ``` diff --git a/doc/disk-shugart_drive.md b/doc/disk-shugart_drive.md index a1f8685a..086e1d39 100644 --- a/doc/disk-shugart_drive.md +++ b/doc/disk-shugart_drive.md @@ -10,6 +10,6 @@ on Greaseweazle hardware. For example: ``` -fluxengine read -c ibm --720 shugart_drive +fluxengine read ibm --720 shugart_drive ``` diff --git a/lib/config/config.cc b/lib/config/config.cc index 3a96df88..cec45b20 100644 --- a/lib/config/config.cc +++ b/lib/config/config.cc @@ -5,6 +5,7 @@ #include "lib/core/utils.h" #include #include +#include static Config config; @@ -181,35 +182,8 @@ ConfigProto* Config::combined() { _combinedConfig = _baseConfig; - /* First apply any standalone options. */ - - std::set options = _appliedOptions; - for (const auto& option : _baseConfig.option()) - { - if (options.find(option.name()) != options.end()) - { - _combinedConfig.MergeFrom(option.config()); - options.erase(option.name()); - } - } - - /* Then apply any group options. */ - - for (auto& group : _baseConfig.option_group()) - { - const OptionProto* selectedOption = &*group.option().begin(); - - for (auto& option : group.option()) - { - if (options.find(option.name()) != options.end()) - { - selectedOption = &option; - options.erase(option.name()); - } - } - - _combinedConfig.MergeFrom(selectedOption->config()); - } + for (const auto& optionInfo : _appliedOptions) + _combinedConfig.MergeFrom(optionInfo.option->config()); /* Add in the user overrides. */ @@ -241,51 +215,27 @@ std::vector Config::validate() { std::vector results; - std::set optionNames = _appliedOptions; - std::set appliedOptions; - for (const auto& option : _baseConfig.option()) - { - if (optionNames.find(option.name()) != optionNames.end()) + /* Ensure that only one item in each group is set. */ + + std::map optionsByGroup; + for (auto [group, option, hasArgument] : _appliedOptions) + if (group) { - appliedOptions.insert(&option); - optionNames.erase(option.name()); + auto& o = optionsByGroup[group]; + if (o) + results.push_back( + fmt::format("multiple mutually exclusive values set for " + "group '{}': valid values are: {}", + group->comment(), + fmt::join(std::views::transform( + group->option(), &OptionProto::name), + ", "))); + o = option; } - } - - /* Then apply any group options. */ - - for (auto& group : _baseConfig.option_group()) - { - int count = 0; - - for (auto& option : group.option()) - { - if (optionNames.find(option.name()) != optionNames.end()) - { - optionNames.erase(option.name()); - appliedOptions.insert(&option); - - count++; - if (count == 2) - results.push_back( - fmt::format("multiple mutually exclusive options set " - "for group '{}'", - group.comment())); - } - } - } - - /* Check for unknown options. */ - - if (!optionNames.empty()) - { - for (auto& name : optionNames) - results.push_back(fmt::format("'{}' is not a known option", name)); - } /* Check option requirements. */ - for (auto& option : appliedOptions) + for (auto [group, option, hasArgument] : _appliedOptions) { try { @@ -360,11 +310,12 @@ void Config::readBaseConfig(std::string data) error("couldn't load external config proto"); } -const OptionProto& Config::findOption(const std::string& optionName) +Config::OptionInfo Config::findOption( + const std::string& name, const std::string value) { const OptionProto* found = nullptr; - auto searchOptionList = [&](auto& optionList) + auto searchOptionList = [&](auto& optionList, const std::string& optionName) { for (const auto& option : optionList) { @@ -377,17 +328,39 @@ const OptionProto& Config::findOption(const std::string& optionName) return false; }; - if (searchOptionList(base()->option())) - return *found; + /* First look for any group names which match. */ + + if (!value.empty()) + for (const auto& optionGroup : base()->option_group()) + if (optionGroup.name() == name) + { + /* The option must therefore be one of these. */ + + if (searchOptionList(optionGroup.option(), value)) + return {&optionGroup, found, true}; + + throw OptionNotFoundException(fmt::format( + "value {} is not valid for option {}; valid values are: {}", + value, + name, + fmt::join(std::views::transform( + optionGroup.option(), &OptionProto::name), + ", "))); + } + + /* Now search for individual options. */ + + if (searchOptionList(base()->option(), name)) + return {nullptr, found, false}; for (const auto& optionGroup : base()->option_group()) { - if (searchOptionList(optionGroup.option())) - return *found; + if (optionGroup.name().empty()) + if (searchOptionList(optionGroup.option(), name)) + return {nullptr, found, false}; } - throw OptionNotFoundException( - fmt::format("option {} not found", optionName)); + throw OptionNotFoundException(fmt::format("option {} not found", name)); } void Config::checkOptionValid(const OptionProto& option) @@ -445,22 +418,20 @@ bool Config::isOptionValid(const OptionProto& option) } } -bool Config::isOptionValid(std::string option) -{ - return isOptionValid(findOption(option)); -} - -void Config::applyOption(const OptionProto& option) +void Config::applyOption(const OptionInfo& optionInfo) { + auto* option = optionInfo.option; log(OptionLogMessage{ - option.has_message() ? option.message() : option.comment()}); + option->has_message() ? option->message() : option->comment()}); - _appliedOptions.insert(option.name()); + _appliedOptions.insert(optionInfo); } -void Config::applyOption(std::string option) +bool Config::applyOption(const std::string& name, const std::string value) { - applyOption(findOption(option)); + auto optionInfo = findOption(name, value); + applyOption(optionInfo); + return optionInfo.usesValue; } void Config::clearOptions() diff --git a/lib/config/config.h b/lib/config/config.h index 5025347e..e3026336 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -66,6 +66,18 @@ struct FluxConstructor class Config { +private: + struct OptionInfo + { + bool operator==(const OptionInfo& other) const = default; + std::strong_ordering operator<=>( + const OptionInfo& other) const = default; + + const OptionGroupProto* group; + const OptionProto* option; + bool usesValue; + }; + public: /* Direct access to the various proto layers. */ @@ -124,12 +136,12 @@ public: /* Option management: look up an option by name, determine whether an option * is valid, and apply an option. */ - const OptionProto& findOption(const std::string& option); + OptionInfo findOption( + const std::string& name, const std::string value = ""); void checkOptionValid(const OptionProto& option); bool isOptionValid(const OptionProto& option); - bool isOptionValid(std::string option); - void applyOption(const OptionProto& option); - void applyOption(std::string option); + void applyOption(const OptionInfo& optionInfo); + bool applyOption(const std::string& name, const std::string value = ""); void clearOptions(); /* Adjust overall inputs and outputs. */ @@ -165,7 +177,7 @@ private: ConfigProto _baseConfig; ConfigProto _overridesConfig; ConfigProto _combinedConfig; - std::set _appliedOptions; + std::set _appliedOptions; bool _configValid; FluxSourceProto _verificationFluxSourceProto; diff --git a/lib/config/config.proto b/lib/config/config.proto index e98c85ec..9db8f972 100644 --- a/lib/config/config.proto +++ b/lib/config/config.proto @@ -73,5 +73,6 @@ message OptionProto message OptionGroupProto { optional string comment = 1 [(help) = "help text for option group"]; - repeated OptionProto option = 2; + optional string name = 2 [(help) = "option group name"]; + repeated OptionProto option = 3; } diff --git a/lib/config/flags.cc b/lib/config/flags.cc index f474673b..f61b0dac 100644 --- a/lib/config/flags.cc +++ b/lib/config/flags.cc @@ -158,7 +158,7 @@ std::vector FlagGroup::parseFlagsWithFilenames(int argc, index += usesthat; } else - globalConfig().applyOption(path); + usesthat = globalConfig().applyOption(path, value); } else error("unrecognised flag '-{}'; try --help", key); @@ -197,6 +197,7 @@ void FlagGroup::parseFlagsWithConfigFiles(int argc, const char* argv[], const std::map& configFiles) { + globalConfig().readBaseConfigFile("_global_options"); FlagGroup({this, &configGroup}).parseFlags(argc, argv); } diff --git a/src/formats/40track_drive.textpb b/src/formats/40track_drive.textpb deleted file mode 100644 index 39b16f95..00000000 --- a/src/formats/40track_drive.textpb +++ /dev/null @@ -1,22 +0,0 @@ -comment: 'Adjust configuration for a 40-track drive' -is_extension: true - -documentation: -<<< -This is an extension profile; adding this to the command line will configure -FluxEngine to read from 40-track, 48tpi 5.25" drives. You have to tell it because there is -no way to detect this automatically. - -For example: - -``` -fluxengine read ibm --180 40track_drive -``` ->>> - -drive { - tracks: "c0-40h0-1" - drive_type: DRIVETYPE_40TRACK -} - - diff --git a/src/formats/_global_options.textpb b/src/formats/_global_options.textpb new file mode 100644 index 00000000..7619f5da --- /dev/null +++ b/src/formats/_global_options.textpb @@ -0,0 +1,77 @@ +comment: 'Options which can be applied everywhere.' +is_extension: true + +option_group { + comment: "Drive type" + name: "drivetype" + + option { + name: "80" + comment: '80 track drive' + set_by_default: true + + config { + } + } + + option { + name: "40" + comment: '40 track drive' + + config { + drive { + tracks: "c0-40h0-1" + drive_type: DRIVETYPE_40TRACK + } + } + } + + option { + name: "160" + comment: '160 track Apple II drive' + + config { + drive { + tracks: "c0-159h0" + drive_type: DRIVETYPE_APPLE2 + } + } + } +} + +option_group { + comment: 'Bus interface' + name: "bus" + + option { + name: "pc" + comment: 'PC drive interface' + set_by_default: true + } + + option { + name: "shugart" + comment: 'Shugart bus interface (only on Greaseweazle)' + + config { + usb { + greaseweazle { + bus_type: SHUGART + } + } + } + } + + option { + name: "appleii" + comment: 'Apple II bus interface (only on Greaseweazle)' + + config { + usb { + greaseweazle { + bus_type: APPLE2 + } + } + } + } +} diff --git a/src/formats/apple2_drive.textpb b/src/formats/apple2_drive.textpb deleted file mode 100644 index 64532bcc..00000000 --- a/src/formats/apple2_drive.textpb +++ /dev/null @@ -1,29 +0,0 @@ -comment: 'Adjust configuration for a 40-track Apple II drive' -is_extension: true - -documentation: -<<< -This is an extension profile; adding this to the command line will configure -FluxEngine to adjust the pinout and track spacing to work with an Apple II -drive. This only works on Greaseweazle hardware and requires a custom -connector. - -For example: - -``` -fluxengine read apple2 --160 apple2_drive -``` ->>> - -usb { - greaseweazle { - bus_type: APPLE2 - } -} - -drive { - tracks: "c0-159h0" - drive_type: DRIVETYPE_APPLE2 -} - - diff --git a/src/formats/build.py b/src/formats/build.py index b4689560..99f0591e 100644 --- a/src/formats/build.py +++ b/src/formats/build.py @@ -3,14 +3,13 @@ from build.c import cxxlibrary from scripts.build import protoencode formats = [ - "40track_drive", + "_global_options", "acornadfs", "acorndfs", "aeslanier", "agat", "amiga", "ampro", - "apple2_drive", "apple2", "atarist", "bk", @@ -33,7 +32,6 @@ formats = [ "psos", "rolandd20", "rx50", - "shugart_drive", "smaky6", "tartu", "ti99", diff --git a/src/formats/shugart_drive.textpb b/src/formats/shugart_drive.textpb deleted file mode 100644 index 8734c2fc..00000000 --- a/src/formats/shugart_drive.textpb +++ /dev/null @@ -1,22 +0,0 @@ -comment: 'Adjust configuration for a Shugart drive' -is_extension: true - -documentation: -<<< -This is an extension profile; adding this to the command line will configure -FluxEngine to adjust the pinout to work with a Shugart drive. This only works -on Greaseweazle hardware. - -For example: - -``` -fluxengine read ibm --720 shugart_drive -``` ->>> - -usb { - greaseweazle { - bus_type: SHUGART - } -} - diff --git a/tests/options.cc b/tests/options.cc index 547e9021..37f8af64 100644 --- a/tests/options.cc +++ b/tests/options.cc @@ -55,14 +55,14 @@ static void test_option_validity() } )M"); - AssertThat( - globalConfig().isOptionValid(globalConfig().findOption("option1")), + AssertThat(globalConfig().isOptionValid( + *globalConfig().findOption("option1").option), Equals(true)); - AssertThat( - globalConfig().isOptionValid(globalConfig().findOption("option2")), + AssertThat(globalConfig().isOptionValid( + *globalConfig().findOption("option2").option), Equals(false)); - AssertThat( - globalConfig().isOptionValid(globalConfig().findOption("option3")), + AssertThat(globalConfig().isOptionValid( + *globalConfig().findOption("option3").option), Equals(true)); } From 979b55017856d424425a89edf6d5f2350a315a90 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 21 Aug 2025 01:19:19 +0200 Subject: [PATCH 5/5] Looks like our string_view fix hasn't worked --- tweak. --- scripts/mkdocindex.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/mkdocindex.cc b/scripts/mkdocindex.cc index 7a3bb716..dbbb3db5 100644 --- a/scripts/mkdocindex.cc +++ b/scripts/mkdocindex.cc @@ -43,8 +43,9 @@ int main(int argc, const char* argv[]) { const auto* descriptor = FilesystemProto::FilesystemType_descriptor(); - std::string name = - descriptor->FindValueByNumber(fs.type())->name(); + auto name = + (std::string)descriptor->FindValueByNumber(fs.type()) + ->name(); filesystems.insert(name); }