I want to use the Prop as a kind of preprocessor for a legacy test and measurement system. The command syntax is of the form: !CMD123;-456;78;90 Instead of writing a complete parser I modified the TACHYON input reader to transform this into FORTH syntax and then I let the FORTH system handle the processing. so the above command string is converted to: 123 -456 78 90 CMD If CMD is a defined Forth word the command is handled. This way I can keep the interactive Forth prompt, can write command scripts (words...) AND support the old syntax. To enable this I created a hook into the standard TACHYON MAIN CONSOLE TERMINAL (see below) at the 'word not found' error. Bevor this is called my mini-parser checks for a ! and then does the transformation. The result is pushed back in the front of the input queue. This is done by UNREADBUF which stuffs characters back into the queue. Since this runs inside the kernel the code is written in precompiled bytecode form. This can best be seen by comparing the original Tachyon 2.1 spin file with my modified version. I recommend e.g. beyond ccompare shareware tool. Just try entering s.th. like !XYZ123;45;6;-7 at the prompt { by defining the required commands as Forth words we get the required vocabulary. \ redirect to serial pin #24 : SEREMIT 24d SEROUT ; \ switch EMIT to serial line : TOSER ' SEREMIT uemit W! ; \ find the code field address for our LCD EMIT and set the output vector to it \ ( : TOTERM 0 uemit W! ; ) \ set emit back to normal \ is simply handled by CON : LON TOSER ." !SET117" $0D EMIT CON ; : LOFF TOSER ." !CLR117" $0D EMIT CON ; \ define some commands : SUP TOSER ." !SUP" SWAP $A .NUM ";" EMIT $A .NUM $0D EMIT CON ; : SSV TOSER ." !SSV" SWAP $A .NUM ";" EMIT $A .NUM $0D EMIT CON ; DECIMAL 0 0 SSV 100 FOR IX 10 * 50 SUP 1 seconds NEXT \ try this !SUP1000;100 } READBUF byte DUP,DEC,DEC,DUP,WFETCH ' point to read index ( buffer writeptr writeindex ) byte SWAP,DEC,DEC,WFETCH,SWAP ' ( buffer readindex writeindex ) byte OVER,EQ,_IF,03,DROP2,_0,EXIT ' empty, return with null ' ( buffer read ) byte OVER,PLUS,CFETCH,_WORD,$01,00,PLUS ' get char ( buffer [buffer+read]+$100 ) ' +$100 is the char recieved flag used by KEY? and stripped by KEY ' to distinguish char 0 from no char byte SWAP,_4,MINUS ' key readptr ) byte DUP,WFETCH,INC,REG,rxsz,WFETCH,DEC,_AND ' handle wrap around @ rxsz = rx-size which needs to be power of 2 byte SWAP,WSTORE,EXIT ': UNREADBUF (ch --) ' MJB UNREADBUF ' byte _BYTE,"%", XCALL, xEMIT ' print ! just to see word executes byte REG,rxptr,WFETCH byte DUP,_4,MINUS,DUP,WFETCH ' point to read index ( ch buffer rdptr readindex) byte DEC ' new readindex - since we want to stuff char on front of queue byte REG,rxsz,WFETCH,DEC,_AND ' adjust for wrap at rx-size ' ( ch buffer rdptr newreadindex) byte SWAP ' ( ch buffer newreadindex rdptr) byte OVER ' ( ch buffer newreadindex rdptr newreadindex) byte SWAP ' ( ch buffer newreadindex newreadindex rdptr) byte WSTORE ' store readindex back ( ch buffer newreadindex) byte PLUS,CSTORE ' store character at newreadindex in buffer byte EXIT { ****** MAIN CONSOLE TERMINAL ****** } org ' align the label TERMINAL byte XCALL,xInitStack byte _WORD,02,00,XCALL,xms ' a little startup delay (also wait for serial cog) byte _WORD,bufsize>>8,bufsize byte REG,rxsz,WSTORE byte _BYTE,echo,REG,flags,CSTORE ' echo flag byte BL,REG,delim,CSTORE,XCALL,xHEX ' default delimiter ' byte _6,_3,COGREG,COGSTORE ' default bytes/line for VGA byte _BYTE,txd,MASK,OUTSET byte _BYTE,$0C,XCALL,xEMIT,XCALL,xPRTVER ' VERSION byte REG,cold,WFETCH,_WORD,$A5,$5A,EQ,ZEQ ' performing a check for a saved session byte _IF,@warmst-@tm01 ' or not tm01 byte XCALL,xCOLDST ' defaults warmst ' byte XCALL,xSTATS ' AUTORUN? byte XCALL,xKEYQ,_AND,_1,EQ,_NOT,_IF,@termnew-@chkauto ' abort autostart with ^A chkauto byte REG,autovec,WFETCH,QDUP,_IF,@termnew-@runauto ' check for an AUTORUN runauto byte ACALL ' and execute it termnew byte XCALL,xSCRUB termcr byte REG,prompt,CFETCH,QDUP,_IF,02,XCALL,xEMIT byte XCALL,xHERE,REG,codes,WSTORE ' reset temporary code compilation pointer ' ' Main console loop - read a word and process termlp byte XCALL,xGETWORD ' Read a word from input stream etc byte CFETCH,ZEQ,_IF,@trm1-@trm2 ' ignore empty string trm2 byte REG,delim+1,CFETCH,_BYTE,$18,EQ,_NOT,_IF,@execinp-@trm3 ' if ^X then repeat last line trm3 byte REG,delim+1,CFETCH,_BYTE,$0D,EQ,_NOT,_IF,@chkeol-@trm1 ' trm1 byte REG,prompt+1,CFETCH,QDUP,_IF,02,XCALL,xEMIT ' echo prompt+1 character if set ' Preprocess prefixed numbers #$% byte REG,wordbuf,CFETCH,_BYTE,$23,_BYTE,$25,XCALL,xWITHIN byte REG,wordbuf-1,CFETCH,_2,GT,_AND byte REG,wordbuf-1,DUP,CFETCH,PLUS,CFETCH byte DUP,_BYTE,"0",_BYTE,"9",XCALL,xWITHIN byte SWAP,_BYTE,"A",_BYTE,"F",XCALL,xWITHIN,_OR,_AND byte ZEQ,_IF,@tryanum-@trm4 ' Search the dicitonary for a match trm4 byte REG,wordbuf,DEC,XCALL,xSEARCH ' try and find that word in the dictionary(s) byte QDUP,_IF,@notfound-@foundword ' found it foundword ' found the word in the dictionary - compile or execute? byte XCALL,xNFACFA,DEC byte PUSH1,im,OVER,XCALL,xSETQ byte _BYTE,comp,REG,flags,XCALL,xSETQ,ZEQ,_AND ' Immediate word? and comp flag off byte _IF,@compword-@immed ' immed byte INC,CFETCHINC,SWAP,CFETCH,XCALL,xEXECUTE ' Fetch and execute code immediately byte _ELSE,@chkeol-@compword compword byte XCALL,xBCOMPILE ' or else compile the bytecode(s) for ths word byte _BYTE,comp,REG,flags,CLR ' END OF LINE CHECK chkeol byte REG,delim+1,CFETCH,PUSH1,$0D,EQ ' Was this the end of line? byte DUP,_IF,@eol01-@eol00 eol00 byte XCALL,xSPACE ' Yes, put a space between any user input and response byte _BYTE,linenums,REG,flags,XCALL,xSETQ,_IF,@eol01-@prtline prtline byte _BYTE,$0D,XCALL,xEMIT byte REG,linenum,WFETCH,XCALL,xPRTDEC,XCALL,xSPACE byte _1,REG,linenum,WPLUSST eol01 byte DUP,_BYTE,defining,REG,flags,XCALL,xSETQ,_AND ' and are we in a definition or interactive? byte _IF,02,XCALL,xCR ' If not interactive then CRLF (no other response) byte _BYTE,defining,REG,flags,XCALL,xSETQ,ZEQ,_AND ' do not execute if still defining byte _UNTIL,@execs-@termlp ' wait until CR to execute compiled codes ' EXECUTE CODE from user input execs byte PUSH1,EXIT,XCALL,xBCOMP ' done - append an EXIT (minimum action on empty lines) execinp byte XCALL,xHERE,ACALL ' execute from beginning byte XCALL,xOK byte _AGAIN,@notfound-@termcr notfound ' NOT FOUND - before trying to convert to a number check encoding for ASCII literals (^ and ") ' MJB check for SMMU Command flag false = continue normal parsing ' else restart parser with new tokens added ' to front of input buffer un07 byte XCALL,xSMMUParse,_IF,@tryanum-@un06 un06 byte _AGAIN,@tryanum-@chkeol ' end MJB Peter's original code follows tryanum byte REG,wordbuf,XCALL,xNUMBER,_IF,@unknown-@compnum compnum byte XCALL,xLITCOMP byte _AGAIN,@unknown-@chkeol ' is it a number? ( value digits ) unknown byte REG,unum,WFETCH,QDUP,_IF,03,ACALL,_AGAIN,@un01-@chkeol un01 byte _BYTE,echo,REG,flags,XCALL,xSETQ,ZEQ,_IF,@un03-@un00 byte _WORD,$02,14,XOP,x_EMIT,_ELSE,@un04-@un03 un03 byte XCALL,xPRTSTR," ??? ",7,0 ' ??? un04 byte XCALL,xERROR un02 byte _AGAIN,@trmend-@termlp trmend ' MJB extension ' if an unknown word starts with ! we try to convert it to Forth syntax ' Words are of this form: !CMD123;456;-789;1011 ' first a "!" then a 3 Char Command followed by up to 4 signed integers separated by ";" or ":" ' this is converted to ' 123 456 -789 1011 CMD ' which is valid Forth syntax, hopefully CMD is a definded word ... ' but the Forth system is doing all further required parsing and executing. SMMUParse '( -- true | false ) ' true = SMMU false = normal continue ' MJB check if first char of word is ! and then do SMMU parsing ' byte _BYTE,"!", XCALL, xEMIT ' print ! just to see word executes byte REG,wordbuf,CFETCH,_BYTE,"!",EQ,_IF,@sm09-@sm01 sm01 byte _BYTE,$0D,XCALL,xUNREADBUF ' execute on reparse byte REG,wordbuf,DUP,_3,PLUS,DUP,CFETCH,XCALL,xUNREADBUF '(wordbuf wb+3) byte DEC,DUP,CFETCH,XCALL,xUNREADBUF '(wordbuf wb+2) byte DEC,CFETCH,XCALL,xUNREADBUF '(wordbuf ) byte _BYTE," ",XCALL,xUNREADBUF '(wordbuf ) ' loop over wordbuf backwards and put chars back to rxbuf ' replace :; by space byte _3,PLUS ' length of CMD+! ' byte XCALL,xPRTSTK ' .S show stack - for debugging byte REG,wordcnt,CFETCH,_3,MINUS,FOR,DUP '(wordbuf wordbuf) ' byte XCALL,xPRTSTK ' .S byte XCALL,xIX,PLUS,CFETCH ' get loop index, add to wordbuf and fetch char ' byte XCALL,xPRTSTK ' .S byte DUP,_BYTE,":",EQ,_IF,02,DROP,BL byte DUP,_BYTE,";",EQ,_IF,02,DROP,BL ' byte XCALL,xPRTSTK ' .S byte XCALL,xUNREADBUF ' push to front of rxbuf ' byte XCALL,xPRTSTK ' .S byte forNEXT byte DROP ' clean stack ' byte XCALL,xPRTSTK ' .S byte _1,EXIT sm09 byte _0,EXIT