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') ENDThe 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 ENDIn 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 ENDAs 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.