[comp.lang.modula2] Make-like tools

GRANT@LAUCOSC.LAURENTIAN.CA ("Grant R. Guenther") (02/13/89)

I been unable to reply directly to Terry Klarich, who was asking about
alternatives to the Logitech M2Make program, so I'll post my (long) note.

I have a pair of tools called Uses and Update that were written for a different
system, but that I have ported to the PC.  I'm enclosing the manuals and
the release notes - let me know if you are interested and I can mail
you the sources.  I won't go into the philosophy behind the design - most
of it should be evident from the manuals.

Grant Guenther
Dept. of Mathematics and Computer Science
Laurentian University
Sudbury, Ontario, Canada, P3E 2C6

GRANT@LAUCOSC.BITNET
Grant@LauCosc.Laurentian.CA

===================== release.txt ===========================================

                        RELEASE NOTES


Software:  Uses      V1D     1988 06 20
           Update    V1D     1988 06 20

This document describes the distribution files, installation
procedures, restrictions and extensions of the programs Uses
and Update for the MS-DOS environment.

1.  Distribution files

The distribution kit contains:

        RELEASE.TXT       --   These notes
        USES.EXE          --   The executable Uses program
        UPDATE.EXE        --   The executable Update program
        STDBUILD.UPD      --   A prototype file for $Build
        USES.MAN          --   The users' manual for Uses
        UPDATE.MAN        --   The users' manual for Update

2.  Installation procedures

Use of these tools assumes some familiarity with MS-DOS and
the Logitech Modula-2/86 system.  Consult the documentation
for these products if you are unfamiliar with terms used in
these directions or the users' manuals.

Copy USES.EXE and UPDATE.EXE from the distribution medium to
a directory in your normal search path.  Place a copy of
STBUILD.UPD in a convenient library directory, C:\M2LIB, say.
Now, edit your AUTOEXEC.BAT file to include the following
line (which sets the environment variable BUILD to refer to
the standard build file):

        SET BUILD=C:\M2LIB\STDBUILD.UPD

(You must substitute the actual directory path for C:\M2LIB.)

Note that Update expects the environment variable M2SYM to be
set to the library directory where symbol files are stored.
This is usually done by the Modula-2 installation procedure.

You should print copies of USES.MAN and UPDATE.MAN if you
need them.  (The files are simply formatted and make no
special assumptions about your printer.)

3.  Restrictions

The following restrictions apply to this version (V1D) of
Uses and Update.

  o  These programs require MS-DOS V3.1 (or later).

  o  V1D of Uses supports the file naming conventions of
     Logitech Modula-2/86 version 3. If you wish to use this
     tool with version 2 of Modula-2/86, you should set the
     (MS-DOS) environment variable M2TYPES as follows:

        SET M2TYPES=.DEF,.SYM,.MOD,.LNK,.LOD

  o  Owing to weaknesses in MS-DOS, it is not possible for
     Update to obtain the status returned by any system
     command.  Update detects rebuilding errors by looking
     for the first named product after a rebuilding step
     has been completed.

  o  MS-DOS maintains file time stamps to an accuracy of
     only 2 seconds.  If Update is used with very fast tools
     or very fast machines it could fail to detect some
     required operations.

4.  Extensions

You should be aware of two extensions in Update.

  o  If an INCLUDE clause in an Update description contains
     a file name beginning with a "$" the program will try
     to replace the name with the value of a DOS environment
     variable.  For example, INCLUDE "$Build" will actually
     open the file C:\M2LIB\STDBUILD.UPD (if BUILD is set as
     shown above).

  o  The assignment statement (in Update) has been extended
     beyond the behaviour documented in section 3 of the
     users' manual.  The right side of an assignment may
     contain an elementary string operation.  Two such
     operations are possible:

        <expr> + <expr>       the strings are concatenated

        <expr> - <expr>       the first occurrence of the
                              second expression is deleted
                              from the first.

     These operations are available only in assignment
     statements and may not be further combined.

     This is an experimental extension.  DO NOT assume that
     other versions of Update will include these string
     operations.

===================== uses.man ==============================================

                       Users' manual -- Uses

     1. Introduction

     This manual describes the Uses program.  Uses analyses Modula-2
     programs and deduces the dependencies between modules.  You
     should be familiar with Modula-2 programming and the programming
     conventions of LUMOS-2 before reading this manual. The main
     application of Uses is to produce description files for the
     Update tool.  It is recommended that you read the documentation
     for Update along with this manual.

     2. Invoking Uses

     Uses may be started with a command of the form:

          Uses <root> [ <option> [ <builder> [ <include> ]]]

     <root>     is the name of a Modula-2 program module. If you do
                not specify a file type, .MOD will be assumed.  Uses
                will analyse this file and all modules that it
                explicitly or implicitly imports.  If you omit this
                filename altogether, Uses will prompt you for all the
                command arguments.

     <option>   is one of the two letters: D or U.  If you enter D,
                Uses will construct an ordered table of the module
                dependencies and write it on a file with a name
                derived from the <root> by replacing .MOD with .DEP.
                If you enter U, which is also the default value for
                this argument, Uses will produce a .UPD file in the
                format required by Update.

     <builder>  is the procedure name that will be written in the BY
                part of every MODULE clause generated by Uses.  This
                name is only used in the U mode.  The default value of
                this argument, which is used if nothing is entered
                here, is the name "Build".

     <include>  is a file name for which an INCLUDE directive will be
                generated in the .UPD file.  The default value is
                derived from the <builder> argument by suffixing .UPD.
                If the <builder> argument was not specified <include>
                is given the value "$Build".  (This is a logical name
                that usually refers to a file containing a general
                purpose Build procedure.) This argument, too, is used
                only in the U mode.

     Examples:

          Uses King

               Examines King.MOD and produces King.UPD for Update. The
               lines of King.UPD might look like:

               INCLUDE "$Build";
               MODULE "King.EXE" USES "King.OBJ", "SysCalls.OBJ"
                 BY Build("King.OBJ") END;

          Uses King D

               Examines King.MOD and writes out King.DEP containing
               the module dependencies of King.  The format of this
               file is explained below.

          Uses King.OLD U SysBuild MyBuild

               This command will try to find a program module in
               King.OLD.  It will generate an Update description file
               using "SysBuild" in the BY phrases and "MyBuild" in the
               INCLUDE directive.

     3. Principles of Operation - D mode

     When Uses examines a module it reads all the IMPORT and FROM
     clauses in the module and keeps a list of the external modules
     named there.  (Uses does not attempt to find local modules.)
     Having built such a list for the root module, the process repeats
     on both the definition and implementation parts of every module
     named.  If any new modules are encountered, they too will have
     such lists built.  If uses discovers an import from a module that
     it cannot locate in the current directory, it assumes that this
     is a library module and does not process it further.

     This process will eventually stop when all referenced modules
     have been located and examined.  The list of module names will
     then be sorted so that every name occurs before any module it
     imports.   This list is then written to the .DEP file in the
     format suggested by the following example:

          King:
            Queen, Duke, (Earl)
          Queen:
          Duke:
            Earl
          Earl:
            SysCalls

     Notice that Queen imports nothing and that SysCalls does not
     occur on the list (it could not be found). Names that are
     referenced in the implementation part of a module, but not in the
     definition part, are enclosed in parentheses (like Earl in the
     example above).

     4. Principles of Operation - U mode

     When Uses is called on to construct an Update description file,
     it performs the same basic analysis as described above.  In this
     mode, however, definition and implementation modules are
     considered as distinct modules.  The clauses written to the .UPD
     file take three different forms.

     A definition module generates a MODULE clause for its symbol file
     in which the USES part contains the .DEF file itself, and the
     .SYM files of any imports. For example, if Earl.DEF imports from
     SysCalls the following MODULE clause will be generated:

          MODULE "Earl.SYM" USES "Earl.DEF", "SysCalls.SYM"
            BY Build("Earl.DEF") END;

     An implementation module, similarly, generates a clause for its
     .OBJ file.  For Earl.MOD this would be:

          MODULE "Earl.OBJ" USES "Earl.MOD", "Earl.SYM",
            "SysCalls.SYM" BY Build("Earl.MOD") END;

     A program module has no corresponding definition module, so does
     not implicitly import its own .SYM file.  Each program module
     corresponds to an executable file, however.  King.MOD would
     produce the following two clauses:

          MODULE "King.OBJ" USES "King.MOD", "Queen.SYM",
            "Duke.SYM", "Earl.SYM" BY Build("King.MOD") END;
          MODULE "King.EXE" USES "King.OBJ", "Queen.OBJ",
            "Duke.OBJ", "Earl.OBJ", "SysCalls.OBJ"
            BY Build("King.OBJ") END;

     5. Error messages

     Uses can stumble for several reasons.  In every case, the
     computation is abandoned and the output file is deleted.  The
     following list contains the messages that are printed when an
     error occurs, and the possible causes.


     Cannot create output file

          Uses is unable to create the output .DEP or .UPD file.
          Check that you have write permission in the current
          directory and that the volume has room for the file.

     Cycle in dependencies

          In the D mode, Uses may encounter circular dependencies in
          the modules.  This is bad programming practice, and causes
          Uses to fail.  (It can happen if an implementation module
          imports a module that itself imports the definition of the
          first module.) The program should be redesigned to avoid the
          circular dependencies.

     File not found: ...

          This message is printed if the <root> file cannot be found
          in the current directory.  It can also occur if an
          implementation module is missing.  Missing definition
          modules are assumed to be in a library and do not generate
          this error.

     I/O error

          Unexpected failures while reading or writing files can
          generate this error message.  Check for hardware problems.

     Internal error: ...

          Uses is confused. Report this error to your system manager,
          include as much information about the error as you can.

     Modula-2 syntax error in: ...

          Although Uses recognises only a small portion of the
          Modula-2 syntax, it can detect that some modules are
          syntactically invalid.  Use the Modula-2 compiler to
          identify the error and repair it.

     Out of memory

          Rarely, a system may be so large that Uses' internal tables
          exhaust available memory.  There is no convenient remedy for
          this problem.

     Stopped by user

          You pressed the system break key.

     Unrecognised option

          At present, Uses accepts only the D and U option letters.

==================== update.man ============================================

                       Users' Manual -- Update

     1. Introduction

     This manual describes the Update program.  Update regenerates
     programs when changes are made to their components.  Regeneration
     is directed by a description file.  Update does no more work than
     is required.  You should be familiar with Modula-2 programming
     and the programming conventions of LUMOS-2 before reading this
     manual.  The description files used by Update are often produced
     by the Uses tool.  You should read the manual for Uses along with
     this manual.

     2. Invoking Update

     Update may be started with a command of the form:

          Update <descriptor> [<ident>[="<string>"]] ...

     <descriptor>  is the name of an Update description file.  If you
                   do not specify a file type, .UPD will be assumed.
                   Update will use this file to direct the rebuilding
                   of the software system that it describes. If you do
                   not provide this argument, Update will prompt you
                   for your command. (The syntax of Update description
                   files is described below.)

     <ident>       is an identifier. (As in Modula-2, it must begin
                   with a letter and contain only letters or digits.)
                   Declaring an identifier on the command line gives
                   it a known value as a variable in the Update
                   description.  The value may be any character
                   string.  If a value is not given explicitly on the
                   command line, the value "T" is used.  These
                   variable assignments may be used to choose between
                   variations in the rebuilding method.

     <string>      is any string of characters that will be taken as
                   the value of the preceding identifier.

     Examples:

          Update King

               Will examine King.UPD and, if necessary, perform some
               or all of the rebuilding operations described there.

          Update MyOwnOS map install="C:"

               This command follows the rebuilding instructions in
               MyOwnOS.UPD with the (Update) variable 'map' set to "T"
               and the variable 'install' set to "C:".

     3. Tutorial Introduction to the Update Description Language

     A description file contains three kinds of clauses: MODULE,
     PROCEDURE and BEGIN clauses.  The clauses may be arranged in any
     order, as long as there is only one BEGIN clause and it is the
     last one in the description.

     A typical description file will contain several MODULE clauses.
     Each MODULE clause describes a particular manufacturing step in
     the rebuilding of the system.  The clause names the required
     components for this step, the products of the operations and the
     commands that must be executed to perform this step.

     The commands may be listed explicitly in the MODULE clause, or
     they may be encapsulated in a procedure that is named instead.
     For example:

          MODULE "OpCode.SYM" USES "OpCode.DEF"
            BY * M2C OpCode.DEF; END;

     describes a simple manufacturing step with an explicit command.
     For another example:

          MODULE "OpCode.OBJ" USES "OpCode.MOD", "OpCode.SYM"
            BY Build("OpCode.MOD") END;

     describes a more complicated manufacturing step in which one
     product requires two components for its construction.  The
     commands are referenced indirectly through the procedure named
     "Build". In yet another example:

          MODULE "OpCodes.DEF", "OpCodes.MOD" USES "OpCode.TAB"
            BY * MakeTable ; END;

     the MODULE clause describes a manufacturing step that produces
     two outputs at once from a single input.

     When Update interprets these clauses, it will select and order
     them automatically so that only necessary steps are performed and
     that required components are ready before they are used.

     The actual building steps, whether explicit or contained in a
     procedure, are expressed as a sequence of statements.  The
     command statement is the most important of these; it invokes the
     system's command interpreter to execute a program (such as a
     compiler or linker). Command statements begin with the '*' symbol
     and extend to the next ';'.  You will see other kinds of
     statements shortly.

     A collection of statements may be grouped together and named in a
     PROCEDURE clause, as in the example:

          PROCEDURE  BuildSystem();
            * Del System.LNK ;
            * M2C System ;
            END;

     To be really useful, procedures need parameters.  Update allows
     procedures to be qualified with any number of parameters.  These
     parameters are considered to be character string variables.  One
     way that parameters and variables can be used is to include their
     contents in command statements.  This is done by including the
     variable name, surrounded by "back ticks", in the command text.
     For example:

          PROCEDURE  Build(file);
            * M2C `file`;
            END;

     If this procedure is called by Build("Duke") then the command

          Modula Duke

     would be executed.

     Variables are not limited to procedure parameters, however.  They
     may be defined and given values when Update is invoked. For
     example:

          Update King map install="A:"

     starts Update with the variable 'map' set to "T" and the variable
     'install' set to "A:".

     Variables may also be used in two other kinds of statements,
     assignments and conditionals.  Assignments can be used to give a
     variable a value during the execution of the rebuilding process.
     (A variable name that has never been given a value in a parameter
     list, on the command line or in an assignment statement is
     assumed to be an empty string.) Here is a typical assignment
     statement:

          mapflag := "/NOM";

     To use conditional statements effectively, you should know that
     variables and literal strings may be combined in relational
     expressions using the operators: = (for equality), # (inequality)
     and <= (string inclusion).  Relational expressions can be
     combined using parentheses and the logical operators: AND, OR and
     NOT.

     A conditional statement looks like:

          IF map = "T" THEN * Link `file`;
                       ELSE * Link `file`/NOM; END;

     The ELSE clause is optional (as in Modula-2).  The previous
     example could also be written as:

          IF map # "T" THEN mapflag := "/NOM" END;
          * Link `file``mapflag` ;

     Many applications of Update will share common procedures. The
     INCLUDE directive tells Update to read from another file as if it
     were part of the description file.  INCLUDE directives are
     recognised as clauses; consequently, included files should
     contain complete clauses.  Sometimes, it is necessary to arrange
     for certain statements to execute before any of the automatically
     sequenced rebuilding operations.  This can be done by including
     these statements in a BEGIN clause.  There is a special
     statement, ABORT, that causes Update to stop (prematurely).
     Update description files may also include comments, in the usual
     Modula-2 syntax.

     A final example:

          (* A description file for a small program,
             with some complications *)
          MODULE "Earl.EXE" USES "Earl.OBJ", "InOut.OBJ"
             BY Build("Earl.OBJ") END;
          MODULE "Earl.OBJ" USES "Earl.MOD", "InOut.SYM"
             BY Build("Earl.MOD") END;
          PROCEDURE Build(file);
          IF ".OBJ" <= file THEN * M2L `file``mapflag` ;
            ELSE IF (".DEF" <= file) OR (".MOD" <= file)
                   THEN * M2C `file`;
                   ELSE * Echo Unexpected file type in: `file`;
                        ABORT
                   END
            END
          END;
          BEGIN IF map # "T" THEN mapflag="/NOM" END;
          END.

     4. Formal Syntax of the Update Description Language

     <description> ::= <cl_list> [ ';' <begin> ] '.'
     <cl_list>     ::= <clause> ( ';' <clause> )*
     <clause>      ::= <step> | <include> | <proc>
     <include>     ::= 'INCLUDE' <literal>
     <step>        ::= 'MODULE' <list> 'USES' <list>
                       'BY' <stat_seq> 'END'
     <list>        ::= <literal> ( ',' <literal> )*
     <begin>       ::= 'BEGIN' <stat_seq> 'END'
     <stat_seq>    ::= <statement> | <command> |
                       <command> <stat_seq> |
                       <statement> ';' <stat_seq>
     <statement>   ::= <cond> | <call> | 'ABORT' | <assign>
     <proc>        ::= 'PROCEDURE' <ident> '(' <ident_seq> ')' ';'
                       <stat_seq> 'END'
     <call>        ::= <ident> '(' <expr_seq> ')'
     <ident>       ::= <letter> ( <letter> | <digit> )*
     <ident_seq>   ::= <empty> | <ident> ( ',' <ident> )*
     <expr_seq>    ::= <empty> | <expr> ( ',' <expr> )*
     <command>     ::= '*' ( <com_char> | <subst> )* ';'
     <com_char>    ::= <printable> - ';' - '`'
     <subst>       ::= '`' <ident> '`'
     <expr>        ::= <ident> | <literal>
     <literal>     ::= '"' <string> '"'
     <string>      ::= <str_char>*
     <str_char>    ::= <printable> - '"'
     <cond>        ::= 'IF' <boolean> 'THEN' <stat_seq>
                           [ 'ELSE' <stat_seq> ] 'END'
     <assign>      ::= <ident> ':=' <expr> [ ('+' | '-') <expr> ]
     <boolean>     ::= <bool_term> ( 'OR' <bool_term> )*
     <bool_term>   ::= <bool_fact> ( 'AND' <bool_fact> )*
     <bool_fact>   ::= '(' <boolean> ')' | 'NOT' <bool_fact> | <rel>
     <rel>         ::= <expr> <relop> <expr>
     <relop>       ::= '=' | '#' | '<='

     5. Principles of Operation

     Update sorts the MODULE clauses into an order consistent with the
     dependencies between the manufacturing steps.  It then considers
     each clause.  If any of the product files have creation dates
     earlier than any of their required components then the rebuilding
     statements in that clause are executed.

     If Update is unable to locate a required file to obtain its date,
     it will try to find the file in the Modula-2 library directories
     (identified by the environment variables M2*).

     Update honours the value of a special variable, Test.  If Test is
     "T", then the selected rebuilding commands are not executed, they
     are only printed out.  Normally, each command is printed to the
     terminal as it is executed.  The special variable Quiet may be
     used to suppress this printing.

     Description files are often generated by the Uses program.  In
     its default mode of operation, Uses writes an INCLUDE statement
     for the file $Build.  This file normally contains a single
     procedure called Build, which is sufficient for ordinary compile
     and link operations.  You should examine $Build to be sure that
     you understand what it does.

     In Update, all variables are global.  Procedure parameters,
     however, are local in scope so procedures can call other
     procedures.

     6. Error Messages

     Update detects many errors.  In each case, Update's operation is
     terminated.  If the rebuilding operation has been partially
     completed, no attempt is made to remove the intermediate
     products.  The following list contains the messages that are
     printed when an error occurs.

     ABORT statement executed

          The Update description file contains an ABORT statement.
          It has just been executed.  If you did not write the
          description file, look at the file for a possible
          explanation.

     Cannot open description file

          The description file named on the command line does not
          exist, or is protected.

     Cannot open INCLUDE file: ...

          A file named in an INCLUDE directive cannot be found or is
          protected.

     Command line syntax error

          If a "=" occurs on the command line, it must be followed by
          a quoted string.  If the string or a quote is missing you
          will receive this error.

     Cycle in dependencies

          The description file describes a system that cannot be
          constructed because of circular dependencies.  You must
          correct the file.

     Expected product not present: ...

          If the execution of a manufacturing step did not produce
          the expected output, this message will appear.  You should
          read the error messages produced by the rebuilding command.

     I/O error

          This message indicates that an unexpected error occurred
          while reading a file.  Check for hardware problems.

     Internal error: ...

          Update has detected an inconsistency in its own operation.
          Please report this to your system manager, giving as much
          detail as possible.

     Invalid identifier syntax: ...

          You have attempted to set a variable on the command line.
          The variable name must begin with a letter and contain
          only letters and digits.

     Out of memory

          If a system is very large, Update may not be able to obtain
          enough memory to hold its tables.  There is no effective
          remedy for this problem.  This error can also occur if
          infinite recursion is attempted.  Check for recursive
          procedures in the description file.

     More than one way to rebuild: ...

          The named component appears as a product in more than one
          manufacturing step.

     Procedure multiply defined: ...

          The Update description file defines a procedure more
          than once.  Repair the file.

     Procedure not declared: ...

          The Update description file does not contain a declaration
          for the named procedure.  Repair the file.

     Stopped by user

          You pressed the system break key.

     Substitution error in: ...

          While performing variable substitution on a command,
          Update has encountered mismatched back ticks.  Repair
          the description file.

     System is up to date

          Update has determined that there is nothing for it to do.

     Syntax error: ...

          This message will contain a description of the error and the
          offending text.  Repair the description file and try again.
          (Syntax errors are detected before any statements are
          executed.)

============================================================================

klarich@A.CS.OKSTATE.EDU (02/14/89)

I would appreciate it if you could mail me the sources and or the
executables.  I have some generic modules (stack,red-black tree, queue and
binary tree I would be willing to trade.

Thanks
--
Terry Klarich (klarich@a.cs.okstate.edu) n5hts
A man is not complete until he is married then, he is finished.

ben@val.UUCP (Ben Thornton) (02/16/89)

Would you please mail me a copy of your Modula-2 make-like utilities?

Thanks

--

Ben Thornton             packet:  WD5HLS @ KB5PM
Video Associates Labs      uucp:  ...!cs.utexas.edu!oakhill!val!ben
Austin, TX              fidonet:  1:382/40 - The Antenna Farm BBS