mcopy scanner.macros **************************************************************** * * Convertsl - Convert a string to a long integer * * Inputs: * str - pointer to the string * * Outputs: * Returns the value. * * Notes: * Assumes the string is valid. * **************************************************************** * Convertsl start val equ 0 return value subroutine (4:str),4 stz val initialize the number to zero stz val+2 lda [str] set X to the number of characters and #$00FF tax ldy #1 Y is the disp into the string lb1 asl val val := val*10 rol val+2 ph2 val+2 lda val asl val rol val+2 asl val rol val+2 adc val sta val pla adc val+2 sta val+2 lda [str],Y add in the new digit and #$000F adc val sta val bcc lb2 inc val+2 lb2 iny next character dex bne lb1 return 4:val end **************************************************************** * * KeyPress - Has a key been presed? * * If a key has not been pressed, this function returns * false. If a key has been pressed, it clears the key * strobe. If the key was an open-apple ., a terminal exit * is performed; otherwise, the function returns true. * **************************************************************** * KeyPress start KeyPressGS kpRec lda kpAvailable beq rts ReadKeyGS rkRec lda rkKey cmp #'.' bne lb1 lda rkModifiers and #$0100 beq lb1 ph2 #4 jsl TermError lb1 lda #1 rts rtl kpRec dc i'3' kpKey ds 2 kpModifiers ds 2 kpAvailable ds 2 rkRec dc i'2' rkKey ds 2 rkModifiers ds 2 end **************************************************************** * * NextCh - Read the next character from the file, skipping comments * * Outputs: * ch - character read * **************************************************************** * NextCh start eofChar equ 0 end of file character eolChar equ 13 end of line character stackFrameSize equ 14 size of the work space maxPath equ 255 max length of a path name fp equ 1 file record pointer; work pointer p1 equ 5 work pointer p2 equ 9 cch equ 13 enum (illegal,ch_special,ch_dash,ch_plus,ch_lt,ch_gt,ch_eq,ch_exc),0 enum (ch_and,ch_bar,ch_dot,ch_white,ch_eol,ch_eof,ch_char,ch_string) enum (ch_asterisk,ch_slash,ch_percent,ch_carot,ch_pound,letter,digit) tsc create stack frame sec sbc #stackFrameSize tcs phd tcd ! {flag for preprocessor check} ! if lastWasReturn then ! lastWasReturn := charKinds[ord(ch)] in [ch_eol,ch_white] ! else ! lastWasReturn := charKinds[ord(ch)] = ch_eol; lda ch asl A tax lda charKinds,X ldy #1 cmp #ch_eol beq pf2 ldx lastWasReturn beq pf1 cmp #ch_white beq pf2 pf1 dey pf2 sty lastWasReturn ! 1: lab1 anop ! if chPtr = eofPtr then begin {flag end of file if we're there} lda chPtr cmp eofPtr bne la1 lda chPtr+2 cmp eofPtr+2 beq la2 la1 brl lb5 la2 anop ! if not lastWasReturn then begin ! lastWasReturn := true; ! needWriteLine := true; ! ch := chr(eolChar); ! goto le2; ! end; {if} lda lastWasReturn bne la3 lda #1 sta lastWasReturn sta needWriteLine lda #eolChar sta ch brl le2 ! ch := chr(eofChar); la3 stz ch ! if needWriteLine then begin {do eol processing} ! WriteLine; ! lineNumber := lineNumber+1; ! firstPtr := chPtr; ! end; {if} lda needWriteLine beq lb1 jsl WriteLine inc lineNumber move4 chPtr,firstPtr lb1 anop ! if fileList = nil then begin lda fileList ora fileList+2 bne lb3 lb2 anop ! skipping := false; sta skipping ! end {if} brl le2 ! else begin lb3 anop ! {purge the current source file} ! with ffDCBGS do begin ! pCount := 5; lda #5 sta ffDCBGS ! action := 7; lda #7 sta ffDCBGS+2 ! name := @includeFileGS.theString lla ffDCBGS+12,includeFileGS+2 ! end; {with} ! FastFileGS(ffDCBGS); FastFileGS ffDCBGS ! fp := fileList; {open the file that included this one} move4 fileList,fp ! fileList := fp^.next; ldy #2 lda [fp] sta fileList lda [fp],Y sta fileList+2 ! includeFileGS := fp^.name; ! sourceFileGS := fp^.sname; add4 fp,#4,p1 add4 fp,#4+maxPath+4,p2 short M ldy #maxPath+3 lb4 lda [p1],Y sta includeFileGS,Y lda [p2],Y sta sourceFileGS,Y dey bpl lb4 long M ! lineNumber := fp^.lineNumber; ldy #4+maxPath+4+maxPath+4 lda [fp],Y sta lineNumber ! ReadFile; jsl ReadFile ! eofPtr := pointer(ord4(bofPtr) + ffDCBGS.fileLength); add4 bofPtr,ffDCBGS+46,eofPtr ! chPtr := pointer(ord4(bofPtr) + fp^.disp); ! includeChPtr := chPtr; ! firstPtr := chPtr; ldy #4+maxPath+4+maxPath+4+2 clc lda bofPtr adc [fp],Y sta chPtr sta firstPtr sta includeChPtr lda bofPtr+2 iny iny adc [fp],Y sta chPtr+2 sta firstPtr+2 sta includeChPtr+2 ! needWriteLine := false; stz needWriteLine ! dispose(fp); ph4 fp jsl ~Dispose ! includeCount := includeCount + 1; inc includeCount ! goto 1; brl lab1 ! end; {if} ! end {if} ! else begin lb5 anop ! ch := chr(chPtr^); {fetch the character} move4 chPtr,p1 lda [p1] and #$00FF sta ch ! if needWriteLine then begin {do eol processing} ! WriteLine; ! lineNumber := lineNumber+1; ! firstPtr := chPtr; ! end; {if} lda needWriteLine beq lb6 jsl WriteLine inc lineNumber move4 chPtr,firstPtr lb6 anop ! needWriteLine := charKinds[ord(ch)] = ch_eol; stz needWriteLine lda ch asl A tax lda charKinds,X cmp #ch_eol bne lb7 inc needWriteLine lb7 anop ! chPtr := pointer(ord4(chPtr) + 1); inc4 chPtr ! 2: if (ch = '\') and (charKinds[chPtr^] = ch_eol) then begin ! chPtr := pointer(ord4(chPtr) + 1); ! DebugCheck; ! needWriteLine := true; ! goto 1; ! end; {if} lab2 lda ch cmp #'\' bne lb8 move4 chPtr,p1 lda [p1] and #$00FF asl A tax lda charKinds,X cmp #ch_eol bne lb8 inc4 chPtr jsr DebugCheck lda #1 sta needWriteLine brl lab1 lb8 anop ! {check for debugger code} ! if needWriteLine then ! DebugCheck; lda needWriteLine beq lb9 jsr DebugCheck lb9 anop ! ! {if it's a comment, skip the comment } ! {characters and return a space. } ! if (not doingstring) and (ch = '/') and (chPtr <> eofPtr) ! and ((chr(chPtr^) = '*') ! or ((chr(chPtr^) = '/') and slashSlashComments))then begin lda doingstring jne lc6 lda ch cmp #'/' jne lc7 lda chPtr cmp eofPtr bne lc1 lda chPtr+2 cmp eofPtr+2 jeq lc6 lc1 move4 chPtr,p1 lda [p1] and #$00FF cmp #'*' beq lc1a cmp #'/' jne lc6 ldx slashSlashComments jeq lc6 ! cch := chr(chPtr^); lc1a sta cch ! chPtr := pointer(ord4(chPtr)+1); {skip the '*' or '/'} inc4 chPtr ! done := false; ! repeat lc2 anop ! if chPtr = eofPtr then {if at eof, we're done} ! done := true lda chPtr cmp eofPtr bne lc2a lda chPtr+2 cmp eofPtr+2 jeq lc5 ! else if (cch = '/') and (chPtr^ = return) then begin lc2a lda cch cmp #'/' bne lc2b ! if charKinds[ord(ch)] = ch_eol then ! done := true ! else ! chPtr := pointer(ord4(chPtr)+1); move4 chPtr,p1 lda [p1] and #$00FF asl A tax lda charKinds,X cmp #ch_eol jeq lc5 inc4 chPtr bra lc2 ! end {else if} ! else begin ! ch := chr(chPtr^); {check for terminating */} lc2b move4 chPtr,p1 lda [p1] and #$00FF sta ch ! if charKinds[ord(ch)] = ch_eol then begin ! WriteLine; ! lineNumber := lineNumber+1; ! firstPtr := pointer(ord4(chPtr)+1); ! end; {if} asl A tax lda charKinds,X cmp #ch_eol bne lc3 jsl WriteLine inc lineNumber add4 chPtr,#1,firstPtr lc3 anop ! chPtr := pointer(ord4(chPtr)+1); inc4 chPtr ! if ch = '*' then ! if (chr(chPtr^) = '/') and (chPtr <> eofPtr) then begin ! chPtr := pointer(ord4(chPtr)+1); ! done := true; ! end; {if} lda ch cmp #'*' jne lc2 lda chPtr cmp eofPtr bne lc4 lda chPtr+2 cmp eofPtr+2 jeq lc2 lc4 move4 chPtr,p1 lda [p1] and #$00FF cmp #'/' jne lc2 inc4 chPtr ! end; {else} ! until done; lc5 anop ! {return a space as the result} ! ch := ' '; lda #' ' sta ch ! end {if} brl le2 ! else if (ch = '?') and (chPtr <> eofPtr) and (chr(chPtr^) = '?') then begin lc6 lda ch lc7 cmp #'?' jne le2 lda chPtr cmp eofPtr bne lc8 lda chPtr+2 cmp eofPtr+2 jeq le2 lc8 move4 chPtr,p1 lda [p1] and #$00FF cmp #'?' jne le2 ! chPtr2 := pointer(ord4(chPtr) + 1); inc4 p1 ! if (chPtr2 <> eofPtr) lda p1 cmp eofPtr bne ld1 lda p1+2 cmp eofPtr+2 beq le2 ld1 anop ! and (chr(chPtr2^) in ['(','<','/','''','=',')','>','!','-']) then begin ! case chr(chPtr2^) of ! '(': ch := '['; lda [p1] and #$00FF cmp #'(' bne ld2 lda #'[' bra le1 ! '<': ch := '{'; ld2 cmp #'<' bne ld3 lda #'{' bra le1 ! '/': ch := '\'; ld3 cmp #'/' bne ld4 lda #'\' bra le1 ! '''': ch := '^'; ld4 cmp #'''' bne ld5 lda #'^' bra le1 ! '=': ch := '#'; ld5 cmp #'=' bne ld6 lda #'#' bra le1 ! ')': ch := ']'; ld6 cmp #')' bne ld7 lda #']' bra le1 ! '>': ch := '}'; ld7 cmp #'>' bne ld8 lda #'}' bra le1 ! '!': ch := '|'; ld8 cmp #'!' bne ld9 lda #'|' bra le1 ! '-': ch := '~'; ld9 cmp #'-' bne le2 lda #'~' ! end; {case} le1 sta ch ! chPtr := pointer(ord4(chPtr2) + 1); add4 chPtr,#2 ! goto 2; brl lab2 ! end; {if} ! end; {if} ! end; {else} le2 anop pld tsc clc adc #stackFrameSize tcs rtl ! end; {NextCh} ; ; Local subroutine ; enum (stop,break,autogo),0 line number debug types ! procedure DebugCheck; ! ! {Check for debugger characters; process if found } ! ! begin {DebugCheck} DebugCheck anop ! if chPtr = eofPtr then ! debugType := stop lda chPtr ldx chPtr+2 cmp eofPtr bne db1 cpx eofPtr+2 bne db1 stz debugType bra db5 ! else if ord(chPtr^) = $07 then begin db1 sta p1 stx p1+2 lda [p1] and #$00FF cmp #$07 bne db2 ! debugType := break lda #break sta debugType bra db3 ! else if ord(chPtr^) = $06 then db2 cmp #$06 bne db4 ! debugType := autoGo; lda #autoGo sta debugType ! chPtr := pointer(ord4(chPtr) + 1); db3 inc4 chPtr ! end {if} bra db5 ! else ! debugType := stop; db4 stz debugType ! end; {DebugCheck} db5 rts end **************************************************************** * * SetDateTime - set up the date/time strings * * Outputs: * dateStr - date * timeStr - time string * **************************************************************** * SetDateTime private pha get the date/time pha pha pha _ReadTimeHex lda 1,S set the minutes xba jsr convert sta time+5 pla set the seconds jsr convert sta time+8 lda 1,S set the hour jsr convert sta time+2 pla set the year xba jsr convert sta date+11 lda 1,S set the day inc A jsr convert sta date+6 pla set the month xba and #$00FF asl A asl A tax lda month,X sta date+2 lda month+1,X sta date+3 pla lla timeStr,time set the addresses lla dateStr,date rtl month dc c'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec' date dc i'12',c'mmm dd 19yy',i1'0' time dc i'9',c'hh:mm:ss',i1'0' convert and #$00FF ldx #0 cv1 sec sbc #10 bcc cv2 inx bra cv1 cv2 clc adc #10 ora #'0' xba pha txa ora #'0' ora 1,S plx rts end