What would DCL-style syntax for ffmpeg look like? I suppose one
obvious equivalence would be
ffmpeg -
«infile-1»/«local-input-options-1»,«infile-2»/«local-input-options-2»,... -
«outfile-1»/«local-output-options-1»,«outfile-2»/«local-output-options-2»,... -
(being very careful about where the commas go), but what about the
syntax for filtergraphs? Would it be something like
/vf=(«filter-name-1»=«filter-params-1»,«filter-name-2»=«filter-params-2»...)
Does DCL have provision for this sort of complexity?
On 2/13/2025 5:52 PM, Lawrence D'Oliveiro wrote:
What would DCL-style syntax for ffmpeg look like? I suppose one
obvious equivalence would be
ffmpeg -
«infile-1»/«local-input-options-1»,«infile-2»/«local-input-
options-2»,... -
«outfile-1»/«local-output-options-1»,«outfile-2»/«local-
output-options-2»,... -
(being very careful about where the commas go), but what about the
syntax for filtergraphs? Would it be something like
/vf=(«filter-name-1»=«filter-params-1»,«filter-name-2»=«filter-
params-2»...)
Does DCL have provision for this sort of complexity?
You can do quite a bit with CDU, CLD and CLI$:
$ type fun.cld
define verb fun
image "sys$disk:[]fun"
parameter p1, value(type=$file)
parameter p2, value(type=$file)
parameter p3, value(type=$file)
parameter p4, value(type=$file)
parameter p5, value(type=$file)
parameter p6, value(type=$file)
parameter p7, value(type=$file)
parameter p8, value(type=$file)
qualifier q1, placement=local
qualifier q2, value(type=a_and_b, list, required), placement=local
define type a_and_b
keyword a, value(type=$number, required)
keyword b, value(type=$number, required)
$ type fun.pas
[inherit('sys$library:pascal$cli_routines')]
program fun(input,output);
type
pstr = varying [255] of char;
procedure check(pn : pstr);
var
fnm, a, b : pstr;
begin
if odd(cli$present(pn)) then begin
cli$get_value(pn, fnm.body, fnm.length);
write(pn, '=', fnm);
if odd(cli$present('Q1')) then begin
write(' Q1=present')
end else begin
write(' Q1=notpresent')
end;
if odd(cli$present('Q2')) then begin
cli$get_value('Q2.A', a.body, a.length);
write(' A=', a);
cli$get_value('Q2.B', b.body, b.length);
write(' B=', b);
end;
writeln;
end;
end;
begin
check('P1');
check('P2');
check('P3');
check('P4');
check('P5');
check('P6');
check('P7');
check('P8');
end.
$ pas fun
$ lin fun
$ set comm fun
$ fun x.dat /q2=(a:1,b:2) y.dat /q1 /q2=(a:3,b:4) z.dat /q2=(a:5,b:6) P1=x.dat Q1=notpresent A=1 B=2
P2=y.dat Q1=present A=3 B=4
P3=z.dat Q1=notpresent A=5 B=6
What?s the most complex *nix command you?ve come across? I think it
has to be ffmpeg. This looks broadly like
ffmpeg local-input-options-1 -i infile-1 \
local-input-options-2 -i infile-2 ... \
local-output-options-1 outfile-1 \
local-output-options-2 outfile-2 ...
The convention is that options apply to the immediately following file specification: this is prefixed with ?-i? for an input file, and is a
plain argument for an output file. Note the lack of ?global? options:
all settings apply to a particular file.
But that?s not where it ends. Certain of the options can specify ?filtergraphs?, which are entire chains of effects operations to be
applied to a particular video or audio stream. The man page talks
about ?simple? versus ?complex? filtergraphs, but even the ?simple?
ones can be pretty complex.
Filtergraphs can also be used during real-time playback, with the
?ffplay? command. For example:
ffplay -autoexit -vf scale=1152:864,setsar=0.9 \
'Sun Is Shining (Official Video).mp4'
That ?-vf? option specifies a sequence of video filters, first to
scale up the video to make more use of my screen, and ?setsar? (?Set
Source Aspect Ratio?) to fix distortion in the shape of the image
(everybody looking squashed) from the original digitization of the
video.
What would DCL-style syntax for ffmpeg look like? I suppose one
obvious equivalence would be
ffmpeg -
infile-1/local-input-options-1,infile-2/local-input-options-2,... -
outfile-1/local-output-options-1,outfile-2/local-output-options-2,... -
(being very careful about where the commas go), but what about the
syntax for filtergraphs? Would it be something like
/vf=(filter-name-1=filter-params-1,filter-name-2=filter-params-2...)
Does DCL have provision for this sort of complexity?
On 2025-02-13, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
What would DCL-style syntax for ffmpeg look like? I suppose one
obvious equivalence would be
ffmpeg -
«infile-1»/«local-input-options-1»,«infile-2»/«local-input-options-2»,... -
«outfile-1»/«local-output-options-1»,«outfile-2»/«local-output-options-2»,... -
(being very careful about where the commas go), but what about the
syntax for filtergraphs? Would it be something like
/vf=(«filter-name-1»=«filter-params-1»,«filter-name-2»=«filter-params-2»...)
Does DCL have provision for this sort of complexity?
Not in any meaningful way. There's no way to validate the syntax or parameters of a filter or other ffmpeg syntax with DCL. For a simple
example, when merging two files, one with an audio stream and one with
a video stream, into a MP4 output container then specifying the input and output video stream numbers would be a parameter along the lines of "0:v:0".
How would you even specify in DCL the first and last fields are numbers
and the middle field is a letter from a list of valid values ?
You can use DCL syntax in the way you specify, but the vast majority
of the parsing would still have to be done in ffmpeg as it is at the
moment. DCL syntax doesn't really give you anything extra.
You can define a bit in CLD. Including specifying that
something is a number and something else is from an
enumeration list.
$ type fun3.cld
define verb fun3
image "sys$disk:[]fun3"
parameter p1, value(type=$file, list, required)
qualifier q, value(type=threeitems, list, required), placement=local
define type threeitems
keyword a, value(type=$number, required)
keyword b, value(type=$quoted_string, required)
keyword c, value(type=myenum, required)
define type myenum
keyword x
keyword y
keyword z
$ type fun3.pas
[inherit('sys$library:pascal$cli_routines')]
program fun3(input,output);
type
pstr = varying [255] of char;
var
fnm, a, b, c : pstr;
begin
while odd(cli$get_value('P1', fnm.body, fnm.length)) do begin
write(fnm);
if odd(cli$present('Q')) then begin
cli$get_value('Q.A', a.body, a.length);
write(' A=', a);
cli$get_value('Q.B', b.body, b.length);
write(' B=', b);
cli$get_value('Q.C', c.body, c.length);
write(' C=', c);
end;
writeln;
end;
end.
$ pas fun3
$ lin fun3
$ set comm fun3
$ fun3 x.dat/q=(a:1,b:"This is x",c:x), y.dat/q=(a:2,b:"This is y",c:y), z.dat/q=(a:3,b:"This is z",c:z)
x.dat A=1 B="This is x" C=X
y.dat A=2 B="This is y" C=Y
z.dat A=3 B="This is z" C=Z
$ on error then continue
$ fun3 x.dat/q=(a:x,b:"This is x",c:x), y.dat/q=(a:2,b:"This is y",c:y), z.dat/q=(a:3,b:"This is z",c:z)
%DCL-W-NUMBER, invalid numeric value - supply an integer
\X\
$ fun3 x.dat/q=(a:1,b:"This is x",c:xdat), y.dat/q=(a:2,b:"This is
y",c:y), z.dat/q=(a:3,b:"This is z",c:z)
%DCL-W-IVKEYW, unrecognized keyword - check validity and spelling
\XDAT\
On 2025-02-14, Arne Vajhøj <arne@vajhoej.dk> wrote:...
You can define a bit in CLD. Including specifying that
something is a number and something else is from an
enumeration list.
$ fun3 x.dat/q=(a:1,b:"This is x",c:x), y.dat/q=(a:2,b:"This is y",c:y),
z.dat/q=(a:3,b:"This is z",c:z)
x.dat A=1 B="This is x" C=X
y.dat A=2 B="This is y" C=Y
z.dat A=3 B="This is z" C=Z
$ on error then continue
$ fun3 x.dat/q=(a:x,b:"This is x",c:x), y.dat/q=(a:2,b:"This is y",c:y),
z.dat/q=(a:3,b:"This is z",c:z)
%DCL-W-NUMBER, invalid numeric value - supply an integer
\X\
$ fun3 x.dat/q=(a:1,b:"This is x",c:xdat), y.dat/q=(a:2,b:"This is
y",c:y), z.dat/q=(a:3,b:"This is z",c:z)
%DCL-W-IVKEYW, unrecognized keyword - check validity and spelling
\XDAT\
But it is no longer ffmpeg syntax, but convoluted DCL syntax.
It also
doesn't help you with the main problem I mentioned, which is parsing
and validating the filter syntax.
How would you turn the list of filters, each with their own syntax, into something that can be validated by DCL ? As a reminder, it is critical
that the filters are available to the program in the order they were specified on the command line.
On 2/14/2025 2:02 PM, Simon Clubley wrote:
It also
doesn't help you with the main problem I mentioned, which is parsing
and validating the filter syntax.
How would you turn the list of filters, each with their own syntax, into
something that can be validated by DCL ? As a reminder, it is critical
that the filters are available to the program in the order they were
specified on the command line.
I think that can be define in CLD.
$ type fun4.cld
define verb fun4
image "sys$disk:[]fun4"
parameter p1, value(type=$file, list, required)
qualifier filter, value(type=filter_type, list, required), placement=local define type filter_type
keyword filtera, value(type=filtera_type, list, required)
keyword filterb, value(type=filterb_type, list, required)
define type filtera_type
keyword a1, value(type=$number, required)
keyword a2, value(type=$number, required)
keyword x, value(type=$number, required)
define type filterb_type
keyword b1, value(type=$number, required)
keyword b2, value(type=$number, required)
keyword x, value(type=$number, required)
$ type fun4.pas
[inherit('sys$library:pascal$cli_routines')]
program fun4(input,output);
type
pstr = varying [255] of char;
filter_type = (filtera, filterb);
var
filter_list : array [1..100] of filter_type;
fnm, filter, a1, a2, b1, b2, x : pstr;
nfilters, i : integer;
begin
while odd(cli$get_value('P1', fnm.body, fnm.length)) do begin
write(fnm);
nfilters := 0;
while odd(cli$get_value('FILTER', filter.body, filter.length)) do begin
nfilters := nfilters + 1;
if index(filter, 'FILTERA') = 1 then
filter_list[nfilters] := filtera
else if index(filter, 'FILTERB') = 1 then
filter_list[nfilters] := filterb
else
halt;
end;
for i := 1 to nfilters do begin
write(' ', filter_list[i]);
case filter_list[i] of
filtera:
begin
write(' filtera');
cli$get_value('FILTERA.A1', a1.body, a1.length);
write(' a1=', a1);
cli$get_value('FILTERA.A2', a2.body, a2.length);
write(' a2=', a2);
cli$get_value('FILTERA.X', x.body, x.length);
write(' x=', x);
end;
filterb:
begin
write(' filterb');
cli$get_value('FILTERB.B1', b1.body, b1.length);
write(' b1=', b1);
cli$get_value('FILTERB.B2', b2.body, b2.length);
write(' b2=', b2);
cli$get_value('FILTERB.X', x.body, x.length);
write(' x=', x);
end;
end;
end;
writeln;
end;
end.
$ pas fun4
$ lin fun4
$ set comm fun4
$ fun4 f1.dat/ filter=(filtera=(a1:12,a2:34,x:1234),filterb=(b1:56,b2:78,x:5678)),-
f2.dat/filter=(filterb=(b2:87,b1:65,x:8765),filtera=(a2:43,a1:21,x:4321)) f1.dat FILTERA filtera a1=12 a2=34 x=1234 FILTERB filterb b1=56 b2=78 x=5678
f2.dat FILTERB filterb b1=65 b2=87 x=8765 FILTERA filtera a1=21 a2=43 x=4321
On 2/14/2025 6:49 PM, Arne Vajhøj wrote:
On 2/14/2025 2:02 PM, Simon Clubley wrote:
It also
doesn't help you with the main problem I mentioned, which is parsing
and validating the filter syntax.
How would you turn the list of filters, each with their own syntax, into >>> something that can be validated by DCL ? As a reminder, it is critical
that the filters are available to the program in the order they were
specified on the command line.
I think that can be define in CLD.
$ type fun4.cld
define verb fun4
image "sys$disk:[]fun4"
parameter p1, value(type=$file, list, required)
qualifier filter, value(type=filter_type, list, required),
placement=local
define type filter_type
keyword filtera, value(type=filtera_type, list, required)
keyword filterb, value(type=filterb_type, list, required)
define type filtera_type
keyword a1, value(type=$number, required)
keyword a2, value(type=$number, required)
keyword x, value(type=$number, required)
define type filterb_type
keyword b1, value(type=$number, required)
keyword b2, value(type=$number, required)
keyword x, value(type=$number, required)
$ type fun4.pas
[inherit('sys$library:pascal$cli_routines')]
program fun4(input,output);
type
pstr = varying [255] of char;
filter_type = (filtera, filterb);
var
filter_list : array [1..100] of filter_type;
fnm, filter, a1, a2, b1, b2, x : pstr;
nfilters, i : integer;
begin
while odd(cli$get_value('P1', fnm.body, fnm.length)) do begin
write(fnm);
nfilters := 0;
while odd(cli$get_value('FILTER', filter.body, filter.length)) >> do begin
nfilters := nfilters + 1;
if index(filter, 'FILTERA') = 1 then
filter_list[nfilters] := filtera
else if index(filter, 'FILTERB') = 1 then
filter_list[nfilters] := filterb
else
halt;
end;
for i := 1 to nfilters do begin
write(' ', filter_list[i]);
case filter_list[i] of
filtera:
begin
write(' filtera');
cli$get_value('FILTERA.A1', a1.body, a1.length);
write(' a1=', a1);
cli$get_value('FILTERA.A2', a2.body, a2.length);
write(' a2=', a2);
cli$get_value('FILTERA.X', x.body, x.length);
write(' x=', x);
end;
filterb:
begin
write(' filterb');
cli$get_value('FILTERB.B1', b1.body, b1.length);
write(' b1=', b1);
cli$get_value('FILTERB.B2', b2.body, b2.length);
write(' b2=', b2);
cli$get_value('FILTERB.X', x.body, x.length);
write(' x=', x);
end;
end;
end;
writeln;
end;
end.
$ pas fun4
$ lin fun4
$ set comm fun4
$ fun4 f1.dat/
filter=(filtera=(a1:12,a2:34,x:1234),filterb=(b1:56,b2:78,x:5678)),-
f2.dat/filter=(filterb=(b2:87,b1:65,x:8765),filtera=(a2:43,a1:21,x:4321))
f1.dat FILTERA filtera a1=12 a2=34 x=1234 FILTERB filterb b1=56
b2=78 x=5678
f2.dat FILTERB filterb b1=65 b2=87 x=8765 FILTERA filtera a1=21
a2=43 x=4321
But I like this version better:
$ type fun5.cld
define verb fun5
image "sys$disk:[]fun5"
parameter p1, value(type=$file, list, required)
qualifier filter, value(type=$quoted_string, list, required),
placement=local
$ type fun5sup.cld
module fun5sup
define verb fa
qualifier a1, value(type=$number, required)
qualifier a2, value(type=$number, required)
qualifier x, value(type=$number, required)
define verb fb
qualifier b1, value(type=$number, required)
qualifier b2, value(type=$number, required)
qualifier x, value(type=$number, required)
$ type fun5.pas
[inherit('sys$library:pascal$cli_routines')]
program fun5(input,output);
type
pstr = varying [255] of char;
finfo = record
fnm : pstr;
nfilter : integer;
filter_list : array [1..100] of pstr;
end;
var
fun5sup : [external] integer;
var
finfo_list : array [1..100] of finfo;
fnm, filter, a1, a2, b1, b2, x : pstr;
n, i, j : integer;
begin
n := 0;
while odd(cli$get_value('P1', fnm.body, fnm.length)) do begin
n := n + 1;
finfo_list[n].fnm := fnm;
finfo_list[n].nfilter := 0;
while odd(cli$get_value('FILTER', filter.body, filter.length)) do begin
finfo_list[n].nfilter := finfo_list[n].nfilter + 1;
finfo_list[n].filter_list[finfo_list[n].nfilter] := substr(filter, 2, length(filter) - 2);
end;
end;
for i := 1 to n do begin
write(finfo_list[i].fnm);
for j := 1 to finfo_list[i].nfilter do begin
cli$dcl_parse(finfo_list[i].filter_list[j], fun5sup);
if index(finfo_list[i].filter_list[j], 'fa') = 1 then begin
write(' fa');
cli$get_value('A1', a1.body, a1.length);
write(' a1=', a1);
cli$get_value('A2', a2.body, a2.length);
write(' a2=', a2);
cli$get_value('X', x.body, x.length);
write(' x=', x);
end else if index(finfo_list[i].filter_list[j], 'fb') = 1 then
begin
write(' fb');
cli$get_value('B1', b1.body, b1.length);
write(' b1=', b1);
cli$get_value('B2', b2.body, b2.length);
write(' b2=', b2);
cli$get_value('X', x.body, x.length);
write(' x=', x);
end else begin
halt;
end;
end;
writeln;
end;
end.
$ set comm/obj fun5sup
$ pas fun5
$ lin fun5 + fun5sup
$ set comm fun5
$ fun5 f1.dat/filter=("fa /a1=12 /a2:34 /x=1234","fb /b1=56 /b2=78 / x=5678"),-
f2.dat/filter=("fb /b2=87 /b1:65 /x:8765","fa /a2=43 /a1=21 / x=4321")
f1.dat fa a1=12 a2=34 x=1234 fb b1=56 b2=78 x=5678
f2.dat fb b1=65 b2=87 x=8765 fa a1=21 a2=43 x=4321
On *nix, one's program can define any command syntax desired since the command-line parsing is done entirely within the program. The shell
doesn't really do anything except try to expand unquoted wildcards
(which somewhat limits the use of wildcards since the program cannot differentiate between a source wildcard and a destination wildcard). On VMS, DCL can do it either way. One can define a syntax that allows DCL
to do the parsing as Arne has shown, or one can tell DCL to simply pass
the command line to the program and let the program do all of the
parsing. One advantage of the former is that if the command-line fails
to parse, the program never even has to be activated.
So, IMHO, DCL is superior in this regard.
On Sat, 15 Feb 2025 12:22:59 -0700, Mark Berryman wrote:
So, IMHO, DCL is superior in this regard.
Unfortunately, no. The fundamental problem with DEC OSes (and this
includes Windows) is that the command line is passed to the program as a single string buffer. On *nix systems, it is passed as an array of
strings.
You should be familiar with the well-known problem of one program invoking another with a command that might include characters with special meanings
to a shell. On a *nix system, there is a simple way to avoid those special meanings: the first program invokes the second program directly, without going through a shell.
Nowadays, there is even a simple library call to do this <https://manpages.debian.org/posix_spawn(3)>.
This is not so easy to do with a DEC-style command line.
On Sat, 15 Feb 2025 12:22:59 -0700, Mark Berryman wrote:
So, IMHO, DCL is superior in this regard.
Unfortunately, no. The fundamental problem with DEC OSes (and this
includes Windows) is that the command line is passed to the program as a single string buffer. On *nix systems, it is passed as an array of
strings.
You should be familiar with the well-known problem of one program invoking another with a command that might include characters with special meanings
to a shell. On a *nix system, there is a simple way to avoid those special meanings: the first program invokes the second program directly, without going through a shell.
Nowadays, there is even a simple library call to do this <https://manpages.debian.org/posix_spawn(3)>.
This is not so easy to do with a DEC-style command line.
On *nix systems, the shell parses the command line into an array of
strings using unquoted spaces as the separator which is then passed to
the created process.
On VMS, the crtl does the same parsing which means the program still
sees an array of strings the same as on a *nix system.
If I choose to use DCL, DCL does all of the parsing for me and the
nature of the command-line is irrelevant.
Programs on DEC OSes can invoke other programs directly and
have been able to at least since the days of the PDP-11 ...
On Sun, 16 Feb 2025 15:52:23 -0700, Mark Berryman wrote:
On *nix systems, the shell parses the command line into an array of
strings using unquoted spaces as the separator which is then passed to
the created process.
If you don’t go through a shell, then you pass an array of already- separated words and you don’t have to worry about shell specials.
On VMS, the crtl does the same parsing which means the program still
sees an array of strings the same as on a *nix system.
Consider what happens: if you pass unquoted text to program X, DCL
converts it to uppercase, and I think also normalizes multiple spaces to a single space. If you don’t want the text to be uppercased or space- normalized, you put it in pairs of double quotes. But then these double quotes also get passed as part of the command line. So the receiving
program has to do some non-trivial parsing just to get simple literal text via the command line.
So now, how do you invoke program X directly from your own program Y,
without going through DCL? For consistency, you have to mimic all the same misbehaviour of DCL to get the command line in the right format. If you don’t want to do that, then you need some option to tell program X to bypass all that special processing, and just accept the command line as
is. So it needs to distinguish between two ways of being invoked: directly
or via DCL!
If I choose to use DCL, DCL does all of the parsing for me and the
nature of the command-line is irrelevant.
If you don’t use DCL, then how do you invoke a program that expects DCL to parse its command line for it? What happens to all of Arne’s lovingly- crafted .CLD files?
Programs on DEC OSes can invoke other programs directly and
have been able to at least since the days of the PDP-11 ...
Yes, and there have been quite a few pitfalls with that, as I mentioned above. Windows suffers from the same drawback, and this has even led to security holes with Windows programs.
On 2/16/25 5:43 PM, Lawrence D'Oliveiro wrote:
Consider what happens: if you pass unquoted text to program X, DCL
converts it to uppercase, and I think also normalizes multiple spaces
to a single space. If you don’t want the text to be uppercased or
space- normalized, you put it in pairs of double quotes. But then these
double quotes also get passed as part of the command line. So the
receiving program has to do some non-trivial parsing just to get simple
literal text via the command line.
So, so, so very wrong. You are *way* behind the times.
I *never* have to quote arguments when using programs that still use
*nix syntax on VMS. My arguments' case is never changed.
Here is the entry point to any C program on VMS:
int main (int argc, char *argv[], char *envp[]);
See? Argument passing works the same on VMS as it does on *nix, as
described above.
Let's see, what's a good example? Ah, here's one:
$ gs -q -P- -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=%stderr -sOutputFile=<something>.pdf <something>.ps
Again, see? No quoting. No case conversion. Ghostscript sees the
command exactly as I typed it and I typed it exactly as I would on a
*nix system.
On 2/17/2025 2:02 PM, Mark Berryman wrote:
On 2/16/25 5:43 PM, Lawrence D'Oliveiro wrote:
If I choose to use DCL, DCL does all of the parsing for me and the
nature of the command-line is irrelevant.
If you don’t use DCL, then how do you invoke a program that expects DCL to
parse its command line for it? What happens to all of Arne’s lovingly- >>> crafted .CLD files?
You apparently know as little about VMS as you do programming in general. The
Docs are online. Go read them. They will answer your questions.
Which is why people need to stop feeding the troll!!!!
Can you show us a simple C program that just prints out its command arguments, and how it responds to some sample command lines?VMS seems to be alone in converting case.
On Mon, 17 Feb 2025 12:02:37 -0700, Mark Berryman wrote:
On 2/16/25 5:43 PM, Lawrence D'Oliveiro wrote:
Consider what happens: if you pass unquoted text to program X, DCL
converts it to uppercase, and I think also normalizes multiple spaces
to a single space. If you don’t want the text to be uppercased or
space- normalized, you put it in pairs of double quotes. But then these
double quotes also get passed as part of the command line. So the
receiving program has to do some non-trivial parsing just to get simple
literal text via the command line.
So, so, so very wrong. You are *way* behind the times.
I *never* have to quote arguments when using programs that still use
*nix syntax on VMS. My arguments' case is never changed.
Prove it. It seems to me what you are claiming would break backward compatibility with the way VMS used to work.
Here is the entry point to any C program on VMS:
int main (int argc, char *argv[], char *envp[]);
See? Argument passing works the same on VMS as it does on *nix, as
described above.
Let's see, what's a good example? Ah, here's one:
$ gs -q -P- -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=%stderr
-sOutputFile=<something>.pdf <something>.ps
Again, see? No quoting. No case conversion. Ghostscript sees the
command exactly as I typed it and I typed it exactly as I would on a
*nix system.
Can you show us a simple C program that just prints out its command arguments, and how it responds to some sample command lines?
VMS seems to be alone in converting case.
✔≻ cat cmdlin.c
/* A program to demo printing of command line args under various OSs. */ #include <stdio.h>
int main( int argc, char *argv[] ) {
printf( "Did I hear you say %s?\n", argv[1] );
return 0;
}
$ cc /version
Compaq C V6.4-005 on OpenVMS VAX V7.3
$ cc cmdlin.c
$ link cmdlin
$ mcr DUA1:[JAYJWA.PROGRAMMING.C]cmdlin Hello World
Did I hear you say hello?
$ mcr DUA1:[JAYJWA.PROGRAMMING.C]cmdlin "Hello World"
Did I hear you say Hello World?
On 2/17/2025 4:49 PM, Lawrence D'Oliveiro wrote:
On Mon, 17 Feb 2025 12:02:37 -0700, Mark Berryman wrote:
$ gs -q -P- -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=%stderr
-sOutputFile=<something>.pdf <something>.ps
Again, see? No quoting. No case conversion. Ghostscript sees the
command exactly as I typed it and I typed it exactly as I would on a
*nix system.
Can you show us a simple C program that just prints out its command
arguments, and how it responds to some sample command lines?
Why would we do that?
$ mcr DUA1:[JAYJWA.PROGRAMMING.C]cmdlin Hello World
Did I hear you say hello?
$ mcr DUA1:[JAYJWA.PROGRAMMING.C]cmdlin Hello World
Did I hear you say hello?
On 2/15/2025 2:22 PM, Mark Berryman wrote:
On *nix, one's program can define any command syntax desired since the
command-line parsing is done entirely within the program. The shell
doesn't really do anything except try to expand unquoted wildcards
(which somewhat limits the use of wildcards since the program cannot
differentiate between a source wildcard and a destination wildcard).
On VMS, DCL can do it either way. One can define a syntax that allows
DCL to do the parsing as Arne has shown, or one can tell DCL to simply
pass the command line to the program and let the program do all of the
parsing. One advantage of the former is that if the command-line
fails to parse, the program never even has to be activated.
A VMS program has choices:
1A) SET COMM and CLI$
1B) SET COMM/OBJ, LIB$GET_FOREIGN and CLI$
2) LIB$GET_FOREIGN and custom parsing
3) Language specific way to get individual arguments
On Mon, 17 Feb 2025 12:02:37 -0700, Mark Berryman wrote:
On 2/16/25 5:43 PM, Lawrence D'Oliveiro wrote:
Consider what happens: if you pass unquoted text to program X, DCL
converts it to uppercase, and I think also normalizes multiple spaces
to a single space. If you don’t want the text to be uppercased or
space- normalized, you put it in pairs of double quotes. But then these
double quotes also get passed as part of the command line. So the
receiving program has to do some non-trivial parsing just to get simple
literal text via the command line.
So, so, so very wrong. You are *way* behind the times.
I *never* have to quote arguments when using programs that still use
*nix syntax on VMS. My arguments' case is never changed.
Prove it. It seems to me what you are claiming would break backward compatibility with the way VMS used to work.
$ gs -q -P- -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=%stderr
-sOutputFile=<something>.pdf <something>.ps
.
.
.
Can you show us a simple C program that just prints out its command arguments, and how it responds to some sample command lines?
On 2/17/25 2:49 PM, Lawrence D'Oliveiro wrote:
Can you show us a simple C program that just prints out its command
arguments, and how it responds to some sample command lines?
Easily.
On Mon, 17 Feb 2025 19:23:07 -0700, Mark Berryman wrote:
On 2/17/25 2:49 PM, Lawrence D'Oliveiro wrote:
Can you show us a simple C program that just prints out its command
arguments, and how it responds to some sample command lines?
Easily.
Try some more subtle examples. On a proper POSIX-type system:
QUOTE='"'
./test "Hello World" ${QUOTE}Hello World${QUOTE}
Hello World
"Hello
World"
Try to get the equivalent in DCL:
quote = """"
«rigmarole equivalent to ./test» "Hello World" 'quote'Hello World'quote'
What’s it going to print?
On 2/18/2025 8:58 PM, Lawrence D'Oliveiro wrote:
On Mon, 17 Feb 2025 19:23:07 -0700, Mark Berryman wrote:
On 2/17/25 2:49 PM, Lawrence D'Oliveiro wrote:
Can you show us a simple C program that just prints out its command
arguments, and how it responds to some sample command lines?
Easily.
Try some more subtle examples. On a proper POSIX-type system:
QUOTE='"'
./test "Hello World" ${QUOTE}Hello World${QUOTE}
Hello World
"Hello
World"
Try to get the equivalent in DCL:
quote = """"
«rigmarole equivalent to ./test» "Hello World" 'quote'Hello >World'quote'
What’s it going to print?
This is more of a shell question than an OS question.
bash and DCL are different.
$ bash
bash-4.4$ QUOTE='"'
bash-4.4$ ./test "Hello World" ${QUOTE}Hello World${QUOTE}
Hello World
"Hello
World"
bash-4.4$ exit
exit
$ quote = """"""
$ mcr sys$disk:[]test "Hello World" "''quote'"Hello World"''quote'"
Hello World
"Hello
World"
I am utterly baffled as to why you continue to regularly
engage with this troll. It's your choice, of course, but
getting the backsplatter is unpleasant for rest of us who
have already plonked him.
On 2/18/2025 10:03 PM, Dan Cross wrote:
I am utterly baffled as to why you continue to regularly
engage with this troll. It's your choice, of course, but
getting the backsplatter is unpleasant for rest of us who
have already plonked him.
+1!
$ bash
bash-4.4$ QUOTE='"'
bash-4.4$ ./test "Hello World" ${QUOTE}Hello World${QUOTE}
Hello World
"Hello
World"
bash-4.4$ exit
exit
$ quote = """"""
$ mcr sys$disk:[]test "Hello World" "''quote'"Hello World"''quote'"
Hello World
"Hello
World"
On 2/18/2025 11:24 PM, Robert A. Brooks wrote:
On 2/18/2025 10:03 PM, Dan Cross wrote:
I am utterly baffled as to why you continue to regularly
engage with this troll. It's your choice, of course, but
getting the backsplatter is unpleasant for rest of us who
have already plonked him.
+1!
I have a different perspective.
[snip]
But it is definitely on topic for c.o.v/I-V.
And maybe (just maybe) it is useful for a current or a future reader.
I do not care much about who raised the question. It doesn't change
being on topic or potential usefulness.
And I came up with:
$ quote = """""""Hello
$ mcr sys$disk:[]test "Hello World" "''quote'"Hello World"''quote'"
Hello World
World"
This is more of a shell question than an OS question.
bash and DCL are different.
Be that as it may, the person you are responding to, and that you
regularly interact with at length, has shown repeatedly that he is not
acting in good faith.
Technical answers to technical questions, and even spirited debates
with vigorous disagreement, are all well and good as long as all
parties are at least attempting to honor a collegial spirit of
cooperation. But in this case, as with most cases involving Lawrence,
the base conditions in which to have the discussion are simply not met.
This is the sort of thing that ought to be in an FAQ.
Is it feasible for DCL? Sure. Though it'll likely involve passing some
of the syntax to lib$table_parse or ilk for parsing, as do a few DCL
commands I've encountered (or have written) over the years.
On 2025-02-13, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
What?s the most complex *nix command you?ve come across? I think it
has to be ffmpeg. This looks broadly like
ffmpeg «local-input-options-1» -i «infile-1» \
«local-input-options-2» -i «infile-2» ... \
«local-output-options-1» «outfile-1» \
«local-output-options-2» «outfile-2» ...
The convention is that options apply to the immediately following file
specification: this is prefixed with ?-i? for an input file, and is a
plain argument for an output file. Note the lack of ?global? options:
all settings apply to a particular file.
But that?s not where it ends. Certain of the options can specify
?filtergraphs?, which are entire chains of effects operations to be
applied to a particular video or audio stream. The man page talks
about ?simple? versus ?complex? filtergraphs, but even the ?simple?
ones can be pretty complex.
Filtergraphs can also be used during real-time playback, with the
?ffplay? command. For example:
ffplay -autoexit -vf scale=1152:864,setsar=0.9 \
'Sun Is Shining (Official Video).mp4'
That ?-vf? option specifies a sequence of video filters, first to
scale up the video to make more use of my screen, and ?setsar? (?Set
Source Aspect Ratio?) to fix distortion in the shape of the image
(everybody looking squashed) from the original digitization of the
video.
What would DCL-style syntax for ffmpeg look like? I suppose one
obvious equivalence would be
ffmpeg -
«infile-1»/«local-input-options-1»,«infile-2»/«local-input-options-2»,... -
«outfile-1»/«local-output-options-1»,«outfile-2»/«local-output-options-2»,... -
(being very careful about where the commas go), but what about the
syntax for filtergraphs? Would it be something like
/vf=(«filter-name-1»=«filter-params-1»,«filter-name-2»=«filter-params-2»...)
Does DCL have provision for this sort of complexity?
Not in any meaningful way. There's no way to validate the syntax or parameters of a filter or other ffmpeg syntax with DCL. For a simple
example, when merging two files, one with an audio stream and one with
a video stream, into a MP4 output container then specifying the input and output video stream numbers would be a parameter along the lines of "0:v:0".
How would you even specify in DCL the first and last fields are numbers
and the middle field is a letter from a list of valid values ?
You can use DCL syntax in the way you specify, but the vast majority
of the parsing would still have to be done in ffmpeg as it is at the
moment. DCL syntax doesn't really give you anything extra.
Similar comments apply to mplayer BTW, and to make something clear to
people reading this (which is only implied above), the filters MUST be executed in the order given. For example, with mplayer, I might first
use a crop filter to get rid of black bars within a frame and then
apply a scale filter to the resulting frame.
Simon.
On Fri, 21 Feb 2025 16:42:56 -0500, Stephen Hoffman wrote:
Is it feasible for DCL? Sure. Though it'll likely involve passing some
of the syntax to lib$table_parse or ilk for parsing, as do a few DCL
commands I've encountered (or have written) over the years.
What happens when you bypass DCL? So one program directly spawns another
and gives it a command to execute. Can the receiving program behave the
same in that case as if it were invoked from a shell?
Otherwise, devise a better and more sane syntax to specify and pass
myriaD arguments with qualifiers and parameters thereto.
It is possible to start a process without CLI (sys$creprc or run process
- with an image that is not loginout.exe).
In that case I don't think there are a concept of arguments.
I don't see a way to pass arguments. Arguments are something CLI provide
to image, so no CLI means no arguments.
On Fri, 21 Feb 2025 19:45:05 -0500, Arne Vajhøj wrote:
It is possible to start a process without CLI (sys$creprc or run process
- with an image that is not loginout.exe).
In that case I don't think there are a concept of arguments.
I don't see a way to pass arguments. Arguments are something CLI provide
to image, so no CLI means no arguments.
Mr Berryman, further up this thread, was so insistent that I was talking through my hat. Remember he said:
] Wrong again. There are a number of ways to invoke a program without
] going through DCL.
and furthermore
] You apparently know as little about VMS as you do programming in
] general.
as well as
] Everyone else: Yes, I've once again been forced to face the fact
] that you can't fix stupid.
He couldn’t have made a mistake, could he?
On 2/21/2025 10:09 PM, Lawrence D'Oliveiro wrote:
On Fri, 21 Feb 2025 19:45:05 -0500, Arne Vajhøj wrote:
It is possible to start a process without CLI (sys$creprc or run process >>> - with an image that is not loginout.exe).
In that case I don't think there are a concept of arguments.
I don't see a way to pass arguments. Arguments are something CLI provide >>> to image, so no CLI means no arguments.
Mr Berryman, further up this thread, was so insistent that I was talking
through my hat. Remember he said:
] Wrong again. There are a number of ways to invoke a program without
] going through DCL.
and furthermore
] You apparently know as little about VMS as you do programming in
] general.
as well as
] Everyone else: Yes, I've once again been forced to face the fact
] that you can't fix stupid.
He couldn’t have made a mistake, could he?
I don't see any indication of that.
There are some ways to start a process with a DCL command
(and therefore DCL mapped).
There are some ways to start a process without specifying a DCL
command and still getting a process with DCL mapped.
There are some ways to start a process without DCL mapped.
Arne
On Fri, 21 Feb 2025 16:42:56 -0500, Stephen Hoffman wrote:
Is it feasible for DCL? Sure. Though it'll likely involve passing some
of the syntax to lib$table_parse or ilk for parsing, as do a few DCL
commands I've encountered (or have written) over the years.
What happens when you bypass DCL? So one program directly spawns another
and gives it a command to execute. Can the receiving program behave the
same in that case as if it were invoked from a shell?
On Fri, 21 Feb 2025 19:02:20 -0500, Brian Schenkenberger wrote:
Otherwise, devise a better and more sane syntax to specify and pass
myriaD arguments with qualifiers and parameters thereto.
What would you propose, that is suitably respectful of traditional VMS values?
There are some ways to start a process without DCL mapped.
On 2/21/2025 11:15 PM, Arne Vajhøj wrote:
There are some ways to start a process with a DCL command
(and therefore DCL mapped).
There are some ways to start a process without specifying a DCL
command and still getting a process with DCL mapped.
There are some ways to start a process without DCL mapped.
Now I'm confused. Were we discussing starting an image in an existing process, or starting a new process?
On 2/22/2025 12:53 AM, Dave Froble wrote:
On 2/21/2025 11:15 PM, Arne Vajhøj wrote:
There are some ways to start a process with a DCL command
(and therefore DCL mapped).
There are some ways to start a process without specifying a DCL
command and still getting a process with DCL mapped.
There are some ways to start a process without DCL mapped.
Now I'm confused. Were we discussing starting an image in an existing
process, or starting a new process?
Starting a new process.
Because it is about a program running another program. And that
indicate starting a new process.
On 2/21/2025 5:18 PM, Lawrence D'Oliveiro wrote:
On Fri, 21 Feb 2025 16:42:56 -0500, Stephen Hoffman wrote:
Is it feasible for DCL? Sure. Though it'll likely involve passing some
of the syntax to lib$table_parse or ilk for parsing, as do a few DCL
commands I've encountered (or have written) over the years.
What happens when you bypass DCL? So one program directly spawns another
and gives it a command to execute. Can the receiving program behave the
same in that case as if it were invoked from a shell?
Well, that depends upon the requirements and design, right?
I've done quite a bit of such, but, I never depended on some set design, never >even considered it, I designed what I needed and implemented it.
Don't know why anyone would ever do anything else ??????
On 2/22/2025 8:53 AM, Arne Vajhøj wrote:
On 2/22/2025 12:53 AM, Dave Froble wrote:
On 2/21/2025 11:15 PM, Arne Vajhøj wrote:
There are some ways to start a process with a DCL command
(and therefore DCL mapped).
There are some ways to start a process without specifying a DCL
command and still getting a process with DCL mapped.
There are some ways to start a process without DCL mapped.
Now I'm confused. Were we discussing starting an image in an existing
process, or starting a new process?
Starting a new process.
Because it is about a program running another program. And that
indicate starting a new process.
Unless LIB$DO_COMMAND which is special.
Arne
In the context of this thread, they probably wouldn't.
This discussion, which Arne is jumping into as a willing
participant, is not about technical enlightenment or discussion,
but rather a vehicle for the troll OP to preen and strut around,
imaging himself oh-so-very-clever indeed, while making snide
comments about systems he doesn't even attempt to appreciate.
- Dan C.
On 2/22/2025 9:29 AM, Arne Vajhøj wrote:
On 2/22/2025 8:53 AM, Arne Vajhøj wrote:
On 2/22/2025 12:53 AM, Dave Froble wrote:
On 2/21/2025 11:15 PM, Arne Vajhøj wrote:
There are some ways to start a process with a DCL command
(and therefore DCL mapped).
There are some ways to start a process without specifying a DCL
command and still getting a process with DCL mapped.
There are some ways to start a process without DCL mapped.
Now I'm confused. Were we discussing starting an image in an existing >>>> process, or starting a new process?
Starting a new process.
Because it is about a program running another program. And that
indicate starting a new process.
Unless LIB$DO_COMMAND which is special.
I recall that that starts a subprocess. If I remember correctly. Which would be a new process.
Unless LIB$DO_COMMAND which is special.
On 2025-02-14 13:38:59 +0000, Simon Clubley said:
Your anti-VMS sentiments are one of the reasons why my life has been so
much more enjoyable because I haven't been reading c.o.v daily.
What’s the most complex *nix command you’ve come across? I think it has to be ffmpeg.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 437 |
Nodes: | 16 (2 / 14) |
Uptime: | 193:49:10 |
Calls: | 9,135 |
Calls today: | 2 |
Files: | 13,432 |
Messages: | 6,035,425 |