Design of the Poplog command tool - GetPoplog/Seed GitHub Wiki

Aims

The poplog command tool is designed to do away with the need to include a poplog.sh script before you can use the Poplog commands of pop11, prolog, clisp, ved, xved etc. This has several benefits:

  • It makes installation simpler - there's no configure-and-debug step
  • It makes Poplog much more familiar to new Linux/Unix users, working much like Python or Ruby with a single entry-point.
  • Scripting with Poplog is now as easy as scripting with Python/Ruby etc - no more detection of whether or not the poplog.sh script has been run etc.
  • It makes scripting safer because it prevents hijacking of the script through environment-variable manipulation.
  • It directly supports multiple Poplog versions without the need to manipulate environment-variables.
  • It keeps the environment-variables clean and easy to understand.
  • It prevents accidental command completions against Poplog's many scripts (e.g. pu).
  • Supports direct entry for help/teach/ref and immediate modes.
  • Allows future convergence on more familiar long options without the need to hack the pop sources.

A version of this tool was moth-balled by Steve Leach in Nov 2002 under the banner of the poplog-wrapper. We reviewed this work as part of this new design effort and it strongly influenced the choice of design from amongst the possible alternatives.

Possible Designs

There were three designs considered. The first was the simplest possible idea, where % poplog <command> <options> would simply spawn a process, set up the Poplog environment, and run the <command> <options>. This was very attractive in terms of simplicity but was not as ambitious in linuxifying Poplog. For example poplog --help would not do anything useful or expected and poplog on its own would be an error. And accessing HELP * SYSTEM would be poplog pop11 help system, which seemed excessively indirect.

The next option was to provide a fully linuxified command-line with long and short options and more rigorous and orthogonal design of the modes for running Poplog. This means taking over the command line processing entirely and rewriting it into the idiosyncratic Poplog option-format. That is exactly what the poplog-wrapper work did in 2002. The big catch is that this is surprisingly difficult because of the non-orthogonality of the current options - and it requires writing a lot of documentation from scratch - and risks lacking familiarity and appeal to Poplog experts.

So we struck a careful compromise: poplog <action> <options> would treat <action> as a keyword describing the action to be taken rather than just the name of an executable. The actions would be chosen to correspond to familiar Poplog commands. For example poplog clisp runs the clisp command. And poplog ved myfile.p runs the Ved editor on a file. But this gave the freedom to be able to handle poplog im for going straight into an immediate mode buffer. And poplog exec <command> was the get-out-of-jail action that allowed the user to perform any Poplog command and not just the ones that have actions assigned.

We felt this compromise would be reasonably acceptable to both new users and Poplog experts alike. And, it is important to add, this poplog command takes nothing away from existing users who can carry on using their usual set-up.

Self-homing and setting $usepop

One of the implementation objectives was to be able to move the Poplog-tree easily. This was achieved by having the poplog command-tool dynamically discovering its own location and hence the location of the Poplog-tree and setting the $usepop variable to that value. This value is then substituted into Poplog's environment variables as needed.

For an executable to reliably discover its canonical location has traditionally been an intractable task. With more recent versions of Linux it has been made possible through the use of /proc/self/exe.

Substituting $usepop

Broadly speaking, $usepop is the root of the Poplog-tree. Many other Poplog environment variables reference $usepop. So this presented a design challenge: how to capture the set of environment-variables set up by running $popcom/popenv.sh but reliably identify where $usepop had been substituted?

We achieved the capture by running the popenv.sh script inside env -i, which creates a clean, empty environment, and then running env again. We identify where $usepop was substituted by a simple match against its value. Now this might be unreliable, finding accidental matches. However we re-run the process with a different value for $usepop and see if the results are stable. This is not perfect but it is effective in practice.

However there is an annoying wrinkle, which is that the value of $usepop must point to a valid Poplog-tree. That is because the popenv.sh finds further scripts inside the Poplog-tree to run. So we constructed the second value of $usepop by using $usepop/pop/.. because pop is guaranteed to exist in a valid Poplog-tree.

Dynamically writing C-code

The command-tool is written in C. However, we capture the environment variables by running the $popcom/popenv.sh and from the output of that command we write the C code. Now it is arguable that the neatest solution is to script the C code using Pop-11. However we wanted to both minimise the dependencies and avoid strange failure modes. And that meant not assuming Pop-11 was available. So we reverted to the small set of tools on which the Poplog build process depends i.e. gcc and basic Unix tools like sh, sed, grep etc. Hence we chose to generate the C-code using a shell script.

We considered writing this in Python, which is certainly a much more natural tool for tasks like this. But we have a general reluctance to widen the dependencies to include any other complex programming language and this use-case just didn't seem to justify that big increase.

Allowing Selective Overriding of the Poplog Environment Variables

A legitimate use-case for advanced Poplog programmers is to selectively override some of Poplog's environment variables in order to try out some new build of Poplog. This can be achieved by % poplog exec env VAR=VALUE COMMAND. However, in order to make it clear that this is a supported scenario the env action was added that simply invokes the env program.

Update: Major Enhancement 17th Aug 2021

One of the limitations of Poplog has been that GUI support is baked in by the newpop command, depending on which option is used (nox, xt, xm). However the command-tool effectively sets up the Poplog working environment each time Poplog is started, so it becomes possible build all three editions of Poplog and select the correct edition at run-time.

The key to this is setting up each environment in turn and capturing the Poplog environment variables - because the variables slightly differ for each. This required editing makeStage2.sh so that the environment was captured, the edition copied, and then the process repeated another two times.

⚠️ **GitHub.com Fallback** ⚠️