
               Welmat Programming Language - WPL
               ---------------------------------

  WPL Internals  (For information purposes only)
  -------------

  While there will be direct user access to many of the internals of WPL
via a WPL Programmers Interface (WPI for short), this interface has not yet
been standardized.  In order to give potential developers an idea of the
direction that we are headed, I will give a bit of documentation here.

  To start, one must first understand what happens when WPL loads a script
into memory.  While the language is an interpreted language like AREXX, 
unlike AREXX each command and parameters are tokenized as it is loaded
so that the running of the script will be faster.  The script is loaded,
line by line, and analysed according to this very basic layout:

  [label:] WPL_Command [parameter1] [parameter2]

  It then first checks if the first character of the WPL_Command is a
semicolon, and if this is the case the entire line (except the possible label)
is thrown out.

  Labels are attached to the next valid WPL Command, so the following are
equivalent:

  ; Comment
  label: WPL_Command

  label: ; Comment
  WPL_Command

  label:
  ; Comment
  WPL_Command

  redundant_label:
  label:
  ; Comment
  WPL_Command

(NOTE: With 'redundant_label:' above, this information is thrown away as
there is no command to associate with the label information.  WPL is not
like other languages in that labels are more like 'named addresses' as
opposed to labels.  Two labels cannot indicate the same place in
the script).


  The tokenizer will next look up the WPL Command in an internal list of
commands to try to figure out it's 'token number'.  An instruction token
is just a simple unique 32-bit number.  This number is specific to the 
revision of WPL currently running, and is also dependant on any WPL
language extension libraries that might be attached to wpl.library.

  Once the token is found, attached with the token is a number that
corresponds to the number of parameters that are required by the
specific command.  The specified number of parameters are accepted from
the command line, and added into the instruction list element.  One should
note that extra parameters are just ignored, and not included in the parsed
memory version of the instruction.

  Two special 'parameter numbers' exist, one to signify an unlimited number
of parameters being accepted, and another to indicate that an unlimited
number of parameter pairs are accepted.


  For those versed in the language 'C', the current internal instruction
structure looks like the following:

struct wProgNode {
  struct Node wp_Node;   /* ln_Name points to label if exists, or NULL */
  unsigned long wp_Size; /* entire size of this structure for free'ing purposes */
  unsigned long wp_Inst; /* instruction number - language revision specific */
  struct wProgNode *wp_Goto; /* address of possible label */
  unsigned long wp_Argc; /* Number of arguments */
  char *wp_Argv[1];      /* Array of argument strings */
  /* start of memory for arguments/label */
};

  In the above, the wp_Goto is used to store a wProgNode location
the first time a *JUMP instruction is executed.  The next time it hits the
JUMP instruction, the command runs considerably faster.


  The arguments are stored in a very familiar argc,argv format, just like
what one would normally use with C main() calls.

  Now, when an instruction is executed, the wp_Inst is used as an
array index into a table of instructions, and from this table a pointer to
the actual function is found.  The generic prototype for an instruction is:

void wi_instruction(unsigned long argc,char *argv[],slave *thisSlave);

  As an example, the simplest instruction in WPL would
be the 'print' instruction, and it's code is as follows:

void wi_Print(unsigned long argc,char *argv[],slave *thisSlave)
{
  char temp[256];

  wpi_getstring(argv[1],temp,sizeof(temp),thisSlave);
  PutStr(temp);
}


  Aside:  If anyone ever wants to know the specifics of how an instruction
is implemented, please just ask and I will send them the code for that
instruction.

Note: 'slave *' is a general pointer to a structure who's internal
composition is not available to a WPL instruction.  It is a 'cookie value'
that is passed to most WPI interface functions.  Currently most instructions
still make use of the ->scratch information, but this will be slowly
removed as instructions are made more WPI compatable.


  Inside of a function, it is allowed only to access other parts of WPL
through the WPI interface.  An exception to this would be the 'built in'
instructions such as the *JUMP commands which have intimate knowledge of
the internals of WPL beyond the definition of a wProgNode, and the interface
functions defined with wpl.library.

  Here is a list of ideas.  I will likely not complete all of these before
making a preliminary release, and all documentation on these will be
subject to change as the need arises until the first 'totally public'
release (At which time anything that is documented will have to be cast
in stone!).  I will be expanding this documentation as time permits to
express current design ideas.

(Note: A '*' in front of the command means that it is implemented, and
currently in use)
 

Group-I: - XPR defined calls.  These calls will have exactly the same
      structure as the XPR callback functions, except that they are accessed
      as library calls, and the additional parameter of 'slave *' is also
      passed.  One should note that the XPR callbacks within WPL are just
      simple assembly stubs that in one way or another will obtain this
      slave pointer.  These functions are defined and expanded as XPR is 
      expanded.  See the XPR documentation for more information.
      The XPR 3.0 proposed callbacks that have the XPR_IO structure being
      passed are also shown.  The XPR 2.0 prototype is the same, but without
      the addition of the XPR_IO structure passed in A3.

  void *xpr3_fopen(char *filename,char *accessmode,struct XPR_IO *io);
* void *wpi_fopen(char *filename,char *accessmode,slave *thisSlave);
    D0                   A0            A1               A3

    - Open inbound/outbound file

  void xpr3_fclose(void *fileptr,struct XPR_IO *io);
* void wpi_fclose(void *fileptr,slave *thisSlave);
                        A0            A3
    - Close file

  long xpr3_fread(char *buffer,long size,long count,void *fileptr,struct XPR_IO *io);
* long wpi_fread(char *buffer,long size,long count,void *fileptr,slave *thisSlave);
    D0              A0            D0       D1        A1            A3
    - Get data from file

  long xpr3_fwrite(char *buffer,long size,long count,void *fileptr,struct XPR_IO *io);
* long wpi_fwrite(char *buffer,long size,long count,void *fileptr,slave *thisSlave);
    D0                     A0       D0       D1        A1             A3
    - Put data to file


  long xpr3_sread(char *buffer,long size,long timeout,struct XPR_IO *io);
* long wpi_sread(char *buffer,long size,long timeout,slave *thisSlave);
    D0              A0            D0       D1            A3
    - Get string from serial

  long xpr3_swrite(char *buffer,long size,struct XPR_IO *io);
* long wpi_swrite(char *buffer,long size,slave *thisSlave);
    D0                A0           D0        A3
    - Put string to serial

  long xpr3_sflush(struct XPR_IO *io);
* long wpi_sflush(slave *thisSlave);
    D0                A3
    - Flush serial input buffer

  void xpr3_update(struct XPR_UPDATE *updatestruct,struct XPR_IO *io);
* void wpi_update(struct XPR_UPDATE *updatestruct,slave *thisSlave);
                      A0                             A3
    - Update file transfer status

  long xpr3_chkabort(struct XPR_IO *io);
* long wpi_chkabort(slave *thisSlave);
    D0                 A3
    - Check for abort

  long xpr3_chkmisc(struct XPR_IO *io);
* long wpi_chkmisc(slave *thisSlave);
    D0                A3
    - Check the public port for any pending messages.
      This call is currently equivalant to wpi_waitpubmsg(NULL,thisSlave).


  long xpr3_gets(char *prompt,char *buffer,struct XPR_IO *io);
  long wpi_gets(char *prompt,char *buffer,slave *thisSlave);
    D0             A0           A1            A3
    - Get string interactively 

  long xpr3_setserial(long newstatus,struct XPR_IO *io);
* long wpi_setserial(long newstatus,slave *thisSlave);
    D0                   D0           A3
    - Set and Get serial info

  long xpr3_ffirst(char *buffer,char *pattern,struct XPR_IO *io);
* long wpi_ffirst(char *buffer,char *pattern,slave *thisSlave);
    D0               A0          A1             A3
    - Find first file name for batch transfers

  long xpr3_fnext(long oldstate,char *buffer,char *pattern,struct XPR_IO *io);
* long wpi_fnext(long oldstate,char *buffer,char *pattern,slave *thisSlave);
    D0             D0             A0           A1            A3
    - Find next file name

  long xpr3_finfo(char *filename,long typeofinfo,struct XPR_IO *io);
* long wpi_finfo(char *filename,long typeofinfo,slave *thisSlave);
    D0             A0             D0              A3
    - Return file info

  long xpr3_fseek(void *fileptr,long offset,long origin,struct XPR_IO *io);
* long wpi_fseek(void *fileptr,long offset,long origin,slave *thisSlave);
    D0             A0             D0         D1          A3
    - Seek in a file

  long xpr3_options(long n,struct xpr_option **opt,struct XPR_IO *io);
* long wpi_options(long n,struct xpr_option **opt,slave *thisSlave);
    D0                D0     A0                     A3
    - Better GUI based option requesting.
      (Just a stub function for the future)

  long xpr3_unlink(char *filename,struct XPR_IO *io);
* long wpi_unlink(char *filename,slave *thisSlave);
    D0              A0               A3
    - Delete a file
      (Not currently supported, but stubbed)

  long xpr3_squery(struct XPR_IO *io);
* long wpi_squery(slave *thisSlave);
    D0                A3
    - Query serial device

  long *xpr3_getptr(long type,struct XPR_IO *io);
* long *wpi_getptr(long type,slave *thisSlave);
    D0                D0        A3
    - Get various host ptrs



Group-II - Variable control

* UBYTE *wpi_getstring(UBYTE *oldstring,UBYTE *buffer,ULONG len,slave *thisSlave);
    D0                  A0               A1            D0        A2
    - Get WPI variable replacement string.

* BOOL wpi_setvar(UBYTE *variable,UBYTE *value,slave *thisSlave);
    D0             A1               A1          A2
    - Set a variable to a null terminated string value.

* BOOL wpi_getvarnum(UBYTE *variable,ULONG *number,slave *thisSlave);
    D0                 A0             A1            A2
    - Returns a long integer value from a variable.

* BOOL wpi_setvarnum(UBYTE *variable,ULONG number,slave *thisSlave);
    D0                 A0              D0          A1
    - Set a variable to a given long integer.

* BOOL wpi_getvarbool(UBYTE *variable,slave *thisSlave);
    D0                   A0             A1
    - Returns boolean value of variable.

* BOOL wpi_setvarbool(UBYTE *variable,BOOL boolean,slave *thisSlave);
    D0                  A0             D0            A1
    - Sets a boolean variable. (Strings "TRUE":"FALSE")


  Group-III - WPI control

  void wpi_docmd(LONG command,ULONG argc,char *argv[],slave *thisSlave)
             D0            D1        A0           A1
    - Executes a single WPL command, and is also the same call that is
      used within a WPI extension library.  The top 16-bits of the
      command are a library number, and the bottom 16 bits are a specific
      command within a given WPI extension library.

      In the case of an extension library, the top 16 bits of the command 
      should be stripped.  If the command is '-1', then this is a request 
      by wpl.library for this library to indicate it's command list.  
      The library should then open wpl.library, and pass in it's library
      table.  [this idea is not yet settled].

* void wpi_execscript(UBYTE *start,slave *thisSlave);
                       A0            A1
    - Runs a WPL script in the current context - Must be
      a 'Slave' context executed from within a WPL 
      extension library.  A 'return' will cause the flow of
      control to return to your program.

* slave *wpi_findslave(void);
    D0
    - Returns a 32-bit value defining the slave.  This
      is for WPI libraries who run within the process
      of a slave.

* ULONG wpi_launch(UBYTE *name,UBYTE *startup,ULONG priority,ULONG stack);
   D0               A0          A1             D0              D1
    - Launches a new Slave.  The name must be unique, and is used for both
      the message port name, as well as what will be shown in the list of 
      CLI's.  The startup string is a script!label specification, and
      must be included.  The priority and stack are the process' priority
      and stack respectively.

      A return code of 0 means that it was successfull, and all other returns
      indicate a specific error.

        0 - All OK so far.
        1 - Can't create public port.
        2 - Can't open timer.
        3 - Can't allocate vars structure.
        4 - Can't open xferq.library
       99 - No memory in slave.
      101 - No memory for structure.
      102 - Error in new process launching.


* BOOL wpi_loadscript(char *scriptname,char *infile);
   D0                   A0              A1
    - Loads in a WPL script ready to be executed.  The script name must 
      be unique, and is the name given in any script!label specifications 
      within a script.  If a script by that name is already loaded, it will
      attempt to flush it.  If the script is locked by a running slave, then
      the operation will fail.

      The infile is the full pathname to the file that should be loaded, or
      NULL to indicate that you just wish to flush the current named script
      from memory.
 
      The return code is a boolean TRUE or FALSE that indicates whether the
      operation was successfull.  If a filename is given, TRUE means that
      the given script was loaded correctly, and a FALSE will indicate eithor
      that a script by the given name is already loaded, or an error occured
      during loading.  If NULL was given in the filename field, TRUE means
      that the given script was found and flushed , and FALSE would indicate
      that the given script was in-use, and could not be flushed.

* struct MsgPort *wpi_publicport(slave *thisSlave);
   D0                              A0
    - Returns a pointer to this slaves public message port.  This port
      can be used as the reply-port for a single message that would
      then be waited for using the wpi_waitpubmsg() call.  This is
      usefull for sending messages that might take a long time
      to return (Such as a REXX message), and you wish to allow
      WPL to process it's REXX port during the wait.

* void wpi_waitpubmsg(struct Message *myMsg,slave *thisSlave);
                         A0                  A1
    - This function will process the public message port awaiting
      a specific message to return before completing.
      Using a message of 'NULL' indicates that you wish any pending
      messages to be processed, and then to return.  During any
      time consuming calculation, this call should periodically be
      made.  Plese see wpi_publicport() for further information.


Future:


  wpi_controlTags() Generic interface to various internal controls.
                    The interface to allow the adding of various transfer 
                    status GUI handlers, Handlers for additional REXX based 
                    commands,  WPL language extensions and other related
                    functions will be supported.

