/*- * Copyright (c) 2000 Ben Harris * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* bastok -- BBC BASIC tokenizer */ /* Not handled: * - Abbreviated keywords * - Explicit line numbers */ /* In condition COMMENT, we ignore everything except EOL. */ %x COMMENT #define p1(x) thisline[pos++] = x #define p2(x, y) p1(x); p1(y) char thisline[256]; int pos; int baslinenum = 10; void linedone(void); %% pos = 0; ABS p1(0x94); ACS p1(0x95); ADVAL p1(0x96); /* AD. */ AND p1(0x80); /* A. */ APPEND p2(0xC7, 0x8E); /* AP. */ ASC p1(0x97); ASN p1(0x98); ATN p1(0x99); AUTO p2(0xC7, 0x8F); /* AU. */ BEAT p2(0xC6, 0x8F); BEATS p2(0xC8, 0x9E); /* BEA. */ BGET p1(0x9A); /* B. */ BPUT p1(0xD5); /* BP. */ CALL p1(0xD6); /* CA. */ CASE p2(0xC8, 0x8E); CHAIN p1(0xD7); /* CH. */ CHR\$ p1(0xBD); CIRCLE p2(0xC8, 0x8F); /* CI. */ CLEAR p1(0xD8); /* CL. */ CLG p1(0xDA); CLOSE p1(0xD9); /* CLO. */ CLS p1(0xDB); COLOR p1(0xFB); /* C. */ COLOUR p1(0xFB); /* C. */ COS p1(0x9B); COUNT p1(0x9C); /* COU. */ DATA { p1(0xDC); BEGIN(COMMENT); } /* D. */ DEF p1(0xDD); DEG p1(0x9D); DELETE p2(0xC7, 0x90); /* DEL. */ DIM p1(0xDE); DIV p1(0x81); DRAW p1(0xDF); /* DR. */ EDIT p2(0xC7, 0x91); /* ED. */ ELLIPSE p2(0xC8, 0x9D); /* ELL. */ ELSE p1(0xCC); /* CONSTA = 1 */ /* EL. */ END p1(0xE0); ENDCASE p1(0xCB); /* ENDC. */ ENDIF p1(0xCD); ENDPROC p1(0xE1); /* E. */ ENDWHILE p1(0xCE); /* ENDW. */ EOF p1(0xC5); EOR p1(0x82); ERL p1(0x9E); ERR p1(0x9F); ERROR p1(0x85); /* ERR. */ EVAL p1(0xA0); /* EV. */ EXP p1(0xA1); EXT p1(0xA2); FALSE p1(0xA3); /* FA. */ FILL p2(0xC8, 0x90); /* FI. */ FN p1(0xA4); FOR p1(0xE3); /* F. */ GCOL p1(0xE6); /* GC. */ GET p1(0xA5); GET\$ p1(0xBE); /* GE. */ GOSUB p1(0xE4); /* CONSTA = 1 */ /* GOS. */ GOTO p1(0xE5); /* CONSTA = 1 */ /* G. */ HELP p2(0xC7, 0x92); /* HE. */ ^HIMEM p1(0xD3); /* H. */ HIMEM p1(0x93); /* H. */ IF p1(0xE7); INKEY p1(0xA6); INKEY\$ p1(0xBF); /* INK. */ INPUT p1(0xE8); /* I. */ INSTALL p2(0xC8, 0x9A); /* INS. */ INSTR\( p1(0xA7); /* INS. */ INT p1(0xA8); LEFT\$\( p1(0xC0); /* LE. */ LEN p1(0xA9); LET p1(0xE9); LIBRARY p2(0xC8, 0x9B); /* LIB. */ LINE p1(0x86); LIST p2(0xC7, 0x93); /* L. */ LN p1(0xAA); LOAD p2(0xC7, 0x94); /* LO. */ LOCAL p1(0xEA); LOG p1(0xAB); ^LOMEM p1(0xD2); /* LOM. */ LOMEM p1(0x92); /* LOM. */ LVAR p2(0xC7, 0x95); /* LV. */ MID\$\( p1(0xC1); /* M. */ MOD p1(0x83); MODE p1(0xEB); /* MO. */ MOUSE p2(0xC8, 0x97); /* MOU. */ MOVE p1(0xEC); NEW p2(0xC7, 0x96); NEXT p1(0xED); /* N. */ NOT p1(0xAC); OF p1(0xCA); OFF p1(0x87); OLD p2(0xC7, 0x97); /* O. */ ON p1(0xEE); OPENIN p1(0x8E); /* OP. */ OPENOUT p1(0xAE); /* OPENO. */ OPENUP p1(0xAD); OR p1(0x84); ORIGIN p2(0xC8, 0x91); /* OR. */ OSCLI p1(0xFF); /* OS. */ OTHERWISE p1(0x7F); /* OT. */ OVERLAY p2(0xC8, 0xA3); /* OV. */ ^PAGE p1(0xD0); /* PA. */ PAGE p1(0x90); /* PA. */ PI p1(0xAF); PLOT p1(0xF0); /* PL. */ POINT p2(0xC8, 0x92); POINT\( p1(0xB0); /* PO. */ POS p1(0xB1); PRINT p1(0xF1); /* P. */ PROC p1(0xF2); ^PTR p1(0xCF); PTR p1(0x8F); QUIT p2(0xC8, 0x98); /* Q. */ READ p1(0xF3); RECTANGLE p2(0xC8, 0x93); /* REC. */ REM { p1(0xF4); BEGIN(COMMENT); } RENUMBER p2(0xC7, 0x98); /* REN. */ REPEAT p1(0xF5); /* REP. */ REPORT p1(0xF6); /* REPO. */ RESTORE p1(0xF7); /* RES. */ RETURN p1(0xF8); /* R. */ RIGHT\$\( p1(0xC2); /* RI. */ RND p1(0xB3); RUN p1(0xF9); SAVE p2(0xC7, 0x99); /* SA. */ SGN p1(0xB4); SIN p1(0xB5); SOUND p1(0xD4); /* SO. */ SPC p1(0x89); SQR p1(0xB6); STEP p1(0x88); /* S. */ STEREO p2(0xC8, 0xA2); /* STER. */ STOP p1(0xFA); STR\$ p1(0xC3); STRING\$\( p1(0xC4); /* STRI. */ SUM p2(0xC6, 0x8E); SUMLEN p2(0xC6, 0x8E); /* XXX */ SWAP p2(0xC8, 0x94); /* SW. */ SYS p2(0xC8, 0x99); TAB\( p1(0x8A); TAN p1(0xB7); /* T. */ TEMPO p2(0xC8, 0x9F); /* TE. */ THEN p1(0x8C); /* CONSTA = 1 */ /* TH. */ ^TIME p1(0xD1); /* TI. */ TIME p1(0x91); /* TI. */ TINT p2(0xC8, 0x9C); TO p1(0xB8); TRACE p1(0xFC); /* TR. */ TRUE p1(0xB9); TWIN p2(0xC7, 0x9A); TWINO p2(0xC7, 0x9B); /* TW. */ UNTIL p1(0xFD); /* U. */ USR p1(0xBA); VAL p1(0xBB); VDU p1(0xEF); /* V. */ VOICE p2(0xC8, 0xA1); VOICES p2(0xC8, 0xA0); /* VO. */ VPOS p1(0xBC); /* VP. */ WAIT p2(0xC8, 0x96); /* WA. */ WHEN p1(0xC9); WHILE p2(0xC8, 0x95); /* W. */ WIDTH p1(0xFE); /* WI. */ /* Strings aren't tokenised */ \"[^\"]*\" { memcpy(thisline + pos, yytext, yyleng); pos += yyleng; } . p1(*yytext); \n linedone(); %% #include #include #include #include void filedone(void); void usage(void); void linedone() { fputc(0x0D, yyout); fputc(baslinenum >> 8, yyout); fputc(baslinenum & 0xff, yyout); fputc(pos + 4, yyout); fwrite(thisline, 1, pos, yyout); baslinenum += 10; pos = 0; BEGIN(INITIAL); } void filedone() { fputs("\x0d\xff", yyout); } int main(int argc, char **argv) { int ch; while ((ch = getopt(argc, argv, "")) != -1) switch (ch) { case '?': default: usage(); } argc -= optind; argv += optind; if (*argv != NULL) { yyin = fopen(*argv, "r"); if (yyin == NULL) err(1, "%s", *argv); } yylex(); filedone(); } void usage() { fprintf(stderr, "usage: bastok [file]\n"); exit(1); }