In this section a complete example is described. The language name is set to USER, and it is highly recommended to use the same normalization conventions for the subroutine names. The example takes advantage of the multi-language capabilities of the SIC monitor by making also the GreG system available in addition to the user's commands. The extra code involved is marked by the flag !!GREG!! and can be removed without affecting the user commands.
The list of routines described here is, in current order :
USER The main program
LOAD_USER The initialization routine (#)
EXEC_USER To enter Execute Mode. Execute a single
SIC/USER valid command (may be a call to a
procedure) and returns (#).
Switches to Read Mode on an error condition
(Interactive session only) or if a PAUSE
is encountered. Switches back to Execute Mode
with CONTINUE or EXIT.
PLAY_USER To enter Read Mode with a SIC/USER valid
command passed as the first thing to do (#)
ENTER_USER To enter Read Mode (#). Reads commands on the
logical unit 5. Error recovery is provided for
interactive sessions only.
RUN_USER Dispatching program to execute the user commands
COM1 Example of interface between a "simple"
Fortran subroutine and a SIC command.
US_EXEC Interface routine for the Library Version
US_ERROR idem.
(#) The inclusion of the extra code flagged as !!GREG!! gives
also access to the command of GREG in the three routines EXEC_USER
PLAY_USER and ENTER_USER.
In addition, the ``true'' library mode is accessible by calling US_EXEC, which is described completely in Section 2.6. This is a
complete example which really contains all the relevant structure. The
rules for building conventional names are quite obvious.
The following source program available in VMS GAG_UTIL:SICUSER.FOR, and UNIX $GAG_REF/help/sic/sicuser.f)
PROGRAM USER
INTEGER ICODE,SIC_GET_FOREIGN,LENC,L,NL,SIC_PURGE
CHARACTER*80 FILE,COMMAND,CHAIN,NAME*12
CHARACTER BACKSLASH*1
LOGICAL EXIST
*
* Optionally, get the Foreign argument.
ICODE = SIC_GET_FOREIGN(COMMAND,NL)
IF (MOD(ICODE,2).EQ.0) CALL SYSEXI(ICODE)
* Build the names of the log file.
NAME = 'user'
CALL SIC_PARSEF (NAME,FILE,'GAG_LOG:','.log')
* Purge older versions of the log file
ICODE = SIC_PURGE (FILE,1)
IF (MOD(ICODE,2).EQ.0) CALL SYSEXI(ICODE)
*
* Initialize the command monitor with a nice Prompt, and stack capability
NAME = 'USER'
CALL SIC_OPT(NAME,FILE,.TRUE.)
* Then load all languages
CALL LOAD_USER
* Demonstration of multi-language capabilities
CALL LOAD_GREG('LIBRARY') !!GREG!!
* Define a default macro extension
CHAIN = 'SIC'//BACKSLASH//'SIC EXTENSION .user'
* Execute the "login" macro
NAME = 'init'
CALL SIC_PARSEF (NAME,FILE,'GAG_INIT:','.user')
L = LENC(FILE)
INQUIRE (FILE=FILE(1:L),EXIST=EXIST)
IF (EXIST) THEN
CHAIN = '@ ``!'//FILE(1:L)//''''
CALL EXEC_USER (CHAIN)
ENDIF
* Activate the monitor
IF (NL.NE.0) THEN
* First executing the foreign argument if available
CALL PLAY_USER(COMMAND(1:NL))
ELSE
* Or not
CALL ENTER_USER
ENDIF
END
SUBROUTINE LOAD_USER
INTEGER MCOM
PARAMETER (MCOM=3)
CHARACTER*12 VOCAB(MCOM)
DATA VOCAB / ' COM1' , '/GAG' , ' COM2' /
CALL SIC_LOAD('USER','GAG_HELP:sicuser.hlp',MCOM,VOCAB,
& '4.0 24-AUG-1984')
END
The example shows how to retrieve a first command from the operating system
at run time (SIC_GET_FOREIGN), how to define a default macro
extension, and how to execute the user initialization macro if
it exists.
Two types of complete calls to the SIC/USER system are demonstrated.
SUBROUTINE EXEC_USER(BUFFER)
LOGICAL ERROR
CHARACTER*(*) BUFFER
CHARACTER LINE*256, COMM*12, LANG*12
INTEGER ICODE,OCODE
*
LINE = BUFFER
ICODE = -1
GOTO 10
*
ENTRY PLAY_USER(BUFFER)
LINE = BUFFER
ICODE = 2
GOTO 10
*
ENTRY ENTER_USER
ICODE = 1
GOTO 10
*
* Call the monitor again after completion of every user command.
10 CALL SIC_RUN (LINE,LANG,COMM,ERROR,ICODE,OCODE)
IF (OCODE.EQ.0) THEN
IF (LANG.EQ.'USER') THEN
CALL RUN_USER (LINE,COMM,ERROR)
ELSEIF (LANG.EQ.'GREG1') THEN !!GREG!!
CALL RUN_GREG1 (LINE,COMM,ERROR) !!GREG!!
ELSEIF (LANG.EQ.'GREG2') THEN !!GREG!!
CALL RUN_GREG2 (LINE,COMM,ERROR) !!GREG!!
ELSEIF (LANG.EQ.'GTVL') THEN !!GREG!!
CALL RUN_GTVL (LINE,COMM,ERROR) !!GREG!!
IF (COMM.EQ.'CLEAR') CALL GRESET !!GREG!!
ELSE
WRITE(6,*) 'Unrecognized Language ',LANG
ERROR = .TRUE.
ENDIF
ELSEIF (OCODE.EQ.-1) THEN
* Must return immediately from the Execute Mode,
RETURN
ELSEIF (OCODE.EQ.1) THEN
* Any other code may be added before returning to the main program
RETURN
ENDIF
ICODE = 0
GOTO 10
END
In the Execute Mode, all SIC capabilities are enabled. A more
restrictive Library Mode, in which only the command line
interpretor of SIC is used will be shown in Section 2.6
SUBROUTINE RUN_USER(LINE,COMM,ERROR)
CHARACTER*(*) LINE,COMM
LOGICAL ERROR
*
* Call appropriate subroutine according to COMM
IF (COMM.EQ.'COM1') THEN
CALL COM1(LINE,ERROR)
ELSEIF (COMM.EQ.'COM2') THEN
WRITE (6,*) 'Command COM2 activated'
* CALL COM2(LINE,ERROR)
ENDIF
END
SUBROUTINE COM1(LINE,ERROR)
CHARACTER*(*) LINE
LOGICAL ERROR
LOGICAL SIC_PRESENT
INTEGER IARG1_OPT1
REAL ARG1
*
* Test presence of option 1, and if so
* Decode Argument 1 of this option with a default value
IF (SIC_PRESENT(1,0)) THEN
IARG1_OPT1 = 10
CALL SIC_I4 (LINE,1,1,IARG1_OPT1,.FALSE.,ERROR)
IF (ERROR) RETURN
WRITE (6,*) 'Option 1 Set With Argument',IARG1_OPT1
ENDIF
*
* Retrieves and decode first argument of the command
CALL SIC_R4 (LINE,0,1,ARG1,.TRUE.,ERROR)
IF (ERROR) RETURN
WRITE (6,*) 'Command COM1 activated. ARG1',ARG1
* End of interface analysis, call a standard FORTRAN routine with
* all parameters now defined
* CALL SUB1(ARG1,ARG2,...,IARG1,...,ERROR)
RETURN
END
As in this example, it is HIGHLY RECOMMENDED to pass the command
buffer LINE by argument and NOT IN A COMMON. This will allow later an
easy implementation of a multi-language program if necessary, and the
possibility of sharing languages with other users. Use of
commons may break these possibilities. It is also recommended to have an
``interface'' routine for each command which takes all the decoding
functions. However, for very simple commands, this may not be necessary
and the interface may be in the RUN_USER routine.