!+ ! NAME ! scan_cms_command -- scans CMS command line to see if NODE ! information needs to be passed to server ! ! DESCRIPTION ! This SCAN module determines whether a /INPUT or /OUTPUT ! qualifier has been used (or is needed) on a CMS command. ! If so, it then could potentially alter the qualifier so that ! I/O goes to the users default directory on the CLIENT node. ! ! The altered command gets sent back to the C calling routine. ! ! This routine gets called for partial commands also and is patient ! enough to figure out /INs and /OUTs across partial commands. ! ! RETURN VALUE ! ! HISTORY ! 7-18-88 Bauer Initial version. ! !- MODULE RCMS$SCAN_CMS_COMMAND IDENT 'V1.0'; ! ! Set definitions ! SET digit ( '0' .. '9' ); SET alpha ( 'a'.. 'z' OR 'A'..'Z' OR '_' OR '$'); SET alpha_num ( alpha OR digit ); SET white_space ( ' ' OR S'ht' ); SET id_start ( alpha OR digit OR '_' OR '$' ); SET id_part ( alpha OR digit OR '_' OR '$' ); ! ! Token Definitions ! TOKEN blanks IGNORE { white_space [white_space ...] }; TOKEN help_T CASELESS { {'HE' | 'HEL' | 'HELP' } }; TOKEN show_T CASELESS { {'SH' | 'SHO' | 'SHOW' } }; TOKEN fetch_T CASELESS { {'FE' | 'FET' | 'FETC' | 'FETCH'} }; TOKEN create_T CASELESS { {'CR' | 'CRE' | 'CREA' | 'CREAT' | 'CREATE' } }; TOKEN element_T CASELESS { {'EL' | 'ELE' | 'ELEM' | 'ELEME' | 'ELEMEN' | 'ELEMENT' } }; TOKEN delete_T CASELESS { {'DE' | 'DEL' | 'DELE' | 'DELET' | 'DELETE' } }; TOKEN group_T CASELESS { {'GR' | 'GRO' | 'GROU' | 'GROUP' } }; TOKEN class_T CASELESS { {'CL' | 'CLA' | 'CLAS' | 'CLASS' } }; TOKEN gen_T CASELESS { {'GEN' | 'GENE' | 'GENER' | 'GENERA' | 'GENERAT' | 'GENERATI' | 'GENERATIO' | 'GENERATION'} }; TOKEN version_T CASELESS { {'VER' | 'VERS' | 'VERSI' | 'VERSIO' | 'VERSION' } }; TOKEN replace_T CASELESS { {'REP' | 'REPL' | 'REPLA' | 'REPLAC' | 'REPLACE' } }; TOKEN library_T CASELESS { {'LI' | 'LIB' | 'LIBR' | 'LIBRA' | 'LIBRAR' | 'LIBRARY' } }; TOKEN reserve_T CASELESS { {'RES' | 'RESE' | 'RESER' | 'RESERV' | 'RESERVE' | 'RESERVA' | 'RESERVAT' | 'RESERVATI' | 'RESERVATIO' | 'RESERVATION' | 'RESERVATIONS' } }; TOKEN diff_T CASELESS { {'DI' | 'DIF' | 'DIFF' | 'DIFFE' | 'DIFFER' | 'DIFFERE' | 'DIFFEREN' | 'DIFFERENC' | 'DIFFERENCE' | 'DIFFERENCES' } }; TOKEN annotate_T CASELESS { {'AN' | 'ANN' | 'ANNO' | 'ANNOT' | 'ANNOTA' | 'ANNOTAT' | 'ANNOTATE' } }; TOKEN history_T CASELESS { {'HI' | 'HIS' | 'HIST' | 'HISTO' | 'HISTOR' | 'HISTORY' } }; TOKEN slash_output_T CASELESS { {'/OU' | '/OUT' | '/OUTP' | '/OUTPU' | '/OUTPUT' } }; TOKEN slash_input_T CASELESS { {'/IN' | '/INP' | '/INPU' | '/INPUT' } }; TOKEN identifier CASELESS { 'TT:' | 'SYS$OUTPUT:' | { id_start [id_part ...] } }; TOKEN semi_colon ALIAS ';' { ';' }; TOKEN lbracket ALIAS '[' { '[' }; TOKEN rbracket ALIAS ']' { ']' }; TOKEN quote ALIAS '"' { '"' }; TOKEN dot ALIAS '.' { '.' }; TOKEN equals ALIAS '=' { '=' }; TOKEN colon { ':' }; TOKEN colon_colon { '::' }; ! ! Global Variables ! DECLARE output_needed : GLOBAL INTEGER; DECLARE input_needed : GLOBAL INTEGER; DECLARE slash_output_given : GLOBAL INTEGER; DECLARE slash_input_given : GLOBAL INTEGER; DECLARE current_directory_D : STRING; DECLARE node_D : STRING; DECLARE current_command : STRING; DECLARE slash_output_string : STRING; DECLARE slash_input_string : STRING; DECLARE node_name : STRING; DECLARE disk_name : STRING; DECLARE directory_name : STRING; DECLARE file_name : STRING; DECLARE help_flag : GLOBAL INTEGER; DECLARE partial_flag : GLOBAL BOOLEAN; DECLARE show_time : GLOBAL BOOLEAN; !+ ! MACRO Definitions follow for MACROS: ! !- MACRO node_name_M SYNTAX { node1: { identifier colon_colon } | node2: { identifier quote identifier identifier quote colon_colon } }; IF node1 <> '' THEN node_name = node1; ELSE node_name = node2; END IF; END MACRO; MACRO disk_spec_M SYNTAX { save_disk: { identifier colon } }; disk_name = UPPER(save_disk); END MACRO; MACRO dir_spec_M SYNTAX { save_dir: { '[' FIND ( ']' ) ']' } }; directory_name = directory_name & save_dir; END MACRO; MACRO file_spec_M SYNTAX { save_file: { [ identifier ] [ '.' [ identifier [ ';' [ identifier ] ] ] ] } }; file_name = save_file; END MACRO; MACRO help_me_please_M TRIGGER { help_T }; help_flag = 1; END MACRO; MACRO show_identifier_M SYNTAX { text: { element_T | history_T | class_T | gen_T | group_T | library_T | reserve_T | version_T } }; ANSWER text; END MACRO; MACRO output_needed_M TRIGGER { save_command: { fetch_T | { delete_T history_T } | { show_T show_identifier_M } | diff_T | annotate_T | reserve_T } }; output_needed = 1; current_command = save_command; ANSWER save_command; IF save_command[1..2] = 'SH' THEN slash_output_given = 1; slash_output_string = '/OUTPUT=SYS$OUTPUT'; show_time = TRUE; END IF; END MACRO; MACRO partial_M TRIGGER { save_command : { create_T | delete_T | show_T } }; IF save_command[1..2] = 'SH' THEN show_time = TRUE; END IF; partial_flag = TRUE; ANSWER save_command; END MACRO; MACRO complete_partial_M TRIGGER { save_command: { show_identifier_M } }; IF partial_flag THEN current_command = save_command; save_command = UPPER (save_command); IF show_time THEN output_needed = 1; slash_output_given = 1; save_command = save_command & '/OUTPUT=SYS$OUTPUT'; ELSE IF save_command[1..2] = 'EL' THEN input_needed = 1; ELSE output_needed = 1; END IF; END IF; END IF; ANSWER save_command; END MACRO; MACRO input_needed_M TRIGGER { save_command: { { create_T element_T } | replace_T } }; input_needed = 1; current_command = save_command; ANSWER save_command; END MACRO; MACRO slash_o_M TRIGGER { save_slash: slash_output_T equals_given: { [ '=' [ node_name_M ] [ disk_spec_M ] [ dir_spec_M ... ] [ file_spec_M ] ] } }; slash_output_given = 1; IF equals_given = '' AND show_time THEN file_name = 'SYS$OUTPUT'; END IF; IF file_name <> 'SYS$OUTPUT' AND file_name <> 'TT:' AND file_name <> 'SYS$OUTPUT:' THEN IF node_name = '' THEN node_name = node_D; END IF; IF disk_name = '' AND directory_name = '' THEN disk_name = current_directory_D; END IF; slash_output_string = save_slash & '=' & node_name & disk_name & directory_name & file_name; ELSE slash_output_string = '/OUTPUT=SYS$OUTPUT'; END IF; ANSWER slash_output_string; END MACRO; MACRO slash_i_M TRIGGER { save_slash: slash_input_T [ '=' [ node_name_M ] [ disk_spec_M ] [ dir_spec_M ... ] [ file_spec_M ] ] }; slash_input_given = 1; IF node_name = '' THEN node_name = node_D; END IF; IF disk_name = '' AND directory_name = '' THEN disk_name = current_directory_D; END IF; slash_input_string = save_slash & '=' & node_name & disk_name & directory_name & file_name; ANSWER slash_input_string; END MACRO; ! ! PROCEDURES Follow ! PROCEDURE scan_cms_command ( tcommand : STRING, tcommand_length : INTEGER, new_command_flag : VALUE INTEGER, cur_node_D : STRING, cur_dir_D : STRING ); DECLARE trash_bin : STRING; DECLARE all_blanks : BOOLEAN; DECLARE i,save_position : INTEGER; DECLARE command : STRING; EXTERNAL PROCEDURE send_back_new_command (STRING, VALUE INTEGER); EXTERNAL PROCEDURE send_back_new_parameter (STRING, VALUE INTEGER); node_D = cur_node_D; current_directory_D = cur_dir_D; slash_output_string = '/OUTPUT=' & node_D & current_directory_D; slash_input_string = '/INPUT=' & node_D & current_directory_D; current_command = ''; IF new_command_flag = 1 THEN partial_flag = FALSE; show_time = FALSE; help_flag = 0; node_name = ''; disk_name = ''; directory_name = ''; file_name = ''; slash_output_given = 0; slash_input_given = 0; output_needed = 0; input_needed = 0; END IF; tcommand = UPPER(tcommand); IF help_flag = 0 THEN START SCAN INPUT STRING tcommand OUTPUT STRING trash_bin; END IF; command = tcommand & ' '; ! write 'Tcommand = ', tcommand; ! write 'Trash bin = ', trash_bin; ! write 'Current command = "',current_command,'"'; ! write 'Command is "',command,'"'; IF current_command <> '' THEN IF output_needed = 1 AND slash_output_given = 0 THEN save_position = INDEX (command, current_command) + LENGTH(current_command)-1; trash_bin = command[1..save_position] & slash_output_string & ' ' & command[save_position+1 ..]; command = trash_bin; END IF; IF input_needed = 1 AND slash_input_given = 0 THEN save_position = INDEX (command, current_command) + LENGTH(current_command)-1; trash_bin = command[1..save_position] & slash_input_string & ' ' & command[save_position+1 ..]; END IF; command = trash_bin; END IF; all_blanks = TRUE; save_position = LENGTH(command); FOR i = save_position TO 1 STEP -1; IF command[i..i] <> ' ' THEN all_blanks = FALSE; save_position = i; i = 1; END IF; END FOR; IF all_blanks THEN command = ''; ELSE command = command[1..save_position]; END IF; ! write 'Command is "',command,'"'; IF help_flag = 0 THEN IF new_command_flag = 1 THEN CALL send_back_new_command (command, LENGTH (command)); ELSE CALL send_back_new_parameter (command, LENGTH (command)); END IF; ELSE IF new_command_flag = 1 THEN CALL send_back_new_command (tcommand, LENGTH (tcommand)); ELSE CALL send_back_new_parameter (tcommand, LENGTH (tcommand)); END IF; END IF; END PROCEDURE; END MODULE;