/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2014, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include "opctable.h"
#include "output.h"
#include "scanner.h"
+#include "segment.h"
" -v\t\t\tIncrease verbosity\n"
" -F\t\t\tAdd formfeeds to the output\n"
" -S addr\t\tSet the start/load address\n"
+ " -s\t\t\tAccept line markers in the info file\n"
" -V\t\t\tPrint the disassembler version\n"
"\n"
"Long options:\n"
" --mnemonic-column n\tSpecify mnemonic start column\n"
" --pagelength n\tSet the page length for the listing\n"
" --start-addr addr\tSet the start/load address\n"
+ " --sync-lines\t\tAccept line markers in the info file\n"
" --text-column n\tSpecify text start column\n"
" --verbose\t\tIncrease verbosity\n"
" --version\t\tPrint the disassembler version\n",
static void RangeCheck (const char* Opt, unsigned long Val,
unsigned long Min, unsigned long Max)
/* Do a range check for the given option and abort if there's a range
- * error.
- */
+** error.
+*/
{
if (Val < Min || Val > Max) {
Error ("Argument for %s outside valid range (%ld-%ld)", Opt, Min, Max);
static unsigned long CvtNumber (const char* Arg, const char* Number)
/* Convert a number from a string. Allow '$' and '0x' prefixes for hex
- * numbers.
- */
+** numbers.
+*/
{
unsigned long Val;
int Converted;
+static void OptSyncLines (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Handle the --sync-lines option */
+{
+ SyncLines = 1;
+}
+
+
+
static void OptTextColumn (const char* Opt, const char* Arg)
/* Handle the --text-column option */
{
const char* Arg attribute ((unused)))
/* Print the disassembler version */
{
- fprintf (stderr, "da65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
static void OneOpcode (unsigned RemainingBytes)
/* Disassemble one opcode */
{
+ unsigned I;
+ unsigned OldPC = PC;
+
/* Get the opcode from the current address */
unsigned char OPC = GetCodeByte (PC);
/* Get the output style for the current PC */
attr_t Style = GetStyleAttr (PC);
+ /* If a segment begins here, then name that segment.
+ ** Note that the segment is named even if its code is being skipped,
+ ** because some of its later code might not be skipped.
+ */
+ if (IsSegmentStart (PC)) {
+ StartSegment (GetSegmentStartName (PC), GetSegmentAddrSize (PC));
+ }
+
/* If we have a label at this address, output the label and an attached
- * comment, provided that we aren't in a skip area.
- */
+ ** comment, provided that we aren't in a skip area.
+ */
if (Style != atSkip && MustDefLabel (PC)) {
const char* Comment = GetComment (PC);
if (Comment) {
}
/* Check...
- * - ...if we have enough bytes remaining for the code at this address.
- * - ...if the current instruction is valid for the given CPU.
- * - ...if there is no label somewhere between the instruction bytes.
- * If any of these conditions is false, switch to data mode.
- */
+ ** - ...if we have enough bytes remaining for the code at this address.
+ ** - ...if the current instruction is valid for the given CPU.
+ ** - ...if there is no label somewhere between the instruction bytes.
+ ** - ...if there is no segment change between the instruction bytes.
+ ** If any one of those conditions is false, switch to data mode.
+ */
if (Style == atDefault) {
if (D->Size > RemainingBytes) {
Style = atIllegal;
Style = atIllegal;
MarkAddr (PC, Style);
} else {
- unsigned I;
- for (I = 1; I < D->Size; ++I) {
- if (HaveLabel (PC+I) || HaveSegmentChange (PC+I)) {
+ for (I = PC + D->Size; --I > PC; ) {
+ if (HaveLabel (I) || IsSegmentStart (I)) {
+ Style = atIllegal;
+ MarkAddr (PC, Style);
+ break;
+ }
+ }
+ for (I = 0; I < D->Size - 1u; ++I) {
+ if (IsSegmentEnd (PC + I)) {
Style = atIllegal;
MarkAddr (PC, Style);
break;
case atCode:
/* Beware: If we don't have enough bytes left to disassemble the
- * following insn, fall through to byte mode.
- */
+ ** following insn, fall through to byte mode.
+ */
if (D->Size <= RemainingBytes) {
/* Output labels within the next insn */
- unsigned I;
for (I = 1; I < D->Size; ++I) {
ForwardLabel (I);
}
DataByteLine (1);
++PC;
break;
+ }
+ /* Change back to the default CODE segment if
+ ** a named segment stops at the current address.
+ */
+ for (I = PC - OldPC; I > 0; --I) {
+ if (IsSegmentEnd (PC - I)) {
+ EndSegment ();
+ break;
+ }
}
}
{ "--mnemonic-column", 1, OptMnemonicColumn },
{ "--pagelength", 1, OptPageLength },
{ "--start-addr", 1, OptStartAddr },
+ { "--sync-lines", 0, OptSyncLines },
{ "--text-column", 1, OptTextColumn },
{ "--verbose", 0, OptVerbose },
{ "--version", 0, OptVersion },
OptStartAddr (Arg, GetArg (&I, 2));
break;
+ case 's':
+ OptSyncLines (Arg, 0);
+ break;
+
case 'V':
OptVersion (Arg, 0);
break;
}
/* Check the formatting options for reasonable values. Note: We will not
- * really check that they make sense, just that they aren't complete
- * garbage.
- */
+ ** really check that they make sense, just that they aren't complete
+ ** garbage.
+ */
if (MCol >= ACol) {
AbEnd ("mnemonic-column value must be smaller than argument-column value");
}
}
/* Get the current time and convert it to string so it can be used in
- * the output page headers.
- */
+ ** the output page headers.
+ */
T = time (0);
strftime (Now, sizeof (Now), "%Y-%m-%d %H:%M:%S", localtime (&T));