home *** CD-ROM | disk | FTP | other *** search
/ ftp.robelle3000.ai 2014 / 2014.06.ftp.robelle3000.ai.tar / ftp.robelle3000.ai / source / qaccess.spl
Text File  |  1998-10-08  |  58KB  |  2,101 lines

  1. << Qaccess/Qlib.  Routine to Read QEDIT file.  CM or NM >>
  2. $set x5 = on               ! ON = SPL/V Off = SPLASH
  3. $if x5=off or xsplash      ! SPL/V ignores the "OR XSPLASH"
  4. $   set x5 = off           ! Not MPE/V, Yes SPLASH is here!
  5. $if
  6. $if x5=off     <<Splash>>
  7. $control native
  8. $if
  9. $if x5=off and x6=on      <<Splash Debugging>>
  10. $control debugpcal,stmt
  11. $if x5=off and x6=off     <<No Splash debugging>>
  12. $control nosubrnames
  13. $if
  14. $control subprogram,nolist,errors = 5,segment = qedit
  15. <<
  16. QeditAccess Intrinsic.
  17.  
  18.     programmer: Robert M. Green
  19.                 David J. Greer
  20.                 David Lo
  21.                 Robelle Consulting Ltd.
  22.                 Unit 201, 15399 - 102A Avenue
  23.                 Surrey, B.C.
  24.                 Canada   V3R 7K1
  25.                 (604) 582-1700
  26.  
  27.     Purpose:    Allows a user program to read and/or
  28.                 write QEDIT's special workfiles.
  29.  
  30.     Compiling and linking:  see Qaccess.qlibjob
  31.  
  32.     Changes:
  33.  
  34.  3.5  rmg Oct89  Convert to Native Mode.
  35.  3.6  jim Sep90  Don't rewind file if no records read when
  36.                  checking the language (fixes bug in Append function).
  37.                  Release space when closing new files on MPE XL.
  38.                  Added entry-point for current'version.
  39.  3.8  dlo Jul90  Added function 17: read'line.
  40.                  Can read variable length files again.
  41.  3.9  dlo Feb92  Fixed bug in function 17 reading cobol keep files.
  42.  4.0  dlo Apr92  Can handle message files (ref 4864)
  43.  4.1  dlo Mar93  Added function 18: explain
  44.  4.2  rmg May94  support jumbo files: new functions
  45.  4.3
  46.  4.2.01 djg Nov94  fixed bug in writing large files
  47.                    renamed version entry from qeditaccess.. to qaccess..
  48.  4.2.02  dlo Jun95  fixed bug in reading jumbo text files
  49.          dlo Sep95  fixed qacc/cm problem in reading jumbo files
  50.  4.4     dlo Jan97  check for filereclen>maxlinelen; define maxlinelen
  51.  4.5     dlo Feb98  fixed jumbo file reading missing half of last block
  52. >>
  53. begin ! source
  54.  
  55. $if x5=on
  56. define
  57.      addrtype = integer#
  58.     ,optiontype = option #
  59.     ;
  60. $if x5=off
  61. define
  62.      addrtype = double#
  63.     ,optiontype = option nocc,quick,#
  64.     ;
  65. $if
  66.  
  67. define current'version = qaccess'4'5#;
  68. equate rtn = 13;
  69. define
  70.    end'if   = end#  ,end'else = end#  ,end'while= end#
  71.   ,end'case = end#  ,end'do   = end#  ,end'proc = end#
  72.   ,end'subr = end#
  73.   ,p = move pbuf:=#
  74.   ,out = ,2;output'(*)#
  75.   ,allocate = begin tos := #, end'alloc = ;adds 0);end#
  76.   ,words'to = ;assemble(lra s-0;stor#
  77.   ,bytes'to = ;assemble(inca;lsr 1;lra s-0;lsl 1;stor#
  78.   ;
  79.  
  80. equate
  81.    min'blocks = 4
  82.   ;
  83.  
  84. intrinsic ascii, dascii, dbinary
  85.          ,fcheck, fclose, ferrmsg, fopen, fread, fwrite
  86.          ,printfileinfo, print, debug, quit, fpoint
  87.          ,fgetinfo, father, activate, xcontrap
  88.          ;
  89.  
  90. << Format of block zero of qedit workfile:
  91.  
  92.    0  First Linenumber  (double)
  93.    1
  94.    2  Number of blocks
  95.    3  Number of lines
  96.    4  First empty block
  97.    5  Flags
  98.    6  Internal language code (0=spl)
  99. >>
  100. $page "qeditaccess procedure"
  101. <<
  102.     This is a stand-alone procedure built into the qcopy program.
  103.     Users may install the procedure in an SL using the stream
  104.     provided in qcopy.job or they can lift the source code and
  105.     insert it in their own spl programs. See qcopy.doc for
  106.     complete documentation.
  107. >>
  108. procedure qeditaccess (function, workspace, argument);
  109.   integer array function;
  110.   array workspace, argument;
  111.   optionTYPE check 2;
  112. begin
  113.   entry qaccess; ! for pascal/robelle
  114.   entry current'version; ! a define used to determine the version#
  115.    <<WARNING:  This procedure uses the global definitions for
  116.                "end'" constructs.  If this procedure is moved to
  117.                another program, those defines must be moved as
  118.                well.
  119.    >>
  120.  
  121. !  jumbo file variables
  122.  
  123. equate    j'wl  = 512       !jumbo files
  124.          ,regular'wl = 256 !old files
  125.          ,u0'wi = 256      ! word index of qedit0 table in record 0
  126.          ,u0'di = 128      ! double index of qedit0
  127.          ,maxlinelen = 1000     ! regular jumbo files
  128. !         ,maxlinelen = 8172     ! longlines workfile
  129.          ;
  130. define  block'start = (if filejumbo then 4 else 1)#
  131.        ,block'size  = (if filejumbo then j'wl
  132.                             else regular'wl)#
  133.        ;
  134. !$if x5=on <<spl-cm>>
  135. !
  136. !logical pointer   jbuf;        ! allocate dynamically
  137. !double  pointer   d'jbuf = jbuf;
  138. !byte    pointer   jbuf'  = jbuf;
  139. !logical   jbuf'allocated := false
  140. !         ;
  141. !$if x5=off <<splash>>
  142. logical array     jbuf(0:j'wl); !lots of space in native mode   ;
  143. double  array     d'jbuf (*)= jbuf;
  144. byte    array     jbuf'(*)  = jbuf;
  145. logical   jbuf'allocated := true;
  146. !$if
  147.  
  148. define    u0'lang      = jbuf(u0'wi + 4)#
  149.          ,u0'num'lines = d'jbuf(u0'di+57)#
  150.          ,u0'data'len  = jbuf(u0'wi + 17)#
  151.          ;
  152.   << language code used by Qeditaccess >>
  153.   equate
  154.      no'lang   = 0
  155.     ,spl'lang  = 1
  156.     ,ftn'lang  = 2
  157.     ,cob'lang  = 3
  158.     ,rpg'lang  = 4
  159.     ,job'lang  = 5
  160.     ,text'lang = 6 << 256 bytes>>
  161.     ,pasc'lang = 7 <<new, treat like spl>>
  162.     ,cobx'lang = 8 <<cobolx, instead of cobol>>
  163.     ,data'lang = 9
  164.     ;
  165.  
  166.   equate  max'lang   = 9
  167.          ,max'func   = 32
  168.          ;
  169.   logical anysize'flag := false;
  170.   << Convert Qedit's internal'lang to Qaccess's filelang
  171.      rpg fix:  second last digit was 5.
  172.   >>
  173.   array langtable(0:max'lang)=pb:=1,2,3,4,8,5,4,6,7,9;
  174.  
  175.   << convert Qaccess's filelang to Qedit's internal'lang
  176.   >>
  177.   integer array int'lang(1:max'lang)=pb:=0,1,2,6,5,7,8,4,9;
  178.  
  179.   integer dummy;
  180.   integer internal'language; <<from filebuf(6), 0=spl, 1=ftn, etc. >>
  181.  
  182.   << rpg fix:  keylefttable and keylentable changed to be indexed by
  183.      internal'language instead of external filelang.
  184.   >>
  185.   array keylefttable(0:max'lang) = pb :=
  186.     false, false, true, true, true, false, false, false, false, false;
  187.  
  188.   array keylentable (0:max'lang) = pb :=
  189.     8,     8,     6,    5,    6,    0,     0,     0,     8,   0;
  190.  
  191.   logical foptions  <<bits 8:2=1 means variable length file>>
  192.                     <<bits 2:3=6 means message file>>
  193.          ,is'variable'len
  194.          ,is'message'file
  195.          ;
  196.   integer fcode;
  197.   integer integer'parm, wl'workspace:=270; <<old size>>
  198.  
  199. equate    type'keep        = 0         ! reading:
  200.          ,type'qedit       = 1
  201.          ,type'mpe         = 2
  202.          ,type'new'qedit   = 3         ! writing:
  203.          ,type'rep'mpe     = 4
  204.          ,type'app'mpe     = 5
  205.          ,type'rep'qedit   = 6
  206.          ,type'app'qedit   = 7
  207.  
  208.          ,type'writing     = 3
  209.  
  210.          ;
  211.   << define structure of the Workspace >>
  212.   array <<equivalences>>
  213.    filestatus       (*) = workspace
  214.   ,filenumber       (*) = workspace(1)
  215.   ,filetype         (*) = workspace(2)
  216.   ,filelang         (*) = workspace(3)
  217.   ,filereclen       (*) = workspace(4)
  218.   ;
  219.   double array
  220.    filesize         (*) = workspace(5)  !  open func results
  221.   ,filecurkey       (*) = filesize    ! read/write func, line# result
  222.   ;
  223.   array
  224.    fileblock'r      (*) = workspace(7) ! see fileblock'j
  225.   ,fileindex        (*) = workspace(8)
  226.   ,filecurlen       (*) = workspace(9) <<read>>
  227.   ,filenewblocks    (*) = workspace(9) <<write>>
  228.   ,fileleft         (*) = workspace(10)
  229.   ,filekeylen       (*) = workspace(11)
  230.  
  231.   ,filereadflags    (*) = workspace(12) ! Read flags, see below
  232.   ,fileprevblock    (*) = workspace(12) ! Write
  233.  
  234.   ,filenewlines     (*) = workspace(13) <<write>>
  235.   ,physbuf          (*) = workspace(14)
  236.   ;
  237. logical pointer
  238.    filebuf          := @physbuf  !adjust for jumbo files
  239.    ;
  240. double pointer
  241.    d'filebuf        = filebuf
  242.    ;
  243. byte array
  244.    physbuf'         (*) = workspace(14)
  245.    ;
  246.  
  247. define         ! read mode flags (not WRITE!)
  248.    fileserial           = filereadflags.(15:1)#
  249.   ,filejumbo            = filereadflags.(14:1)#
  250.   ,filefirstread        = filereadflags.(13:1)#
  251.   ,fileanysize          = filereadflags.(12:1)# !func 30 or 31
  252.   ,fileeof              = filereadflags.(11:1)#
  253.   ,fileblock'j          = filereadflags.(0:8)#
  254.   ;
  255.  
  256. ! local variables extracted from workspace (regular or jumbo fmt):
  257. double fileblock;  ! fileblock'r & fileblock'j
  258.    logical array fileblock0 (*) = fileblock
  259.                 ,fileblock1 (*) = fileblock0(1)
  260.                 ;
  261. <<
  262. Word   Contents  Meaning
  263. offset
  264. ------------------------------------------------------------
  265. 1      status    mpe error number of last operation
  266.                  or 0 if ok. end of file is indicated
  267.                  by a -1
  268.  
  269. 2      filenum   mpe filenumber returned by fopen
  270.                  can be used to call printfileinfo
  271.  
  272. 3      type      0 = /keep file,      1 = a qedit file,
  273.                  2 = other MPE,       3 = new Qedit write,
  274.                  4 = overwrite MPE,   5 = append MPE,
  275.                  6 = overwrite Qedit, 7 = append Qedit
  276.  
  277. {{ rpg fix:  lang codes 5 and 6 were missing }}
  278. 4      lang      0=unknown, 1=spl, 2=fortran, 3=cobol,
  279.                  4=rpg, 5=job, 6=text, 7=pascal, 8=cobolx, 9=data
  280.  
  281. 5      length    the normal record length in bytes
  282.  
  283. 6/7    size      the number of records in the file
  284.    or  currec    line number of last line read/written
  285.  
  286. 8      block     current disc block, qedit only (low 16-bits)
  287.  
  288. 9      index     current index into block, qedit only
  289.  
  290. 10     readlen   length in bytes of last read
  291.  
  292. 11     left      0 = linenum at right end of record
  293.                  1 = linenum at left end of record
  294.  
  295. 12     keylen   length of the linenumber key in bytes
  296.  
  297. 13/14           reserved for internal use
  298.  
  299. 15-270          buffer space for qedit file
  300. >>
  301.  
  302. << variables required by qedit read subrs >>
  303. integer x = x;
  304.  
  305. !byte pointer tos's1'ptr = s-1;
  306. !byte pointer tos's2'ptr = s-2;
  307. !byte pointer tos's3'ptr = s-3;
  308. !byte pointer tos's4'ptr = s-4;
  309. !byte pointer tos's5'ptr = s-5;
  310. !byte pointer tos's6'ptr = s-6;
  311.  
  312. double  pointer dp;
  313. integer pointer ip;
  314. integer indent'hwds,
  315.         indent'bytes,
  316.         line'ovhd:=3,
  317.         data'hwds,
  318.         usable'data,
  319.         worddatalen,
  320.         total;
  321. logical readmode;
  322.  
  323. byte array argument'(*) = argument;
  324.  
  325. <<variables added for FIND function>>
  326.   double  array d'arg   (*) = argument;
  327.   logical rec'found;
  328.   double  closest'linenum;
  329.   integer pointer fileblock'table; <<84 words>>
  330.   double  pointer firstlinenum;    <<6 words>>
  331.   double  pointer linetable; <<83 times 2>>
  332.   integer arg;
  333.  
  334.   logical user'opened;
  335.  
  336. << declarations added for qout functions >>
  337.  
  338.   << redefine function parm as a descriptor >>
  339.   double array d'function(*)=function;
  340.   << for open-new>>
  341.     define lang = function(1)# <<1=spl, not 0>>
  342.           ,text'length = function(2)# <<if lang=6>>
  343.           ,size'in'blocks = function(3)#
  344.           ,numext = function(4)#
  345.           ,initext = function(5)#
  346.           ,outfilename = argument#
  347.           ;
  348.   << for write line>>
  349.     define
  350.         reclen = function(1)#
  351.        ,lino   = d'function(1)#
  352.        ,record = argument#
  353.        ;
  354.   byte array b'record (*) = record;
  355.   double array qzero'line (*) = physbuf;
  356.  
  357.   << header >>
  358.   double line'h;
  359.   logical descriptor;
  360.   array header(*)=line'h; <<3 words>>
  361.  
  362.    define check'err=if <> then begin
  363.                      fcheck(filenumber,filestatus);
  364.                      if filestatus = 0 then filestatus := -1;
  365.                      return;
  366.                   end#;
  367.  
  368. intrinsic fcheck, fopen, fread, freaddir, fcontrol, fclose, fwrite
  369.          ,fgetinfo, debug, freadlabel, fwritedir, fwritelabel
  370.          ;
  371.  
  372. integer procedure thiscpu; option external;
  373.  
  374. $page "findclosestblock"
  375. subroutine findclosestblock(target,index);
  376.   value target, index;
  377.   double target; integer index;
  378. begin
  379.   << finds the block closest to target linenum >>
  380. ! print(physbuf,move physbuf:="findclosestblock",0);debug;
  381.     @firstlinenum := @physbuf;
  382.   @fileblock'table := @firstlinenum(3); ! instead of +6
  383.   @linetable := @firstlinenum(44); !instead of +88;
  384.  
  385.   fileblock := 1d;
  386.   fileindex := block'start;
  387.   freaddir(filenumber,firstlinenum,regular'wl,0d);
  388.   if <> then return;
  389.   closest'linenum := if filejumbo then 0d
  390.                      else firstlinenum;
  391.   index := 0;
  392.   while (index:=index+1) <= 83    do
  393.   begin
  394.      if fileblock'table(index)<>0 and
  395.         linetable(index) <= target and
  396.         linetable(index) > closest'linenum then
  397.      begin
  398.        fileblock := double(fileblock'table(index));
  399.        closest'linenum := linetable(index);
  400.     end'if;
  401.   end'while;
  402.  
  403.   freaddir(filenumber,physbuf,
  404.            regular'wl,fileblock);
  405.  
  406. ! fileindex := 1; <<start of block >>
  407. end'subr;
  408.  
  409. $page "utility used by all levels - geterr"
  410. subroutine geterr(errornum);
  411.    value   errornum;
  412.    integer errornum;
  413. begin
  414.   fcheck(filenumber,filestatus);
  415.   if filestatus = 0 then
  416.     filestatus := errornum;
  417. <<fileblock := 0;    version 2.7:
  418.   no longer force eof on read error! >>
  419. end'subr;
  420.  
  421. $page "utility used by all levels - lengthfromlabel"
  422. integer subroutine lengthfromlabel;
  423. begin
  424.   freadlabel(filenumber,physbuf,128,0);
  425.   if <> or physbuf'<>"QEDIT0" or
  426.      not(1<=integer(physbuf(17))<=256) then
  427.     lengthfromlabel := 256
  428.   else
  429.     lengthfromlabel := physbuf(17); <<u0'data'len>>
  430. end'subr; <<lengthfromlabel>>
  431.  
  432. $page "qaccess - get'qjumbo'attributes"
  433. subroutine get'qjumbo'attributes(num'flag);
  434.   value num'flag; logical num'flag;
  435. begin
  436.  
  437. !  print(physbuf,move physbuf:="subr: get'qjumbo",0); debug;
  438.  
  439. $if x5=on <<spl>>
  440.    if not jbuf'allocated then
  441.    begin
  442.       if not user'opened then
  443.       begin
  444.          fclose(filenumber,0,0); ! code will reopen it
  445.          filenumber := 0;
  446.       end'if;
  447.       go to allocate'jbuf;    ! kludge - cannot allocate buffer in subr
  448.    end'if;
  449. $if
  450.  
  451.    freaddir(filenumber,jbuf,j'wl,0d);
  452.    if <> then geterr(-5)
  453.    else
  454.    if jbuf<>"QE" or jbuf(1)<>"DI" or jbuf(2)<>"T2" then
  455.       geterr(-6)
  456.    else
  457.    begin       ! this is a jumbo file
  458.       internal'language := u0'lang;
  459.       filetype          := type'qedit;
  460.       filejumbo         := true;
  461.       if not (0<=integer(internal'language)<=max'lang) then
  462.         geterr(-4)
  463.       else
  464.       begin
  465.         filelang   := langtable(internal'language);
  466.         filesize   := u0'num'lines;         ! same as filecurkey field
  467.         filereclen := if filelang=text'lang or filelang=data'lang then
  468.                          u0'data'len
  469.                       else
  470.                       if filelang = cob'lang then
  471.                          72
  472.                       else
  473.                          80;
  474.         fileanysize := anysize'flag;
  475.         if filereclen > 256 and not fileanysize then ! use jumbo open
  476.            geterr(-7);
  477. ! print(physbuf,move physbuf:="debug: this is jumbo file",0); debug;
  478.         fileleft   := keylefttable(internal'language);
  479.         filekeylen := keylentable(internal'language);
  480.         if num'flag and filekeylen=0 then ! user needs seq numbers
  481.         begin <<append sequence numbers anyway!serial dump>>
  482.            filekeylen := 8;
  483.            filereclen := filereclen + 8;
  484.         end'if; <<add seq numbers>>
  485.         if filereclen > maxlinelen then
  486.           filereclen := maxlinelen;
  487.       end'else;
  488.    end'else;
  489. end'subr; <<get'qjumbo'attributes>>
  490.  
  491. $page "qaccess - get'qedit'attributes"
  492. subroutine get'qedit'attributes(num'flag);
  493.   value num'flag; logical num'flag;
  494. begin
  495.   freaddir(filenumber,physbuf,regular'wl,0d);
  496.   if <> then geterr(-5)
  497.   else
  498.   begin
  499.     internal'language := physbuf(6);
  500.     filetype := type'qedit;
  501.     if not (0<=integer(internal'language)<=max'lang) then
  502.       geterr(-4)
  503.     else
  504.     begin
  505.       filelang   := langtable(internal'language);
  506.       filesize   := double(physbuf(3)); <<!!same as filecurkey>>
  507.       filereclen := if filelang=text'lang then
  508.                        lengthfromlabel
  509.                     else
  510.                     if filelang = cob'lang then
  511.                        72
  512.                     else
  513.                        80;
  514.       fileleft   := keylefttable(internal'language);
  515.       filekeylen := keylentable(internal'language);
  516.       if num'flag and filekeylen=0 then
  517.       begin <<append sequence numbers anyway!serial dump>>
  518.         filekeylen := 8;
  519.         filereclen := filereclen + 8;
  520.       end'if; <<add seq numbers>>
  521.       if filereclen > maxlinelen then
  522.         filereclen := maxlinelen;
  523.     end'else;
  524.   end'else;
  525. end'subr; <<get'qedit'attributes>>
  526.  
  527. $page "qaccess - get'keep'attributes"
  528. <<  This next routine attempts to determine the language type
  529.     for an regular /keep file.  In general, we assume that code=1052
  530.     is a COBOL file, 80-byte files with line numbers are SPL, any
  531.     other 80-byte file records is Job, and everything else is Text.
  532. >>
  533. subroutine get'keep'attributes(filecode,len);
  534.    value   filecode, len;
  535.    integer filecode, len;
  536. begin
  537. $if x5=on  <<spl>>
  538.    if not jbuf'allocated then
  539.       go to allocate'jbuf;
  540. $if
  541.  
  542.    fileanysize :=anysize'flag;
  543.    if filereclen>256 and not fileanysize then
  544.       filereclen:=256; <<3.4>>
  545.    if filereclen > maxlinelen then
  546.       filereclen := maxlinelen;
  547.  
  548.    << this bit of code does not work for var-len files, which
  549.       might also have sequence numbers at the end of each line.>>
  550.  
  551.    if filecode = 1052 then         ! COBOL
  552.       if filereclen >= 80 then
  553.       begin
  554.          filelang := cobx'lang;
  555.          filereclen := 80;
  556.       end'if
  557.       else
  558.       begin
  559.          filereclen := 72;
  560.          filelang := cob'lang
  561.       end'else
  562.  
  563.    else if filereclen <> 80 then
  564.       if filereclen > 256 then filelang := data'lang
  565.       else filelang := text'lang      ! what about numbered TEXT?
  566.  
  567.    else if is'message'file then
  568.       filelang := text'lang
  569.  
  570.    else
  571.    begin
  572.       fread(filenumber,jbuf,-filereclen);
  573.       if <> then
  574.          filelang := job'lang
  575.       else
  576.       begin
  577.          if jbuf'(72) = numeric and jbuf'(73) = numeric and
  578.             jbuf'(74) = numeric and jbuf'(75) = numeric and
  579.             jbuf'(76) = numeric and jbuf'(77) = numeric and
  580.             jbuf'(78) = numeric and jbuf'(79) = numeric then
  581.             filelang := spl'lang
  582.          else
  583.             filelang := job'lang;
  584.          fcontrol(filenumber,5,len);  !only rewind if record read
  585.          if <> then geterr(-1);
  586.       end'else
  587.    end'else;
  588.  
  589.    fileleft := keylefttable( int'lang( filelang ));
  590.    filekeylen := keylentable( int'lang( filelang ));
  591. <<
  592.    Can't do filecurkey:=0 here, since caller expects filesize to
  593.    still contain a valid value
  594. >>
  595.    if readmode then
  596.       filefirstread := true;
  597.  
  598. ! fileleft := false;
  599. ! filekeylen := 0;
  600. ! if filelang = cob'lang or filelang = cobx'lang then
  601. ! begin
  602. !    fileleft   := true;
  603. !    filekeylen := 6;
  604. ! end'if
  605. ! else
  606. ! if filelang = spl'lang then
  607. !    filekeylen := 8;
  608. end'subr;     <<get'keep'attributes>>
  609.  
  610. $page "2nd level - get'var'attributes"
  611. subroutine get'var'attributes(filecode,len);
  612.    value   filecode, len;
  613.    integer filecode, len;
  614. begin
  615. $if x5=on  <<spl>>
  616.    if not jbuf'allocated then
  617.       go to allocate'jbuf;
  618. $if
  619.  
  620. !  print(jbuf,move jbuf:="subr get'var'attr",0); debug;
  621.    fileanysize :=anysize'flag;
  622.    if filereclen>256 and not fileanysize then
  623.       filereclen:=256;      << this could be 512, but qacc'argument
  624.                                is only 256 bytes big >>
  625.    if filecode=1052 and filereclen >  80 then
  626.       filereclen := 80;
  627.  
  628.    if is'message'file then
  629.       filelang := text'lang
  630.    else
  631.    begin
  632.  
  633.    len := fread(filenumber,jbuf, -filereclen);
  634. !           -(if filereclen>512 then 512
  635. !             else filereclen));
  636.    if <> then
  637.       filelang := job'lang
  638.    else
  639.    begin
  640.       if filecode = 1052 then         ! COBOL
  641.          filelang := cobx'lang
  642.  
  643.       else if len<8 or len>80 then
  644.          if len>256 then filelang := data'lang
  645.          else filelang := text'lang
  646.  
  647.       << should check next n lines for ascending line numbers
  648.       >>
  649.       else if jbuf'(len-8)=numeric and jbuf'(len-7)=numeric and
  650.               jbuf'(len-6)=numeric and jbuf'(len-5)=numeric and
  651.               jbuf'(len-4)=numeric and jbuf'(len-3)=numeric and
  652.               jbuf'(len-2)=numeric and jbuf'(len-1)=numeric then
  653.          filelang := spl'lang
  654.  
  655.       else
  656.          filelang := text'lang;
  657.  
  658.       fcontrol(filenumber,5,len);  !only rewind if record read
  659.       if <> then geterr(-1);
  660.    end;
  661.  
  662.    end; <<if is'message'file>>
  663.  
  664.    fileleft := keylefttable( int'lang( filelang ));
  665.    filekeylen := keylentable( int'lang( filelang ));
  666. <<
  667.    Can't do filecurkey:=0 here, since caller expects filesize to
  668.    still contain a valid value
  669. >>
  670.    if readmode then
  671.       filefirstread := true;
  672. end'subr;     <<get'var'attributes>>
  673.  
  674.  
  675. !subroutine format'key(starting);
  676. ! byte array starting;
  677. !begin
  678. ! tos := dp; << the linenumber in binary >>
  679. ! tos := 10000; << decimal divisor >>
  680. ! assemble(ldiv); << 32 bits / 16 bits, leave quot/remainder>>
  681. ! x := 3;
  682. ! do begin
  683. !   @tos's3'ptr:=@tos's3'ptr-1;
  684. !   tos := 10;
  685. !   assemble(div);
  686. !   tos := tos + "0";
  687. !   tos's4'ptr := tos;
  688. ! end
  689. ! until dxbz;
  690. ! << final remainder is on stack >>
  691. ! @tos's3'ptr := @tos's3'ptr - 1;
  692. ! tos's3'ptr := tos + "0";
  693. ! x := filekeylen - 4; <<cobol=2,others=4>>
  694. ! while dxbz do begin
  695. !   @tos's2'ptr := @tos's2'ptr - 1;
  696. !   tos := 10;
  697. !   assemble(div);
  698. !   tos := tos + "0";
  699. !   tos's3'ptr := tos;
  700. ! end'while;
  701. ! @tos's2'ptr := @tos's2'ptr - 1;
  702. ! tos's2'ptr := tos + "0";
  703. !end'subr; <<format'key>>
  704.  
  705. $page "2nd level - formatkey"
  706. subroutine formatkey (line,where,count);
  707.    value line, count, where;
  708.    integer count;
  709.    double line;
  710.    byte pointer where;
  711. begin
  712.    while (count:=count-1) >= 0 do
  713.    begin
  714.       @where := @where(-1);
  715.       where := "0" + byte(integer(line mod 10d));
  716.       line := line / 10d;
  717.    end'while;
  718. end'subr;  <<formatkey>>
  719.  
  720. $page "2nd level - ascii'to'dbl"
  721. logical subroutine ascii'to'dbl (line, num, count);
  722.    value line, count;
  723.    integer count;
  724.    double num;
  725.    byte pointer line;
  726. begin
  727.    ascii'to'dbl:=true;
  728.    num := 0d;
  729.    while (count:=count-1) >= 0 do
  730.    begin
  731.       if line=numeric then
  732.       begin
  733.          num := num*10d + double(byte(line) - "0");
  734.          @line := @line(+1);
  735.       end
  736.       else
  737.       begin
  738.          ascii'to'dbl:=false;
  739.          count:=0;
  740.       end;
  741.    end'while;
  742. end'subr;  <<ascii'to'dbl>>
  743.  
  744.  
  745. $page "2nd level - blank..."
  746. subroutine blanks ( up'to );
  747.   value up'to; integer up'to;
  748. begin
  749.   if (up'to:=up'to-total) > 0 then
  750.   begin
  751.     argument(total) := "  ";
  752.     if (up'to:=up'to-1) > 0 then
  753.       move argument(total+1) := argument(total),
  754.            (up'to);
  755.   end'if;
  756. end'subr; <<blanks>>
  757.  
  758. subroutine byte'blanks (up'to);
  759.   value up'to; integer up'to;
  760. begin
  761.   if (up'to:=up'to-total)>0 then
  762.   begin
  763.     argument'(total):=" ";
  764.     if (up'to:=up'to-1)>0 then
  765.        move argument'(total+1):=argument'(total),
  766.           (up'to);
  767.   end'if;
  768. end'subr; <<byte'blanks>>
  769.  
  770. subroutine b'blank(buf,count);
  771.    value count;
  772.    integer count;
  773.    byte array buf;
  774. begin
  775.    if count > 0 then
  776.    begin
  777.       buf:=" ";
  778.       if (count:=count-1)>0 then
  779.          move buf(1):=buf,(count);
  780.    end'if;
  781. end'subr; <<b'blank>>
  782. <<
  783.   for jumbo files we can only keep 1/2 block in the workspace, so
  784.   we have to re-read the full block when we cross block boundary.
  785.   keeping track of forward pointer is tricky.  when fileindex >= 256,
  786.   we replace fileblock with filenextblock value!
  787. >>
  788.  
  789. subroutine getotherhalfblock;
  790. begin
  791.  
  792. !  print(argument,move argument:="subr getotherhalfblock",0); debug;
  793. $if x5=on  <<spl>>
  794.    if not jbuf'allocated then
  795.       go to allocate'jbuf;
  796. $if
  797.  
  798.    freaddir(filenumber,jbuf,j'wl,fileblock);
  799.    if <> then geterr(-3)
  800.    else
  801.    begin
  802.       @filebuf :=@jbuf;
  803.       move physbuf := jbuf(regular'wl),(regular'wl);
  804.       if not fileserial then
  805.          fileblock := d'filebuf(1); ! the forward pointer
  806.    end'else;
  807. end'subr; <<getotherhalfblock>>
  808. $page "compute'next'block"
  809.  
  810. double subroutine compute'next'block;
  811. begin
  812.    compute'next'block :=
  813.              if fileserial then fileblock + 1d
  814.              else
  815.              if filejumbo then
  816.                 if fileindex >= regular'wl then fileblock !next ptr
  817.                 else d'filebuf(1)
  818.              else ! regular file
  819.                 double(filebuf); <<forward pointer >>
  820. end'subr; <<compute'next'block>>
  821. $page "getnextrecord"
  822.  
  823. subroutine getnextrecord (target,num'flag,compare'op);
  824.   value target,num'flag,compare'op;
  825.   logical num'flag;
  826.   integer compare'op; <<0=next, 1:>=target, 2:last 3:<=back>>
  827.   double target; <<only used if function=6>>
  828. begin
  829.   worddatalen:=filereclen/2;
  830.   filecurlen := 0;
  831.   rec'found := false;
  832.   while filestatus=0 and not rec'found do
  833.   begin
  834. !    if fileblock = 0d then ! eof
  835.     if fileeof<>0 then
  836.       filestatus := -1
  837.     else
  838.     begin
  839.       if filejumbo then
  840.       begin
  841. !        print(argument,move argument:="jumbo getnextrec",0);debug;
  842.          if fileindex >= 256 then
  843.             @filebuf := @physbuf(-regular'wl) !second half of block
  844.          else
  845.          if fileindex>=252 then
  846.             getotherhalfblock;
  847.       end'if;
  848.       @dp := @filebuf(fileindex);
  849.       @ip := @dp(1);  ! 4 bytes for line#, then lengths
  850.       if filejumbo then
  851.       begin
  852.          data'hwds := ip(0);
  853.          indent'hwds := ip(1);
  854.          line'ovhd := 4;
  855.          if fileindex + 4  < regular'wl and
  856.             fileindex + 4 + logical(data'hwds) >= regular'wl then
  857.          begin
  858.             getotherhalfblock;
  859.             @dp := @filebuf(fileindex);
  860.             @ip := @dp(1);  ! 4 bytes for line#, then lengths
  861.          end'if;
  862.       end'if
  863.       else
  864.       begin
  865.          data'hwds := ip.(0:8);
  866.          indent'hwds := ip.(8:8);
  867.       end'else;
  868.       if compare'op=0 or compare'op=1 and dp>=target then
  869.       begin <<we want this line>>
  870.         rec'found := true;
  871.          << leave this in for old rpg files>>
  872.         if filekeylen = 5 then
  873.         begin <<rpg, obsolete>>
  874.           if indent'hwds + data'hwds > 38 then
  875.              indent'hwds := 0;
  876.           indent'bytes := indent'hwds * 2 + (total := 5);
  877.           if num'flag then
  878.              formatkey(dp,argument'(filekeylen),filekeylen)
  879.           else
  880.              move argument':="     ";
  881.           byte'blanks(indent'bytes);
  882. $if x5=on
  883.           ! splash insists that * = byte address
  884.           tos := @filebuf(fileindex+logical(line'ovhd)) & lsl(1);   !  s
  885. $if x5=off
  886.           tos := @filebuf(fileindex+logical(line'ovhd));
  887. $if
  888.           move argument'(indent'bytes):=
  889.                * , (data'hwds*2); !byte count
  890.           total := total + indent'bytes;
  891.           byte'blanks(80);
  892.           total := (total+1)/2; <<convert to words>>
  893.         end'if
  894.         else
  895.         begin
  896.           if fileleft and num'flag then
  897.           begin <<cobol type and want seq numbers!>>
  898.              formatkey(dp,argument'(6),6);
  899.              indent'hwds := indent'hwds +
  900.                             (total := 3);
  901.           end'if
  902.           else
  903.              total:= 0;
  904.           if indent'hwds > worddatalen then
  905.              indent'hwds:=worddatalen ;
  906.           usable'data :=
  907.              if indent'hwds+data'hwds>worddatalen then
  908.                worddatalen-indent'hwds
  909.             else
  910.                data'hwds;
  911.           blanks(indent'hwds);
  912.           move argument(indent'hwds) :=
  913.                filebuf(fileindex+logical(line'ovhd)) ,
  914.                (usable'data);
  915.           total := usable'data + indent'hwds;
  916.           blanks(worddatalen);<<rest of line>>
  917.           if not fileleft and filekeylen <> 0 and num'flag then <<3.0>>
  918.              formatkey(dp,argument'(filereclen),8);
  919.         end'else;
  920.         filecurlen := if num'flag then filereclen
  921.                       else total * 2;
  922.       end'if;
  923.  
  924.       ! increment to next line
  925.       fileindex:= fileindex + logical(data'hwds + line'ovhd);
  926.       filecurkey := dp; <<return line number>>
  927.       @dp := @filebuf(fileindex);
  928.  
  929.       ! see if we need to read another block
  930.       if fileindex > logical(block'size - line'ovhd) or
  931.          dp > 99999999d or
  932.          dp <= 0d then ! we need another block
  933.  
  934.    !  if filebuf=0 <<no more blocks>> and
  935.       if compare'op=2 <<last blk >> and
  936.          compute'next'block=0d <<no more blocks>> then
  937.       begin
  938.           filestatus := -2; <<fileblock is one we want>>
  939.           return;
  940.       end'if
  941.       else
  942.       begin
  943.         do
  944.         begin
  945.           fileblock :=  compute'next'block;
  946.           fileindex := block'start;
  947.           @filebuf := @physbuf;
  948. !          if fileblock <> 0d then
  949.           if fileblock=0d then
  950.              fileeof:=1
  951.           else
  952.           begin
  953.             freaddir(filenumber,filebuf,regular'wl,fileblock);
  954.             if > then  <<end-of-file>>
  955.             begin
  956.                if not fileserial then
  957.                begin
  958.                   move filebuf:="Unexpected EOF in QEDIT file.";
  959.                   print(filebuf,-29,0);
  960.                end;
  961.                fileblock := 0d; <<stop loop>>
  962.                fileeof := 1;
  963.             end
  964.             else
  965.             if < then
  966.             begin <<read error!>>
  967.                printfileinfo(filenumber);
  968.                geterr(-1);
  969.                if fileserial then
  970.                   move filebuf:=8(0)     <<make it empty,read again>>
  971.                else
  972.                begin
  973.                   fileblock := 0d; <<stop loop>>
  974.                   fileeof := 1;
  975.                end;
  976.             end'if
  977.             else
  978.             if filejumbo and fileserial then
  979.             begin
  980.                if d'filebuf <> 0d then !not a data block
  981.                   move filebuf:=8(0); !empty block, read again
  982.             end'if;
  983.           end'if;
  984.           @dp := @filebuf(block'start);
  985.           end'do
  986.         until fileblock=0d or
  987.               dp <= 99999999d and
  988.               dp > 0d;
  989.       end'if;
  990.     end'else;
  991.   end'while;
  992. end'subr; <<getnextrecord>>
  993.  
  994. subroutine linenum'error;
  995. begin
  996.    << don't reset filelang, since it is needed to calculate increment
  997.    >>
  998.    filekeylen := 0;
  999.    if filelang=cob'lang or filelang=cobx'lang then
  1000.       filecurkey := filecurkey + 100d
  1001.    else
  1002.       filecurkey := filecurkey + 1000d;
  1003. end'subr; <<linenum'error>>
  1004.  
  1005. $page "read'keep'line"
  1006. subroutine read'keep'line( len, new'linenum );
  1007.    value   len, new'linenum;
  1008.    integer len;
  1009.    double  new'linenum;
  1010. begin
  1011. !  print(jbuf,move jbuf:="read'keep'line",0); debug
  1012.  
  1013. $if x5=on  <<spl>>
  1014.    if not jbuf'allocated then
  1015.       go to allocate'jbuf;
  1016. $if
  1017.  
  1018.    len := fread(filenumber, jbuf, -filereclen);
  1019.    if < then
  1020.       geterr(-1)
  1021.    else if > then
  1022.       filestatus := -1
  1023.    else
  1024.    begin
  1025.       indent'hwds := 0;
  1026.       if (filefirstread) then
  1027.       begin
  1028.          filefirstread := false;
  1029.          filecurkey    := 0d;
  1030.       end;
  1031.  
  1032.       if filekeylen>0 then    << has line number >>
  1033.       begin
  1034.          if len<integer(filekeylen) then
  1035.             linenum'error
  1036.          else if fileleft then     << line number at left >>
  1037.          begin
  1038.             if ascii'to'dbl( jbuf',new'linenum,filekeylen ) and
  1039.                new'linenum>filecurkey then
  1040.             begin
  1041.                filecurkey := new'linenum;
  1042.                indent'hwds := filekeylen;
  1043.             end
  1044.             else
  1045.                linenum'error;
  1046.          end
  1047.  
  1048.          else                 << line number at right >>
  1049.          begin
  1050.             if ascii'to'dbl(jbuf'(len-integer(filekeylen))
  1051.                            ,new'linenum
  1052.                            ,filekeylen
  1053.                            ) and
  1054.             new'linenum>filecurkey then
  1055.                filecurkey := new'linenum
  1056.             else
  1057.                linenum'error;
  1058.          end;
  1059.       end
  1060.  
  1061.       else                    << no line number in line >>
  1062.       begin
  1063.          if filelang=cob'lang or filelang=cobx'lang then
  1064.             filecurkey := filecurkey + 100d
  1065.          else
  1066.             filecurkey := filecurkey + 1000d;
  1067.       end;
  1068.  
  1069.       if len<integer(filekeylen)then
  1070.          usable'data := 0  << assertion failure! >>
  1071.       else
  1072.          usable'data := len - integer(filekeylen);
  1073.  
  1074.       move argument':=jbuf'(indent'hwds),(usable'data);
  1075.       b'blank(argument'(usable'data)
  1076.              ,integer(filereclen)-usable'data
  1077.              );
  1078.  
  1079.       while (usable'data>0) and (argument'(usable'data-1)=" ") do
  1080.          usable'data := usable'data-1;
  1081.       filecurlen := usable'data;
  1082.    end'if
  1083. end'subr; <<read'keep'line>>
  1084.  
  1085.  
  1086. $page "1st level - openold"
  1087. logical subroutine openold(write'access);
  1088.   value write'access;
  1089.   logical write'access;
  1090. begin
  1091.   user'opened := false;
  1092.   workspace := 0;
  1093.   move workspace(1):=workspace,(wl'workspace-1);
  1094.   fileblock  := 0d;
  1095.   filenumber := fopen(argument <<filename>>
  1096.   <<foptions>>       ,3 <<perm or temp>>
  1097.   <<aoptions:nobuf>> ,if write'access then [1/1,2/0,6/4]
  1098.                       else [1/1,2/0,6/0]); <<read>>
  1099.   if <> then geterr(-1)
  1100.   else openold := true;
  1101. end'subr; <<open'old>>
  1102.  
  1103. subroutine already'open;
  1104. begin
  1105. ! print(physbuf,move physbuf:="subr already'open",0); debug;
  1106.   user'opened := true;
  1107.   workspace := 0;
  1108.   move workspace(1):=workspace,(wl'workspace-1);
  1109.   fileblock  := 0d;
  1110.   filenumber := argument;
  1111. end'subr; <<already'open>>
  1112.  
  1113. subroutine getfirstblock;
  1114. begin
  1115. !$if x5=on <<spl>>
  1116. !  WE DON"T need jbuf because we only want first 256-wds anyway.
  1117. !  if filejumbo and not jbuf'allocated then
  1118. !     go to allocate'jbuf;
  1119. !$if
  1120.  
  1121.   fileblock := 1d;
  1122.   fileindex := block'start;
  1123.   fileeof   := 0;
  1124.  
  1125. !  if filejumbo then
  1126. !  begin
  1127. !     freaddir(filenumber
  1128. !             ,jbuf    ! dynamic allocation
  1129. !             ,j'wl
  1130. !             ,1d);
  1131. !     if <> then geterr(-3)
  1132. !     else
  1133. !    if filejumbo then
  1134. !       move physbuf := jbuf,(regular'wl); !truncate
  1135. ! end'if
  1136. ! else
  1137.   begin
  1138.      freaddir(filenumber
  1139.              ,physbuf
  1140.              ,regular'wl
  1141.              ,1d);
  1142.      if <> then geterr(-3)
  1143.   end'else;
  1144. end'subr; <<getfirstblock>>
  1145.  
  1146. subroutine write'userlabel0;
  1147. begin
  1148.  
  1149.   << reset userlabel 0 to default >>
  1150.   move physbuf := (
  1151.     "QEDIT0",  <<id for userlabel>>
  1152.     2 <<version>>, 0 <<spl>>, 1 <<namelen>>, 6(0),72<<right>>,
  1153.     [1/1,2/1] <<ascii,old>>, 3(0),72<<len>>,8<<key>>,5(0),
  1154.     100("  "), <<last'textname, free space>>
  1155.     4(0));    << (124,125,126,127 unused>>
  1156.  
  1157.   << adjust language >>
  1158.     physbuf(4) := int'lang(lang);
  1159.   << adjust rightmargin and datalen >>
  1160.     physbuf(12) := if lang=6 then text'length
  1161.                    else if lang=3 then 66
  1162.                    else 80-keylentable(physbuf(4));
  1163.     physbuf(17):=physbuf(12);
  1164.   <<adjust keylen, left flag, unn flag>>
  1165.     if fileleft then
  1166.     begin
  1167.       physbuf(18):=6;
  1168.       physbuf(16):=1; <<left flag>>
  1169.     end
  1170.     else
  1171.     if 4<=lang<=6 then <<unn>>
  1172.       physbuf(16).(0:1) := 1;
  1173.  
  1174.   fwritelabel(filenumber,physbuf,128,0);
  1175.   if <> then geterr(-5);
  1176.  
  1177. end'subr; <<write'userlabel0>>
  1178.  
  1179. subroutine erase'existing'qedit;
  1180. begin
  1181.   if 1<=lang<=max'lang and
  1182.      (lang<>6 or (1<=text'length<=256)) then
  1183. begin
  1184.   filecurkey := 0d; <<erase filesize>>
  1185.   fcontrol(filenumber,5,physbuf); <<rewind>>
  1186.   if <> then geterr(-5);
  1187.   fcontrol(filenumber,6,physbuf); << write eof, erases>>
  1188.   if <> then geterr(-5);
  1189.   fileblock := 1d;
  1190.   fileindex := 1;
  1191.   fileleft      :=  if lang=3 or lang=8 then true else false;
  1192.   filenewlines  := 0;
  1193.   fileprevblock := 0;
  1194.   filenewblocks := 0;
  1195.   write'userlabel0; <<erase existing label>>
  1196.   << reset block zero >>
  1197.   physbuf:=0; move physbuf(1):=physbuf,(255);
  1198.   physbuf(5) := %100000;
  1199.   physbuf(6):=int'lang(lang); <<the internal number>>
  1200.   fwritedir(filenumber,physbuf,256,0d);
  1201.   if <> then geterr(-5);
  1202.   filelang := lang; <<external code>>
  1203.   filetype := type'rep'qedit;
  1204.   physbuf:=0;move physbuf(1):=physbuf,(255);
  1205. end
  1206. else filestatus := -1;
  1207. end; <<erase'existing'qedit>>
  1208.  
  1209. subroutine append'to'qedit'file (eof);
  1210.   value eof;
  1211.   double eof;
  1212. begin
  1213.   if filesize=0d then
  1214.     erase'existing'qedit
  1215.   else
  1216.   begin
  1217.     filecurkey := 0d;  <<reset filesize>>
  1218.     filetype   := type'app'qedit;
  1219.     filestatus := 0;
  1220.     findclosestblock(100000000d,0);
  1221.     getnextrecord(100000000d,false,2); <<find last block>>
  1222.     if filestatus<>-2 or filecurkey=0d then
  1223.     begin
  1224.       filestatus := -1;
  1225.       fclose(filenumber,0,0);
  1226.     end
  1227.     else
  1228.     begin << found last block >>
  1229.       filestatus    := 0; <<okay>>
  1230.       fileprevblock := integer(fileblock);
  1231.       filenewlines  := 0;
  1232.       filenewblocks := 0;
  1233.       << set up append line number >>
  1234.       filecurkey := (filecurkey/1000d+1d) * 1000d; <<round up>>
  1235.       << find eof >>
  1236.       fgetinfo(filenumber,,,,,,,,,,eof);
  1237.       if <> then geterr(-5);
  1238.       fileblock := eof;
  1239.       fileindex :=  1;
  1240.       << fix block to point to eof, next available, fileblock>>
  1241.       filebuf := integer(fileblock); !  filebuf still contains last bloc
  1242.       fwritedir(filenumber,filebuf,256,double(fileprevblock));
  1243.       if <> then geterr(-5);
  1244.       << zero out the buffer for new lines >>
  1245.       filebuf:=0; move filebuf(1):=filebuf,(255);
  1246.     end'else;
  1247.   end;
  1248. end; <<append'to'qedit'file>>
  1249.  
  1250. subroutine determine'type(num'flag,access'code);
  1251.   value num'flag,access'code;
  1252.   logical num'flag;
  1253.   integer access'code; <<0=read,1=overwrite,2=append>>
  1254. begin
  1255. !  print(physbuf,move physbuf:="determine'type subr",0); debug;
  1256.    fgetinfo(filenumber,,foptions,,filereclen,,,,
  1257.             fcode,,filesize);  <<filesize:=eof>>
  1258.    if <> then
  1259.       geterr(-1)
  1260.    else
  1261.    begin
  1262.       if fcode = 111 then
  1263.       begin << qedit file, regular or jumbo? >>
  1264.          filetype := type'qedit;
  1265.          if filereclen = j'wl then
  1266.          begin
  1267.             if access'code <> 0 then geterr(-8)
  1268.             else get'qjumbo'attributes(num'flag);
  1269.          end'if
  1270.          else
  1271.             get'qedit'attributes(num'flag);
  1272.          if filestatus = 0 then
  1273.          begin
  1274.             if access'code=0 then <<read>>
  1275.             begin
  1276.                if filesize = 0d then ! boundary case for empty file
  1277.                begin
  1278.                   fileblock := 0d;
  1279.                   fileeof := 1;
  1280.                end
  1281.                else
  1282.                   getfirstblock;
  1283.             end
  1284.             else
  1285.             if access'code=1 then <<overwrite>>
  1286.                erase'existing'qedit
  1287.             else
  1288.             if access'code=2 then <<append>>
  1289.                append'to'qedit'file(0d)
  1290.             else filestatus := -1;
  1291.          end'if
  1292.     end'if
  1293.     else << not a qedit file >>
  1294.     begin
  1295.       if not user'opened then
  1296.       begin
  1297.         <<keep file, close and reopen buffered>>
  1298.         fclose(filenumber,0,0);
  1299.         filenumber := fopen(argument,3,  <<old or oldtemp>>
  1300.                            if access'code=0 then 0 else
  1301.                            if access'code=1 then 1 else
  1302.                            3 <<append>>);
  1303.         if <> then geterr(-1);
  1304.       end'if;
  1305.       if filenumber<>0 then
  1306.       begin
  1307.         fgetinfo(filenumber,,foptions,,filereclen,,,,
  1308.                ,,filesize); <<17 jul 86,rmg fix bug>>
  1309.         << make filereclen positive number of bytes >>
  1310.         if integer(filereclen) > 0 then
  1311.         begin
  1312.           filetype := type'mpe;
  1313.           filereclen := filereclen * 2
  1314.         end'if
  1315.         else
  1316.         begin
  1317.           filetype := type'keep;
  1318.           filereclen := -integer(filereclen);
  1319.         end'else;
  1320.         if access'code=1 then filetype := type'rep'mpe else
  1321.         if access'code=2 then filetype := type'app'mpe;
  1322.  
  1323.         is'variable'len := foptions.(8:2)=1;
  1324.         is'message'file := foptions.(2:3)=6;
  1325.         if is'message'file then
  1326.         begin
  1327. !          integer'parm:=0;
  1328.            ! Disable extended wait.  We don't want it disabled,
  1329.            ! since the default is wait on first i/o, no wait on rest.
  1330.            ! This allows the qaccess process to start before the
  1331.            ! writer has started.
  1332. !          fcontrol( filenumber, 45, integer'parm );
  1333.         end;
  1334.  
  1335.         if is'variable'len then  << variable length file >>
  1336.            get'var'attributes(fcode,0)
  1337.         else if filereclen > 256 and not anysize'flag then
  1338.           filestatus := -2
  1339.         else
  1340.           get'keep'attributes(fcode,0);
  1341.       end'if;
  1342.     end'else;
  1343.   end'else;
  1344.   if filestatus <> 0 and not user'opened then
  1345.   begin
  1346.     fclose(filenumber,0,0);
  1347.     filenumber:=0;
  1348.   end'if;
  1349. end'subr; <<determine'type>>
  1350.  
  1351. $page "open'new'qedit'file ..."
  1352. subroutine open'new'qedit'file (fsz);
  1353.   value fsz;
  1354.   integer fsz;
  1355. begin
  1356.    workspace :=0;
  1357.    move workspace(1):=workspace,(wl'workspace-1);
  1358.    fileblock := 0d;
  1359.    fileleft := if lang=3 or lang=8 then true else false;
  1360.    fsz:=if size'in'blocks < min'blocks then min'blocks
  1361.         else size'in'blocks;
  1362.    filenumber:=
  1363.       fopen(outfilename
  1364.       ,0   <<new, binary>>    << foptions         lv >>
  1365.       ,[1/1,2/2,6/4]<<nobuf,excl,inout : aoptions lv >>
  1366.       ,256                    << recsize          iv >>
  1367.       ,                       << device           ba >>
  1368.       ,                       << formmsg          ba >>
  1369.       ,2                      << userlabels       iv >>
  1370.       ,                       << blockfactor      iv >>
  1371.       ,                       << numbuffers       iv >>
  1372.       ,double(fsz)            << filesize         dv >>
  1373.       ,numext                 << numextents       iv >>
  1374.       ,initext                << initialloc       iv >>
  1375.       ,111                    << filecode         iv >>
  1376.       );
  1377.    check'err;
  1378.    filecurkey     := 0d;
  1379.    filenewlines   := 0;
  1380.    fileblock      := 1d;
  1381.    fileindex      := 1;
  1382.    fileprevblock  := 0;  !write only
  1383.    filenewblocks  := 0;
  1384.    << rest of filebuf is set to zero above>>
  1385.    move filebuf := (0,0,0,0,0,%100000,0,0); << in use flag>>
  1386.    filebuf(6) := int'lang(lang); <<the internal number, parameter>>
  1387.    filelang := lang;
  1388.    fwritedir(filenumber,
  1389.              filebuf,
  1390.              256,
  1391.              0d);
  1392.    check'err;
  1393.    if lang=6 then <<text>>
  1394.      write'userlabel0;
  1395.    filebuf:=0;   <<data'hwds block>>
  1396.    move filebuf(1):=filebuf,(255);
  1397.    filetype := type'new'qedit;
  1398. end; <<open'new'qedit'file>>
  1399.  
  1400. subroutine reset'fwd'ptr;
  1401. begin
  1402.   if fileprevblock>0 then
  1403.   begin
  1404.     freaddir(filenumber,filebuf,256,double(fileprevblock));
  1405.     if = then
  1406.     begin
  1407.       filebuf := 0;
  1408.       fwritedir(filenumber,filebuf,256,double(fileprevblock));
  1409.     end;
  1410.   end'if;
  1411. end;  <<reset'fwd'ptr>>
  1412.  
  1413. subroutine close'write'file (domain);
  1414.   value domain;
  1415.   integer domain;
  1416. << could be new qedit file (filetype=3) or old MPE file (4,5)
  1417.    or old QEDIT file (6,7). all with write access >>
  1418. begin
  1419.   if filetype=type'rep'mpe or filetype=type'app'mpe then
  1420.   begin
  1421.     fclose(filenumber,0,0); <<existing file>>
  1422.     return;
  1423.   end;
  1424.   << now deal with qedit files, post last block >>
  1425.   if filetype=type'app'qedit and filenewlines=0 then
  1426.   begin
  1427.     << nothing appended !! special case >>
  1428.     reset'fwd'ptr; << to 0>>
  1429.   end
  1430.   else
  1431.   begin
  1432.     filebuf:=0; <<fwd ptr>>
  1433.     fwritedir(filenumber,
  1434.               filebuf,
  1435.               256,
  1436.               fileblock);
  1437.     check'err;
  1438.     filenewblocks := filenewblocks + 1; <<last one>>
  1439.   end;
  1440.  
  1441.   << read block zero, update >>
  1442.   freaddir(filenumber
  1443.           ,filebuf
  1444.           ,256
  1445.           ,0d);
  1446.   check'err;
  1447.  
  1448.    filebuf(2) := filebuf(2) + filenewblocks;
  1449.    filebuf(3) := filebuf(3) + filenewlines;
  1450.    << filebuf(4) := 0;   ..first empty block, leave as is for old>>
  1451.    filebuf(5) := 0;   <<flags reset>>
  1452.    << filebuf(6) contains internal'language code >>
  1453.    fwritedir(filenumber,
  1454.              filebuf,
  1455.              256,
  1456.              0d);
  1457.    check'err;
  1458.  
  1459.    fclose (filenumber,domain,0);
  1460.    check'err;
  1461. end; <<close'write'file>>
  1462.  
  1463. subroutine update'first'line(linenum);
  1464.   value linenum;
  1465.   double linenum;
  1466. begin
  1467.   freaddir(filenumber
  1468.           ,filebuf
  1469.           ,256
  1470.           ,0d
  1471.           );
  1472.   if = then
  1473.   begin
  1474.     qzero'line:=linenum;
  1475.     fwritedir(filenumber
  1476.              ,filebuf
  1477.              ,256
  1478.              ,0d);
  1479.     filebuf:=0;
  1480.     move filebuf(1):=filebuf,(255);
  1481.   end;
  1482. end; <<update'first'line>>
  1483.  
  1484. subroutine write'qedit'line(length);
  1485.   value length;
  1486.   integer length;
  1487. begin
  1488.   << check length >>
  1489.   length:=if reclen>256 then 256 else reclen;
  1490.   while length>0 and b'record(length-1)=" "
  1491.      do length := length - 1;
  1492.  
  1493.   << increment count of lines >>
  1494.   filenewlines:=filenewlines+1;
  1495.  
  1496.   << compute indentation >>
  1497.   indent'hwds := 0;
  1498.   while indent'hwds < length and
  1499.         b'record(indent'hwds)=" " do
  1500.     indent'hwds := indent'hwds + 1;
  1501.   indent'hwds := indent'hwds & lsr(1); <<divide by 2, words>>
  1502.   data'hwds := (length+1) & lsr(1) - indent'hwds;
  1503.   if logical(length) then
  1504.     b'record(length) := " ";
  1505.   descriptor.(8:8) := indent'hwds;
  1506.   descriptor.(0:8) := data'hwds;
  1507.   line'h:=if filetype<>type'app'qedit and lino>filecurkey then lino
  1508.         else << auto increment >>
  1509.           filecurkey+(if fileleft then 100d else 1000d);
  1510.   if fileleft and line'h > 999999d or
  1511.      not fileleft and line'h > 99999999d then
  1512.   begin
  1513.     filestatus := -1;
  1514.     return;
  1515.   end;
  1516.   if filecurkey = 0d then
  1517.     update'first'line(line'h);
  1518.   filecurkey := line'h;
  1519.   if fileindex + 3 + logical(data'hwds) > 256 then
  1520.   begin
  1521.     << block is full, get a new one >>
  1522.     filebuf := integer(fileblock) + 1;
  1523.     fwritedir(filenumber,
  1524.               filebuf,
  1525.               256,
  1526.               fileblock);
  1527.     if > then
  1528.       reset'fwd'ptr
  1529.     else
  1530.       check'err;
  1531.     if filebuf=0 then ! forward pointer
  1532.     begin
  1533.       fclose(filenumber,1,0);
  1534.       filestatus := -1;
  1535.       return;
  1536.     end;
  1537.     fileprevblock := integer(fileblock); !write only
  1538.     filenewblocks := filenewblocks + 1;
  1539.     fileblock     := fileblock+1d;
  1540.     fileindex     := 1;
  1541.  
  1542.     filebuf:=0;
  1543.     move filebuf(1) := filebuf,(255);
  1544.   end;
  1545.   << move to buf >>
  1546.   move filebuf(fileindex):=header,(3),2;
  1547.   move * := record(indent'hwds),(data'hwds);
  1548.   fileindex := fileindex + 3 + logical(data'hwds);
  1549. end; <<write'qedit'line>>
  1550.  
  1551. $page "qacc'explain"
  1552. subroutine qacc'explain( stat );
  1553.    value   stat;
  1554.    integer stat;
  1555. begin
  1556.   stat := filestatus;
  1557.   b'blank( argument', 72 );
  1558.   if stat>0 then
  1559.     ferrmsg( stat, argument, filecurlen )
  1560.   else if stat=0 then
  1561.     filecurlen :=
  1562.     move argument':="Qaccess: No error"
  1563.   else if stat=-1 then
  1564.     filecurlen :=
  1565.     move argument':="Qaccess: End of File"
  1566.   else if stat=-2 then
  1567.     filecurlen :=
  1568.     move argument':="Qaccess: File record length >256, Max is 256"
  1569.   else if stat=-3 then
  1570.     filecurlen :=
  1571.     move argument':="Qaccess: Unable to read 1st block, Fcheck=0"
  1572.   else if stat=-4 then
  1573.     filecurlen :=
  1574.     move argument':="Qaccess: Invalid function. Valid range is 1..31"
  1575.   else if stat=-5 then
  1576.     filecurlen :=
  1577.     move argument':="Qaccess: File system error, Fcheck=0"
  1578.   else if stat=-6 then
  1579.     filecurlen :=
  1580.     move argument':="Qaccess: Invalid format for Jumbo Qedit file."
  1581.   else if stat=-7 then
  1582.     filecurlen :=
  1583.     move argument':="Qaccess: use Jumbo Open (func 30) if rec>256"
  1584.   else if stat=-8 then
  1585.     filecurlen :=
  1586.     move argument':="Qaccess: Write/Append to jumbo not impl yet."
  1587.   else
  1588.     filecurlen :=
  1589.     move argument':="Qaccess: Unknown stat";
  1590. end; <<qacc'explain>>
  1591. $page "qaccess/get-put workspace"
  1592. <<
  1593.     we need to redefine workspace for jumbo files, so
  1594.     have subr to copy fields into local variables and put
  1595.     them back
  1596. >>
  1597.  
  1598. subroutine get'workspace;
  1599. begin
  1600.  
  1601.    wl'workspace := 270; ! old size
  1602.    fileblock1 := fileblock'r;
  1603.    fileblock0 := 0;
  1604. !   if function <> 12 then ! not write line
  1605.    if function <> 10   and  ! Not close-old
  1606.       function <> 11   and  ! Not close-new
  1607.       function <> 12   then ! Not write-line
  1608.       fileblock0 := fileblock'j; !jumbo extension
  1609.  
  1610. end'subr; <<get'workspace>>
  1611.  
  1612. subroutine put'workspace;
  1613. begin
  1614.  
  1615.    fileblock'r    := fileblock1;
  1616.    if function <> 12 then !not write line
  1617.       fileblock'j    := fileblock0;
  1618.  
  1619. end'subr; <<put'workspace>>
  1620. $page "qeditaccess/mainline"
  1621.  
  1622. qaccess: ! entry point for pascal
  1623. current'version: ! dummy entry'point to make version accessible
  1624.  
  1625. $if x5=on <<spl>>
  1626. !go around;
  1627.  
  1628. allocate'jbuf:
  1629.    ! kludge:  for jumbo files we need 512 word buffer, but might
  1630.    !          cause stack overflow in some tools.  not needed for
  1631.    !          regular qedit files.  cannot allocate dynamic buffer
  1632.    !          in subr or it screws up return address. must GO TO
  1633.    !          main line of procedure and restart!
  1634.    if not jbuf'allocated then
  1635.       allocate j'wl words'to jbuf end'alloc;
  1636.    jbuf'allocated := true;
  1637. !  print(jbuf,move jbuf:="debug:alloc jbuf",0); debug;
  1638. around:
  1639. $if
  1640.  
  1641. if not (1<=function<=max'func) then
  1642.   filestatus := -4
  1643. else
  1644. begin
  1645.  
  1646. if function<>18 then
  1647.    filestatus := 0;
  1648.  
  1649. get'workspace;
  1650.  
  1651. case function - 1 of
  1652. begin
  1653.   <<1: open>>
  1654.  
  1655.   begin
  1656.     readmode := true;
  1657.     if openold(false) then
  1658.       determine'type(false,0);
  1659.   end;
  1660.  
  1661.   <<2: read>>
  1662.  
  1663.   begin
  1664.     if filenumber=0 or filetype>=type'writing then
  1665.       filestatus := 72
  1666.     else
  1667.       if filetype = type'qedit then
  1668.         getnextrecord (0d,true,0)
  1669.       else
  1670.       begin
  1671.         filecurkey := 0d;
  1672.         filecurlen := fread(filenumber, argument, -filereclen);
  1673.         if < then
  1674.           geterr(-1) <<12may80>>
  1675.         else if > then
  1676.           filestatus := -1; <<eof>>
  1677.       end'else;
  1678.   end;
  1679.  
  1680.   <<3: close>>
  1681.  
  1682.   begin
  1683.     if filenumber = 0 or filetype>=type'writing then <<only for read>>
  1684.       filestatus := 72
  1685.     else
  1686.     begin
  1687.       fclose(filenumber,0,0);
  1688.       if <> then geterr(-1)
  1689.       else filenumber := 0;
  1690.     end'else;
  1691.   end;
  1692.  
  1693.   <<4: rewind>>
  1694.  
  1695.   begin
  1696.     if filenumber = 0 or filetype>=type'writing then
  1697.       filestatus := 72
  1698.     else
  1699.       if filetype = type'keep then
  1700.       begin
  1701.         fcontrol(filenumber,5,dummy);
  1702.         if <> then geterr(-1);
  1703.       end'if
  1704.       else
  1705.       begin  << qedit >>
  1706.         filecurlen := 0;
  1707.         getfirstblock;
  1708.       end'else;
  1709.   end;
  1710.  
  1711.   <<5: serial'flag>>
  1712.  
  1713.   begin
  1714.     readmode := true;
  1715.     if openold(false) then
  1716.     begin
  1717.       determine'type(true,0);
  1718.       if filestatus=0 then
  1719.          fileserial := true;
  1720.     end'if;
  1721.   end;
  1722.  
  1723.   <<6: find>>
  1724.  
  1725.   begin
  1726.     if filenumber<>0 then
  1727.       if filetype=type'keep then geterr(-1)
  1728.       else
  1729.       begin
  1730. !       print(physbuf,move physbuf:="6:find",0);debug;
  1731.         findclosestblock(d'arg,0);
  1732.         getnextrecord(d'arg,true,1);
  1733.       end'else;
  1734.   end;
  1735.  
  1736.   <<7: already'open>>
  1737.  
  1738.   begin
  1739. !   print(physbuf,move physbuf:="main func already'open",0); debug;
  1740.     readmode := true;
  1741.     already'open;
  1742.     determine'type(false,0);
  1743.   end;
  1744.  
  1745.   <<8: read'unn>>
  1746.  
  1747.   begin
  1748.     if filenumber=0 or filetype>=type'writing then
  1749.       filestatus := 72
  1750.     else
  1751.       if filetype = type'qedit then
  1752.         getnextrecord (0d,false,0)
  1753.       else
  1754.       begin
  1755.         filecurkey := 0d;
  1756.         filecurlen := fread(filenumber,
  1757.           argument,-filereclen);
  1758.         if < then
  1759.           geterr(-1) <<12may80>>
  1760.         else if > then
  1761.           filestatus := -1; <<eof>>
  1762.       end'else
  1763.   end;
  1764.  
  1765.   <<9: open'new>>
  1766.  
  1767.   begin <<function parm has descriptors>>
  1768.     if 1<=lang<=8 then
  1769.       open'new'qedit'file(0)
  1770.     else
  1771.       filestatus:=72;
  1772.   end;
  1773.  
  1774.   <<10: write'close-save as old file>>
  1775.  
  1776.   begin
  1777.     if filetype>=type'writing then
  1778.     begin
  1779.       if thiscpu >= 16 then   <<release disc space on XL>>
  1780.         close'write'file(%21)
  1781.       else
  1782.         close'write'file(1)
  1783.     end'if
  1784.     else
  1785.       filestatus := 72;
  1786.   end;
  1787.  
  1788.   <<11: save new temp>>
  1789.  
  1790.   begin
  1791.     if filetype=type'new'qedit then
  1792.       close'write'file(2)
  1793.     else
  1794.       filestatus := 72;
  1795.   end;
  1796.  
  1797.   <<12: write'line>>
  1798.  
  1799.   begin
  1800.     if filetype>=type'writing then
  1801.     begin
  1802.       if filetype=type'rep'mpe or filetype=type'app'mpe then
  1803.       begin <<lino is ignored!>>
  1804.         fwrite(filenumber,argument, -reclen, 0);
  1805.         if <> then filestatus := -1;
  1806.       end
  1807.       else
  1808.       if filetype=type'new'qedit or
  1809.          filetype=type'rep'qedit or
  1810.          filetype=type'app'qedit then
  1811.         write'qedit'line(0)
  1812.       else
  1813.         filestatus := 72
  1814.     end
  1815.     else
  1816.       filestatus := 72;
  1817.   end;
  1818.  
  1819.   <<13: overwrite>>
  1820.  
  1821.   begin
  1822.     readmode := false;
  1823.     if openold(true) then
  1824.       determine'type(false,1);
  1825.   end;
  1826.  
  1827.   <<14: overwrite-already-open>>
  1828.  
  1829.   begin
  1830.     readmode := false;
  1831.     already'open;
  1832.     determine'type(false,1);
  1833.   end;
  1834.  
  1835.   <<15: append>>
  1836.  
  1837.   begin
  1838.     readmode := false;
  1839.     if openold(true) then
  1840.       determine'type(false,2)
  1841.   end;
  1842.  
  1843.   <<16: append-already-open>>
  1844.  
  1845.   begin
  1846.     readmode := false;
  1847.     already'open;
  1848.     determine'type(false,2);
  1849.   end;
  1850.  
  1851.   <<17: read-line>>
  1852.  
  1853.   begin
  1854.     if filenumber=0 or filetype>=type'writing then
  1855.       filestatus := 72
  1856.     else
  1857.       if filetype = type'qedit then
  1858.       begin
  1859.         getnextrecord (0d,false,0);
  1860.         while (filecurlen>0) and (argument'(filecurlen-1)=" ") do
  1861.            filecurlen := filecurlen - 1;
  1862.       end
  1863.       else
  1864.       begin
  1865.         read'keep'line(0,0d);
  1866.       end'else;
  1867.   end;
  1868.  
  1869.   <<18: explain>>
  1870.  
  1871.   begin
  1872.     qacc'explain(0);
  1873.   end;
  1874.  
  1875.   <<19:>> filestatus := -4;
  1876.   <<20:>> filestatus := -4;
  1877.   <<21:>> filestatus := -4;
  1878.   <<22:>> filestatus := -4;
  1879.   <<23:>> filestatus := -4;
  1880.   <<24:>> filestatus := -4;
  1881.   <<25:>> filestatus := -4;
  1882.   <<26:>> filestatus := -4;
  1883.   <<27:>> filestatus := -4;
  1884.   <<28:>> filestatus := -4;
  1885.   <<29:>> filestatus := -4;
  1886.  
  1887.   <<30: open>>
  1888.  
  1889.   begin
  1890.     readmode     := true;
  1891.     anysize'flag := true;
  1892.     if openold(false) then
  1893.       determine'type(false,0);
  1894.   end;
  1895.  
  1896.   <<31: already'open, any record size >>
  1897.  
  1898.   begin
  1899. !   print(physbuf,move physbuf:="main func already'open",0); debug;
  1900.     readmode       := true;
  1901.     anysize'flag   := true;
  1902.     already'open;
  1903.     determine'type (false,0);
  1904.   end;
  1905.  
  1906.  
  1907.   <<32: jumbo serial'flag>>
  1908.  
  1909.   begin
  1910.     readmode := true;
  1911.     anysize'flag := true;
  1912.     if openold(false) then
  1913.     begin
  1914.       determine'type(true,0);
  1915.       if filestatus=0 then
  1916.          fileserial := true;
  1917.     end'if;
  1918.   end;
  1919.  
  1920. end'case;
  1921.  
  1922. end'if;
  1923.  
  1924. put'workspace;
  1925.  
  1926. end'proc;    <<qeditaccess>>
  1927. $page "qout routines to write qedit workfiles"
  1928. <<
  1929.  
  1930.           q o u t   r o u t i n e s
  1931.  
  1932. purpose: qout contains routines to allow an application
  1933.          program to create and fill qedit workfiles of any size
  1934.          and type.  these workfiles can then be /open'ed
  1935.          and edited in qedit.
  1936.  
  1937. contents: qouto    open a new qedit workfile.
  1938.           qoutw    write a line to a qedit workfile.
  1939.           qoutc    close a qedit workfile.
  1940.  
  1941. installation:
  1942.  
  1943. history:
  1944.  
  1945.         written by staff of campbell and cook
  1946.                             10th floor, 459 collins street
  1947.                             melbourne, victoria 3000
  1948.                             austrialia
  1949.  
  1950. history:
  1951.         revised and documented further, 13 feb79 by robelle.
  1952.         added text files  13 aug79 by robelle.
  1953.         added pasc files  28 jan83 by robelle.
  1954.  
  1955. use:
  1956.  
  1957.         you must provide a workspace array for each file
  1958.         to be written concurrently (as in qeditaccess of
  1959.         qcopy).  these routines can be called from spl,
  1960.         fortran, or cobol.
  1961. >>
  1962.  
  1963. $page "qoutc"
  1964. << close the new qedit file and save it PERMANENT.
  1965.    post the last block
  1966.    update record zero
  1967. >>
  1968. procedure qoutc(workspace);
  1969.    array workspace;
  1970.    OPTIONTYPE CHECK 2;
  1971. << cobol call:
  1972.  
  1973.    call "QOUTC" using workspace. (see qouto)
  1974.  
  1975. >>
  1976. begin
  1977.   integer function := 10;
  1978.  
  1979.   qeditaccess(function,workspace,function);
  1980.  
  1981. end; << of qoutc >>
  1982. $page "qoutw"
  1983. procedure qoutw (workspace,record,reclen,lino);
  1984.    double lino;
  1985.    integer reclen;
  1986.    array record ;
  1987.    array workspace;
  1988.    optiontype check 2;
  1989.    << parameters:
  1990.        workspace : as for qouto.
  1991.        record    : integer or logical array containing the line
  1992.                    to be written. does not contain the line number!
  1993.        reclen    : byte length of line, exclusive of trailing blanks.
  1994.                    lines too long are truncated.
  1995.        lino      : line number to be used. if lino <= current line then
  1996.                    current line + increment will be used.
  1997.                    if lineno > maximum linenumber allowed, qoutw
  1998.                    will return with error -1
  1999.        >>
  2000.  
  2001. << cobol call:
  2002.  
  2003.    call "QOUTW" using workspace  (see qouto)
  2004.                       record     ( pic x(80) )
  2005.                       reclen     ( pic s9(4) comp)
  2006.                       lineo.     ( pic s9(8) comp)
  2007. >>
  2008. begin
  2009.   integer array function(0:10);
  2010.   double array d'function (*) = function;
  2011.  
  2012.   function := 12; <<write>>
  2013.   function(1):= reclen;
  2014.   d'function(1) := lino;
  2015.  
  2016.   qeditaccess(function,workspace,record);
  2017.  
  2018. end;
  2019. $page "qouto"
  2020. procedure qouto(workspace
  2021.                ,outfilename,size'in'blocks,numext,initext,lang);
  2022.    array workspace;
  2023.    array outfilename;
  2024.    integer size'in'blocks,numext,initext,lang;
  2025.    optiontype check 2;
  2026.    << parameters :
  2027.       workspace : logical array of 270 words; word 0 is set to 0 if no
  2028.                   error occurs,-1 if eof is met,
  2029.                     otherwise = file system error number.
  2030.                   word 1 is set to mpe file number.
  2031.                   workspace should not be modified by the caller
  2032.                   between the call to qouto and the call to qoutc.
  2033.       outfilename : integer or logical array containing filename.
  2034.                     definition as for fopen.
  2035.       size'in'blocks :    integer containing number of blocks required.
  2036.                     allow roughly (number of lines)/8+1.
  2037.                     it is not possible to use more than (lines-1)/5+2.
  2038.       numext   :    number of extents. as for fopen(1-32)
  2039.       initext  :      "    "    "     INITIALLY ALLOCATED. AS FOR FOPEN.
  2040.                     (0 to numext.)
  2041.       lang     :    "LANGUAGE" parameter for file.
  2042.                     0 -> spl
  2043.                     1 -> ftn
  2044.                     2 -> cob
  2045.                     3 -> old rpg
  2046.                     4 -> cobx
  2047.                     5 -> job
  2048.                     6 -> new rpg
  2049.                     7 -> text (256 byte records)
  2050.                     8 -> pascal
  2051.  
  2052. >>
  2053.  
  2054. << cobol call:
  2055.  
  2056.    call "QOUTO" using workspace (see below)
  2057.                       outfilename (pic x(30))
  2058.                       size'in'blocks    (s9(4) comp)
  2059.                       numext      (s9(4) comp)
  2060.                       initext     (s9(4) comp)
  2061.                       lang.       (s9(4) comp)
  2062.  
  2063.   declaration of workspace:
  2064.  
  2065.     01  workspace.
  2066.         05  qout-status   pic s9(4) comp.
  2067.         05  filler        pic s9(4) comp 0ccurs 269 times.
  2068.  
  2069. >>
  2070. begin
  2071.    integer array function(0:10);
  2072.  
  2073.   integer array qout'lang(0:8)=pb := <<qeditaccess codes>>
  2074.     1 <<spl=0>>
  2075.    ,2 <<ftn=1>>
  2076.    ,3 <<cob=2>>
  2077.    ,4 <<rpg-old=3>>
  2078.    ,8 <<cobolx=4>>
  2079.    ,5 <<job=5>>
  2080.    ,4 <<rpg-new=6>>
  2081.    ,6 <<text=7>>
  2082.    ,7 <<pas=8>>
  2083.    ;
  2084.  
  2085.  
  2086.   if 0<=lang<=8 then
  2087.   begin
  2088.     function := 9; <<open'new>>
  2089.     function(1) := qout'lang(lang); <<convert int=>ext>>
  2090.     function(2) := 256; <<text length for text files>>
  2091.     function(3) := size'in'blocks;
  2092.     function(4) := numext;
  2093.     function(5) := initext;
  2094.     qeditaccess(function,workspace,outfilename);
  2095.   end
  2096.   else workspace := 72;
  2097.  
  2098. end; << of qouto >>
  2099. $control list
  2100. end.  <<qaccess/qlib>>
  2101.