home *** CD-ROM | disk | FTP | other *** search
- Program.txt - Notes for programming external shell modules
- -----------
- This file contains information necessary for writing OPL modules
- that can be used by Shell3a as external commands.
-
- Contents: How commands are executed
- Command arguments
- Wildcards
- Shell3a variables
- Shell3a procedures
- Programming for 'pipes'
- Detailed descriptions of some procedures
-
- 1) How commands are executed
- ============================
-
- When a command is typed the shell processes it as follows:
-
- (a) The input is compared with the aliases and any substitutions
- are made. A '\' as the first non-blank character prevents
- aliases being expanded.
- (b) The arguments are parsed one at a time. If a wildcard is
- found this is expanded. If no matches are found an error is
- generated, otherwise all arguments are stored in memory. The
- array argv%() points to successive arguments. The last
- argument in this array is always 0. Comments and variable
- substitutions are made.
- (c) Redirection of output is handled.
- (d) The first argument is matched against the following:-
- (i) The shell builtins
- (ii) Stored entries in the path
- (iii) A valid .bat, .opo, .opa or .opa file in the path
- (iv) A valid directory to 'cd' to
-
- Modules are stored in the shell's path as their filename. ie.
- LOC::M:\OPO\MORE.OPO would be stored as 'more.opo' and can be
- accessed as either 'more' or 'more.opo'. When 'more' is typed at
- the prompt and found not to match any of the builtin functions or
- aliases, the path is searched and it's found here. The module
- LOC::M:\OPO\MORE.OPO is then LOADMed and a function more%:(x%)
- is called.
- The module MUST contain a function of this specification - it
- must be called the same as the .opo file, return an integer and
- take 1 integer argument. Currently the return value of the
- procedure isn't used.
-
- e.g. To have a command 'newcom' recognized:
-
- (a) Write an opl module with a procedure newcom%:(int%)
- (b) Compile this module to newcom.opo
- (c) Move newcom.opo into a directory in the path
- (d) If you want a manual page for your command (e.g. if you want
- to distribute the module), compile a help file 'newcom.hlp'
- using the hcp.opo module, and put it in the helppath directory.
-
-
- 2) Command arguments
- ====================
- The input string is parsed by the shell and split into separate
- arguments. These are stored on the heap and are referenced by
- the argv%(n%) array. For example
-
- cp file1.txt file2.txt
-
- Stores: argv%(1)="cp"
- argv%(2)="file1.txt"
- argv%(3)="file2.txt"
- argv%(4)=0 <- marks the end of the list
-
- Your module is passed the number of arguments - in this case 3 -
- as it's only parameter.
- All text within quotes is stored as a single argument.
-
-
- 3) Wildcards
- ============
- Wildcards are expanded before they are passed to the individual
- commands. e.g. ls LOC::M:/ would pass 'ls' a command line like
-
- ls,LOC::M:\AGN,LOC::M:\APP,LOC::M:\OPO,...
-
- Note that wildcards are expanded to absolute pathnames and always
- have the native separator '\'.
- To pass wildcards to a module they need to be quoted "*".
-
-
- 4) Shell3a variables
- ====================
- Internal global variables that are generally not intended for
- external use have names starting with "SH" to avoid accidental
- conflicts. The 'useful' globals are listed below along with a
- BRIEF description:
-
- argv%() the command argument array, discussed above
- varStyl% the current font style
- varStat% set if the status panel is visible
- varUnix% set if / is to be used as the pathname separator
- varApp% set if output redirection should always append to the output file
- varEcho% set if commands in batch files are to be displayed as executed
- ScrInfo%() the data obtained from SCREENINFO function on the current screen
-
- [NB. Unsetting a shell variable that has a corresponding var*% OPL
- variable (eg. varUNIX% and $unix) will have no effect on the
- var*%, these are only changed when shell variables are set.]
-
-
- 5) Shell3a procedures
- =====================
- Internal functions are prefaced by 'sh'; to avoid possible
- conflicts you should avoid functions starting 'sh...'. Also
- avoid function names that appear as builtin commands and the
- ones listed below.
-
- Procedures that will be useful in writing modules are listed
- below. Some are described in greater detail in section (6) and
- are denoted with an asterix:
-
- SetVar%:(var$,val$) Store val$ in the shell variable var$
- s$=GetVar$:(var$) Return the value of the shell variable var$
- FreeVar%:(var$) Delete the shell variable var$
- *ret%=Fparse%:(add%,s$) Enhanced PARSE$ function
- *ret%=fprint%:(string$) Handle output redirection
- p$=PrPath$:(buf$) convert a path to UNIX form (if necessary)
- *err$:(n%) Enhanced err$ function
- ShErr:(i%,n%) PRINT PrPath$:(PEEK$(argv%(i%))),"-",err$:(n%)
- *log:(flag%,message$) Display a message in the status window
-
-
- 6) Programming for 'pipes'
- ==========================
- As stated in the general Readme, commands must be specially written
- for input/output edirection and pipes to work. Pipes aren't coded
- for specially, if you code commands to use redirection, pipes will
- work!
-
- Output Redirection: A command is informed if the output is
- redirected by a non-zero value for SHout%. This value is the OPL
- handle for the file that output is to be written to with the
- IOWRITE command. The easiest way to handle this is to use fprint%:
- to produce any output. The command should only write to SHout%,
- it shouldn't change the value or close the file handle.
-
- Input redirection: A command is informed if the output is
- redirected by a non-zero value for SHin%. In general input
- redirection is only really useful for commands that could already
- take their input from a file. For redirected input, rather than
- opening a file whose name was supplied on the command line, data is
- read directly from SHin% with IOREAD. As with SHout%, SHin% should
- not have it's value changed and it should not be closed.
- Included is Wc.opl, the source for a command that counts the
- characters, words and lines of a file, to demonstrate the redirection
- of input.
-
-
- 7) Detailed descriptions of some procedures
- ===========================================
- (a) Fparse%: ret%=Fparse%:(add%,s$) Enhanced PARSE$ function
-
- It handles relative paths and appends the trailed \ onto
- directories.
-
- add% - the address of a string, length 128 bytes. This will
- contain the parsed string.
- s$ - the path to be parsed.
- ret% - the status of the file as follows:
-
- -33 : File / directory doesn't exist
- -127: Path contains wildcards
- <0 : OPL error - the status of the returned pathname is undefined
- and shouldn't be used.
-
- >0 : Bit 0: file is not ReadOnly
- Bit 1: file is Hidden
- Bit 2: file is a System file
- Bit 3: file is a Volume name
- Bit 4: file is a Directory
- Bit 5: file is Modified
- These are the values returned by the system call FilStatusGet
- (Fn $87 Sub $08)
-
- eg. To test for a directory
-
- LOCAL x%,path$(128)
-
- x%=Fparse%:(ADDR(path$),"LOC::M:/APP/TEST")
- IF x%<0
- IF x%=-33
- PRINT "Directory doesn't exist"
- ELSE
- PRINT ERR$(x%)
- ENDIF
- ELSEIF x% AND 16
- PRINT "Found directory"
- ELSE
- PRINT "Isn't a directory"
- ENDIF
-
- -------------------------------------------------------------------
-
- (b) ret%=fprint%:(string$) Handle output redirection
-
- This procedure should be used to make use of output redirection.
- Depending on internal variables it either prints the string to the
- screen or to the file specified on the command line.
-
- -------------------------------------------------------------------
-
- (c) s$=err$:(n%) Enhanced err$ function
-
- Returns error string as ERR$ except for these values for n%:
-
- -127 "Wildcards not allowed"
- -111 "Argument overflow"
- -33 "No such file or directory"
- 1 "Not a directory"
- 2 "Must be a directory"
- 3 "Not a plain file"
- 4 "No match"
- 5 "Redirection isn't the penultimate argument"
- 6 "No such variable"
- 7 "Missing '"
- 8 "Bad ${..}"
- 8 "Not in autoexec.bat"
-
- -------------------------------------------------------------------
-
- (d) log:(flag%,message$) Display a message in the status window
-
- Display message$ modified by flag% as follows:
-
- Bit 0: set to create the window
- Bit 1: set to destroy the window
- Bit 2: set to display message$ on a new line
- Bit 3: set to display message$ in bold
- Bit 4: set to display message$
- Bit 5: set to use message$ as the title
-