diff --git a/src/lib/netlist/buildVS/netlist.sln b/src/lib/netlist/buildVS/netlist.sln
index a06f407d3c2..433d034cf6f 100755
--- a/src/lib/netlist/buildVS/netlist.sln
+++ b/src/lib/netlist/buildVS/netlist.sln
@@ -1,12 +1,14 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netlistlib", "netlistlib.vcxproj", "{A374399B-B87F-4E0F-9525-6C099600705F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nltool", "nltool.vcxproj", "{9204EC28-A29B-4A36-9E47-2C46041D67D3}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nlwav", "nlwav.vcxproj", "{48D0ADAF-62EC-472E-A51B-8D837280649D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -31,8 +33,19 @@ Global
{9204EC28-A29B-4A36-9E47-2C46041D67D3}.Release|x64.Build.0 = Release|x64
{9204EC28-A29B-4A36-9E47-2C46041D67D3}.Release|x86.ActiveCfg = Release|Win32
{9204EC28-A29B-4A36-9E47-2C46041D67D3}.Release|x86.Build.0 = Release|Win32
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}.Debug|x64.ActiveCfg = Debug|x64
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}.Debug|x64.Build.0 = Debug|x64
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}.Debug|x86.ActiveCfg = Debug|Win32
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}.Debug|x86.Build.0 = Debug|Win32
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}.Release|x64.ActiveCfg = Release|x64
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}.Release|x64.Build.0 = Release|x64
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}.Release|x86.ActiveCfg = Release|Win32
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {992701A0-B9F5-4F7D-BF3F-5B0EBEA51F04}
+ EndGlobalSection
EndGlobal
diff --git a/src/lib/netlist/buildVS/netlistlib.vcxproj.user b/src/lib/netlist/buildVS/netlistlib.vcxproj.user
deleted file mode 100755
index abe8dd8961e..00000000000
--- a/src/lib/netlist/buildVS/netlistlib.vcxproj.user
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/lib/netlist/buildVS/nlwav.vcxproj b/src/lib/netlist/buildVS/nlwav.vcxproj
new file mode 100755
index 00000000000..7b191fedccd
--- /dev/null
+++ b/src/lib/netlist/buildVS/nlwav.vcxproj
@@ -0,0 +1,162 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+ {a374399b-b87f-4e0f-9525-6c099600705f}
+
+
+
+ 16.0
+ {48D0ADAF-62EC-472E-A51B-8D837280649D}
+ Win32Proj
+ nlwav
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+
+
+ Level3
+ true
+ true
+
+
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)..\..\
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/lib/netlist/buildVS/nlwav.vcxproj.filters b/src/lib/netlist/buildVS/nlwav.vcxproj.filters
new file mode 100755
index 00000000000..7b114761bb4
--- /dev/null
+++ b/src/lib/netlist/buildVS/nlwav.vcxproj.filters
@@ -0,0 +1,22 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h
index 3a807c3c7f0..2db0e7e9585 100755
--- a/src/lib/netlist/plib/poptions.h
+++ b/src/lib/netlist/plib/poptions.h
@@ -12,6 +12,7 @@
#include "pstonum.h"
#include "pstring.h"
#include "putil.h"
+#include "pfmtlog.h"
namespace plib {
@@ -27,7 +28,7 @@ namespace plib {
PCOPYASSIGNMOVE(option_base, delete)
- pstring help() const { return m_help; }
+ virtual pstring help() const { return m_help; }
private:
pstring m_help;
};
@@ -169,16 +170,23 @@ namespace plib {
public:
option_num(options &parent, const pstring &ashort, const pstring &along, T defval,
const pstring &help,
- T minval = std::numeric_limits::min(),
+ T minval = std::numeric_limits::lowest(),
T maxval = std::numeric_limits::max() )
: option(parent, ashort, along, help, true)
, m_val(defval)
, m_min(minval)
, m_max(maxval)
+ , m_def(defval)
{}
T operator ()() const { return m_val; }
+ pstring help() const override
+ {
+ auto hs(option::help());
+ return plib::pfmt(hs)(m_def, m_min, m_max);
+ }
+
protected:
int parse(const pstring &argument) override
{
@@ -191,6 +199,7 @@ namespace plib {
T m_val;
T m_min;
T m_max;
+ T m_def;
};
class option_vec : public option
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index ca05dc689b7..f2d18092629 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -1195,14 +1195,9 @@ int tool_app_t::execute()
return 1;
}
}
- catch (netlist::nl_exception &e)
- {
- perr("Netlist exception caught: {}\n", e.text());
- return 2;
- }
catch (plib::pexception &e)
{
- perr("plib exception caught: {}\n", e.text());
+ perr("Exception caught: {}\n", e.text());
return 2;
}
diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp
old mode 100644
new mode 100755
index 0606c583e07..a444e2f9ef9
--- a/src/lib/netlist/prg/nlwav.cpp
+++ b/src/lib/netlist/prg/nlwav.cpp
@@ -1,14 +1,21 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
-#include "plib/pstring.h"
+#include "netlist/plib/pstring.h"
#include "netlist/nl_setup.h"
-#include "plib/plists.h"
-#include "plib/pmain.h"
-#include "plib/ppmf.h"
-#include "plib/pstream.h"
+#include "netlist/plib/plists.h"
+#include "netlist/plib/pmain.h"
+#include "netlist/plib/ppmf.h"
+#include "netlist/plib/pstream.h"
#include
+// see below - this belongs somewhere else!
+#ifdef _WIN32
+#include
+#include
+#include
+#endif
+
// From: https://ffmpeg.org/pipermail/ffmpeg-devel/2007-October/038122.html
// The most compatible way to make a wav header for unknown length is to put
// 0xffffffff in the header. 0 as the RIFF length and 0 as the data chunk length
@@ -24,12 +31,20 @@
class wav_t
{
public:
- // XXNOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
- wav_t(std::ostream &strm, bool is_seekable, std::size_t sr, std::size_t channels)
+
+ enum format
+ {
+ s16,
+ s32,
+ f32
+ };
+
+ wav_t(std::ostream &strm, bool is_seekable, format fmt, std::size_t sr, std::size_t channels)
: m_f(strm)
, m_stream_is_seekable(is_seekable)
+ , m_format(fmt)
// force "play" to play and warn about eof instead of being silent
- , m_fmt(static_cast(channels), static_cast(sr))
+ , m_fmt(static_cast(channels), static_cast(sr), fmt)
, m_data(is_seekable ? 0 : 0xffffffff)
{
@@ -60,17 +75,43 @@ public:
template
void write(const T &val)
{
+ static_assert(sizeof(std::ostream::char_type) == 1, "char_type size must be 1");
auto ptr(reinterpret_cast(&val));
m_f.write(ptr, sizeof(T));
}
- void write_sample(const int *sample)
+ template
+ void write_sample_int(double sample)
+ {
+ const auto mmax(static_cast(plib::numeric_limits::max()));
+ const auto mmin(static_cast(plib::numeric_limits::min()));
+
+ sample *= mmax;
+ sample = std::max(mmin, sample);
+ sample = std::min(mmax, sample);
+ const auto dest(static_cast(sample));
+ write(dest);
+ }
+
+ // expects normalized samples between -1.0 to 1.0 for s16 and s32
+ void write_samples(double *sample)
{
m_data.len += m_fmt.block_align;
for (std::size_t i = 0; i < channels(); i++)
{
- auto ps = static_cast(sample[i]); // 16 bit sample, FIXME: Endianess?
- write(ps);
+ switch (m_format)
+ {
+ case s16:
+ write_sample_int(sample[i]);
+ break;
+ case s32:
+ write_sample_int(sample[i]);
+ break;
+ case f32:
+ const auto df32(static_cast(sample[i]));
+ write(df32);
+ break;
+ }
}
}
@@ -84,8 +125,23 @@ private:
struct riff_format_t
{
- riff_format_t(uint16_t achannels, uint32_t asample_rate)
+ riff_format_t(uint16_t achannels, uint32_t asample_rate, format fm)
{
+ switch (fm)
+ {
+ case s16:
+ format_tag = 0x0001; // PCM
+ bits_sample = 16;
+ break;
+ case s32:
+ format_tag = 0x0001; // PCM
+ bits_sample = 32;
+ break;
+ case f32:
+ format_tag = 0x0003; // FLOAT
+ bits_sample = 32;
+ break;
+ }
channels = achannels;
sample_rate = asample_rate;
block_align = channels * ((bits_sample + 7) / 8);
@@ -93,12 +149,12 @@ private:
}
std::array signature = {{'f','m','t',' '}};
uint32_t fmt_length = 16;
- uint16_t format_tag = 0x0001; // PCM
+ uint16_t format_tag;
uint16_t channels;
uint32_t sample_rate;
uint32_t bytes_per_second;
uint16_t block_align;
- uint16_t bits_sample = 16;
+ uint16_t bits_sample;
};
struct riff_data_t
@@ -111,6 +167,7 @@ private:
std::ostream &m_f;
bool m_stream_is_seekable;
+ format m_format;
riff_chunk_t m_fh;
riff_format_t m_fmt;
@@ -240,52 +297,130 @@ private:
std::vector cursam;
};
+struct filter_hp
+{
+ using callback_type = plib::pmfp;
+
+ filter_hp(double freq, bool boost, std::size_t channels, callback_type cb)
+ : m_channels(channels)
+ , m_cb(cb)
+ , m_hp_omega(plib::constants::two() * plib::constants::pi() * freq)
+ , m_boost(boost)
+ , m_lt(channels, 0.0)
+ , m_in(channels, 0.0)
+ , m_cap(channels, 0.0)
+ { }
+ void process(std::size_t chan, double time, double val)
+ {
+ // based on CR filter
+ auto dt(time - m_lt[chan]);
+
+ double omega = ((m_boost && (time < 1.0/m_hp_omega)) ? 1e12 : m_hp_omega);
+ auto m(1.0 - plib::exp(-dt * omega));
+ m_cap[chan] += m * (m_in[chan] - m_cap[chan]);
+ // out = in - vcap
+ m_cb(chan, time, m_in[chan] - m_cap[chan]);
+
+ m_in[chan] = val;
+ m_lt[chan] = time;
+ }
+
+private:
+ std::size_t m_channels;
+ callback_type m_cb;
+ double m_hp_omega;
+ bool m_boost;
+ std::vector m_lt;
+ std::vector m_in;
+ std::vector m_cap;
+};
+
+struct filter_lp
+{
+ using callback_type = plib::pmfp;
+
+ filter_lp(double freq, std::size_t channels, callback_type cb)
+ : m_channels(channels)
+ , m_cb(cb)
+ , m_lp_omega(plib::constants::two() * plib::constants::pi() * freq)
+ , m_lt(channels, 0.0)
+ , m_in(channels, 0.0) // lp filter
+ , m_cap(channels, 0.0) // hp filter
+ { }
+ void process(std::size_t chan, double time, double val)
+ {
+ // based on RC filter
+ auto dt(time - m_lt[chan]);
+
+ auto m(1.0 - plib::exp(-dt * m_lp_omega));
+
+ m_cap[chan] += m * (m_in[chan] - m_cap[chan]);
+ // out = vcap
+ m_cb(chan, time, m_cap[chan]);
+
+ m_in[chan] = val;
+ m_lt[chan] = time;
+ }
+
+private:
+ std::size_t m_channels;
+ callback_type m_cb;
+ double m_lp_omega;
+ std::vector m_lt;
+ std::vector m_in;
+ std::vector m_cap;
+};
+
class wavwriter
{
public:
- wavwriter(std::ostream &fo, bool is_seekable, std::size_t channels, std::size_t sample_rate, double ampa)
- : mean(channels, 0.0)
- , means(channels, 0.0)
- , maxsam(channels, -1e9)
+ wavwriter(std::ostream &fo, bool is_seekable, wav_t::format fmt,
+ std::size_t channels, std::size_t sample_rate, double ampa)
+ : maxsam(channels, -1e9)
, minsam(channels, 1e9)
, m_n(channels, 0)
, m_samples(channels, 0)
, m_last_time(0)
, m_fo(fo)
- , m_amp(ampa)
- , m_wo(m_fo, is_seekable, sample_rate, channels)
+ , m_amp(ampa <= 0.0 ? 1.0e6 : ampa)
+ , m_auto(ampa <= 0.0)
+ , m_wo(m_fo, is_seekable, fmt, sample_rate, channels)
{ }
void process(std::size_t chan, double time, double outsam)
{
if (time > m_last_time)
- m_wo.write_sample(m_samples.data());
+ m_wo.write_samples(m_samples.data());
m_last_time = time;
- means[chan] += outsam;
maxsam[chan] = std::max(maxsam[chan], outsam);
minsam[chan] = std::min(minsam[chan], outsam);
m_n[chan]++;
- //mean = means / (double) m_n;
- mean[chan] += 5.0 / static_cast(m_wo.sample_rate()) * (outsam - mean[chan]);
- outsam = (outsam - mean[chan]) * m_amp;
- outsam = std::max(-32000.0, outsam);
- outsam = std::min(32000.0, outsam);
- m_samples[chan] = static_cast(outsam);
+ auto val(outsam * m_amp);
+ if (m_auto && plib::abs(val) > 1.0)
+ {
+ do
+ {
+ m_amp /= 2.0;
+ val = outsam * m_amp;
+ } while (plib::abs(val) > 1.0);
+ // FIXME: log this in state and provide on verbose output
+ //printf("dynamp adjusted to %f at %f\n", m_amp, time);
+ }
+ m_samples[chan] = val;
}
- std::vector mean;
- std::vector means;
std::vector maxsam;
std::vector minsam;
std::vector m_n;
- std::vector m_samples;
+ std::vector m_samples;
double m_last_time;
private:
std::ostream &m_fo;
double m_amp;
+ bool m_auto;
wav_t m_wo;
};
@@ -441,18 +576,23 @@ class nlwav_app : public plib::app
public:
nlwav_app() :
plib::app(),
- opt_fmt(*this, "f", "format", 0, std::vector({"wav","vcda","vcdd", "tab"}),
- "output format. Available options are wav|vcda|vcdd|tab."
- " wav : multichannel wav output"
- " vcda : analog VCD output"
- " vcdd : digital VCD output"
- " tab : sampled output"
+ opt_fmt(*this, "f", "format", 0, std::vector({"wav16s","wav32s","wav32f","vcda","vcdd", "tab"}),
+ "output format. Available options are wav16s|wav32s|wav32f|vcda|vcdd|tab.\n"
+ " wav16s : multichannel wav output 16 bit signed\n"
+ " wav32s : multichannel wav output 32 bit signed\n"
+ " wav32f : multichannel wav output 32 bit float\n"
+ " vcda : analog VCD output\n"
+ " vcdd : digital VCD output\n"
+ " tab : sampled output\n"
" Digital signals are created using the --high and --low options"
),
opt_out(*this, "o", "output", "-", "output file"),
opt_grp1(*this, "wav options", "These options apply to wav output only"),
opt_rate(*this, "r", "rate", 48000, "sample rate of output file"),
opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction"),
+ opt_lowpass(*this, "", "lowpass", 20000.0, "lowpass filter frequency.\nDefault {1:.0} Hz."),
+ opt_highpass(*this, "", "highpass", 20.0, "highpass filter frequency.\nDefault is {1:.0} Hz."),
+ opt_hpboost(*this, "", "hpboost", "enable highpass boost to filter out initial click."),
opt_grp2(*this, "vcdd options", "These options apply to vcdd output only"),
opt_high(*this, "u", "high", 2.0, "minimum input for high level"),
opt_low(*this, "l", "low", 1.0, "maximum input for low level"),
@@ -468,8 +608,8 @@ public:
opt_help(*this, "h", "help", "display help and exit"),
opt_ex1(*this, "./nlwav -f vcdd -o x.vcd log_V*",
"convert all files starting with \"log_V\" into a digital vcd file"),
- opt_ex2(*this, "./nlwav -f wav -o x.wav log_V*",
- "convert all files starting with \"log_V\" into a multichannel wav file"),
+ opt_ex2(*this, "./nlwav -f wav16s -o x.wav log_V*",
+ "convert all files starting with \"log_V\" into a multichannel wav file (16bit, signed)"),
opt_ex3(*this, "./nlwav -f tab -o x.tab -s 0.0000005 -i 0.000001 -n 256 log_BLUE.log",
"convert file log_BLUE.log to sampled output. First sample at 500ns "
"followed by 255 samples every micro-second.")
@@ -479,7 +619,7 @@ public:
pstring usage() override;
private:
- void convert_wav(std::ostream &ostrm);
+ void convert_wav(std::ostream &ostrm, wav_t::format fmt);
void convert_vcd(std::ostream &ostrm, vcdwriter::format_e format);
void convert_tab(std::ostream &ostrm);
void convert(const pstring &outname);
@@ -489,6 +629,9 @@ private:
plib::option_group opt_grp1;
plib::option_num opt_rate;
plib::option_num opt_amp;
+ plib::option_num opt_lowpass;
+ plib::option_num opt_highpass;
+ plib::option_bool opt_hpboost;
plib::option_group opt_grp2;
plib::option_num opt_high;
plib::option_num opt_low;
@@ -509,16 +652,20 @@ private:
std::vector> m_instrms;
};
-void nlwav_app::convert_wav(std::ostream &ostrm)
+void nlwav_app::convert_wav(std::ostream &ostrm, wav_t::format fmt)
{
double dt = plib::reciprocal(static_cast(opt_rate()));
+ auto nchan = m_instrms.size();
- plib::unique_ptr wo = plib::make_unique(ostrm, opt_out() != "-", m_instrms.size(), opt_rate(), opt_amp());
- plib::unique_ptr ago = plib::make_unique(m_instrms.size(), dt, aggregator::callback_type(&wavwriter::process, wo.get()));
- aggregator::callback_type agcb = log_processor::callback_type(&aggregator::process, ago.get());
+ auto wo = plib::make_unique(ostrm, opt_out() != "-", fmt, nchan, opt_rate(), opt_amp());
+ auto ago = plib::make_unique(nchan, dt, aggregator::callback_type(&wavwriter::process, wo.get()));
+ auto fgo_hp = plib::make_unique(opt_highpass(), opt_hpboost(), nchan, filter_hp::callback_type(&aggregator::process, ago.get()));
+ auto fgo_lp = plib::make_unique(opt_lowpass(), nchan, filter_lp::callback_type(&filter_hp::process, fgo_hp.get()));
- log_processor lp(m_instrms.size(), agcb);
+ auto topcb = log_processor::callback_type(&filter_lp::process, fgo_lp.get());
+
+ log_processor lp(nchan, topcb);
lp.process(m_instrms);
@@ -591,6 +738,10 @@ static void open_ostream_and_exec(pstring fname, bool binary, F func)
else
{
std::cout.imbue(std::locale::classic());
+ // FIXME: switch to binary on windows
+#ifdef _WIN32
+ _setmode(_fileno(stdout), _O_BINARY);
+#endif
func(std::cout);
}
}
@@ -600,15 +751,21 @@ void nlwav_app::convert(const pstring &outname)
switch (opt_fmt())
{
case 0:
- open_ostream_and_exec(outname, true, [this](std::ostream &ostrm) { convert_wav(ostrm); });
+ open_ostream_and_exec(outname, true, [this](std::ostream &ostrm) { convert_wav(ostrm, wav_t::s16); });
break;
case 1:
- open_ostream_and_exec(outname, false, [this](std::ostream &ostrm) { convert_vcd(ostrm, vcdwriter::ANALOG); });
+ open_ostream_and_exec(outname, true, [this](std::ostream &ostrm) { convert_wav(ostrm, wav_t::s32); });
break;
case 2:
- open_ostream_and_exec(outname, false, [this](std::ostream &ostrm) { convert_vcd(ostrm, vcdwriter::DIGITAL); });
+ open_ostream_and_exec(outname, true, [this](std::ostream &ostrm) { convert_wav(ostrm, wav_t::f32); });
break;
case 3:
+ open_ostream_and_exec(outname, false, [this](std::ostream &ostrm) { convert_vcd(ostrm, vcdwriter::ANALOG); });
+ break;
+ case 4:
+ open_ostream_and_exec(outname, false, [this](std::ostream &ostrm) { convert_vcd(ostrm, vcdwriter::DIGITAL); });
+ break;
+ case 5:
open_ostream_and_exec(outname, false, [this](std::ostream &ostrm) { convert_tab(ostrm); });
break;
default:
@@ -637,23 +794,34 @@ int nlwav_app::execute()
return 0;
}
- for (const auto &oi: opt_args())
+ try
{
- plib::unique_ptr fin;
- if (oi == "-")
+ for (const auto &oi: opt_args())
{
- auto temp(plib::make_unique());
- plib::copystream(*temp, std::cin);
- fin = std::move(temp);
+ plib::unique_ptr fin;
+ if (oi == "-")
+ {
+ auto temp(plib::make_unique());
+ plib::copystream(*temp, std::cin);
+ fin = std::move(temp);
+ }
+ else
+ {
+ fin = plib::make_unique(plib::filesystem::u8path(oi), std::ios::in);
+ if (fin->fail())
+ throw plib::file_open_e(oi);
+ }
+ fin->imbue(std::locale::classic());
+ m_instrms.push_back(std::move(fin));
}
- else
- fin = plib::make_unique(plib::filesystem::u8path(oi));
- fin->imbue(std::locale::classic());
- m_instrms.push_back(std::move(fin));
+
+ convert(opt_out());
+ }
+ catch (plib::pexception &e)
+ {
+ perr("Exception caught: {}\n", e.text());
+ return 1;
}
-
- convert(opt_out());
-
return 0;
}