// Files.bcpl - derived from Files.bcpl (Press) 2/7/83 // errors 400 // //Disk i/o for PD printer // //A "file" is described by a structure. Files must be initialized by the // user, as the structure contains data required from a directory // (see PressInit for initialization) // // //FileStuff(file,dp) // Returns in dp (double precision) the file size, in words. // Returns as value the page size. // //FileVDA(file,page) // Returns virtual disk address of the given page of the file. // //FileChangeType(file,filetype) // Changes file type // //FileReadPage(file,page,coreaddress[,cnt[,lvdoneflag]]) // Reads a number of pages from the file. "Page" starts numbering // at 0. Cnt is the number of pages to read; default 1. // Lvdoneflag, if provided, means that the routine is not to wait until // the transfer is complete, but should return immediately, and set // @lvdoneflag=true when the transfer completes. // //FileWritePage(file,page,coreaddress[,cnt[,lvdoneflag]]) // Similar, but for writing pages. // //A note about how "files" on the Model 31 are represented: // Since every file that PRESS printing deals with is an integral number // of pages long, we conform to the operating system conventions for such // files. That is: // -- a leader page // -- n useful pages // -- a final page with the "number of chars" =0 // The table of disk addresses recorded in the F structure is for // all three kinds. Hence there are +1's in various places. get "PDInternals.d" get "AltoFileSys.d" get "Disks.d" get "IfsIsf.d" // outgoing procedures external [ FileReadPage FileWritePage FileStuff FileChangeType FileVDA ] // outgoing statics //external // [ // ] //static // [ // ] // incoming procedures external [ //METER MeterBlock //PDPRINT DblShift PDError //BFS for Model 31 ActOnDiskPages //IfsIsf LookupFmap ] // incoming statics external [ sysDisk tridentVec ] // internal statics //static // [ // ] // File-wide structure and manifest declarations. // Procedures let FileStuff(file,length; numargs n)=valof [ if n ne 1 then [ length!0=0 length!1=file>>F.Pagecnt DblShift(length,-file>>F.LogPagesize) ] resultis file>>F.Pagesize ] and FileChangeType(file,type) be [ file>>F.Type=type ] //---------------------------------------------------------------------------- and FileVDA(file, page) = valof //---------------------------------------------------------------------------- [ let pageCount = nil; test file>>F.Name eq FILEBits ifnot pageCount = file>>F.Pagecnt; ifso [ let device = file>>F.Device; let disk = (device ge DISKT80? tridentVec!(device - 2), sysDisk); if disk eq 0 then PDError(401); pageCount = file>>F.Pagecnt lshift (10 - disk>>DSK.lnPageSize); ] if page ge pageCount then PDError(403, file>>F.Name); let fda = file>>F.DAFirst; if fda then resultis fda + page; let fmap = lv file>>F.fmap; fmap>>FM.fmap = fmap; // assure that fmap is current resultis LookupFmap(fmap, page + 1); ] and FileReadPage(file,page,coreaddress,cnt,lvdoneflag;numargs n) be [ if file>>F.Type eq FILEWO then return //No need to read FileDoPage(file,page,coreaddress,cnt,lvdoneflag,n,DCreadD) ] and FileWritePage(file,page,coreaddress,cnt,lvdoneflag;numargs n) be [ if file>>F.Type eq FILERO then PDError(400) FileDoPage(file,page,coreaddress,cnt,lvdoneflag,n,DCwriteD) ] and FileDoPage(file,page,coreaddress,cnt,lvdoneflag,n,how) be [ if n ls 4 then cnt=1 let flg=nil if n ls 5 then lvdoneflag=lv flg compileif MeterSw then [ let b=vec (size FLStat/16) b>>FLStat.File=file>>F.Name b>>FLStat.Cnt=cnt b>>FLStat.Page=page MeterBlock( ((how eq DCreadD)? METERRead,METERWrite), b,size FLStat/16) ] let dev=file>>F.Device let disk=(dev ge DISKT80)? (tridentVec!(dev-2)), sysDisk if dev eq DISK31B then sysDisk>>DSK.driveNumber=1 if disk eq 0 then PDError(401) //Check last page within bounds on file. let pageSize=file>>F.Pagesize let pageCnt=file>>F.Pagecnt if dev ls DISKT80 & pageSize eq 1024 then [ //Simulating 1024-word pages on Model 31 page=page*4 cnt=cnt*4 pageSize=256 pageCnt=pageCnt*4 ] //Prepare CA vector just for those pages transferred if cnt gr 50 then PDError(402) let CAs=vec 50 for i=0 to cnt-1 do [ CAs!i=coreaddress coreaddress=coreaddress+pageSize ] //Prepare DAs vector just for those pages transferred let seqDAs = vec 50; seqDAs!0 = FileVDA(file, page); for i = 1 to cnt - 1 do seqDAs!i = fillInDA; let DAs = seqDAs - page - 1; page=page+1 let lastpage=page+cnt-1 if lastpage gr pageCnt then [ PDError(403, file>>F.Name) lastpage=pageCnt ] ActOnDiskPages(disk,CAs-page,DAs,lv file>>F.fp,page, lastpage,how, 0, 0, 0, 0, lv FileError) @lvdoneflag=true sysDisk>>DSK.driveNumber=0 //Return sysDisk to original condition ] and FileError(a, b, c) be [ sysDisk>>DSK.driveNumber=0 //Return sysDisk to original condition PDError(404) ]