/* ---------------------------------------------------------------------- */ /* Copyright (C) 1992 by Natrlich! */ /* This file is copyrighted! */ /* Refer to the documentation for details. */ /* ---------------------------------------------------------------------- */ /* rev. history 1.0 -- */ /* 1.1 -- */ /* 1.2 -- removed NIL crashes on faulty MAC65 */ /* 1.3 -- -c option searches directory */ /* 1.4 -- faulty M65 files are treated kinder */ /* 1.5 -- no real changes */ /* ---------------------------------------------------------- */ #include "defines.h" #if __NSTDC__ && __TURBOC__ #pragma warn -pia /* Don't want those if( foo = bar) warnings */ #endif #include #include #include #include #include #define __BIG_GENERATOR__ #include OSBIND #include "code.h" #define COMMENTPAD 24 #define MACROPAD 06 #define INSTRPAD 06 #define DATAPAD 12 #if OS == TOS struct { char reserved[ 21]; byte attribs; word time, date; lword len; char name[ 14]; } dir; #endif void convert(), nflush(), io(), label(), nput(), nprint(), comment(), padto(); struct { word fefe, len; } header; #ifdef NIL #undef NIL #endif #define NIL (char *) 0 #define TAB1SIZE 95 char *table1[] = { "error -", ".if", ".else", ".endif", ".macro", ".endm", ".title", NIL, ".page", ".word", ".error", ".byte", ".sbyte", ".dbyte", ".end", ".opt", ".tab", ".include", ".ds", ".org", ".equ", "bra", "trb", "tsb", ".float", ".cbyte", "", ".local", ".set", "*=", "=", ".=", "jsr", "jmp", "dec", "inc", "ldx", "ldy", "stx", "sty", "cpx", "cpy", "bit", "brk", "clc", "cld", "cli", "clv", "dex", "dey", "inx", "iny", "nop", "pha", "php", "pla", "plp", "rti", "rts", "sec", "sed", "sei", "tax", "tay", "tsx", "txa", "txs", "tya", "bcc", "bcs", "beq", "bmi", "bne", "bpl", "bvc", "bvs", "ora", "and", "eor", "adc", "sta", "lda", "cmp", "sbc", "asl", "rol", "lsr", "ror", NIL, "stz", "dea", "ina", "phx", "phy", "plx", "ply" }; static char ref[] = ".ref ", and[] = ".and ", not[]= ".not ", or[] = ".or ", def[] = ".def "; #define TAB2SIZE 78 char otable2[] = /* 0 - 77 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; char *table2[] = /* 0 - 77 */ { NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, "%$", "%", "*", " ", " ", "a", "q", "+", "-", "*", "/", "&", NIL, "=", "<=", ">=", "<>", ">", "<", "-", "[", "]", or, and, not, "!", "^", ref, "\\", NIL, NIL, NIL, NIL, "Edit", "What!", "Text:", ref, def, not, and, or, "<", ">", ",x)", "),y", ",y", ",x", ")", NIL, NIL, ",", "#", "a", "(", "\"", "$", NIL, NIL, "no ", "obj ", "err ", "eject ","list ", "xref ", "mlist ","clist ","num " }; #define tolower( c) ((c) >= 'A' && (c) <= 'Z' ? (c) + 32 : (c)) #if OS == TOS int tossable; #endif char *currfile = "[none]"; jmp_buf errjmp; static char tiny[8], infile[ 256], outfile[256]; word __x; byte huge *p; long len; int fp, forceit, delete; FILE *fq; void nferror( s) char *s; { fprintf( stderr, "demac65: \"%s\" Fatal error - %s\n", currfile, s); exit(1); } void nerror( s) char *s; { fprintf( stderr, "demac65: \"%s\" Error - %s\n", currfile, s); Fclose( fp); if( outfile[ 0]) fclose( fq); longjmp( errjmp, 1); } unsigned int lines; void nwarning( s) char *s; { fprintf( stderr, "demac65: \"%s\" ca. line %d, Warning - %s\n", currfile, lines + 1, s); } void complete( filename, ext, force) char *filename, *ext; { char *x; if( x = strrchr( filename, '.')) { if( strchr( x, DIRSLASH) > x) goto dis; if( force) while( *++x = *++ext); } else dis: strcat( filename, ext); } int chk_ext( filename, ext) char *filename, *ext; { char *x; if( x = strrchr( filename, '.')) if( strchr( x, DIRSLASH) <= x) return( strcmp( x + 1, ext)); return( 1); } int main( argc, argv) int argc; char *argv[]; { int i = 0; fq = stdout; /* done here for some bogus Amiga CC */ while( ++i < argc) { if( *argv[i] == '-') switch( argv[i][1]) { #if OS == TOS case 'T' : case 't' : tossable = ! tossable; break; #endif case 'D' : case 'd' : delete = ! delete; break; case 'C' : case 'c' : forceit = ! forceit; break; #ifdef __DATE__ case ':' : fputs( __DATE__, stderr); # ifdef __TIME__ fprintf( stderr, " %s", __TIME__); # endif putc( '\n', stderr); break; #endif case 'V' : case 'v' : fprintf( stderr, "demac65 v1.5 (c) 1992 by Natuerlich! -- detokenizes MAC65 files\n"); break; } else if( ! infile[0]) strcpy( infile, argv[i]); else if( ! outfile[0]) strcpy( outfile, argv[i]); else goto usage; } if( ! infile[0]) goto usage; if( ! setjmp( errjmp)) { if( forceit) { strcpy( outfile, infile); complete( outfile, ".s65", 1); #if OS == TOS if( strchr( infile, '*')) /* doesn't work well but works */ { Fsetdta( (void *) &dir); if( Fsfirst( infile, 0)) nferror( "No MaTcH"); /* waste user lifetime */ do if( chk_ext( dir.name, "S65")) { strcpy( outfile, dir.name); complete( outfile, ".s65", 1); if( ! setjmp( errjmp)) io( dir.name, outfile); } while( ! Fsnext()); return( 0); } #endif } io( infile, outfile); return( 0); } return( 1); usage: #if OS == TOS fprintf( stderr, "usage: demac65 [-{td}]{-c |[-c] \ [outfile]}\n"); fputs( "\t-c : convert 1 or more files, f.e. -c '*.*' converts all\n", stderr); #else fprintf( stderr, "usage: demac65 [-{cd}] [outfile]\n"); #endif fputs( "\ \t-c : convert to .S65\n\ \t-d : delete after conversion\n\ \t-v : version\n", stderr); #if OS == TOS fputs( "\t-t : wait for keypress before exiting\n", stderr); keypress(); #endif return(1); } void io( in, out) char *in, *out; { static char buf[256]; currfile = in; if( (fp = (int) Fopen( in, 0)) < 0) { sprintf( buf, "Couldn't open source file \"%s\"", in); nferror( buf); } if( Fread( fp, 4L, &header) < 4) nerror("File trunctated"); if( header.fefe != 0xFEFE) nerror("Not a MAC65 token file"); if( len = dpeek( &header.len)) { if( ! (p = (byte huge *) Malloc( len))) nferror("Out of memory"); if( Fread( fp, len, p) < len) nerror("Source file truncated"); if( out[0] && ! (fq = fopen( out, "w"))) { sprintf( buf, "Couldn't create output file \"%s\"", out); nferror( buf); } convert(); if( delete && ! unlink( in)) fprintf( stderr, "Deleted \"%s\"\n", in); if( out[0]) fclose( fq); } Fclose( fp); } int indent, pad, i, inquotes; byte c, d; void convert() { lines = 1; indent = inquotes = 0; while( len) { pad = 0; /* start from left */ p += 2; /* ignore lineno */ i = (word) *p++ - 3; /* line length */ len -= 3 + i; /* minus lineno + linelength + linebyte */ while( i) { i--; c = *p & 0x7F; if( c != *p++) { label( 0); nput( ' '); continue; } switch( c) { case 0 : nprint( table1[0]); /* am i lazy... */ comment(); break; case 7 : padto(MACROPAD); c = *p++ & 0x7F; i--; label(1); nput(' '); if( xconvert()) goto salvage; break; case 88 : comment(); break; default : d = c; if( d == 2 || d == 3 || d == 5) /* .ELSE .ENDIF .ENDM*/ indent -= 3; padto( INSTRPAD); if( c >= TAB1SIZE) { nerror("Got an totally unknown instr. token"); salvage: p += i; i = 0; break; } else nprint( table1[ c]); nput(' '); if( xconvert()) goto salvage; if( d == 1 || d == 2 || d == 4) indent += 3; } } nput( '\n'); lines++; } } xconvert() { inquotes = 0; if( i) padto( DATAPAD); while( i) { i--; c = *p & 0x7F; if( c != *p++) { label( inquotes); continue; } switch( c) { case 1 : case 3 : case 5 : sprintf( tiny, "$%X", ((word) p[1] << 8) | (word) *p); p += 2; i -= 2; nprint( tiny); break; case 0 : case 2 : case 4 : case 6 : sprintf( tiny, "$%X", (word) *p++); i--; nprint( tiny); break; case 7 : case 9 : sprintf( tiny, "%u", ((word) p[1] << 8) | *p); p += 2; i -= 2; nprint( tiny); break; case 8 : sprintf( tiny, "%u", *p++); i--; nprint( tiny); break; case 10 : nput('\''); nput( (int) *p++); i--; break; case 59 : padto( COMMENTPAD); if( *p != ';') nput( ';'); comment(); break; case 65 : inquotes = ! inquotes; default : { if( c >= TAB2SIZE) { nerror("Got an undetokenizable token"); return( 1); } else { if( ! otable2[ c]) nwarning("Unusual token"); nprint( table2[ c]); } } } } return( 0); } /* Vot = 0 lower case */ void label( vot) { char v; int x = c; i -= c; while( x) { x--; v = *p++; nput( (int) (vot ? v : tolower(v))); } } void comment() { while( i) { i--; nput( (int) *p++); } } void padto(to) int to; { to += indent; while( pad < to) nput(' '); } void nput( c) int c; { putc( c, fq); pad++; } void nprint( s) char *s; { int i; if( s) { i = (int) strlen( s); if( fputs( s, fq)) nferror("Disk full ?"); pad += i; } else nerror("Got an undetokenizable token"); } keypress() { #if OS == TOS if( tossable) { while( Bconstat( 2)) Bconin( 2); Bconin( 2); } #endif }