Chead
From Pickwiki
Jump to navigationJump to searchBack to BasicSource
This is a QM-only utility to display information about compiled code. It can display the header information and the flags set in the header.
It can also show the local and common variables used, the line concordance, and a dump of the code using decimal or hexadecimal output, but these are not accurate if the DEBUGGING compile option was used.
It can also be used to display the opcodes QM uses (as at version 2.6).
program chead
*
* To investigate QMBASIC object code. Version 1.0
*
copyright = 'Copyright Keith Robert Johnson 2008'
*v This data is from the open source OPCODES.H - Version 2.6
* Simple opcodes
opcodes = "STOP]ABORT]RETURN]JMP]JPO]JPZ]JNG]JZE"
opcodes := "]JNZ]]GOSUB]RETURNTO]CALL]ONGOTO]ONGOSUB]RUN"
opcodes := "]LDSINT]LDLINT]LDSTR]LDNULL]LDLCL]LDCOM]STOR]POP"
opcodes := "]DUP]LDSLCL]LDSYS]LD0]LD1]NULL]EXCH]VALUE"
opcodes := "]ADD]SUB]MUL]DIV]NEG]INT]INC]DEC"
opcodes := "]MOD]PWR]ABS]REM]LN]EXP]REUSE]IDIV"
opcodes := "]DSP]DSPNL]LDUNASS]AT]PROFF]PRON]PAGE]BREAKCT"
opcodes := "]KEYRDY]KEYIN]PRINTERR]PROMPT]GETPROMPT]KEYINC]BREAK]LOCATE"
opcodes := "]LEN]SUBSTR]SUBSTRE]CAT]REMOVE]CHAR]SEQ]EXTRACT"
opcodes := "]REPLACE]INS]DEL]LOCATES]SPACE]STR]DNCASE]UPCASE"
opcodes := "]RMVTKN]INSERT]FIELD]COL1]COL2]FLDSTOR]FMT]ICONV"
opcodes := "]OCONV]SUBSTRA]TRIM]TRIMF]TRIMB]COUNT]DCOUNT]INDEX"
opcodes := "]EQ]NE]GT]LT]NOT]AND]OR]BITAND"
opcodes := "]BITOR]BITNOT]GE]LE]SHIFT]BITXOR]BITSET]BITRESET"
opcodes := "]OPEN]READ]READV]WRITEV]DELETE]WRITE]CLOSE]QUOTIENT"
opcodes := "]FORLOOPS][[FOR1S]]]KEYINR]OPENPATH]SYSDIR]KEYINT]KEYINCT]TRANS"
opcodes := "]DIMLCL]DIMCOM]INDX1]INDX2]INMAT]INMATA]KEYINRT]MATCOPY"
opcodes := "]MATFILL]MATPARSE]MATBUILD]DELCOM]MATREAD]GETREM]SETREM]COMMON"
opcodes := "]STATUS]ONERROR]NOWAIT]SETMODE]CLRMODE]SETSTAT]SWAP]FOLD3"
opcodes := "]FILEINFO]OSPATH]TIME]DATE]TIMEDATE]EXECUTE]]ITYPE"
opcodes := "]ALPHA]NUM]APPEND]TRIMX]SOUNDEX]MATCHES]RAISE]LOWER"
opcodes := "]SUM]CONVERT]FCONVERT]COMPARE]FLDSTORF]MATCHFLD]QUOTE]RMVF"
opcodes := "]SELECT]CLEARSEL]CLEARALL]SLCTINFO]READNEXT]RDNXEXP]RDNXPOS]SSELECT"
opcodes := "]FORMLIST]READLIST]SYSMSG]]]]JFALSE]JTRUE"
opcodes := "]ACOS]ASIN]ATAN]COS]SIN]TAN]SQRT]RND"
opcodes := "]LDFLOAT]REP]STZ]STNULL]LDSYSV]UNASS]BITTEST]PREFIX"
opcodes := "]FORINIT]FORLOOP]FOR1]SLEEP]CLRFILE]QUIT]LOCK]UNLOCK"
opcodes := "]RELEASE]RECLCKD]FILELOCK]FLUNLOCK]LOCKREC]RLSALL]GETLOCKS]FOLD"
opcodes := "]SAVESCRN]RSTSCRN]TRACE]PRECISION]CHKCAT]CLEAR]CLRCOM]CHAIN"
opcodes := "]ULOCK]LLOCK]MVD]MVDS]MVDSS]MVDSSS]ASS]MVDD"
opcodes := "]CLRINPUT]HUSH]DATA]TESTLOCK]HEADING]FOOTING]PRNT]PRNL"
opcodes := "]PSET]PRCLOSE]PRFILE]SH]DEBUG]DBGINF]DBGBRK]KERNEL"
convert ']' to @vm in opcodes
* Extended opcodes
excodes = "PABORT]NAP]TOTAL]IFS]SETNLS]GETNLS]ITYPE2]CALLV"
excodes := "]ABORTMSG]PWCRYPT]LOGIN]UMASK]TERMINFO]KEYCODE]ERRMSG]VARTYPE"
excodes := "]CROP]FIND]CHANGE]VSLICE]FINDSTR]SUBSTRNG]SWAPCASE]REPADD"
excodes := "]REPSUB]REPMUL]REPDIV]REPCAT]MAXIMUM]MINIMUM]CHANGED]REPSUBST"
excodes := "]DBGON]DBGOFF]UNLOAD]CAPTURE]PHANTOM]RTNLIST]SYSTEM]ABTCAUSE"
excodes := "]LOGOUT]USERNO]ISSUBR]LISTCOM]DBGWATCH]EVENTS]DBGSET]PCONFIG"
excodes := "]TTYGET]TTYSET]INPUTAT]INPUT]PRNAME]PRDISP]COMO]PTERM"
excodes := "]HEADINGN]PRRESET]EBCDIC]ASCII]DTX]GETLIST]SAVELIST]GETPU"
excodes := "]RDIV]SUMMATION]SEED]SETPU]OPTION]ENV]CONFIG]SENDMAIL"
excodes := "]SQUOTE]DELLIST]SORTDATA]SELECTV]SELECTE]PASSLIST]BINDKEY]CHECKSUM"
excodes := "]SEEK]READBLK]WRITEBLK]ANALYSE]CONFIGFL]FLUSH]CREATESQ]UNLK"
excodes := "]UNLKFL]OSRENAME]GRPSTAT]SETTRIG]KEYCODET]KEYEDIT]KEYEXIT]KEYTRAP"
excodes := "]OPENSEQ]READSEQ]WRITESEQ]WEOFSEQ]WRITESEQF]OPENSEQP]CREATEAK]AKRELEASE"
excodes := "]AKWRITE]AKREAD]AKDELETE]DELETEAK]SELINDX]SELINDXV]AKCLEAR]AKENABLE"
excodes := "]CREATEDH]CREATET1]MAPMARKS]SELLEFT]SELRIGHT]SETLEFT]SETRIGHT]INDICES1"
excodes := "]INDICES2]TXNBGN]TXNCMT]TXNEND]TXNRBK]OSERROR]NOBUF]XTD"
excodes := "]BTINIT]BTADD]BTSCAN]BTRESET]BTADDA]BTMODIFY]BTFIND]BTSCANA"
excodes := "]LOADOBJ]LOADED]SPLICE]PACKAGE]LOCATEF]LISTINDX]MIN]MAX"
excodes := "]SORTINIT]SORTADD]SORTNEXT]SORTCLR]RLSFILE]DIR]PMATRIX]DIMLCLP"
excodes := "]LOGMSG]SHCAP]PROCREAD]DEREF]IADD]ISUB]IMUL]SCALE"
excodes := "]READPKT]WRITEPKT]CHGPHANT]ONGOTOP]ONGOSUBP]READONLY]PICKREAD]STORSYS"
excodes := "]SUBST]PSUBSTRA]SAVEADDR]COMPREP]COMPINS]COMPINSRT]COMPREPLC]FCONTROL"
excodes := "]GETPORT]SETPORT]CCALL]ENTER]SETFLAGS]GETMSG]CSVDQ]OJOIN"
excodes := "]EXPANDHF]LOCAL]DELLCL]AKMAP]SRVRADDR]OBJECT]OBJMAP]OBJREF"
excodes := "]OPENSKT]CLOSESKT]READSKT]WRITESKT]SRVRSKT]ACCPTSKT]SKTINFO]SETSKT"
excodes := "]FORMCSV]ISMV]SETUNASS]TIMEOUT]IN]ME]GET]SET"
excodes := "]ARGCT]ARG]RTRANS]PAUSE]WAKE]PSUBSTRB]DELSEQ]CNCTPORT"
excodes := "]LGNPORT]OBJINFO]INHERIT]DISINH]CREATESH]LDLSTR]RDNXINT]ENCRYPT"
excodes := "]DECRYPT]CRYPT]INPUTBLK]NEGS]ABSS]LENS]SPACES]TRIMS"
excodes := "]TRIMFS]TRIMBS]NOTS]NUMS]SOUNDEXS]STRS]FMTS]ICONVS"
excodes := "]OCONVS]COUNTS]FOLDS]INDEXS]FOLDS3]TRIMXS]FIELDS]MODS"
excodes := "]CATS]EQS]NES]GTS]LTS]ANDS]ORS]GES"
excodes := "]LES"
convert ']' to @vm in excodes
* Extended opcode values
values = "52992]52993]52994]52995]52996]52997]52998]52999"
values := "]53000]53001]53002]53003]53004]53005]53006]53007"
values := "]53008]53009]53010]53011]53012]53013]53014]53015"
values := "]53016]53017]53018]53019]53020]53021]53022]53023"
values := "]53024]53025]53026]53027]53028]53029]53030]53031"
values := "]53032]53033]53034]53035]53036]53037]53038]53039"
values := "]53040]53041]53042]53043]53044]53045]53046]53047"
values := "]53048]53049]53050]53051]53052]53053]53054]53055"
values := "]53056]53057]53058]53059]53060]53061]53062]53063"
values := "]53064]53065]53066]53067]53068]53069]53070]53071"
values := "]53072]53073]53074]53075]53076]53077]53078]53079"
values := "]53080]53081]53082]53083]53084]53085]53086]53087"
values := "]53088]53089]53090]53091]53092]53093]53094]53095"
values := "]53096]53097]53098]53099]53100]53101]53102]53103"
values := "]53104]53105]53106]53107]53108]53109]53110]53111"
values := "]53112]53113]53114]53115]53116]53117]53118]53119"
values := "]53120]53121]53122]53123]53124]53125]53126]53127"
values := "]53128]53129]53130]53131]53132]53133]53134]53135"
values := "]53136]53137]53138]53139]53140]53141]53142]53143"
values := "]53144]53145]53146]53147]53148]53149]53150]53151"
values := "]53152]53153]53154]53155]53156]53157]53158]53159"
values := "]53160]53161]53162]53163]53164]53165]53166]53167"
values := "]53168]53169]53170]53171]53172]53173]53174]53175"
values := "]53176]53177]53178]53179]53180]53181]53182]53183"
values := "]53184]53185]53186]53187]53188]53189]53190]53191"
values := "]53192]53193]53194]53195]53196]53197]53198]53199"
values := "]53200]53201]53202]53203]53204]53205]53206]53207"
values := "]53208]53209]53210]53211]53212]53213]53214]53215"
values := "]53216]53217]53218]59940]59946]59968]59980]59994"
values := "]59995]59996]60004]60065]60068]60237]60246]60247"
values := "]60248]60253]60383]60511]60567]60579]60754]61224"
values := "]61251]61280]61281]61282]61283]61285]61286]61290"
values := "]61291"
convert ']' to @vm in values
* Simple and extended opcode modes
smodes = "AAABBBBBB.BBCMMACDFAEHAAANCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAC.AAAAAAAAAAAAAAAAAAAAAAAAAAAC...BBAAAAAAAAGAAACAAKABBAAAAAAAAAAAAAAAAAAAAAAALLLLALAAAAAAAAAAAAJAAA"
xmodes = "AACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAMMAAAAAAAAAAAAAAAPAAAAQEAACRCAAAAAAAAAAAAAACCAAAAAAAAAAAAASAAAAA............................."
*^ End of data derived from OPCODES.H
* Parse the command line
comd = @sentence
comd = trim(comd)
convert ' ' to @am in comd
loop
this = comd<1>
del comd<1>
until upcase(this) eq 'CHEAD' or comd eq '' do
repeat
* Help
if comd<2> eq '' then
crt
crt 'Program to display information about compiled code.'
crt '---------------------------------------------------'
crt 'syntax: [RUN file] CHEAD FILE ITEM'
crt
crt 'This program will display information about'
crt 'the object code and about QMBASIC opcodes.'
crt
crt 'The output can be printed using P toggle.'
crt
crt 'NOTE: Incorrect if DEBUGGING option used.'
crt
stop
end
namf = comd<1>
name = comd<2>
* Get the source code if possible
if namf[4] eq '.OUT' then namf = namf[1,len(namf)-4]
sourcode = ''
open namf to srs.file then
read sourcode from srs.file,name else null
end
* Get the object code
namf = namf:'.OUT'
open namf to obj.file else
crt 'Cannot open object file ':namf
stop
end
read this from obj.file,name else
crt 'Cannot read object code ':name
stop
end
* Calculate the object size from the header information
* NOTE: LEN(THIS) is too short for big programs!
blen = oconv(this[25,4],'IL')
* The standard read converts char(10) to attribute marks
* Get item with a block sequential read to avoid this
openseq namf,name to code then
readblk this from code,blen else null
closeseq code
end
crt
* Get the header
lenh = 164
head = this[1,lenh]
begn = lenh+2
* Get the various variables we are interested in
nolocvar = oconv(head[13,2],'IS')
nosubarg = oconv(head[11,2],'IS')
symtabof = oconv(head[17,4],'IL')
lcordoff = oconv(head[21,4],'IL')
code.len = oconv(head[25,4],'IL')
hdrflags = oconv(head[29,2],'IS')
compiled = oconv(head[31,4],'IL')
d = int(compiled/86400)
t = rem(compiled,86400)
compiled = oconv(d,'D'):' ':oconv(t,'MTS')
* Change for later version
vers = seq(this[2,1])
if vers > 0 and symtabof then
lcordoff = symtabof + 4
symtabof += oconv(this[symtabof+2,2],'is')+4
end
* Some more for thoroughness
hdroffst = oconv(head[7,4],'IL')
stakdeep = oconv(head[15,2],'IS')
headrefs = oconv(head[35,2],'IS')
progname = head[37,128]
progname = trim(progname)
progname = trim(progname,char(0))
* Get the symbol table
symtable = ''
if symtabof then symtable = this[symtabof+1,blen]
symtable = trim(symtable,char(1),'T')
* Get the line table
lintable = ''
if lcordoff then
if symtabof
then lintable = this[lcordoff+2,symtabof-lcordoff-1]
else lintable = this[lcordoff+2,blen]
end
loclvars = ''
commvars = ''
commnumb = ''
if symtable ne '' then
loclvars = trim(symtable<1>,@vm,'T')
commvars = symtable
del commvars<1>
xxno = dcount(commvars,@am)
for xx = 1 to xxno
commnumb<-1> = commvars<xx,1>+1
next xx
end
* Get the code
begin case
case lcordoff
this = this[begn,lcordoff-lenh-1]
case symtabof
this = this[begn,symtabof-lenh-1]
case 1
this = this[begn,blen]
end case
* Present the user with a menu
prompt ''
pout = @false
plen = system(3) - 1
loop
crt @(-1),namf,name
crt
crt ' H - Header information'
crt ' F - Flags set in header'
crt ' V - Variables (local)'
crt ' C - Common variables'
crt ' L - Line concordance'
crt ' O - Opcodes'
crt ' E - Extended opcodes'
crt ' D - Dump of code'
crt ' X - heXadecimal code dump'
crt
if pout
then crt ' P - Print output now ON turn OFF'
else crt ' P - Print output now OFF turn ON'
crt
crt ' Q - Quit'
crt
loop
crt @(0):@(-3):
* You can take the boy out of Mangere...
if rnd(20)
then crt ' Press choice key :':
else crt ' Cuzzy Bro - Press [[C_H_O_I_C_E]] key, eh?':
answ = upcase(keycode())
until answ ne '' and index('DXVCLHFPQOE',answ,1) do repeat
crt
if answ eq 'D' then gosub show.code
if answ eq 'X' then gosub show.code
if answ eq 'V' then gosub show.local
if answ eq 'C' then gosub show.common
if answ eq 'L' then gosub show.lines
if answ eq 'H' then gosub show.header
if answ eq 'F' then gosub show.flags
if answ eq 'P' then pout = not(pout)
if answ eq 'O' then gosub show.opcodes
if answ eq 'E' then gosub show.extended.opcodes
until answ eq 'Q' do repeat
crt
stop
************************ SUBROUTINES ********************************
show.code:
if answ eq 'D' then decm = @true else decm = @false
if this eq ''
then disp = 'THERE IS NO CODE TO SHOW'
else disp = 'DUMP OF CODE':@am
cntr = 0
size = 16
loop
part = this[cntr+1,size]
until part eq '' do
line = cntr 'R%4':':'
for xx = 1 to size
bite = part[xx,1]
if bite = '' then
bite = ' '
end else
if decm
then bite = seq(bite) 'R#3'
else bite = ' ':(dtx(seq(bite)) 'R%2')
end
line := bite
next xx
line := ' - ':oconv(part,'MCP')
disp<-1> = line
cntr += size
repeat
gosub display
return
show.local:
disp = ' Local Variables':@am
xxno = dcount(loclvars,@vm)
for xx = 1 to xxno
varb = loclvars<1,xx>
void = space(14-rem(len(varb),10))
locate(xx,commnumb;posn) then
if varb = '$'
then varb := void:'******* common block *******'
else varb := void:'****** labelled common ******'
end
begin case
case varb matches '"__"1[[N0X]]'
varb := void:'***** Temporary Variable ****'
case varb[1,2] eq '__'
varb := void:'******* FILE Variable *******'
case varb[1,1] eq '_'
varb := void:'***** Call to Subroutine ****'
case varb[1,1] eq '~'
varb := void:'******** Object code ********'
case varb[1,1] eq '*'
varb := void:'****** Object Argument ******'
end case
disp<-1> = xx 'R#5':' ':varb
next xx
if loclvars eq '' then disp = 'THERE IS NO VARIABLE INFORMATION'
gosub display
return
show.common:
disp = 'COMMON BLOCK DISPLAY':@am
xxno = dcount(commvars,@am)
for xx = 1 to xxno
line = commvars<xx>
comm = line<1,1>
del line<1,1>
comm += 1
comm = loclvars<1,comm>
if comm = '$'
then disp<-1> = ' Common Block'
else disp<-1> = ' ':comm:' - Labelled common'
yyno = dcount(line,@sm)
for yy = 1 to yyno
disp<-1> = yy 'R#5':' ':line<1,1,yy>
next yy
if xx ne xxno then disp<-1> = ' '
next xx
if commvars eq '' then disp = 'THERE ARE NO COMMON BLOCKS, OR THERE IS NO INFORMATION'
gosub display
return
show.lines:
disp = 'LINE CONCORDANCE TABLE'
disp<-1> = ' Line# Length of object in line'
xx = 0
line = 0
loop
xx += 1
part = lintable[xx,1]
until part eq '' do
seqn = seq(part)
if seqn = 255 then
xx += 1 ; seqn = seq(lintable[xx,1])
xx += 1 ; seqn += seq(lintable[xx,1])*256
end
line += 1
if seqn then disp<-1> = line 'R#6':' ':seqn
repeat
if lintable eq '' then disp = 'THERE IS NO LINE INFORMATION'
gosub display
return
show.header:
disp = 'HEADER INFORMATION - ':progname:@am
disp<-1> = 'Endian hint' 'R#35':' ': seq(head[1,1])
disp<-1> = 'Header Revision' 'R#35':' ': seq(head[2,1])
disp<-1> = 'Header Offset' 'R#35':' ': hdroffst
disp<-1> = 'Number of local variables' 'R#35':' ': nolocvar
disp<-1> = 'Number of subroutine arguments' 'R#35':' ': nosubarg
disp<-1> = 'Stack Depth' 'R#35':' ': stakdeep
disp<-1> = 'Symbol table offset' 'R#35':' ': symtabof
disp<-1> = 'Line concordance offset' 'R#35':' ': lcordoff
disp<-1> = 'Line concordance table size' 'R#35':' ': len(lintable)
disp<-1> = 'Object size' 'R#35':' ': code.len
disp<-1> = 'Code size' 'R#35':' ': len(this)
disp<-1> = 'When compiled' 'R#35':' ': compiled
disp<-1> = 'Header References' 'R#35':' ': headrefs
gosub display
return
show.flags:
disp = 'FLAG INFORMATION':@am
disp<-1> = 'Command processor' 'R#35':' ': bittest(hdrflags,0)
disp<-1> = 'Internal mode program' 'R#35':' ': bittest(hdrflags,1)
disp<-1> = 'Compiled in debug mode' 'R#35':' ': bittest(hdrflags,2)
disp<-1> = 'Debugger' 'R#35':' ': bittest(hdrflags,3)
disp<-1> = 'Case insensitive string operations' 'R#35':' ': bittest(hdrflags,4)
disp<-1> = 'Basic function' 'R#35':' ': bittest(hdrflags,5)
disp<-1> = 'Variable arg count (hdr.args = max)' 'R#35':' ': bittest(hdrflags,6)
disp<-1> = 'Is a recursive program' 'R#35':' ': bittest(hdrflags,7)
disp<-1> = 'Is an A[[/S/C/I]]-type' 'R#35':' ': bittest(hdrflags,8)
disp<-1> = 'Allow break in recursive' 'R#35':' ': bittest(hdrflags,9)
disp<-1> = 'Trusted program' 'R#35':' ': bittest(hdrflags,10)
disp<-1> = 'Allow remote files by NFS' 'R#35':' ': bittest(hdrflags,11)
disp<-1> = 'Program uses case sensitive names' 'R#35':' ': bittest(hdrflags,12)
disp<-1> = 'Can be called using QMCall()' 'R#35':' ': bittest(hdrflags,13)
disp<-1> = 'Is a C-type' 'R#35':' ': bittest(hdrflags,14)
disp<-1> = 'Is CLASS module' 'R#35':' ': bittest(hdrflags,15)
gosub display
return
show.opcodes:
disp = 'Simple OPCODES':@am
xxno = dcount(opcodes,@vm)
for xx = 1 to xxno
numb = xx-1
hexn = dtx(numb) 'R%2'
mode = smodes[xx,1]
gosub get.mode.show
disp<-1> = numb 'R#5':' ':hexn:' ':opcodes<1,xx> 'l#10':show
next xx
if opcodes eq '' then disp = 'THERE ARE NO SIMPLE OPCODES'
gosub display
return
show.extended.opcodes:
disp = 'Extended OPCODES':@am
xxno = dcount(excodes,@vm)
for xx = 1 to xxno
numb = values<1,xx>
hexn = dtx(numb) 'R%4'
mode = xmodes[xx,1]
gosub get.mode.show
line = numb:' ':hexn:' ':excodes<1,xx> 'L#10':show
disp<-1> = line
next xx
if excodes eq '' then disp = 'THERE ARE NO EXTENDED OPCODES'
gosub display
return
get.mode.show:
begin case
case mode eq 'A' ; show = 'Opcode Byte' ; show = '' ; * Tidier
case mode eq 'B' ; show = 'Jump Address'
case mode eq 'C' ; show = 'One Byte Value'
case mode eq 'D' ; show = 'Four Byte Value'
case mode eq 'E' ; show = 'Local Variable'
case mode eq 'F' ; show = 'String Value'
case mode eq 'G' ; show = 'Float Value'
case mode eq 'H' ; show = 'Common Variable'
case mode eq 'I' ; show = 'Common Dcl'
case mode eq 'J' ; show = 'Debug Reference'
case mode eq 'K' ; show = 'Opcode Prefix'
case mode eq 'L' ; show = 'Multivalue Opcode'
case mode eq 'M' ; show = 'Address List'
case mode eq 'N' ; show = 'Short Local'
case mode eq 'O' ; show = 'Pmatdata'
case mode eq 'P' ; show = 'Two Byte Value'
case mode eq 'Q' ; show = 'Local Dcl'
case mode eq 'R' ; show = 'Object Map Data'
case mode eq 'S' ; show = 'Long String Value'
case 1 ; show = ''
end case
return
display:
xxno = dcount(disp,@am)
if pout and xxno gt 1 then gosub print.output ; return
pags = int(xxno/plen)
last = pags * plen
pags += (rem(xxno,plen) ne 0)
dawn = 1
loop
dusk = dawn + plen - 1
for here = dawn to dusk
crt disp<here>
next here
begin case
case xxno le plen
crt 'Press any key to retun to menu ':
wait = upcase(keycode())
return
case here gt last
crt 'Press any key to return to menu or <T>op <P>revious ':
wait = upcase(keycode())
if wait ne 'T' and wait ne 'P' then return
case dusk le plen
crt 'Press any key to continue or <Q> to return to menu ':
wait = upcase(keycode())
if wait eq 'T' or wait eq 'P' then wait = 'C'
case 1
crt 'Press any key to continue or <T>op <P>revious <Q>uit to return to menu ':
wait = upcase(keycode())
end case
begin case
case wait eq 'T' ; dawn = 1
case wait eq 'P' ; dawn -= plen
case 1 ; dawn += plen
end case
crt
until dawn gt xxno or wait eq 'Q' do repeat
return
print.output:
crt
crt disp<1>
loop
crt 'ARE YOU SURE YOU WANT TO PRINT?':
answ = upcase(keycode())
until answ eq 'Y' or answ eq 'N' do
crt 'Please answer "Y" or "N"'
repeat
if answ eq 'Y' then
printer on
print 'Details for ':name:' in ':namf
print
for xx = 1 to xxno
print disp<xx>
next xx
printer off
end
return
end