Tech projects, hobby programming, and geeky thoughts of Paolo Amoroso

An Exec command and other new features of Stringscope

I continued working on Stringscope, the string listing tool I'm developing with Medley Interlisp. I added the function STRINGS to print the strings to the primary output stream rather than in a new window, as well as an Executive command that does the same.

To reflect this work I updated the Stringscope code and documentation hosted on a GitHub gist, describing also the function EXTRACT.STRINGS as part of the interface. The code in the gist is intended for publication and can't be loaded as is into Interlisp.

The functions STRINGS and STRINGSCOPE

In addition to the same arguments as STRINGSCOPE, i.e. a file name FILENAME and the minimum length MIN.LEN strings must have, STRINGS accepts a third optional boolean argument NEWWIN. By default NEWWIN is NIL and makes STRINGS print to the primary output, otherwise the function opens a new window and works exactly like STRINGSCOPE. In fact, STRINGSCOPE is now just a wrapper that calls STRINGS with NEWWIN set to T.

STRINGSCOPE and STRINGS return a window if the functions open it otherwise the primary output stream. In case the input file can not be opened or contains no strings, the functions return NIL and print a warning to the prompt window.

Interlisp functions that create or manipulate a window usually return the window itself as their value, so I adopted a similar convention.

The macro WITH.INPUT-FILE

An early version of STRINGS duplicated a lot of the code of STRINGSCOPE for opening the input stream, checking for errors, evaluating some forms with the stream bound to a variable, and closing the stream. I factored that boilerplate into the macro WITH.INPUT.FILE:

(DEFMACRO WITH.INPUT.FILE ((STREAM FILE)
                           &BODY BODY &AUX (RESULT (GENSYM))
                           (VALUE (GENSYM)))

         (* Opens an input stream to FILE and evaluates the forms in BODY with the stream 
         bound to STREAM. Returns the value of the last form in BODY, or NIL if FILE can 
         not be opened.)

   `(PROG NIL
          [SETQ ,RESULT (NLSETQ (OPENSTREAM ,FILE 'INPUT]
          (if ,RESULT
              then (SETQ ,STREAM (CAR ,RESULT))
                   (SETQ ,VALUE (PROGN ,@BODY))
                   (CLOSEF ,STREAM)
                   (RETURN ,VALUE)
            else (RETURN NIL))))

The Executive command STRINGS

The reason I implemented a function like STRINGS that prints the output to the console is I wanted to try out creating an Executive command.

Also known as a listener in other Lisp environments, an Executive is an Interlisp window that provides a read-eval-print loop. In addition to Lisp expressions, an Executive accepts commands with a non-parenthesized syntax such as DIR (the equivalent of DIR on MS-DOS and ls on Unix) or CONN directory (cd directory on MS-DOS and Unix).

So I defined the Stringscope Executive command STRINGS that works exactly like the function STRINGS but takes only the file name and the minimum length arguments:

STRINGS FILENAME MIN.LEN

The macro DEFCOMMAND defines an Executive command and is really easy to use, here's the definition of STRINGS:

(DEFCOMMAND (STRINGS :EVAL) (FILE &OPTIONAL (MIN.LENGTH SSCOPE.MIN.LEN))
   (STRINGS FILE MIN.LENGTH)
   (CL:VALUES))

The STRINGS command is just a wrapper that calls the function STRINGS with appropriate arguments.

Compiling Stringscope

I initially run Stringscope compiled but it was time to start using the File Manager commands for compiling the code, (MAKEFILE 'STRINGSCOPE 'C) and (CLEANUP 'STRINGSCOPE). However, these commands apparently compile only in memory and don't write a compiled file like (TCOMPL 'STRINGSCOPE), which I have to call manually.

The File Manager is an Interlisp subsystem conceptually similar to the Unix tool Make. It's a collection of tools to notice, keep track of, and write to files the code changes to a Lisp system under development.

Another confusing aspect of compilation is when I load Stringscope with (FILESLOAD STRINGSCOPE), I get a warning I don't understand concerning a comment in the macro WITH.INPUT.FILE: Warning: Possible comment not stripped. I actually see the compiler couldn't strip a comment from the compiled code to save space, but not why.

Further development

Some of these new features were on my initial roadmap, others emerged while coding and using Stringscope.

Since this is an exploration and learning project, going forward I'll go with the flow and implement what I need or find interesting, and consider the initial roadmap more like a source of ideas than an action plan. Which is the kind of exploratory development Lisp supports and makes enjoyable.

#stringscope #Interlisp #Lisp

Discuss...
Email | Reply @amoroso@fosstodon.org