$pascal '92071-1X291 REV.2041 800811'$ $heap 0$ $segment$ PROGRAM PFS3; { * *NAME: PFS3 *SOURCE: 92071-18291 *RELOC: 92071-16291 *PGMR: DAVE NEFF * **************************************************************** * (C) COPYRIGHT HEWLETT-PACKARD COMPANY, 1980. ALL RIGHTS * * RESERVED. NO PART OF THIS PROGRAM MAY BE PHOTOCOPIED, * * REPRODUCED OR TRANSLATED TO ANOTHER PROGRAM LANGUAGE WITHOUT * * THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY. * **************************************************************** } {PFS3 contains the routines which modify the last RP command, as well as a few other commands which I expect to be used infrequently. This segment should only have to be loaded occasionally, and often never. Each routine in PFS3 which is externaled in the main program could readily be moved to some other segment if desired.} {Read in the global constants, variables and types.} $include '&PFGBL'$ {Declaration of FMP routines.} PROCEDURE purge(VAR idcb:dcb; VAR ierr:integer; VAR name:string6; VAR isecu,icrn:integer);external; PROCEDURE fmp_close $ALIAS 'CLOSE'$(VAR idcb:dcb);external; PROCEDURE readf(VAR idcb:dcb; VAR ierr:integer; VAR ibuff:buffer; ilen:integer; VAR len,num:integer);external; PROCEDURE writf(VAR idcb:dcb; VAR ierr:integer; VAR ibuff:buffer; ilen,rec_num:integer);external; {This is an exec abort call, used when handle_error is trapped.} PROCEDURE exec(ecode,place_holder:integer);external; {PFORM calls prtn to return the exit path to the calling program.} PROCEDURE prtn(prams:prtn_prams);external; {Non FMP externals contained in the main program are next.} PROCEDURE namr(VAR buffer:namr_parse_buffer; VAR iline:input_line; length:integer; VAR istrc:integer);external; PROCEDURE error(message:input_line);external; PROCEDURE writline(line:input_line);external; FUNCTION getword(address:integer; VAR idcb:dcb; VAR ibuff:buffer; VAR name:string6; VAR curr_rec:integer):integer; external; PROCEDURE putword(word,address:integer; VAR idcb:dcb; VAR ibuff:buffer; VAR name:string6; VAR curr_rec:integer;post:boolean); external; PROCEDURE fmp_error(VAR ierr:integer; VAR name:string6);external; {handle_error handles certain forms of PASCAL errors, such as a from a terminal causing a program abortion.} {This routine is used, rather than the standard run time error package for two reasons. First of all, it is smaller and is in a segment. Second, this routine makes errors look like normal PFORM error messages, rather than PASCAL errors.} { err_type: Describes the class of the error message. err_number: Some classes of errors have an associated number, passed in this paramater. err_line: Some classes of errors occur at a specific source line, and its number is passed here. err_file: Some errors pass the PASCAL file name identifier as a paramater (i.e. fmp). Note that this paramater contains the internal (i.e. variable name) representation of the file name, not its actual external representation (i.e. namr). err_flen: Number of significant characters in the string err_file.} PROCEDURE handle_error (err_type: error_type; err_number, err_line: integer; VAR err_file: input_line; err_flen:integer); LABEL 99; CONST runtime='PASCAL RUNTIME #'; at_line=' AT LINE '; segl='SEGMENT LOAD FAILURE IN '; io_error='PASCAL IO #'; VAR error_file:string6; {The name of the file in error.} i:integer; BEGIN IF err_type=warn THEN goto 99; {The file name is not always good. Try to detect this case and prevent garbage from being displayed.} IF err_flen=0 THEN error_file.file_name:=' ' ELSE FOR i:= 1 TO 6 DO error_file.file_name[i]:=err_file[i]; {Convert the file name from the internal representation (ifile or ofile) to its external name the user sees.} IF error_file.file_name='IFILE ' THEN error_file:=input_file ELSE IF error_file.file_name='OFILE ' THEN error_file:=output_file; {The error might be related to ifile or ofile. In this case, the attempt to write the error message could in turn result in another call to handle_error, which would then yield an infinite loop of errors. These next few lines do a pretty good job of preventing this problem, but the result is that these errors will only show up on the scheduling terminal.} close(ofile); close(ifile); {Do a rewrite to the terminal. All these errors will go there only.} rewrite(ofile,login_lu.file_name); {No longer can the echo feature be used properly.} echo_prompt:=false; CASE err_type OF fmp: fmp_error(err_number,error_file); seg: BEGIN {Output segment load error.} writeln(ofile,star_error,segl,error_file.file_name); END; io: BEGIN {These errors have their own code.} {Output the general case error message.} write(ofile,star_error,io_error,err_number:3); writeln(ofile,at_line,err_line:5); END; run: BEGIN {Runtime errors also have their own code.} write(ofile,star_error,runtime,err_number:3); writeln(ofile,at_line,err_line:5); END; END; {Case Statement.} {Abort the program with exec call. First give the abortion message.} writeln(ofile,pform_prompt.five_char,aborted); {Cleanup stray files.} IF made_sys_file THEN purge(sys_dcb,ierr,sys_file,sys_secu,sys_crn); IF made_prom_file THEN purge(prom_dcb,ierr,prom_file,prom_secu,prom_crn); {Close the snap.} fmp_close(snap_dcb); {Tell scheduling program the abort path was taken.} prtn('ABORTED '); {Exit with an exec call.} exec(6,0); 99: END;{handle_error} {cleanup_files is the last routine called by PFORM. It closes the PFORM system and snap file, and purges the modified system and last PROM image file if the run was aborted (/A).} PROCEDURE cleanup_files; $direct$ CONST bootable_file='BOOTABLE PROM IMAGE FILE IS: '; modified_system='MODIFIED SYSTEM IMAGE FILE IS: '; period='.'; BEGIN IF pform_ended THEN BEGIN {Set up the prtn return.} prtn('ENDED '); {Close the modified system file.} fmp_close(sys_dcb); {Output the messages.} IF made_sys_file THEN BEGIN writeln(ofile,pform_prompt.five_char,cmpleted); IF echo_prompt THEN writeln(ifile,pform_prompt.five_char, cmpleted); IF boot THEN BEGIN write(ofile,bootable_file); IF echo_prompt THEN write(ifile,bootable_file); END ELSE BEGIN {Give the user the name of the new system file.} write(ofile,modified_system); IF echo_prompt THEN write(ifile,modified_system); END; writeln(ofile,sys_file.file_name,period); IF echo_prompt THEN writeln(ifile,sys_file.file_name,period); END; END ELSE IF abort THEN BEGIN IF made_sys_file THEN purge(sys_dcb,ierr,sys_file,sys_secu,sys_crn); IF made_prom_file THEN purge(prom_dcb,ierr,prom_file,prom_secu, prom_crn); {Set up prtn return.} prtn('ABORTED '); {Output message.} writeln(ofile,pform_prompt.five_char,aborted); IF echo_prompt THEN writeln(ifile,pform_prompt.five_char,aborted); END; {Close the all currently open files.} fmp_close(snap_dcb); close(ifile); close(ofile); END; {cleanup_files} {ss_process changes the system security code to some new value.} PROCEDURE ss_process; $direct$ BEGIN namr(namr_buffer,inline,line_length,istrc); WITH namr_buffer DO IF NOT ((types.param1=numeric) OR (types.param1=ascii)) THEN error(bad_type) ELSE {Put the new code into the system.} putword(param1.int1,sec_addr,sys_dcb,sys_dcb.buff, sys_file,rec_in_sys_dcb,true); END; {ss_process} {st_process defines the startup program, and puts any RMPAR paramaters into its id. If some other program has previously been defined to be the start program, its RMPAR paramaters are cleared.} PROCEDURE st_process; $direct$ VAR post:boolean; {Tells putword to post to disk.} i:integer; {Loop index for changing rampar params.} BEGIN IF NOT good_rp THEN error(bad_command) ELSE BEGIN {Put the current id address at $BOOT.} putword(cur_id_addr,start_addr,sys_dcb,sys_dcb.buff, sys_file,rec_in_sys_dcb,true); post:=false; IF start_specified THEN {Zero out previous RMPAR paramaters.} FOR i:=1 TO 5 DO BEGIN IF i=5 THEN post:=true; putword(0,last_start_id_addr+i,sys_dcb,sys_dcb.buff, sys_file,rec_in_sys_dcb,post); END; start_specified:=true; last_start_id_addr:=cur_id_addr; {Now fill in the correct, new, RMPAR paramaters.} post:=false; FOR i:=1 TO 5 DO BEGIN namr(namr_buffer,inline,line_length,istrc); IF i=5 THEN post:=true; {Shove in ID regardless of type.} putword(namr_buffer.param1.int1,cur_id_addr+i,sys_dcb, sys_dcb.buff,sys_file,rec_in_sys_dcb,post); END; END; END; {st_process} {question_process handles the help (??) facility.} PROCEDURE question_process; $direct$ CONST msg1= ' Commands which are valid in the present context are as follows:'; msg2= ' SS,newcode Change the system security code to newcode.'; msg3= ' PT Display a partition table which describes the'; msg4= ' size, location, and occupant of all partitions.'; msg5= ' RP,prog,[newname] Construct an id segment for the program (using'; msg6= ' newname if specified), relink the program if'; msg7= ' necessary, and store the program in the PROM'; msg8= ' image file.'; msg9= ' LK,prog Relink and fix the short id segments of the'; msg10= ' program (type 6) file if necessary, and store'; msg11= ' the file onto the PROM image file. The program'; msg12= ' can only be executed if the destination system'; msg13= ' has a program containing IDRPL (i.e. FMGR).'; msg13a= ' FI[LE],namr Store the named file (libraries, data, etc.)'; msg13b= ' onto the PROM image file.'; msg14= ' /E End the PFORM process.'; msg15= ' /A Abort the PFORM process. The output file made'; msg16= ' by PFORM is purged.'; msg17= ' /C (also NEXT) Complete the formatting of the current PROM image'; msg18= ' file and continue formatting another file.'; msg19= ' The remaining commands modify the last stored program (if any).'; msg20= ' PR[IORITY],n The program is to be of priority n.'; msg21= ' SZ,nn Size of the program including system common (if'; msg22= ' used) in K words. When specified, this overrides'; msg23= ' the size as defined to the loader.'; msg24= 'The following command modifies the last RPed program (if any).'; msg25= ' ST[ART][,p1]..[,p5] The program is to be the startup program'; msg26= ' with the specified optional RMPAR paramaters.'; PROCEDURE skip_line; {Mearly skips a line to the files.} BEGIN writeln(ofile); IF echo_prompt THEN writeln(ifile); END; BEGIN {question_process} {Output the instructions.} writline(msg1); writline(msg2); writline(msg3); writline(msg4); writline(msg5); writline(msg6); writline(msg7); writline(msg8); writline(msg9); writline(msg10); writline(msg11); writline(msg12); writline(msg13); writline(msg13a); writline(msg13b); writline(msg14); writline(msg15); writline(msg16); writline(msg17); writline(msg18); {Skip a line for cosmetic reasons.} skip_line; writline(msg19); writline(msg20); writline(msg21); writline(msg22); writline(msg23); skip_line; writline(msg24); writline(msg25); writline(msg26); END; {question_process} {pt_process handles the PT command. It outputs the sizes and occupants (if original system was a BUILD output system) of each partition.} PROCEDURE pt_process;$direct$ LABEL 99; CONST header= 'PRTN NUM LOW PAGE LENGTH OCCUPANT'; none=''; unmapped='Unmapped systems have no partition tables.'; none_defined='No partitions have been defined so far.'; VAR cur_mat_addr, {Address of current MAT being scanned.} id_addr_for_mat, {The id segment address contained in the current MAT being scanned.} length, {Length of current partition.} low_page, {Starting page number of current partition.} mat_number:integer; {Current mat number being scanned.} occupant:string6; {Name of occupant of partition.} BEGIN IF NOT mapped_system THEN BEGIN writline(unmapped); goto 99; END; IF matv_num<=0 THEN BEGIN writline(none_defined); goto 99; END; {Output the header.} writline(header); {Initialize the loop starting values.} mat_number:=0; WHILE (mat_numbernumeric THEN BEGIN {An integer was not passed, give bad param type error.} error(bad_type); goto 99; END ELSE IF (new_size>32) OR (new_size<1) THEN BEGIN {Paramater is out of range.} error(bad_range); goto 99; END ELSE IF (new_sizemax_partition_size) THEN BEGIN error(none_big_enough); goto 99; END ELSE BEGIN IF rp_true_lk_false THEN BEGIN {The last program related command was rp, so fix the in memory id.} old_id_field.int:=getword(cur_id_addr+24,sys_dcb, sys_dcb.buff,sys_file,rec_in_sys_dcb); old_id_field.size_less_1:=new_size-1; putword(old_id_field.int,cur_id_addr+24,sys_dcb, sys_dcb.buff,sys_file,rec_in_sys_dcb,true); {If done_with_rp is true, there is no type six file header to modify. Hence exit.} IF done_with_rp THEN goto 99; END; {Fix up the header record of the program to reflect the changed size.} readf(prom_dcb,ierr,prom_dcb.buff,recd_len,irec, first_prog_rec); {No errors should occur here except for disc errors.} IF ierr<0 THEN BEGIN fmp_error(ierr,prom_file); goto 99; END; prom_dcb.id.l20.size_less_1:=new_size-1; {Repair the checksum.} WITH prom_dcb.l20_long_id DO BEGIN ext.idseg_checksum:=0; FOR i:=1 TO 35 DO ext.idseg_checksum:=ext.idseg_checksum+ints[i]; END; {With} {Put the fixed header back on the prom image.} writf(prom_dcb,ierr,prom_dcb.buff,irec,first_prog_rec); IF ierr<0 THEN fmp_error(ierr,prom_file); END; END; END; 99: END; {sz_process} {pr_process changes a programs priority in its header, as well as its ID (if stored with RP).} PROCEDURE pr_process; $direct$ LABEL 99; VAR i:integer; {Loop index for repairing the checksum.} BEGIN IF NOT (good_rp OR good_lk) THEN error(bad_command) ELSE BEGIN {Pick up the new priority.} namr(namr_buffer,inline,line_length,istrc); IF namr_buffer.types.param1<>numeric THEN error(bad_type) ELSE IF namr_buffer.param1.int1<1 THEN error(bad_range) {Note that the priority field is in the same location of the ids for both mapped and unmapped system.} ELSE IF rp_true_lk_false THEN {Last program was stored via RP, so fix its ID.} putword(namr_buffer.param1.int1,cur_id_addr+6, sys_dcb,sys_dcb.buff,sys_file,rec_in_sys_dcb,true); {Fix up the in header on the prom.} readf(prom_dcb,ierr,prom_dcb.buff,recd_len,irec, first_prog_rec); IF ierr<0 THEN BEGIN fmp_error(ierr,prom_file); goto 99; END; prom_dcb.buff[7]:=namr_buffer.param1.int1; {Fix the checsums.} IF mapped_system THEN BEGIN prom_dcb.buff[32]:=0; FOR i:=1 TO 31 DO prom_dcb.buff[32]:=prom_dcb.buff[i]+prom_dcb.buff[32]; END ELSE BEGIN prom_dcb.buff[36]:=0; FOR i:=1 TO 35 DO prom_dcb.buff[36]:=prom_dcb.buff[i]+prom_dcb.buff[36]; END; writf(prom_dcb,ierr,prom_dcb.buff,recd_len,first_prog_rec); IF ierr<0 THEN fmp_error(ierr,prom_file); END; 99: END;.{pr_process,PFS3}