program dotmat(xbook,ybook,mlist,dotmatp,output); (* dotmat: dot matricies of two books by Thomas Schneider from module libraries: delman, delmods, prgmods (modules correspond to program matrix) *) label 1; (* end of program *) const (* begin module version *) version = 3.08; (* of dotmat 1994 sep 5 *) (* end module version *) (* begin module describe.dotmat *) (* name dotmat: dot matrices of two books synopsis dotmat(xbook: in, ybook: in, mlist: out, dotmatp: in, output: out) files xbook: a book from the delila system ybook: a book from the delila system mlist: a dot matrix for each sequence pair between the two books. the "dots" are printed as numbers: 1 means gt base pair 2 means at base pair 3 means gc base pair xbook sequences are written down the page and those of ybook go across the page. if mlist is wider than your printer, use the split program. dotmatp: parameters to control the mlist. if dotmatp is empty, default values are used. otherwise if the first line begins with a "g" then g-u pairs are printed. output: messages to the user description dotmat produces a dot matrix for all complementary base pairs between all pairs of sequences in the two books. because a list of helices is not made, the program is much more efficient for short minimum helices than is the pair of programs helix and matrix. documentation delman.use.comparison J. V. Maizel, Jr. and R. P. Lenk PNAS 78: 7665-7609 (1981) see also helix.p, matrix.p, split.p author thomas d. schneider bugs none known *) (* end module describe.dotmat *) (* more constants: *) nodot = ':'; (* the character to print for background, note: it must not blank, so that the user can align the helices by the numbers. *) prime = ''''; (* single quote *) pagelength = 48; (* lines printed of dotmat on one page in mlist *) (* begin module book.const *) (* constants needed for book manipulations *) dnamax = 3000; (* length of dna arrays *) namelength = 20; (* maximum key name length *) linelength = 80; (* maximum line readable in book *) (* end module book.const version = 'delmod 6.54 86 nov 12 tds/gds' *) type (* begin module book.type *) (* types needed for book manipulations *) chset = set of 'a'..'z'; (* types defined in book definition *) alpha = packed array[1..namelength] of char; (* this is not alfa *) (* name is a left justified string with blanks following the characters *) name = record letters: alpha; length: 0..namelength (* zero means an unspecified structure *) end; lineptr = ^line; line = record (* a line of characters *) letters: packed array [1..linelength] of char; length: 0..linelength; next: lineptr end; direction = (plus, minus, dircomplement, dirhomologous); configuration = (linear, circular); state = (on, off); header = record (* header of key *) keynam: name; (* key name of structure *) fulnam: lineptr; (* full name of structure *) note: lineptr (* note key *) end; (* base types *) base = (a,c,g,t); dnaptr = ^dnastring; dnarange = 0..dnamax; seq = packed array[1..dnamax] of base; dnastring = record part: seq; length: dnarange; next: dnaptr end; orgkey = record (* organism key *) hea: header; mapunit: lineptr (* genetic map units *) end; chrkey = record (* chromosome key *) hea: header; mapbeg: real; (* number of genetic map beginning *) mapend: real (* number of genetic map ending *) end; pieceptr = ^piece; piekey = record (* piece key *) hea: header; mapbeg: real; (* genetic map beginning *) coocon: configuration; (* configruation (circular/linear) *) coodir: direction; (* direction (+/-) relative to genetic map *) coobeg: integer; (* beginning nucleotide *) cooend: integer; (* ending nucleotide *) piecon: configuration; (* configruation (circular/linear) *) piedir: direction; (* direction (+/-) relative to coordinates *) piebeg: integer; (* beginning nucleotide *) pieend: integer; (* ending nucleotide *) end; piece = record key: piekey; dna: dnaptr end; reference = record pienam : name; (* name of piece referred to *) mapbeg : real; (* genetic map beginning *) refdir : direction; (* direction relative to coordinates *) refbeg : integer; (* beginning nucleotide *) refend : integer; (* ending nucleotide *) end; genkey = record (* gene key *) hea : header; ref : reference; end; trakey = record (* transcript key *) hea : header; ref : reference; end; markerptr = ^marker; markey = record (* marker key *) hea : header; ref : reference; sta : state; phenotype : lineptr; next : markerptr; end; marker = record key : markey; dna : dnaptr; end; (* end module book.type version = 'delmod 6.54 86 nov 12 tds/gds' *) var xbook, (* one book *) ybook, (* the other book *) mlist, (* the dot matricies *) dotmatp: (* parameters *) text; xseq, yseq: pieceptr; (* the sequences from the books *) xnumber, ynumber: integer; (* the numbers of the sequences *) guallowed: boolean; (* true means gu pairs are allowed *) xlength, ylength: integer; (* of the sequences *) (* begin module book.var *) (* ************************************************************************ *) (* global variables needed for book manipulations *) (* free storage: *) freeline: lineptr; (* unused lines *) freedna: dnaptr; (* unused dnas *) readnumber: boolean; (* whether to read a number from the notes, or to read in the notes *) number: integer; (* the number of the item just read *) numbered: boolean; (* true when the item just read is numbered *) skipunnum: boolean; (* a control variable to allow skipping of un-numbered items in the book *) (* ************************************************************************ *) (* end module book.var version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module halt *) procedure halt; (* stop the program. the procedure performs a goto to the end of the program. you must have a label: label 1; declared, and also the end of the program must have this label: 1: end. examples are in the module libraries. this is the only goto in the delila system. *) begin writeln(output,' program halt.'); goto 1 end; (* end module halt version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module package.getpiece *) (* ************************************************************************ *) (* begin module package.brpiece *) (* ************************************************************************ *) (* begin module book.basis *) (* procedures needed for book manipulations *) (* get procedures should be used for all linked lists of records *) procedure getline(var l: lineptr); (* obtain a line from the free line list or by making a new one *) begin if freeline<>nil then begin l:=freeline; freeline:=freeline^.next end else new(l); l^.length:=0; l^.next:=nil end; procedure getdna(var l: dnaptr); begin if freedna<>nil then begin l:=freedna; freedna:=freedna^.next end else new(l); l^.length:=0; l^.next:=nil end; (* clear procedures should be called each time the records are no longer needed failure to do this may result in a stack overflow. *) procedure clearline(var l: lineptr); (* return a line to the free line list *) var lptr: lineptr; begin if l<>nil then begin lptr:=l; l:=l^.next; lptr^.next:=freeline; freeline:=lptr end end; procedure cleardna(var l: dnaptr); var lptr: dnaptr; begin if l<>nil then begin lptr:=l; l:=l^.next; lptr^.next:=freedna; freedna:=lptr end end; procedure clearheader(var h: header); (* clear the header h (remove lines to free storage) *) begin with h do begin clearline(fulnam); while note<>nil do clearline(note) end end; procedure clearpiece(var p: pieceptr); (* clear the dna of the piece *) begin while p^.dna<>nil do cleardna(p^.dna); clearheader(p^.key.hea) end; function chartobase(ch:char):base; (* convert a character into a base *) begin case ch of 'a': chartobase:=a; 'c': chartobase:=c; 'g': chartobase:=g; 't': chartobase:=t end end; function basetochar(ba:base):char; (* convert a base into a character *) begin case ba of a: basetochar:='a'; c: basetochar:='c'; g: basetochar:='g'; t: basetochar:='t'; end end; function complement(ba:base):base; (* take the complement of ba *) begin case ba of a: complement:=t; c: complement:=g; g: complement:=c; t: complement:=a; end end; function pietoint(p: integer; pie: pieceptr): integer; (* p is a coordinate on the piece. we want to transform p into a number from 1 to n: an internal coordinate system for easy manipulation of piece coordinates *) var i: integer; (* an intermediate value *) begin with pie^.key do begin case piedir of plus: if p>=piebeg then i:=p-piebeg+1 else i:=(p-coobeg)+(cooend-piebeg)+2; minus: if p<=piebeg then i:=piebeg-p+1 else i:=(cooend-p)+(piebeg-coobeg)+2 end; pietoint:=i end end; function inttopie(i: integer; pie: pieceptr):integer; (* i is in the range 1 to some maximum. it is an internal coordinate system for the program. we want to do a coordinate transformation to obtain a value in the range of the piece called pie: i=1 corresponds to piebeg and i=its maximum corresponds to pieend *) var p: integer; (* an intermediate value *) begin with pie^.key do begin case piedir of plus: begin p:=piebeg+(i-1); if p>cooend then if coocon=circular then p:=p-(cooend-coobeg+1) end; minus: begin p:=piebeg-(i-1); if p '*' then begin writeln(output,' procedure skipstar: bad book'); writeln(output,' "*" expected as first character on the line, but "', thefile^,'" was found'); halt end; get(thefile); (* skip the star *) if thefile^ <> ' ' then begin writeln(output,' procedure skipstar: bad book'); writeln(output,' "* " expected on a line but "*', thefile^,'" was found'); halt end; get(thefile) (* skip the blank *) end; (* skipstar *) (* end module book.skipstar version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brreanum *) procedure brreanum(var thefile: text; var reanum: real); (* read a real number from the file *) begin skipstar(thefile); readln(thefile,reanum); end; (* end module book.brreanum version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brnumber *) procedure brnumber(var thefile: text; var num: integer); (* read a number from the file *) begin skipstar(thefile); readln(thefile,num) end; (* end module book.brnumber version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brname *) procedure brname(var thefile: text; var nam: name); (* read a name from the file *) var i: integer; (* an index to the name *) c: char; (* a character read *) begin (* brname *) skipstar(thefile); with nam do begin length:=0; repeat length:=succ(length); read(thefile,c); letters[length] := c until (eoln(thefile)) or (length>=namelength) or (letters[length]=' '); if letters[length]=' ' then length:=length-1; if length 'n' then begin skipstar(thefile); if not eoln(thefile) then begin if thefile^ = '#' then begin numbered := true; get(thefile); (* move past the number symbol *) read(thefile,number); end end; repeat readln(thefile) until thefile^ = 'n'; readln(thefile) end else readln(thefile) end end; (* brnotenumber *) (* end module book.brnotenumber version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brnote *) procedure brnote(var thefile: text; var note: lineptr); (* read note key *) var newnote: lineptr; (* the new note *) previousnote: lineptr; (* the last line of the notes *) begin (* brnote *) note:=nil; if thefile^ = 'n' then begin (* enter note *) readln(thefile); if thefile^ <> 'n' then begin (* abort null note (n/n) *) getline(note); newnote:=note; while thefile^ <> 'n' do begin (* wait until end of note *) brline(thefile,newnote); previousnote:=newnote; (* get next note *) getline(newnote^.next); newnote:=newnote^.next; end; (* last note was not used, so: *) clearline(newnote); previousnote^.next:=nil; readln(thefile) end else readln(thefile) end end; (* brnote *) (* end module book.brnote version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brheader *) procedure brheader(var thefile: text; var hea: header); (* read the header of a key. *) begin with hea do begin (* read key name *) brname(thefile,keynam); (* read full name *) getline(fulnam); brline(thefile,fulnam); (* read note key *) if readnumber then brnotenumber(thefile,note) else brnote(thefile,note) end end; (* end module book.brheader version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brpiekey *) procedure brpiekey(var thefile: text; var pie: piekey); (* read piece key *) begin with pie do begin brheader(thefile,hea); brreanum(thefile,mapbeg); brconfig(thefile,coocon); brdirect(thefile,coodir); brnumber(thefile,coobeg); brnumber(thefile,cooend); brconfig(thefile,piecon); brdirect(thefile,piedir); brnumber(thefile,piebeg); brnumber(thefile,pieend); end end; (* end module book.brpiekey version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brdna *) procedure brdna(var thefile: text; var dna: dnaptr); (* read in dna from thefile *) (* note: if the dna were circularized, by linking the last dnastring to the first, then the cleardna routine could not clear properly, and would loop forever... there is no reason to do that, since a simple mod function will allow one to access the circle. *) var ch: char; workdna: dnaptr; begin getdna(dna); workdna:=dna; ch:=getto(thefile,['d']); read(thefile,ch); (* skipstar *) while (ch = '*') do begin read(thefile,ch); (* skip blank *) repeat read(thefile,ch); if ch in ['a','c','g','t'] then begin if workdna^.length=dnamax then begin getdna(workdna^.next); workdna:=workdna^.next end; workdna^.length:=succ(workdna^.length); workdna^.part[workdna^.length]:=chartobase(ch) end until eoln(thefile); readln(thefile); (* go to next line *) read(thefile,ch); (* ch is either '*' or 'd' *) end; readln(thefile) end; (* end module book.brdna version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brpiece *) procedure brpiece(var thefile: text; var pie: pieceptr); (* read in a piece *) begin brpiekey(thefile,pie^.key); if numbered or (not skipunnum) then brdna(thefile,pie^.dna) end; (* end module book.brpiece version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.brinit *) procedure brinit(var book: text); (* check that the book is ok to read, and set up the global variables for br routines *) begin (* brinit *) (* halt if the book is bad (first word is 'halt') or the first character is not * *) reset(book); if not eof(book) then begin (* check for the date line *) if book^ <> '*' then begin if book^ <> 'h' then writeln(output, ' this is not the first line of a book:') else writeln(output, ' bad book:'); write(output, ' '); while not (eoln(book) or eof(book)) do begin write(output, book^); get(book) end; writeln(output); halt end end else begin writeln(output, ' book is empty'); halt end; (* initialize free storage *) freeline:=nil; freedna:=nil; readnumber:=true; (* usually we read in numbers for items *) number:=0; (* arbitrary value *) numbered:=false; (* the piece has no number (none yet read in) *) skipunnum:=false; end; (* brinit *) (* end module book.brinit version = 'delmod 6.54 86 nov 12 tds/gds' *) (* ************************************************************************ *) (* end module package.brpiece version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.getpiece *) procedure getpiece(var thefile: text; var pie: pieceptr); (* move to and read in the next piece in the book *) var ch: char; begin ch:=getto(thefile,['p']); (* get to the next p(iece) in the book *) if ch<>' ' then begin brpiece(thefile,pie); ch:=getto(thefile,['p']); (* read past closing p *) end end; (* end module book.getpiece version = 'delmod 6.54 86 nov 12 tds/gds' *) (* ************************************************************************ *) (* end module package.getpiece version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module book.getbase *) function getbase(position: integer; pie: pieceptr):base; (* get a base from the nth position (internal coordinates) of the piece. no protection is made against positions outside the piece *) var workdna: dnaptr; p: integer; (* the last base of the dna part *) begin workdna:=pie^.dna; p:=dnamax; while position>p do begin p:=p+dnamax; workdna:=workdna^.next end; getbase:=workdna^.part[position-(p-dnamax)] end; (* end module book.getbase version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module basepair *) function basepair(xseq,yseq: pieceptr; x,y: integer; guallowed: boolean) :boolean; (* does xseq basepair to yseq at x to y? allow gu pair if guallowed is true. a series of if-then statements are used for speed. *) var bx,by: base; (* bases in the sequences *) begin bx := getbase(x,xseq); by := getbase(y,yseq); if bx = complement(by) then basepair := true else if guallowed then if (bx=g) and (by=t) then basepair := true else if (bx=t) and (by=g) then basepair := true else basepair := false else basepair := false end; (* end module basepair version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module copyaline *) procedure copyaline(var fin, fout: text); (* copy a line from file fin to file fout *) begin (* copyaline *) while not eoln(fin) do begin fout^ := fin^; put(fout); get(fin) end; readln(fin); writeln(fout); end; (* copyaline *) (* end module copyaline version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module unlimitln *) procedure unlimitln(var afile: text); (* this procedure removes a stupid system dependent limit on the number of lines that one can write to a file. you may remove it from the code if your system does not want or need this. suggested method: place comments around the contents of the procedure. *) begin (* linelimit(afile, maxint); (@ set 'infinite' lines allowed for afile *) end; (* end module unlimitln version = 'delmod 6.54 86 nov 12 tds/gds' *) (* begin module package.numbar *) (* ************************************************************************ *) (* begin module numberdigit *) function numberdigit(number, logplace:integer): char; (* return the digit at the place value ('logplace') position of number. example: numberdigit(13625, 3) = 3 numberdigit(13625, 4) = 1 *) var place: integer; (* the exponent of logplace *) count: integer; (* used to make place *) absolute: integer; (* the absolute value of number *) acharacter: char; (* the character to be returned *) procedure digit; (* extract a digit at the place position *) var tenplace: integer; (* ten times place *) z: integer; (* an intermediate value *) d: integer; (* the digit extracted *) begin (* digit *) tenplace:=10*place; z:=absolute-((absolute div tenplace)*tenplace); if place = 1 then d:=z else d:= z div place; case d of 0: acharacter:='0'; 1: acharacter:='1'; 2: acharacter:='2'; 3: acharacter:='3'; 4: acharacter:='4'; 5: acharacter:='5'; 6: acharacter:='6'; 7: acharacter:='7'; 8: acharacter:='8'; 9: acharacter:='9'; end end; (* digit *) procedure sign; (* put a negative sign out or a positive sign *) begin (* sign *) if number <0 then acharacter:='-' else acharacter:='+' end; (* sign *) begin (* numberdigit *) place:=1; for count:=1 to logplace do place:=10*place; if number=0 then begin if place=1 then acharacter:='0' else acharacter:=' ' end else begin absolute:=abs(number); if absolute < (place div 10) then acharacter:=' ' else if absolute >= place then digit else sign end; numberdigit:=acharacter end; (* numberdigit *) (* end module numberdigit version = 'prgmod 3.96 85 mar 18 tds'; *) (* begin module numbersize *) function numbersize(n: integer):integer; (* calculate amount of space to be reserved for the integer n *) const ln10 = 2.30259; (* natural log of 10 - for conversion to log base 10 *) epsilon = 0.00001; (* a small number to correct log base 10 errors *) begin (* numbersize *) if n = 0 then numbersize:=1 else numbersize:=trunc(ln(abs(n))/ln10 + epsilon) + 2; (* the epsilon assures that we do not lose a place due to roundoff. eg, sometimes log base 10 of 10 would be 0.9999 instead of 1, and we would not do it right... note: this will fail for very large numbers on the order of 1/epsilon. *) (* the 2 is for the sign and last digit *) end; (* numbersize *) (* end module numbersize version = 'prgmod 3.96 85 mar 18 tds'; *) (* begin module numberbar *) procedure numberbar(var afile: text; spaces, firstnumber, lastnumber: integer; var linesused: integer); (* write a bar of numbers to a file, with several spaces before. the number of lines used is returned *) var logplace: integer; (* the log of the digit being looked at *) spacecount: integer; (* count of spaces *) number: integer; (* the current number being written *) begin if abs(firstnumber) > abs(lastnumber) then linesused:= numbersize(firstnumber) else linesused:= numbersize(lastnumber); for logplace:=linesused-1 downto 0 do begin for spacecount:=1 to spaces do write(afile,' '); for number:=firstnumber to lastnumber do write(afile,numberdigit(number,logplace)); writeln(afile) end end; (* end module numberbar version = 'prgmod 3.96 85 mar 18 tds'; *) (* ************************************************************************ *) (* end module package.numbar version = 'prgmod 3.96 85 mar 18 tds'; *) procedure initialize; (* set up all the variables *) begin writeln(output,' dotmat ',version:4:2); brinit(xbook); brinit(ybook); rewrite(mlist); unlimitln(mlist); new(xseq); new(yseq); (* read parameters *) reset(dotmatp); if eof(dotmatp) then guallowed:=false else if dotmatp^='g' then guallowed := true else guallowed := false; (* put header in mlist *) writeln(mlist,' dotmat ',version:4:2,' from:'); write(mlist,' '); copyaline(xbook,mlist); write(mlist,' '); copyaline(ybook,mlist); writeln(mlist); write(mlist,' gu pairs are'); if not guallowed then write(mlist,' not'); writeln(mlist,' allowed.'); writeln(mlist); writeln(mlist,' symbols used:'); writeln(mlist,' ',nodot,' no complementary bases between these points'); writeln(mlist,' 1 gt base pair'); writeln(mlist,' 2 at base pair'); writeln(mlist,' 3 gc base pair'); end; (****************************************************************************) (* begin module dotmat.piecebar *) procedure piecebar(var afile: text; spaces: integer; pie: pieceptr; firstnumber,lastnumber: integer; var linesused: integer); (* write a bar of numbers of the piece pie to a file, with several spaces before. the number of lines used is returned. based on procedure numbar. external procedures required: inttopie numbersize numberdigit *) var logpower: integer; (* the log of the digit being looked at *) spacecount: integer; (* count of spaces *) number: integer; (* the current number being written *) numbers: file of integer; (* a file for storing all the piece numbers *) width: integer; (* the lines used by one number *) index: integer; (* to pie *) begin (* calculate lines used and fill up the numbers file *) linesused:=0; rewrite(numbers); for index:=firstnumber to lastnumber do begin number:=inttopie(index,pie); write(numbers,number); width:=numbersize(number); if width > linesused then linesused:=width end; for logpower:=linesused-1 downto 0 do begin for spacecount:=1 to spaces do write(afile,' '); reset(numbers); while not eof(numbers) do begin read(numbers,number); write(afile,numberdigit(number,logpower)) end; writeln(afile) end end; (* end module dotmat.piecebar *) (* begin module dotmat.makedna *) procedure makedna(var afile: text; spaces: integer; pie: pieceptr; firstnumber, lastnumber: integer); (* write a line of dna to a file, preceeded by several spaces *) var spacecount: integer; (* count spaces *) index: integer; (* to pie *) begin for spacecount:=1 to spaces - 3 do write(afile,' '); write(afile,'5',prime,' '); for index:=firstnumber to lastnumber do write(afile,basetochar(getbase(index,pie))); writeln(afile,' 3',prime) end; (* end module dotmat.makedna *) (* begin module dotmat.makepageheader *) procedure makepageheader(var pageheader: text); var lines: integer; (* dummy until lines are counted by matrix *) begin rewrite(pageheader); page(pageheader); writeln(pageheader,' matrix, ', ' x down: ' ,xnumber:1,' ',xseq^.key.hea.keynam.letters, ' y across: ',ynumber:1,' ',yseq^.key.hea.keynam.letters); writeln(pageheader); piecebar(pageheader,10,yseq,1,ylength,lines); makedna(pageheader,10,yseq,1,ylength); writeln(pageheader,' 5',prime); (* 8 spaces *) end; (* end module dotmat.makepageheader *) (* begin module dotmat.printpageheader *) procedure printpageheader(var pageheader: text); (* print the page header *) begin reset(pageheader); while not eof(pageheader) do begin while not eoln(pageheader) do begin write(mlist,pageheader^); get(pageheader) end; readln(pageheader); writeln(mlist) end end; (* end module dotmat.printpageheader *) procedure printarray; (* print out the array to mlist *) var pageheader: text; (* the header for pages of mlist *) x, y: integer; (* a point in the matrix *) bx, by: base; (* bases at x and y of xseq and yseq respecitvely *) begin (* print array *) makepageheader(pageheader); for x:=1 to xlength do begin if ((x mod pagelength) = 0) or (x = 1) then printpageheader(pageheader); bx := getbase(x, xseq); write(mlist,' ',inttopie(x,xseq):6,' ',basetochar(bx),' '); for y:=1 to ylength do if basepair(xseq,yseq,x,y,guallowed) then begin (* make a number at the place *) by := getbase(y, yseq); if bx = complement(by) then case bx of a: write(mlist,'2'); c: write(mlist,'3'); g: write(mlist,'3'); t: write(mlist,'2'); end else write(mlist,'1') (* for gu pairs *) end else write(mlist,nodot); writeln(mlist) end; writeln(mlist,' 3',prime); (* 8 spaces *) end; procedure printdotmat; (* print the dotmat for xseq and yseq *) begin printarray end; begin initialize; while not eof(xbook) do begin getpiece(xbook,xseq); xnumber:=number; xlength:=piecelength(xseq); if not eof(xbook) then begin reset(ybook); while not eof(ybook) do begin getpiece(ybook,yseq); ynumber:=number; ylength:=piecelength(yseq); if not eof(ybook) then begin printdotmat; clearpiece(yseq) end end; clearpiece(xseq) end end; 1: end. (* of dotmat *)