nam Kermit68K ttl Parser subroutines module * Kermit68K: source file K68PSF * * Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet), * Bologna University, Physics Department, July 1987. * * All rights reserved to Bologna University, Italy. * * Permission is granted to any individual or institution * to use, copy, or redistribute this software so long as * it is not sold for profit, provided this copyright * notice is retained. * * Modification History: * * Version Date Who Comments * * 1.0.00 870701 Roberto Bagnara First official release use DefsFile Edition equ 0 psect K68ParserSubs,0,0,Edition,0,0 ******************************** ParsWrd ******************************ok * * * Parse a word string. * * * * Entry conditions : A0.L points to the target string * * A5.L points to the current position * * in the source line * * * * Exit conditions : A0.L points to the last byte of * * the target string * * A5.L points to the current position * * in the source line * * D0.B completion code * * * * -3 nothing to look up (source was null) * * 0 all ok * * * *********************************************************************** ParsWrd: BSR SkipSpr Skip leading separators TST.B (A5) Null source ? BEQ.S ParsWrd4 Yes, return this ParsWrd1 MOVE.B (A5)+,D0 No, get the first character BEQ.S ParsWrd2 End of line, exit loop CMPI.B #' ',D0 Blank ? BEQ.S ParsWrd3 Yes, exit loop CMPI.B #Asc_HT,D0 Tab ? BEQ.S ParsWrd3 Yes, exit loop MOVE.B D0,(A0)+ No, store the character BRA.S ParsWrd1 Loop until end of word ParsWrd2 SUBQ.L #1,A5 Backup line pointer ParsWrd3 CLR.B (A0) Terminate target MOVEQ #0,D0 Return positive completion code RTS ParsWrd4 CLR.B (A0) Terminate target MOVEQ #-3,D0 Return null source completion code RTS ******************************** ParsTxt ******************************ok * * * Parse a text string, quoted or unquoted, this is to allow the * * specification of trailing delimiters. * * * * Entry conditions : A0.L points to the target string * * A5.L points to the current position * * in the source line * * * * Exit conditions : A0.L points to the last byte of * * the target string * * A5.L points to the current position * * in the source line * * D0.B completion code * * D1.B destroyed * * * * -3 nothing to look up (source was null) * * 0 all ok * * * *********************************************************************** ParsTxt: BSR SkipSpr Skip leading separators MOVE.B (A5)+,D0 Get the first character, null source ? BEQ.S ParsTxt7 Yes, return null target cc CMPI.B #$22,D0 Look for a quote character (") BEQ.S ParsTxt1 CMPI.B #$27,D0 Look for a quote character (') BEQ.S ParsTxt1 CMPI.B #$60,D0 Look for a quote character (`) BNE.S ParsTxt2 ParsTxt1 MOVE.B D0,D1 Save the quote character BRA.S ParsTxt4 ParsTxt2 CLR.B D1 Clear the quote register ParsTxt3 MOVE.B D0,(A0)+ Write character to target string ParsTxt4 MOVE.B (A5)+,D0 Get a character BEQ.S ParsTxt6 If end of line exit loop CMP.B D0,D1 Quote character again ? BNE.S ParsTxt3 No, write char to target, stay in loop CLR.B (A0) Yes, terminate target ParsTxt5 MOVEQ #0,D0 Return positive completion code RTS ParsTxt6 MOVE.B -(A5),(A0) Backup line pointer and terminate target BRA.S ParsTxt5 Return positive completion code ParsTxt7 MOVE.B -(A5),(A0) Backup line pointer and terminate target MOVEQ #-3,D0 Return null source completion code RTS ******************************** ParsNm *******************************ok * * * Parse a number. * * * * Entry conditions : D1.L range specification, lower bound * * D2.L range specification, upper bound * * A5.L points to the current position * * in the source line * * * * Exit conditions : D0.L parsed number (if any) * * D1.B completion code * * A0.L destroyed * * A1.L destroyed * * A5.L points to the current position * * in the source line * * * * -3 nothing to parse (source was null) * * -2 number out of range * * -1 illegal number specification * * 0 all ok, number in D0.L * * * *********************************************************************** ParsNm: MOVEM.L D3-D6,-(A7) Save working registers LEA DataBuf(A6),A1 Pointer to temporary buffer MOVEA.L A1,A0 Put here the parsed word BSR ParsWrd Get a word from the source line TST.B D0 Null source ? BLT ParsNm12 Yes, return this condition code MOVEA.L A1,A0 Set up for addressing CLR.L D0 Clear the number register CLR.L D3 Clear the character register MOVE.B (A0)+,D3 Get the first character CMPI.B #'$',D3 Hexadecimal ? BEQ.S ParsNm1 Yes, set base register CMPI.B #'\',D3 Octal ? BEQ.S ParsNm2 Yes, set base register CMPI.B #'%',D3 Binary ? BEQ.S ParsNm3 Yes, set base register to binary MOVEQ #10,D4 No, set base register to decimal BRA.S ParsNm5 ParsNm1 MOVEQ #16,D4 Set base register to hexadecimal BRA.S ParsNm4 ParsNm2 MOVEQ #8,D4 Set base register to octal BRA.S ParsNm4 ParsNm3 MOVEQ #2,D4 Set base register to binary ParsNm4 MOVE.B (A0)+,D3 Got a base specification, get next BEQ.S ParsNm10 End of word, invalid number ParsNm5 CMPI.B #'-',D3 Look for a minus sign SEQ D5 Set a flag accordingly BNE.S ParsNm6 Enter the conversion loop MOVE.B (A0)+,D3 Got a minus sign, get next BEQ.S ParsNm10 End of word, invalid number ParsNm6 BSR UppCase SUBI.B #'0',D3 First offset BLT.S ParsNm10 Less than '0', invalid number CMPI.B #9,D3 Above 9 ? BLE.S ParsNm7 No SUBQ.B #7,D3 Yes, second offset ParsNm7 CMP.B D4,D3 Above the base value ? BGE.S ParsNm10 Yes, invalid number specification MOVE.L D0,D6 Make some computation MULU D4,D0 SWAP D6 MULU D4,D6 SWAP D6 CLR.W D6 ADD.L D6,D0 ADD.L D3,D0 MOVE.B (A0)+,D3 Get the next character, if any BNE.S ParsNm6 Repeat until end of word TST.B D5 Negative number ? BEQ.S ParsNm8 No NEG.L D0 Yes, negate it ParsNm8 CMP.L D1,D0 Less than lower bound ? BLT.S ParsNm11 Yes, return the proper cc CMP.L D2,D0 Greater than upper bound ? BGT.S ParsNm11 Yes, return the proper cc MOVEQ #0,D1 Provide positive completion code ParsNm9 MOVEM.L (A7)+,D3-D6 Restore working registers RTS ParsNm10 MOVEA.L A1,A0 Pointer to the guilty word LEA PrNmStr1(PC),A1 Pointer to the error message string BSR ParsErr Give the appropriate message MOVEQ #-1,D1 Return invalid number cc BRA.S ParsNm9 ParsNm11 MOVEA.L A1,A0 Pointer to the guilty word LEA PrNmStr2(PC),A1 Pointer to the error message string BSR ParsErr Give the appropriate message MOVEQ #-2,D1 Return number out of range cc BRA.S ParsNm9 ParsNm12 SUBA.L A0,A0 No guilty word in this case LEA PrNmStr3(PC),A1 Pointer to the error message string BSR ParsErr Give the appropriate message MOVEQ #-3,D1 Return missing number specification cc BRA.S ParsNm9 ******************************** ParsKyW ******************************ok * * * Parse a keyword, giving, on error, appropriate messages. * * * * Entry conditions : D1.B flag for mandatory keywords * * A1.L points to keywords table * * A5.L points to the current position * * in the source line * * * * Exit conditions : D0.B completion code * * * * -3 nothing to look up (source was null) * * -2 ambiguous keyword * * -1 keyword not found * * n >= 0 value associated with keyword * * * * D2.B destroyed * * A0.L destroyed * * A1.L destroyed * * A2.L destroyed * * * *********************************************************************** ParsKyW: LEA DataBuf(A6),A2 Pointer to temporary buffer MOVEA.L A2,A0 Put here the parsed word BSR ParsWrd Get a word from the source line MOVEA.L A2,A0 Set up for addressing BSR Lookup Search the keyword in the given table TST.B D0 Some error condition reported ? BGE.S ParsKyW5 No, return value in D0.B MOVE.B D0,D2 Yes, save the completion code ADDQ.B #1,D0 Unrecognized keyword ? BEQ.S ParsKyW1 Yes, give error message ADDQ.B #1,D0 Ambiguous keyword ? BEQ.S ParsKyW2 Yes, give error message TST.B D1 No, missing keyword, was it mandatory ? BEQ.S ParsKyW4 No, no message, return bad cc LEA PrKyStr3(PC),A0 Yes, give missing keyword error message BSR ConWrite Write the message MOVEA.L A1,A0 Write the requested object name BSR ConWrite BSR NewLine Start a new line BRA.S ParsKyW4 Newline and return ParsKyW1 LEA PrKyStr1(PC),A0 Give unrecognized keyword error message BRA.S ParsKyW3 Join common part ParsKyW2 LEA PrKyStr2(PC),A0 Give ambiguous keyword error message ParsKyW3 BSR ConWrite Write the error type string MOVEA.L A1,A0 Write the requested object name BSR ConWrite MOVEA.L A2,A0 Write the guilty word SUBA.L A1,A1 Error message already given BSR ParsErr ParsKyW4 MOVE.B D2,D0 Restore the completion code from LookUp ParsKyW5 RTS ******************************* ParsInF *******************************ok * * * Parse an input file name specification. * * * * Entry conditions : A0.L point to the target string * * A5.L points to the current position * * in the source line * * * * Exit conditions : D0.B completion code * * * * -3 nothing to parse (source was null) * * -2 illegal file name specification * * 0 all ok * * * * A1.L destroyed * * A5.L points to the current position * * in the source line * * * *********************************************************************** ParsInF: MOVEA.L A0,A1 Save the target pointer BSR ParsWrd Get a word from the command line TST.B D0 Null source ? BLT.S ParsInF2 Yes, return this MOVEA.L A1,A0 Reload target pointer BSR ChkWild Check for wild characters TST.B D0 Wild filename ? BNE.S ParsInF3 Yes, try to expand it BSR ChkInpF Check if file exists and is readable TST.B D0 Inexistent or unreadable file ? BLT.S ParsInF5 Yes, give error message ParsInF1 MOVEQ #0,D0 No, all ok, return positive cc ParsInF2 RTS ParsInF3 BSR ExpandFN Try to expand the wild file name TST.L D0 Check the result BGT.S ParsInF1 All ok, at least one match BLT.S ParsInF4 Too many matches, give error message LEA PrIFStr4(PC),A0 No matches, error BRA.S ParsInF8 Join common part ParsInF4 LEA PrIFStr5(PC),A0 Notify overflow during name expansion BRA.S ParsInF8 Join common part ParsInF5 ADDQ.B #1,D0 File not found ? BEQ.S ParsInF6 Yes ADDQ.B #1,D0 File not readable ? BEQ.S ParsInF7 Yes LEA PrIFStr3(PC),A0 No, read permission denied BRA.S ParsInF8 Join common part ParsInF6 LEA PrIFStr1(PC),A0 File not found error message BRA.S ParsInF8 Join common part ParsInF7 LEA PrIFStr2(PC),A0 File not readable error message ParsInF8 EXG A0,A1 Setup pointers BSR ParsErr Call the error messages routine MOVEQ #-2,D0 Return a negative completion code RTS ******************************* ParsOuF *******************************ok * * * Parse an output file name specification. * * * * Entry conditions : A0.L point to the target string * * A5.L points to the current position * * in the source line * * * * Exit conditions : A5.L points to the current position * * in the source line * * D0.B completion code * * * * -3 nothing to parse (source was null) * * -2 illegal output file name * * 0 all ok * * * *********************************************************************** ParsOuF: MOVEA.L A0,A1 Save the target pointer BSR ParsWrd Get a word from the command line TST.B D0 Null source ? BLT.S ParsOuF1 Yes, return this MOVEA.L A1,A0 Reload target pointer BSR ChkWild Check for wild characters TST.B D0 Wild filename ? BNE.S ParsOuF2 Yes, give error message BSR ChkOutF Check if file can be created TST.B D0 Permission denied ? BLT.S ParsOuF3 Yes, give error message MOVEQ #0,D0 No, all ok, return positive cc ParsOuF1 RTS ParsOuF2 LEA POuFStr1(PC),A0 Give wildcard not allowed error message BRA.S ParsOuF4 Join common part ParsOuF3 LEA POuFStr2(PC),A0 Give permission denied error message ParsOuF4 EXG A0,A1 Setup pointers BSR ParsErr Call the error messages routine MOVEQ #-2,D0 Return negative completion code RTS ******************************* ChkWild *******************************ok * * * Check a string for wildcard character presence. * * * * Entry conditions : A0.L points to the string to check * * * * Exit conditions : D0.B completion code * * A0.L points to the checked string * * * *********************************************************************** ChkWild: MOVE.L A0,-(A7) Save the string pointer ChkWild1 MOVE.B (A0)+,D0 Get a character BEQ.S ChkWild3 End of string, exit loop, return false CMPI.B #'*',D0 Match-all wildcard character ? BEQ.S ChkWild2 Yes, the file name is wild CMPI.B #'?',D0 Match-one wildcard character ? BNE.S ChkWild1 No, loop until end of string ChkWild2 ST D0 Yes, exit loop, return true ChkWild3 MOVE.L (A7)+,A0 Restore the string pointer RTS ********************************* Lookup ******************************ok * * * Lookup a keyword in the given array of keywords. * * * * Entry conditions : A0.L points to the source string * * null terminated * * A1.L points to the keywords table * * * * Exit conditions : D0.B completion code * * * * -3 nothing to look up (target was null) * * -2 ambiguous keyword * * -1 keyword not found * * n >= 0 value associated with keyword * * * * A0.L points to the source string * * null terminated * * A1.L points to the object name * * * *********************************************************************** Lookup MOVEM.L A2/D1-D4,-(A7) Save working registers CLR.B D1 Clear matchs counter TST.B (A0) Null keyword ? BNE.S Lookup2 No, continue Lookup1 MOVE.B (A1)+,D4 Yes, skip to end of table CMPI.B #-1,D4 End of table ? BNE.S Lookup1 No, loop MOVEQ #-3,D0 Return nothing to look up cc BRA.S Lookup8 Lookup2 MOVE.B (A1)+,D4 Get the value associated to this word CMPI.B #-1,D4 End of table ? BEQ.S Lookup7 Yes, check if match(s) occurred MOVEA.L A0,A2 Lookup3 MOVE.B (A2)+,D3 Get next character from command line BEQ.S Lookup4 End of word, match ! BSR UppCase Upper case it for compare MOVE.B (A1)+,D2 Get a character from table BEQ.S Lookup2 End of word, no match, try the next CMP.B D3,D2 Match ? BNE.S Lookup5 No, skip to the next table element BRA.S Lookup3 Yes, look to the next character Lookup4 TST.B (A1) Match found, is a supermatch ? BEQ.S Lookup6 Yes, stop searching ADDQ.B #1,D1 No, increment matchs counter MOVE.B D4,D0 Load the return value Lookup5 MOVE.B (A1)+,D2 Skip to next table element BNE.S Lookup5 Skip characters until end of word BRA.S Lookup2 Scan all the table elements Lookup6 MOVE.B D4,D0 Supermatch found, load the return value BRA.S Lookup8 Lookup7 CMPI.B #1,D1 Check matchs counter BLT.S Lookup9 If no match return keyword not found cc BGT.S Lookup10 More than 1, ambiguous keyword cc Lookup8 MOVEM.L (A7)+,A2/D1-D4 Restore working registers RTS Lookup9 MOVEQ #-1,D0 Return the keyword not found cc BRA.S Lookup8 Lookup10 MOVEQ #-2,D0 Return the ambiguous keyword cc BRA.S Lookup8 ********************************* ParsErr *****************************ok * * * Give a parsing error message. * * * * Entry conditions : A0.L point to the guilty word * * null terminated, no guilty word * * to print if null pointer passed * * A1.L point to the error message, no * * message to print if null pointer * * passed * * * * Exit conditions : D0.L destroyed * * D1.L destroyed * * * *********************************************************************** ParsErr: EXG A0,A1 Write the error string first, if any MOVE.L A0,D1 Null pointer passed ? BEQ.S ParsErr1 Yes, no error message BSR ConWrite No, write it ParsErr1 MOVE.L A1,D1 Null pointer passed ? BEQ.S ParsErr4 Yes, no guilty word LEA PrErStr1(PC),A0 No, point to separator string BSR ConWrite Write it to terminal MOVEQ #'"',D0 Type the leading quotation mark BSR ConOut ParsErr2 MOVE.B (A1)+,D0 And then the guilty word BEQ.S ParsErr3 If end of word, exit loop BSR ConOut Write a character BRA.S ParsErr2 And the next, if any ParsErr3 MOVEQ #'"',D0 Type the trailing quotation mark BSR ConOut ParsErr4 BSR NewLine Start a new line RTS ******************************* SkipSpr *******************************ok * * * Skip leading separators from the command line. * * * * Entry conditions : A5.L point to the current position * * in the command line * * * * Exit conditions : D0.B destroyed * * A5.L point to the current position * * in the command line * * * *********************************************************************** SkipSpr MOVE.B (A5)+,D0 Get a character BEQ.S SkipSpr1 End of buffer, exit CMPI.B #' ',D0 Blank ? BEQ.S SkipSpr Yes, skip CMPI.B #Asc_HT,D0 Tab ? BEQ.S SkipSpr Yes, skip SkipSpr1 SUBQ.L #1,A5 Backup line pointer RTS ends END