1243 lines
38 KiB
C
1243 lines
38 KiB
C
/*
|
|
** Pretty6502
|
|
**
|
|
** by Oscar Toledo G.
|
|
**
|
|
** © Copyright 2017-2018 Oscar Toledo G.
|
|
**
|
|
** Creation date: Nov/03/2017.
|
|
** Revision date: Nov/06/2017. Processor selection. Indents nested IF/ENDIF.
|
|
** Tries to preserve vertical structure of comments.
|
|
** Allows label in its own line. Allows to change case
|
|
** of mnemonics and directives.
|
|
** Revision date: Apr/16/2018. Added support for Z80 + tniASM. Solved bug in
|
|
** processing of apostrophe in operand.
|
|
** Revision date: Apr/17/2018. Added support for CP1610 + as1600 (Intellivision).
|
|
** Comments now also include indentation. Working in
|
|
** TMS9900 mode.
|
|
** Revision date: Apr/18/2018. Added support for TMS9900 + xas99 (TI-99/4A), also
|
|
** special syntax (comments must be separated by 2
|
|
** spaces).
|
|
** Revision date: May/04/2020. Adjusted CP1610 for indenting REPEAT directive.
|
|
** Revision date: Apr/12/2021. Added support for 8086 + nasm.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#define VERSION "v0.7"
|
|
|
|
int tabs; /* Size of tabs (0 to use spaces) */
|
|
|
|
enum {
|
|
P_UNK,
|
|
P_6502,
|
|
P_Z80,
|
|
P_CP1610,
|
|
P_TMS9900,
|
|
P_8086,
|
|
P_65C02,
|
|
P_UNSUPPORTED,
|
|
} processor; /* Processor/assembler being used (0-4) */
|
|
|
|
/*
|
|
** 65C02 mnemonics
|
|
*/
|
|
char *mnemonics_65C02[] = {
|
|
"adc" ,"and" ,"asl" ,"bbr0","bbr1","bbr2","bbr3","bbr4",
|
|
"bbr5","bbr6","bbr7","bbs0","bbs1","bbs2","bbs3","bbs4",
|
|
"bbs5","bbs6","bbs7","bcc" ,"bcs" ,"beq" ,"bit" ,"bmi" ,
|
|
"bne" ,"bpl" ,"bra" ,"brk" ,"bvc" ,"bvs" ,"clc" ,"cld" ,
|
|
"cli" ,"clv" ,"cmp" ,"cpx" ,"cpy" ,"dea" ,"dec" ,"dex" ,
|
|
"dey" ,"eor" ,"ina" ,"inc" ,"inx" ,"iny" ,"jmp" ,"jsr" ,
|
|
"lda" ,"ldx" ,"ldy" ,"lsr" ,"nop" ,"ora" ,"pha" ,"php" ,
|
|
"phx" ,"phy" ,"pla" ,"plp" ,"plx" ,"ply" ,"rmb0","rmb1",
|
|
"rmb2","rmb3","rmb4","rmb5","rmb6","rmb7","rol" ,"ror" ,
|
|
"rti" ,"rts" ,"sbc" ,"sec" ,"sed" ,"sei" ,"smb0","smb1",
|
|
"smb2","smb3","smb4","smb5","smb6","smb7","sta" ,"stp" ,
|
|
"stx" ,"sty" ,"stz" ,"tax" ,"tay" ,"trb" ,"tsb" ,"tsx",
|
|
"txa" ,"txs" ,"tya" ,"wai" , NULL,
|
|
};
|
|
|
|
/*
|
|
** 65C02 mnemonics
|
|
*/
|
|
char *mnemonics_6502[] = {
|
|
"adc", "anc", "and", "ane", "arr", "asl", "asr", "bcc",
|
|
"bcs", "beq", "bit", "bmi", "bne", "bpl", "brk", "bvc",
|
|
"bvs", "clc", "cld", "cli", "clv", "cmp", "cpx", "cpy",
|
|
"dcp", "dec", "dex", "dey", "eor", "inc", "inx", "iny",
|
|
"isb", "jmp", "jsr", "las", "lax", "lda", "ldx", "ldy",
|
|
"lsr", "lxa", "nop", "ora", "pha", "php", "pla", "plp",
|
|
"rla", "rol", "ror", "rra", "rti", "rts", "sax", "sbc",
|
|
"sbx", "sec", "sed", "sei", "sha", "shs", "shx", "shy",
|
|
"slo", "sre", "sta", "stx", "sty", "tax", "tay", "tsx",
|
|
"txa", "txs", "tya", NULL,
|
|
};
|
|
|
|
/*
|
|
** Z80 mnemonics
|
|
*/
|
|
char *mnemonics_z80[] = {
|
|
"adc", "add", "and", "bit", "call", "ccf", "cp", "cpd",
|
|
"cpdr", "cpi", "cpir", "cpl", "daa", "dec", "di", "djnz",
|
|
"ei", "ex", "exx", "halt", "im", "in", "inc", "ind",
|
|
"indr", "ini", "inir", "jp", "jr", "ld", "ldd", "lddr",
|
|
"ldi", "ldir", "neg", "nop", "or", "otdr", "otir", "out",
|
|
"outd", "outi", "pop", "push", "res", "ret", "reti", "retn",
|
|
"rl", "rla", "rlc", "rlca", "rld", "rr", "rra", "rrc",
|
|
"rrca", "rrd", "rst", "sbc", "scf", "set", "sla", "sra",
|
|
"srl", "sub", "xor", NULL,
|
|
};
|
|
|
|
/*
|
|
** CP1610 mnemonics
|
|
*/
|
|
char *mnemonics_cp1610[] = {
|
|
"adcr", "add", "add@", "addi", "addr", "and", "and@", "andi",
|
|
"andr", "b", "bc", "beq", "besc", "bext", "bge", "bgt",
|
|
"ble", "blge", "bllt", "blt", "bmi", "bnc", "bneq", "bnov",
|
|
"bnze", "bov", "bpl", "busc", "bze", "clrc", "clrr", "cmp",
|
|
"cmp@", "cmpi", "cmpr", "comr", "decr", "dis", "eis", "gswd",
|
|
"hlt", "incr", "j", "jd", "je", "jr", "jsr", "jsrd",
|
|
"jsre", "movr", "mvi", "mvi@", "mvii", "mvo", "mvo@", "mvoi",
|
|
"negr", "nop", "nopp", "pshr", "pulr", "rlc", "rrc", "rswd",
|
|
"sar", "sarc", "sdbd", "setc", "sin", "sll", "sllc", "slr",
|
|
"sub", "sub@", "subi", "subr", "swap", "tci", "tstr", "xor",
|
|
"xor@", "xori", "xorr", NULL,
|
|
};
|
|
|
|
/*
|
|
** TMS9900 mnemonics
|
|
*/
|
|
char *mnemonics_tms9900[] = {
|
|
"a", "ab", "abs", "ai", "andi", "b", "bl", "blwp",
|
|
"c", "call", "cb", "ci", "ckof", "ckon", "clr", "coc",
|
|
"czc", "dec", "dect", "div", "idle", "inc", "inct", "inv",
|
|
"jeq", "jgt", "jh", "jhe", "jl", "jle", "jlt", "jmp",
|
|
"jnc", "jne", "jno", "joc", "jop", "ldcr", "li", "limi",
|
|
"lrex", "lwpi", "mov", "movb", "mpy", "neg", "nop", "ori",
|
|
"pix", "pop", "push", "ret", "rset", "rt", "rtwp", "s",
|
|
"sb", "sbo", "sbz", "seto", "sla", "slc", "soc", "socb",
|
|
"sra", "src", "srl", "stcr", "stst", "stwp", "swpb", "szc",
|
|
"szcb", "tb", "x", "xop", "xor", NULL,
|
|
};
|
|
|
|
/*
|
|
** 8086 mnemonics
|
|
*/
|
|
char *mnemonics_8086[] = {
|
|
"aaa", "aad", "aam", "aas", "adc", "add", "and", "call",
|
|
"cbw", "clc", "cld", "cli", "cmc", "cmp", "cmps", "cmpsb",
|
|
"cmpsw","cs", "cwd", "daa", "das", "dec", "div", "ds",
|
|
"es", "hlt", "idiv", "imul", "in", "inc", "int", "int3",
|
|
"into", "iret", "ja", "jb", "jbe", "jcxz", "jg", "jge",
|
|
"jl", "jle", "jmp", "jnb", "jno", "jns", "jnz", "jo",
|
|
"jpe", "jpo", "js", "jz", "lahf", "lds", "lea", "les",
|
|
"lock", "lods", "lodsb","lodsw","loop", "loopnz","loopz","mov",
|
|
"movs", "movsb","movsw","mul", "neg", "nop", "not", "or",
|
|
"out", "pop", "popf", "push", "pushf","rcl", "rcr", "rep",
|
|
"repnz","repz", "ret", "retf", "rol", "ror", "sahf", "sar",
|
|
"sbb", "scas", "scasb","scasw","shl", "shr", "ss", "stc",
|
|
"std", "sti", "stos", "stosb","stosw","sub", "test", "wait",
|
|
"xchg", "xlat", "xor", NULL,
|
|
};
|
|
|
|
#define DONT_RELOCATE_LABEL 0x01
|
|
#define LEVEL_IN 0x02
|
|
#define LEVEL_OUT 0x04
|
|
#define LEVEL_MINUS 0x08
|
|
|
|
struct directive {
|
|
char *directive;
|
|
int flags;
|
|
};
|
|
|
|
/*
|
|
** DASM directives
|
|
*/
|
|
struct directive directives_dasm[] = {
|
|
"=", DONT_RELOCATE_LABEL,
|
|
"align", 0,
|
|
"byte", 0,
|
|
"dc", 0,
|
|
"ds", 0,
|
|
"dv", 0,
|
|
"echo", 0,
|
|
"eif", LEVEL_OUT,
|
|
"else", LEVEL_MINUS,
|
|
"end", 0,
|
|
"endif", LEVEL_OUT,
|
|
"endm", LEVEL_OUT,
|
|
"eqm", DONT_RELOCATE_LABEL,
|
|
"equ", DONT_RELOCATE_LABEL,
|
|
"err", 0,
|
|
"hex", 0,
|
|
"if", LEVEL_IN,
|
|
"ifconst", LEVEL_IN,
|
|
"ifnconst", LEVEL_IN,
|
|
"incbin", 0,
|
|
"incdir", 0,
|
|
"include", 0,
|
|
"list", 0,
|
|
"long", 0,
|
|
"mac", LEVEL_IN,
|
|
"mexit", 0,
|
|
"org", 0,
|
|
"processor", 0,
|
|
"rend", 0,
|
|
"repeat", LEVEL_IN,
|
|
"repend", LEVEL_OUT,
|
|
"rorg", 0,
|
|
"seg", 0,
|
|
"set", DONT_RELOCATE_LABEL,
|
|
"subroutine", DONT_RELOCATE_LABEL,
|
|
"trace", 0,
|
|
"word", 0,
|
|
NULL, 0,
|
|
};
|
|
|
|
/*
|
|
** CA65 (https://cc65.github.io/doc/ca65.html) directives
|
|
*/
|
|
struct directive directives_ca65[] = {
|
|
"*", DONT_RELOCATE_LABEL,
|
|
".asize", 0,
|
|
".cpu", 0,
|
|
".isize", 0,
|
|
".paramcount", 0,
|
|
".time", 0,
|
|
".version", 0,
|
|
".addrsize", 0,
|
|
".bank", 0,
|
|
".bankbyte", 0,
|
|
".blank", 0,
|
|
".concat", 0,
|
|
".const", 0,
|
|
".def", LEVEL_IN,
|
|
".definedmacro",0,
|
|
".defined", 0,
|
|
".hibyte", 0,
|
|
".hiword", 0,
|
|
".ident", 0,
|
|
".ismnem", 0,
|
|
".ismnemonic", 0,
|
|
".left", 0,
|
|
".lobyte", 0,
|
|
".loword", 0,
|
|
".match", 0,
|
|
".max", 0,
|
|
".mid", 0,
|
|
".min", 0,
|
|
".ref", 0,
|
|
".referenced", 0,
|
|
".right", 0,
|
|
".sizeof", 0,
|
|
".sprintf", 0,
|
|
".strat", 0,
|
|
".string", 0,
|
|
".strlen", 0,
|
|
".tcount", 0,
|
|
".xmatch", 0,
|
|
".a16", 0,
|
|
".a8", 0,
|
|
".addr", 0,
|
|
".align", 0,
|
|
".asciiz", 0,
|
|
".assert", 0,
|
|
".autoimport", 0,
|
|
".bankbytes", 0,
|
|
".bss", 0,
|
|
".byt", 0,
|
|
".byte", 0,
|
|
".case", 0,
|
|
".charmap", 0,
|
|
".code", 0,
|
|
".condes", 0,
|
|
".constructor", 0,
|
|
".data", 0,
|
|
".dbyt", 0,
|
|
".debuginfo", 0,
|
|
".define", 0,
|
|
".delmac", 0,
|
|
".delmacro", 0,
|
|
".destructor", 0,
|
|
".dword", 0,
|
|
".else", 0,
|
|
".elseif", 0,
|
|
".end", LEVEL_OUT,
|
|
".endenum", LEVEL_OUT,
|
|
".endif", LEVEL_OUT,
|
|
".endmac", LEVEL_OUT,
|
|
".endmacro", LEVEL_OUT,
|
|
".endproc", LEVEL_OUT,
|
|
".endrep", LEVEL_OUT,
|
|
".endrepeat", LEVEL_OUT,
|
|
".endscope", LEVEL_OUT,
|
|
".endstruct", LEVEL_OUT,
|
|
".endunion", LEVEL_OUT,
|
|
".enum", 0,
|
|
".error", 0,
|
|
".exitmac", LEVEL_OUT,
|
|
".exitmacro", LEVEL_OUT,
|
|
".export", 0,
|
|
".exportzp", 0,
|
|
".faraddr", 0,
|
|
".fatal", 0,
|
|
".feature", 0,
|
|
".fileopt", 0,
|
|
".fopt", 0,
|
|
".forceimport", 0,
|
|
".global", 0,
|
|
".globalzp", 0,
|
|
".hibytes", 0,
|
|
".i16", 0,
|
|
".i8", 0,
|
|
".if", LEVEL_IN,
|
|
".ifblank", LEVEL_IN,
|
|
".ifconst", LEVEL_IN,
|
|
".ifdef", LEVEL_IN,
|
|
".ifnblank", LEVEL_IN,
|
|
".ifndef", LEVEL_IN,
|
|
".ifnref", LEVEL_IN,
|
|
".ifp02", LEVEL_IN,
|
|
".ifp4510", LEVEL_IN,
|
|
".ifp816", LEVEL_IN,
|
|
".ifpc02", LEVEL_IN,
|
|
".ifpdtv", LEVEL_IN,
|
|
".ifpsc02", LEVEL_IN,
|
|
".ifref", LEVEL_IN,
|
|
".import", 0,
|
|
".importzp", 0,
|
|
".incbin", 0,
|
|
".include", 0,
|
|
".interruptor", 0,
|
|
".linecont", 0,
|
|
".list", 0,
|
|
".listbytes", 0,
|
|
".literal", 0,
|
|
".lobytes", 0,
|
|
".local", 0,
|
|
".localchar", 0,
|
|
".macpack", 0,
|
|
".mac", LEVEL_IN,
|
|
".macro", LEVEL_IN,
|
|
".org", 0,
|
|
".out", 0,
|
|
".p02", 0,
|
|
".p4510", 0,
|
|
".p816", 0,
|
|
".pagelen", 0,
|
|
".pagelength", 0,
|
|
".pc02", 0,
|
|
".pdtv", 0,
|
|
".popcharmap", 0,
|
|
".popcpu", 0,
|
|
".popseg", 0,
|
|
".proc", 0,
|
|
".psc02", 0,
|
|
".pushcharmap", 0,
|
|
".pushcpu", 0,
|
|
".pushseg", 0,
|
|
".refto", 0,
|
|
".referto", 0,
|
|
".reloc", 0,
|
|
".repeat", LEVEL_IN,
|
|
".res", 0,
|
|
".rodata", 0,
|
|
".scope", 0,
|
|
".segment", 0,
|
|
".set", 0,
|
|
".setcpu", 0,
|
|
".smart", 0,
|
|
".struct", 0,
|
|
".tag", 0,
|
|
".undef", 0,
|
|
".undefine", 0,
|
|
".union", 0,
|
|
".warning", 0,
|
|
".word", 0,
|
|
".zeropage", 0,
|
|
".macpack", 0,
|
|
".tag", 0,
|
|
".org", 0,
|
|
"=", DONT_RELOCATE_LABEL,
|
|
NULL, 0,
|
|
};
|
|
|
|
/*
|
|
** tniASM directives
|
|
*/
|
|
struct directive directives_tniasm[] = {
|
|
"cpu", 0,
|
|
"db", 0,
|
|
"dc", 0,
|
|
"ds", 0,
|
|
"dw", 0,
|
|
"dephase", 0,
|
|
"else", LEVEL_MINUS,
|
|
"endif", LEVEL_OUT,
|
|
"equ", DONT_RELOCATE_LABEL,
|
|
"fname", 0,
|
|
"forg", 0,
|
|
"if", LEVEL_IN,
|
|
"ifdef", LEVEL_IN,
|
|
"ifexist", LEVEL_IN,
|
|
"incbin", 0,
|
|
"include", 0,
|
|
"org", 0,
|
|
"phase", 0,
|
|
"rb", 0,
|
|
"rw", 0,
|
|
NULL, 0,
|
|
};
|
|
|
|
/*
|
|
** as1600 directives
|
|
*/
|
|
struct directive directives_as1600[] = {
|
|
"begin", 0,
|
|
"bidecle", 0,
|
|
"byte", 0,
|
|
"cfgvar", 0,
|
|
"cmsg", 0,
|
|
"dcw", 0,
|
|
"decle", 0,
|
|
"else", LEVEL_MINUS,
|
|
"endi", LEVEL_OUT,
|
|
"endm", LEVEL_OUT,
|
|
"endp", 0,
|
|
"endr", LEVEL_OUT,
|
|
"ends", LEVEL_OUT,
|
|
"err", 0,
|
|
"if", LEVEL_IN,
|
|
"listing", 0,
|
|
"macro", LEVEL_IN,
|
|
"memattr", 0,
|
|
"org", DONT_RELOCATE_LABEL,
|
|
"proc", DONT_RELOCATE_LABEL,
|
|
"qequ", DONT_RELOCATE_LABEL,
|
|
"qset", DONT_RELOCATE_LABEL,
|
|
"repeat", LEVEL_IN,
|
|
"res", 0,
|
|
"reserve", 0,
|
|
"return", 0,
|
|
"rmb", 0,
|
|
"romw", 0,
|
|
"romwidth", 0,
|
|
"rpt", 0,
|
|
"set", DONT_RELOCATE_LABEL,
|
|
"smsg", 0,
|
|
"srcfile", 0,
|
|
"string", 0,
|
|
"struct", DONT_RELOCATE_LABEL | LEVEL_IN,
|
|
"wmsg", 0,
|
|
"word", 0,
|
|
NULL, 0,
|
|
};
|
|
|
|
/*
|
|
** xas99 directives
|
|
*/
|
|
struct directive directives_xas99[] = {
|
|
".defm", LEVEL_IN,
|
|
".else", LEVEL_MINUS,
|
|
".endif", LEVEL_OUT,
|
|
".endm", LEVEL_OUT,
|
|
".error", 0,
|
|
".ifdef", LEVEL_IN,
|
|
".ifeq", LEVEL_IN,
|
|
".ifge", LEVEL_IN,
|
|
".ifgt", LEVEL_IN,
|
|
".ifndef", LEVEL_IN,
|
|
".ifne", LEVEL_IN,
|
|
"aorg", 0,
|
|
"bcopy", 0,
|
|
"bes", 0,
|
|
"bss", 0,
|
|
"byte", 0,
|
|
"cend", 0,
|
|
"copy", 0,
|
|
"cseg", 0,
|
|
"data", 0,
|
|
"def", DONT_RELOCATE_LABEL,
|
|
"dend", 0,
|
|
"dorg", 0,
|
|
"dseg", 0,
|
|
"dxop", 0,
|
|
"end", 0,
|
|
"equ", DONT_RELOCATE_LABEL,
|
|
"even", 0,
|
|
"idt", 0,
|
|
"list", 0,
|
|
"load", 0,
|
|
"page", 0,
|
|
"pend", 0,
|
|
"pseg", 0,
|
|
"ref", 0,
|
|
"rorg", 0,
|
|
"save", 0,
|
|
"sref", 0,
|
|
"text", 0,
|
|
"titl", 0,
|
|
"unl", 0,
|
|
"xorg", 0,
|
|
NULL, 0,
|
|
};
|
|
|
|
/*
|
|
** nasm directives
|
|
*/
|
|
struct directive directives_nasm[] = {
|
|
"%arg", 0,
|
|
"%assign", 0,
|
|
"%define", 0,
|
|
"%defstr", 0,
|
|
"%deftok", 0,
|
|
"%depend", 0,
|
|
"%elif", LEVEL_MINUS,
|
|
"%elifdef", LEVEL_MINUS,
|
|
"%elifn", LEVEL_MINUS,
|
|
"%elifndef",LEVEL_MINUS,
|
|
"%else", LEVEL_MINUS,
|
|
"%endif", LEVEL_OUT,
|
|
"%endmacro",LEVEL_OUT,
|
|
"%endrep", LEVEL_OUT,
|
|
"%error", 0,
|
|
"%fatal", 0,
|
|
"%if", LEVEL_IN,
|
|
"%ifdef", LEVEL_IN,
|
|
"%ifmacro", LEVEL_IN,
|
|
"%ifn", LEVEL_IN,
|
|
"%ifndef", LEVEL_IN,
|
|
"%include", 0,
|
|
"%line", 0,
|
|
"%local", 0,
|
|
"%macro", LEVEL_IN,
|
|
"%pathsearch", 0,
|
|
"%pragma", 0,
|
|
"%pop", 0,
|
|
"%push", 0,
|
|
"%rep", LEVEL_IN,
|
|
"%rotate", 0,
|
|
"%stacksize",0,
|
|
"%strcat", 0,
|
|
"%strlen", 0,
|
|
"%substr", 0,
|
|
"%unmacro", 0,
|
|
"%use", 0,
|
|
"%warning", 0,
|
|
"__sect__", 0,
|
|
"absolute", 0,
|
|
"align", 0,
|
|
"alignb", 0,
|
|
"bits", 0,
|
|
"common", 0,
|
|
"cpu", 0,
|
|
"db", 0,
|
|
"dd", 0,
|
|
"default", 0,
|
|
"do", 0,
|
|
"dq", 0,
|
|
"dt", 0,
|
|
"dw", 0,
|
|
"dy", 0,
|
|
"dz", 0,
|
|
"equ", DONT_RELOCATE_LABEL,
|
|
"export", 0,
|
|
"extern", 0,
|
|
"float", 0,
|
|
"global", 0,
|
|
"import", 0,
|
|
"incbin", 0,
|
|
"library", 0,
|
|
"module", 0,
|
|
"resb", 0,
|
|
"resd", 0,
|
|
"reso", 0,
|
|
"resq", 0,
|
|
"rest", 0,
|
|
"resw", 0,
|
|
"resy", 0,
|
|
"resz", 0,
|
|
"sectalign",0,
|
|
"section", 0,
|
|
"segment", 0,
|
|
"use16", 0,
|
|
"use32", 0,
|
|
"[warning", 0,
|
|
NULL, 0,
|
|
};
|
|
|
|
/*
|
|
** Comparison without case
|
|
*/
|
|
int memcmpcase(char *p1, char *p2, int size)
|
|
{
|
|
while (size--) {
|
|
if (tolower(*p1) != tolower(*p2))
|
|
return 1;
|
|
p1++;
|
|
p2++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Check for opcode or directive
|
|
*/
|
|
int check_opcode(char *p1, char *p2)
|
|
{
|
|
int c;
|
|
int length;
|
|
|
|
if (processor == P_6502) { /* 6502 + DASM */
|
|
for (c = 0; directives_dasm[c].directive != NULL; c++) {
|
|
length = strlen(directives_dasm[c].directive);
|
|
if ((*p1 == '.' && length == p2 - p1 - 1 && memcmpcase(p1 + 1, directives_dasm[c].directive, p2 - p1 - 1) == 0) || (length == p2 - p1 && memcmpcase(p1, directives_dasm[c].directive, p2 - p1) == 0)) {
|
|
return c + 1;
|
|
}
|
|
}
|
|
for (c = 0; mnemonics_6502[c] != NULL; c++) {
|
|
length = strlen(mnemonics_6502[c]);
|
|
if (length == p2 - p1 && memcmpcase(p1, mnemonics_6502[c], p2 - p1) == 0)
|
|
return -(c + 1);
|
|
}
|
|
}
|
|
if (processor == P_65C02) { /* 65C02 + ca65 */
|
|
for (c = 0; directives_ca65[c].directive != NULL; c++) {
|
|
length = strlen(directives_ca65[c].directive);
|
|
if ((*p1 == '.' && length == p2 - p1 - 1 && memcmpcase(p1 + 1, directives_ca65[c].directive, p2 - p1 - 1) == 0) || (length == p2 - p1 && memcmpcase(p1, directives_ca65[c].directive, p2 - p1) == 0)) {
|
|
return c + 1;
|
|
}
|
|
}
|
|
for (c = 0; mnemonics_65C02[c] != NULL; c++) {
|
|
length = strlen(mnemonics_65C02[c]);
|
|
if (length == p2 - p1 && memcmpcase(p1, mnemonics_65C02[c], p2 - p1) == 0)
|
|
return -(c + 1);
|
|
}
|
|
}
|
|
if (processor == P_Z80) { /* Z80 + tniASM */
|
|
for (c = 0; directives_tniasm[c].directive != NULL; c++) {
|
|
length = strlen(directives_tniasm[c].directive);
|
|
if (length == p2 - p1 && memcmpcase(p1, directives_tniasm[c].directive, p2 - p1) == 0) {
|
|
return c + 1;
|
|
}
|
|
}
|
|
for (c = 0; mnemonics_z80[c] != NULL; c++) {
|
|
length = strlen(mnemonics_z80[c]);
|
|
if (length == p2 - p1 && memcmpcase(p1, mnemonics_z80[c], p2 - p1) == 0)
|
|
return -(c + 1);
|
|
}
|
|
}
|
|
if (processor == P_CP1610) { /* CP1610 + as1600 */
|
|
for (c = 0; directives_as1600[c].directive != NULL; c++) {
|
|
length = strlen(directives_as1600[c].directive);
|
|
if (length == p2 - p1 && memcmpcase(p1, directives_as1600[c].directive, p2 - p1) == 0) {
|
|
return c + 1;
|
|
}
|
|
}
|
|
for (c = 0; mnemonics_cp1610[c] != NULL; c++) {
|
|
length = strlen(mnemonics_cp1610[c]);
|
|
if (length == p2 - p1 && memcmpcase(p1, mnemonics_cp1610[c], p2 - p1) == 0)
|
|
return -(c + 1);
|
|
}
|
|
}
|
|
if (processor == P_TMS9900) { /* TMS9900 + xas99 */
|
|
for (c = 0; directives_xas99[c].directive != NULL; c++) {
|
|
length = strlen(directives_xas99[c].directive);
|
|
if (length == p2 - p1 && memcmpcase(p1, directives_xas99[c].directive, p2 - p1) == 0) {
|
|
return c + 1;
|
|
}
|
|
}
|
|
for (c = 0; mnemonics_tms9900[c] != NULL; c++) {
|
|
length = strlen(mnemonics_tms9900[c]);
|
|
if (length == p2 - p1 && memcmpcase(p1, mnemonics_tms9900[c], p2 - p1) == 0)
|
|
return -(c + 1);
|
|
}
|
|
}
|
|
if (processor == P_8086) { /* 8086 + nasm */
|
|
for (c = 0; directives_nasm[c].directive != NULL; c++) {
|
|
length = strlen(directives_nasm[c].directive);
|
|
if (length == p2 - p1 && memcmpcase(p1, directives_nasm[c].directive, p2 - p1) == 0) {
|
|
return c + 1;
|
|
}
|
|
}
|
|
for (c = 0; mnemonics_8086[c] != NULL; c++) {
|
|
length = strlen(mnemonics_8086[c]);
|
|
if (length == p2 - p1 && memcmpcase(p1, mnemonics_8086[c], p2 - p1) == 0)
|
|
return -(c + 1);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Request space in line
|
|
*/
|
|
void request_space(FILE *output, int *current, int new, int force)
|
|
{
|
|
int base;
|
|
int tab;
|
|
|
|
/*
|
|
** If already exceeded space...
|
|
*/
|
|
if (*current >= new) {
|
|
if (force == 1) {
|
|
fputc(' ', output);
|
|
(*current)++;
|
|
} else if (force == 2 && *current != 0) { /* TMS9900 */
|
|
fputc(' ', output);
|
|
(*current)++;
|
|
fputc(' ', output);
|
|
(*current)++;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** Advance one step at a time
|
|
*/
|
|
tab = 0;
|
|
base = *current;
|
|
while (1) {
|
|
if (tabs == 0) {
|
|
fprintf(output, "%*s", new - *current, "");
|
|
*current = new;
|
|
} else {
|
|
fputc('\t', output);
|
|
*current = (*current + tabs) / tabs * tabs;
|
|
tab = 1;
|
|
}
|
|
if (*current >= new) {
|
|
if (force == 2) { /* TMS9900 */
|
|
if (tab == 0) {
|
|
if (*current != 0) {
|
|
base = *current - base;
|
|
if (base < 1) {
|
|
fputc(' ', output);
|
|
(*current)++;
|
|
}
|
|
if (base < 2) {
|
|
fputc(' ', output);
|
|
(*current)++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Check for comment present
|
|
*/
|
|
int comment_present(char *start, char *actual, int left_side)
|
|
{
|
|
if (processor == P_TMS9900) {
|
|
if (actual == start && *actual == '*')
|
|
return 1;
|
|
if (*actual == '*') {
|
|
if (actual == start)
|
|
return 1;
|
|
if (actual == start + 1 && isspace(actual[-1]))
|
|
return 1;
|
|
if (actual >= start + 2) {
|
|
if (isspace(actual[-2]) && isspace(actual[-1]))
|
|
return 1;
|
|
}
|
|
}
|
|
if (isspace(actual[0]) && isspace(actual[1]) && !left_side)
|
|
return 1;
|
|
if (actual[0] == '\t' && !left_side)
|
|
return 1;
|
|
}
|
|
if (*actual == ';')
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Main program
|
|
*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int c;
|
|
int style;
|
|
int start_mnemonic;
|
|
int start_operand;
|
|
int start_comment;
|
|
int align_comment;
|
|
int nesting_space;
|
|
int labels_own_line;
|
|
FILE *input;
|
|
FILE *output;
|
|
int allocation;
|
|
char *data;
|
|
char *p;
|
|
char *p1;
|
|
char *p2;
|
|
char *p3;
|
|
int current_column;
|
|
int request;
|
|
int current_level;
|
|
int prev_comment_original_location;
|
|
int prev_comment_final_location;
|
|
int flags;
|
|
int mnemonics_case;
|
|
int directives_case;
|
|
int indent;
|
|
int something;
|
|
int comment;
|
|
|
|
/*
|
|
** Show usage if less than 3 arguments (program name counts as one)
|
|
*/
|
|
if (argc < 3) {
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Pretty6502 " VERSION " by Oscar Toledo G. http://nanochess.org/\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Usage:\n");
|
|
fprintf(stderr, " pretty6502 [args] input.asm output.asm\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "It's recommended to not use same output file as input,\n");
|
|
fprintf(stderr, "even if possible because there is a chance (0.0000001%%)\n");
|
|
fprintf(stderr, "that you can DAMAGE YOUR SOURCE if Pretty6502 has\n");
|
|
fprintf(stderr, "undiscovered bugs.\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Arguments:\n");
|
|
fprintf(stderr, " -s0 Code in four columns (default)\n");
|
|
fprintf(stderr, " label: mnemonic operand comment\n");
|
|
fprintf(stderr, " -s1 Code in three columns\n");
|
|
fprintf(stderr, " label: mnemonic+operand comment\n");
|
|
fprintf(stderr, " -p0 Processor unknown\n");
|
|
fprintf(stderr, " -p1 Processor 6502 + DASM syntax (default)\n");
|
|
fprintf(stderr, " -p2 Processor Z80 + tniASM syntax\n");
|
|
fprintf(stderr, " -p3 Processor CP1610 + as1600 syntax (Intellivision(tm))\n");
|
|
fprintf(stderr, " -p4 Processor TMS9900 + xas99 syntax (TI-99/4A)\n");
|
|
fprintf(stderr, " -p5 Processor 8086 + nasm syntax\n");
|
|
fprintf(stderr, " -p6 Processor 65c02 + ca65 syntax\n");
|
|
fprintf(stderr, " -m8 Start of mnemonic column (default)\n");
|
|
fprintf(stderr, " -o16 Start of operand column (default)\n");
|
|
fprintf(stderr, " -c32 Start of comment column (default)\n");
|
|
fprintf(stderr, " -t8 Use tabs of size 8 to reach column\n");
|
|
fprintf(stderr, " -t0 Use spaces to align (default)\n");
|
|
fprintf(stderr, " -a0 Align comments to nearest column\n");
|
|
fprintf(stderr, " -a1 Comments at line start are aligned\n");
|
|
fprintf(stderr, " to mnemonic (default)\n");
|
|
fprintf(stderr, " -n4 Nesting spacing (can be any number\n");
|
|
fprintf(stderr, " of spaces or multiple of tab size)\n");
|
|
fprintf(stderr, " -l Puts labels in its own line\n");
|
|
fprintf(stderr, " -dl Change directives to lowercase\n");
|
|
fprintf(stderr, " -du Change directives to uppercase\n");
|
|
fprintf(stderr, " -ml Change mnemonics to lowercase\n");
|
|
fprintf(stderr, " -mu Change mnemonics to uppercase\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Assumes all your labels are at start of line and there is space\n");
|
|
fprintf(stderr, "before mnemonic.\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Accepts any assembler file where ; means comment\n");
|
|
fprintf(stderr, "[label] mnemonic [operand] ; comment\n");
|
|
exit(1);
|
|
}
|
|
|
|
/*
|
|
** Default settings
|
|
*/
|
|
style = 0;
|
|
processor = P_6502;
|
|
start_mnemonic = 8;
|
|
start_operand = 16;
|
|
start_comment = 32;
|
|
tabs = 0;
|
|
align_comment = 1;
|
|
nesting_space = 4;
|
|
labels_own_line = 0;
|
|
mnemonics_case = 0;
|
|
directives_case = 0;
|
|
|
|
/*
|
|
** Process arguments
|
|
*/
|
|
something = 0;
|
|
c = 1;
|
|
while (c < argc - 2) {
|
|
if (argv[c][0] != '-') {
|
|
fprintf(stderr, "Bad argument\n");
|
|
exit(1);
|
|
}
|
|
switch (tolower(argv[c][1])) {
|
|
case 's': /* Style */
|
|
style = atoi(&argv[c][2]);
|
|
if (style != 0 && style != 1) {
|
|
fprintf(stderr, "Bad style code: %d\n", style);
|
|
exit(1);
|
|
}
|
|
break;
|
|
case 'p': /* Processor */
|
|
request = atoi(&argv[c][2]);
|
|
if (request < 0 || request >= P_UNSUPPORTED) {
|
|
fprintf(stderr, "Bad processor code: %d\n", request);
|
|
exit(1);
|
|
}
|
|
processor = request;
|
|
break;
|
|
case 'm': /* Mnemonic start */
|
|
if (tolower(argv[c][2]) == 'l') {
|
|
mnemonics_case = 1;
|
|
} else if (tolower(argv[c][2]) == 'u') {
|
|
mnemonics_case = 2;
|
|
} else {
|
|
start_mnemonic = atoi(&argv[c][2]);
|
|
}
|
|
break;
|
|
case 'o': /* Operand start */
|
|
start_operand = atoi(&argv[c][2]);
|
|
something = 1;
|
|
break;
|
|
case 'c': /* Comment start */
|
|
start_comment = atoi(&argv[c][2]);
|
|
break;
|
|
case 't': /* Tab size */
|
|
tabs = atoi(&argv[c][2]);
|
|
break;
|
|
case 'a': /* Comment alignment */
|
|
align_comment = atoi(&argv[c][2]);
|
|
if (align_comment != 0 && align_comment != 1) {
|
|
fprintf(stderr, "Bad comment alignment: %d\n", align_comment);
|
|
exit(1);
|
|
}
|
|
break;
|
|
case 'n': /* Nesting space */
|
|
nesting_space = atoi(&argv[c][2]);
|
|
break;
|
|
case 'l': /* Labels in own line */
|
|
labels_own_line = 1;
|
|
break;
|
|
case 'd': /* Directives */
|
|
if (tolower(argv[c][2]) == 'l') {
|
|
directives_case = 1;
|
|
} else if (tolower(argv[c][2]) == 'u') {
|
|
directives_case = 2;
|
|
} else {
|
|
fprintf(stderr, "Unknown argument: %c%c\n", argv[c][1], argv[c][2]);
|
|
}
|
|
break;
|
|
default: /* Other */
|
|
fprintf(stderr, "Unknown argument: %c\n", argv[c][1]);
|
|
exit(1);
|
|
}
|
|
c++;
|
|
}
|
|
|
|
/*
|
|
** Validate constraints
|
|
*/
|
|
if (style == 1) {
|
|
if (start_mnemonic > start_comment) {
|
|
fprintf(stderr, "Operand error: -m%d > -c%d\n", start_mnemonic, start_comment);
|
|
exit(1);
|
|
}
|
|
start_operand = start_mnemonic;
|
|
} else if (style == 0) {
|
|
if (start_mnemonic > start_operand) {
|
|
fprintf(stderr, "Operand error: -m%d > -o%d\n", start_mnemonic, start_operand);
|
|
exit(1);
|
|
}
|
|
if (start_operand > start_comment) {
|
|
fprintf(stderr, "Operand error: -o%d > -c%d\n", start_operand, start_comment);
|
|
exit(1);
|
|
}
|
|
}
|
|
if (tabs > 0) {
|
|
if (start_mnemonic % tabs) {
|
|
fprintf(stderr, "Operand error: -m%d isn't a multiple of %d\n", start_mnemonic, tabs);
|
|
exit(1);
|
|
}
|
|
if (start_operand % tabs) {
|
|
fprintf(stderr, "Operand error: -m%d isn't a multiple of %d\n", start_operand, tabs);
|
|
exit(1);
|
|
}
|
|
if (start_comment % tabs) {
|
|
fprintf(stderr, "Operand error: -m%d isn't a multiple of %d\n", start_comment, tabs);
|
|
exit(1);
|
|
}
|
|
if (nesting_space % tabs) {
|
|
fprintf(stderr, "Operand error: -n%d isn't a multiple of %d\n", nesting_space, tabs);
|
|
exit(1);
|
|
}
|
|
}
|
|
if (something && processor == P_TMS9900) {
|
|
fprintf(stderr, "Warning: ignoring operand column, not possible because you selected TMS9900 mode\n");
|
|
}
|
|
|
|
/*
|
|
** Open input file, measure it and read it into buffer
|
|
*/
|
|
input = fopen(argv[c], "rb");
|
|
if (input == NULL) {
|
|
fprintf(stderr, "Unable to open input file: %s\n", argv[c]);
|
|
exit(1);
|
|
}
|
|
fprintf(stderr, "Processing %s...\n", argv[c]);
|
|
fseek(input, 0, SEEK_END);
|
|
allocation = ftell(input);
|
|
data = malloc(allocation + sizeof(char));
|
|
if (data == NULL) {
|
|
fprintf(stderr, "Unable to allocate memory\n");
|
|
fclose(input);
|
|
exit(1);
|
|
}
|
|
fseek(input, 0, SEEK_SET);
|
|
if (fread(data, sizeof(char), allocation, input) != allocation) {
|
|
fprintf(stderr, "Something went wrong reading the input file\n");
|
|
fclose(input);
|
|
free(data);
|
|
exit(1);
|
|
}
|
|
fclose(input);
|
|
|
|
/*
|
|
** Ease processing of input file
|
|
*/
|
|
request = 0;
|
|
p1 = data;
|
|
p2 = data;
|
|
while (p1 < data + allocation) {
|
|
if (*p1 == '\r') { /* Ignore \r characters */
|
|
p1++;
|
|
continue;
|
|
}
|
|
if (*p1 == '\n') {
|
|
p1++;
|
|
|
|
/* Remove trailing spaces */
|
|
while (p2 > data && *(p2 - 1) != '\0' && isspace(*(p2 - 1)))
|
|
p2--;
|
|
*p2++ = '\0'; /* Break line */
|
|
request = 1;
|
|
continue;
|
|
}
|
|
*p2++ = *p1++;
|
|
request = 0;
|
|
}
|
|
if (request == 0)
|
|
*p2++ = '\0'; /* Force line break */
|
|
allocation = p2 - data;
|
|
|
|
/*
|
|
** Now generate output file
|
|
*/
|
|
c++;
|
|
output = fopen(argv[c], "w");
|
|
if (output == NULL) {
|
|
fprintf(stderr, "Unable to open output file: %s\n", argv[c]);
|
|
exit(1);
|
|
}
|
|
prev_comment_original_location = 0;
|
|
prev_comment_final_location = 0;
|
|
current_level = 0;
|
|
p = data;
|
|
while (p < data + allocation) {
|
|
something = 0;
|
|
current_column = 0;
|
|
p1 = p;
|
|
p2 = p1;
|
|
|
|
while (*p2 && !isspace(*p2) && !comment_present(p, p2, 1)) {
|
|
p2++;
|
|
}
|
|
if (p2 - p1) { /* Label */
|
|
something = 1;
|
|
fwrite(p1, sizeof(char), p2 - p1, output);
|
|
current_column = p2 - p1;
|
|
p1 = p2;
|
|
} else {
|
|
current_column = 0;
|
|
}
|
|
while (*p1 && isspace(*p1) && !comment_present(p, p1, 1))
|
|
p1++;
|
|
indent = current_level * nesting_space;
|
|
flags = 0;
|
|
if (*p1 && !comment_present(p, p1, 1)) { /* Mnemonic */
|
|
p2 = p1;
|
|
while (*p2 && !isspace(*p2) && !comment_present(p, p2, 0))
|
|
p2++;
|
|
if (processor != P_UNK) {
|
|
c = check_opcode(p1, p2);
|
|
if (c == 0) {
|
|
request = start_mnemonic;
|
|
} else if (c < 0) {
|
|
request = start_mnemonic;
|
|
} else {
|
|
if (processor == P_6502)
|
|
flags = directives_dasm[c - 1].flags;
|
|
else if (processor == P_Z80)
|
|
flags = directives_tniasm[c - 1].flags;
|
|
else if (processor == P_CP1610)
|
|
flags = directives_as1600[c - 1].flags;
|
|
else if (processor == P_TMS9900)
|
|
flags = directives_xas99[c - 1].flags;
|
|
else if (processor == P_8086)
|
|
flags = directives_nasm[c - 1].flags;
|
|
else if (processor == P_65C02)
|
|
flags = directives_ca65[c - 1].flags;
|
|
if (flags & DONT_RELOCATE_LABEL)
|
|
request = start_operand;
|
|
else
|
|
request = start_mnemonic;
|
|
}
|
|
} else {
|
|
request = start_mnemonic;
|
|
c = 0;
|
|
}
|
|
if (c <= 0) {
|
|
if (mnemonics_case == 1) {
|
|
p3 = p1;
|
|
while (p3 < p2) {
|
|
*p3 = tolower(*p3);
|
|
p3++;
|
|
}
|
|
} else if (mnemonics_case == 2) {
|
|
p3 = p1;
|
|
while (p3 < p2) {
|
|
*p3 = toupper(*p3);
|
|
p3++;
|
|
}
|
|
}
|
|
} else {
|
|
if (directives_case == 1) {
|
|
p3 = p1;
|
|
while (p3 < p2) {
|
|
*p3 = tolower(*p3);
|
|
p3++;
|
|
}
|
|
} else if (directives_case == 2) {
|
|
p3 = p1;
|
|
while (p3 < p2) {
|
|
*p3 = toupper(*p3);
|
|
p3++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Move label to own line
|
|
*/
|
|
if (current_column != 0 && labels_own_line != 0 && (flags & DONT_RELOCATE_LABEL) == 0) {
|
|
fputc('\n', output);
|
|
current_column = 0;
|
|
}
|
|
if (flags & LEVEL_OUT) {
|
|
if (current_level > 0) {
|
|
current_level--;
|
|
indent -= nesting_space;
|
|
}
|
|
}
|
|
if (flags & LEVEL_MINUS) {
|
|
if (indent >= nesting_space)
|
|
indent -= nesting_space;
|
|
else
|
|
indent = 0;
|
|
}
|
|
request += indent;
|
|
request_space(output, ¤t_column, request, 1);
|
|
something = 1;
|
|
fwrite(p1, sizeof(char), p2 - p1, output);
|
|
current_column += p2 - p1;
|
|
p1 = p2;
|
|
while (*p1 && isspace(*p1) && !comment_present(p, p1, 0))
|
|
p1++;
|
|
if (*p1 && !comment_present(p, p1, 0)) { /* Operand */
|
|
if (processor == P_TMS9900)
|
|
request = current_column + 1;
|
|
else
|
|
request = start_operand + indent;
|
|
request_space(output, ¤t_column, request, 1);
|
|
p2 = p1;
|
|
while (*p2 && !comment_present(p, p2, 0)) {
|
|
if (*p2 == '"') {
|
|
p2++;
|
|
while (*p2 && *p2 != '"')
|
|
p2++;
|
|
p2++;
|
|
} else if (*p2 == '\'') {
|
|
p2++;
|
|
if (p2 - p1 < 6 || memcmp(p2 - 6, "AF,AF'", 6) != 0) {
|
|
while (*p2 && *p2 != '\'')
|
|
p2++;
|
|
p2++;
|
|
}
|
|
} else {
|
|
p2++;
|
|
}
|
|
}
|
|
while (p2 > p1 && isspace(*(p2 - 1)))
|
|
p2--;
|
|
something = 1;
|
|
fwrite(p1, sizeof(char), p2 - p1, output);
|
|
current_column += p2 - p1;
|
|
p1 = p2;
|
|
while (*p1 && isspace(*p1) && !comment_present(p, p1, 0))
|
|
p1++;
|
|
}
|
|
if (flags & LEVEL_IN) {
|
|
current_level++;
|
|
}
|
|
}
|
|
if (comment_present(p, p1, !something)) { /* Comment */
|
|
if (processor == P_TMS9900) {
|
|
while (isspace(*p1))
|
|
p1++;
|
|
}
|
|
|
|
/*
|
|
** Try to keep comments aligned vertically (only works
|
|
** if spaces were used in source file)
|
|
*/
|
|
p2 = p1;
|
|
while (p2 - 1 >= p && isspace(*(p2 - 1)))
|
|
p2--;
|
|
if (processor == P_TMS9900 && p2 == p && *p1 == '*') {
|
|
request = 0; /* Cannot be other */
|
|
} else if (p2 == p && p1 - p == prev_comment_original_location) {
|
|
request = prev_comment_final_location;
|
|
} else {
|
|
prev_comment_original_location = p1 - p;
|
|
if (current_column == 0)
|
|
request = 0;
|
|
else if (current_column < start_mnemonic + indent)
|
|
request = start_mnemonic + indent;
|
|
else
|
|
request = start_comment + indent;
|
|
if (current_column == 0 && align_comment == 1)
|
|
request = start_mnemonic + indent;
|
|
prev_comment_final_location = request;
|
|
}
|
|
request_space(output, ¤t_column, request, (*p1 == ';') ? 0 : 2);
|
|
p2 = p1;
|
|
while (*p2)
|
|
p2++;
|
|
while (p2 > p1 && isspace(*(p2 - 1)))
|
|
p2--;
|
|
fwrite(p1, sizeof(char), p2 - p1, output);
|
|
fputc('\n', output);
|
|
current_column += p2 - p1;
|
|
while (*p++) ;
|
|
continue;
|
|
} else if (something == 0) {
|
|
prev_comment_original_location = 0;
|
|
prev_comment_final_location = 0;
|
|
}
|
|
fputc('\n', output);
|
|
while (*p++) ;
|
|
}
|
|
fclose(output);
|
|
free(data);
|
|
exit(0);
|
|
}
|