Specifying command line arguments via the PROGRAM statement

Maybe it could be done with an island grammar, sort of similar to the way RATFOR (PDF, 80.8 KB) preprocessor worked:

The Ratfor grammar is simple and straightforward, being essentially

prog : stat
     | prog stat
stat : if (...) stat
     | if (...) stat else stat
     | while (...) stat
     | for (...; ...; ...) stat
     | do ... stat
     | repeat stat
     | repeat stat until (...)
     | switch (...)
     | { case ...: prog ... 
         default: prog }
     | return
     | break
     | next
     | digits stat
     | { prog }
     | anything unrecognizable

The observation that Ratfor knows no Fortran follows directly from the rule that says a statement is
‘‘anything unrecognizable’’. In fact most of Fortran falls into this category, since any statement that does not begin with one of the keywords is by definition ‘‘unrecognizable.’’


There are several more features which are needed:

  • automating help message generation with flag descriptions
  • customizing the usage message
  • implementing sub-commands (like git has) (somehow similar to entry statements)
  • short flags / flag aliases

There are also Python packages like click, which accomplish the same thing using Python’s function decorator mechanism. I bet we could find more examples.

The best one is so old there probaly is no documentation left. It was in the CDC NOS CCL language, which was basically the shell scripting language for an operating system called NOS. At the top of your script you provided lines like

.PROC,commandname*IP"short command description",
keyword1"description of keyword1"=(rules),
keyword2"description o keyword2=(rules).
.HELP,,NOLIST.
description of program
.HELP,keyword1,NOLIST.
description of keyword 1
.HELP,keyword2,NOLIST.
description of keyword 2
.ENDHELP.

the rules allowed specifying an allowed numeric range, a list of allowed names, a default, .. in a compact syntax.

The real beauty of it was not only could you then call your script positionally or with keywords (much like a combination of list-directed I/O and NAMELIST syntax) but if you entered the keyword names or command with a question mark on the end of the name you got prompted for that parameter interactively, and a screen mode using a TDU (Terminal Definition Utility) interface much like an automatic ncurses interface. Subsequently putting a ? in for a value in line mode produced the help text; or moving the cursor to an input field and pushing the help icon would show you the help on the lower half of the screen.

It was an elegant system from long, long ago that I have never seen the equal of since for ease of use.

I made a modified Bourne shell that did most of that and then set environment variables to the name of the keywords that worked well using ncurses but it was proprietary at a company I worked at long ago that I keep meaning to recreate but never get around to, but I miss how easy that was to create a very user-friendly interface that automatically could be used in batch, prompting and panel mode.

In my mind that is the ideal target, but the closest I have to that currently is probably GitHub - urbanjost/M_CLI2: Fortran commandline-interface using a simple prototype command for easily defining a command line and fixedform as an example of creating panel interfaces from simple text input
and GitHub - urbanjost/M_fixedform: create fixed-form TDU interfaces using ncurses(3c) from Fortran showing how to make a simple panel generator but I never seen to get around to putting it all back together. I wonder of any of these interfaces create screen panel/TLI interfaces or GUI interfaces automatically?

Thanks to Al Kossow and a bunch of us ‘controlfreaks’ who hoarded it for years (much to many of our our wives chagrin), there is a massive amount of CDC documentation at bitsavers. For CCL stuff, check out chapter 4 of: https://bitsavers.org/pdf/cdc/cyber/nos2/60459680M_NOS_2_Reference_Set_Volume_3_System_Commands_198912.pdf

I left the CDC world just as CCL was taking over from the older KCL on the NOS systems. Never got a chance to use NOS/VE.

Still have two or three boxes of CDC stuff I need to get over to Al for scanning.

Never imagined I would see that manual again; although I had some of my own in the attic for a long time. NOS had some features still not matched or that were not matched by other OS for years. The ACL control of files let me say “you can append to this file but not read it until next Friday” and see who had accessed a file and how often (which was invaluable when trying to determine if a library was being used, how much something was used, who to contact if there were issues with the file, ..).

I still miss the NOS concept of a library. They were superficially like an ar archive file but you could load them and they could contain subroutines and scripts and executables (and text). When loaded all the commands were in your “path” and all the subroutines were available to the compiler … you could keep an entire project in a single file including the sources with the executable.

We had to support so many terminal types I think I must have made 40 or so TDU definitions. Do not miss that much but that was true of Unix terminfo and termlib files as well.

It surprises me to think that Linux has not matched or surpassed some of those features, at least in base releases even after all these years. I have
a look-alike of XEDIT written in C that still works. Long story. More to the point I missed that the screen panel API was Fortran-oriented, letting you create a screen panel TDI interface in a day. I started the aforementioned
fixedform program to recreate that. I got it to the point where it was used for the projects that required it but never got it up to the level of the NOS shell and Fortran interfaces; partly just because I could not remember it all. This book is inspiring me to bring some of those features to Linux and back to Fortran. It is hard to remember NOS did not even have a C compiler.

I used NOS/VE which many co-workers thought was the best of Aegis and NOS combined but I actually preferred NOS myself. Cannot imagine going back to 8-character (or was it seven?) upper-case filenames and no subdirectories though.

I had a Viking 721 terminal that supported Tektronix 4010 graphics instructions and had a touch screen, which people were jealous of! Sometimes I cannot believe how much we got done with computers that slow and interfaces that basic.

Seven. The internal FNT/FST tables inside the OS only had 42 bits allocated for file name. This limit dated all the way back to the original Chippewa Operating System of the early '60s that Mr Cray wrote. On SCOPE and NOS/BE, permanent file names could be longer. But on KRONOS and NOS, permanent file names were limited to seven characters as well.

We were one of the first to use FSE (Full Screen Editor). No TDU yet. The operations guy at our computer center had just bought a whole bunch of cheap CRT terminals that didn’t conform to anything CDC supported. So I had to create a modset to FSE to support them. FSE was mostly written in SYMPL - a stripped down version of CDC’s JOVIAL compiler.

EVE, EDT, FSE, XEDIT (IBM), … I preferred FSE over all of them and called vi mostly by four-letter words at first. Use vim for everything anymore. The people that used hunt-and-peck to type hated vi more than I did. When we were phasing over to NOS/VE I kept editing everything on NOS so I could use FSE. Things like paragraph fill and centering and such were hard to come by on other editors back then.
Thinking about NOS reminded me the PROGRAM directive was used back then for arguments in lieu or redirects. That seems to have never made it into the standard though. I think the syntax was something like

      PROGRAM(INPUT,OUTPUT,TAPE5=INPUT,TAPE6=OUTPUT)

where the default files for I/O would then be “INPUT” and “OUTPUT” but you could positionally change the filenames on the command line when executing the program. Redirection as done in Unix is nicer for stdin and stdout, but there is a precedence where the PROGRAM directive took options for the command line, although it was a vendor extension.

FSE was a godsend when it came out. Though as a systems programmer I was able to enjoy using 026 (via DIS) at the operators console - which basically turned the mainframe into a giant PC. CDC’s XEDIT was based on UCEDIT from the U of Calgary. We used UCEDIT on KRONOS, as the CDC EDIT editor on KRONOS and NOS wasn’t that great. When we finally moved to NOS, XEDIT was there so no need for UCEDIT.

Interestingly, in the SCOPE and NOS/BE world, interactive users had access to an editor that was internally coded as a MUJ (“mudge” - a multi-user job). Single program that was multi-threaded for multiple interactive users.

These days I use vi (actually vim) and gedit.

I once stumbled upon some YT videos about a home-brewed command-line interface (CLI) introducing some interesting features (Disclaimer :warning: : most of the content are AI generated images and a guy narrating his vision for a better command-line. The format is kind of long and chatty :hourglass_not_done: … ):

The main thing I thought was cool, was the workflow discovery aids, sort of like this:

$ filter 
  └─┬──┘ input (string) output (string)
    │
    └─── Perform a filter action

where the command is enhanced with suggestions, autocomplete, and both color and font highlighting, providing feedback as you type. Sort of like command-line completion, but on steroids. MATLAB also has these kind of customized code suggestions and completions.


There is (perhaps?) reason to be optimistic as a new set of command-line tools in Go and Rust appear, see this article on The Modern CLI Renaissance and the corresponding HN Thread (I admit not reading the whole discussion). One of the comments echoes the sentiments in this thread,

Shells like Elvish, Nushell, Powershell and my own shell, Murex…

Except nothing of this is really new, this is how REPLs in Xerox PARC worstations, ETHZ and Genera used to work.

The novelty of these shells is a side effect of UNIX wiping out the alternatives.

The shells mentioned in the HN thread:


Some months ago I listened to a related (& opinionated) presentation - HPC Café: Increase productivity with Neovim, Language Server Protocols, and modern terminal tools - introducing tools like:

The slides are available here (1,057 KB).

This is an interesting thread, with a long history of frustration for many Fortran users.

Rewriting the same code, for conceptually simple tasks, as a program interface, often with slightly different syntax requirements, can be so frustrating. Being available in the Fortran standard is so much easier !

When starting a new project, often it is; when do we bite the bullet and adapt a previous module for a different program for this basic task ?
Unfortunately this module can be thousands of lines of code, but the minor adaptation is required for a different project syntax.

It is so much easier if the functionality is in the Fortran intrinsics. These have slowly developed over time.

For me, just yesterday, I again wrote the excel function “@round (a,n)”, which has the sting in that excel has both a value and a format.

For many years, I have (many times) re-written my Fortran free format data file input and line parser, as each project has different requirements. Even simple things like changing the data units in the data file (for data documentstion) can explode the module complexity.

Back to command line arguments, It would be good if some of the work in the progects referenced could be adapted to provide some support for:
“program (style=getopts_long) :: myprogram (a,b,c,title)” or perhaps
“program myprogram (a,b,c,title,style=getopts_long)”

Often these advances are taken from what some compilers already provide as a working extension. Do any exist ?

It is certainly amazing to see how many compiler options Gfortran support. Does that provide any useful example to build from ?

If that can help, I created some time ago some preprocessor macros that go in that direction (see fortiche/app). It is much like the C counterpart int main(int argc, char *argv[])

It does not go as far as Raku, though, but with a preprocessor that supports variadic macros, that should be doable.

#include <app.inc>
console(main)
    main(args)       
        integer :: i, nargs

        nargs = size(args)
        i = 1

        do while (i <= nargs)
            select case(args(i)%chars)
            case ('-d', '--dir')
                ... 
            case ('-o', '--output')
                ...
            case ('-x','--exclude')
                ...
            case ('-v','--version')
                ...
                stop
            case ('-h','--help', '?')
                ...
                stop
            case default
                ...
            end select
            i = i + 1
        end do
    endmain
end