---------------------------------------------------------------------------
Usage: ca65 [options] file
Short options:
- -D name[=value] Define a symbol
- -I dir Set an include directory search path
- -U Mark unresolved symbols as import
- -V Print the assembler version
- -W n Set warning level n
- -g Add debug info to object file
- -h Help (this text)
- -i Ignore case of symbols
- -l Create a listing if assembly was ok
- -mm model Set the memory model
- -o name Name the output file
- -s Enable smart mode
- -t sys Set the target system
- -v Increase verbosity
+ -D name[=value] Define a symbol
+ -I dir Set an include directory search path
+ -U Mark unresolved symbols as import
+ -V Print the assembler version
+ -W n Set warning level n
+ -g Add debug info to object file
+ -h Help (this text)
+ -i Ignore case of symbols
+ -l Create a listing if assembly was ok
+ -mm model Set the memory model
+ -o name Name the output file
+ -s Enable smart mode
+ -t sys Set the target system
+ -v Increase verbosity
Long options:
- --auto-import Mark unresolved symbols as import
- --bin-include-dir dir Set a search path for binary includes
- --cpu type Set cpu type
- --debug-info Add debug info to object file
- --feature name Set an emulation feature
- --forget-inc-paths Forget include search paths
- --help Help (this text)
- --ignore-case Ignore case of symbols
- --include-dir dir Set an include directory search path
- --listing Create a listing if assembly was ok
- --list-bytes n Maximum number of bytes per listing line
- --macpack-dir dir Set a macro package directory
- --memory-model model Set the memory model
- --pagelength n Set the page length for the listing
- --smart Enable smart mode
- --target sys Set the target system
- --verbose Increase verbosity
- --version Print the assembler version
+ --auto-import Mark unresolved symbols as import
+ --bin-include-dir dir Set a search path for binary includes
+ --cpu type Set cpu type
+ --create-dep name Create a make dependency file
+ --create-full-dep name Create a full make dependency file
+ --debug-info Add debug info to object file
+ --feature name Set an emulation feature
+ --forget-inc-paths Forget include search paths
+ --help Help (this text)
+ --ignore-case Ignore case of symbols
+ --include-dir dir Set an include directory search path
+ --listing Create a listing if assembly was ok
+ --list-bytes n Maximum number of bytes per listing line
+ --macpack-dir dir Set a macro package directory
+ --memory-model model Set the memory model
+ --pagelength n Set the page length for the listing
+ --smart Enable smart mode
+ --target sys Set the target system
+ --verbose Increase verbosity
+ --version Print the assembler version
---------------------------------------------------------------------------
</verb></tscreen>
instruction set is "proprietary and confidential".
+ <label id="option-create-dep">
+ <tag><tt>--create-dep name</tt></tag>
+
+ Tells the assembler to generate a file containing the dependency list for
+ the assembled module in makefile syntax. The output is written to a file
+ with the given name. The output does not include files passed via debug
+ information to the assembler.
+
+
+ <label id="option-create-full-dep">
+ <tag><tt>--create-full-dep name</tt></tag>
+
+ Tells the assembler to generate a file containing the dependency list for
+ the assembled module in makefile syntax. The output is written to a file
+ with the given name. The output does include files passed via debug
+ information to the assembler.
+
+
<label id="option--feature">
<tag><tt>--feature name</tt></tag>
/* */
/* */
/* */
-/* (C) 2000-2008 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
MTime = ConstExpression ();
/* Insert the file into the table */
- AddFile (&Name, Size, MTime);
+ AddFile (&Name, FT_DBGINFO, Size, MTime);
/* Free memory used for Name */
SB_Done (&Name);
+#include <stdio.h>
#include <string.h>
+#include <errno.h>
/* common */
#include "check.h"
/* ca65 */
#include "error.h"
#include "filetab.h"
+#include "global.h"
#include "objfile.h"
#include "spool.h"
HashNode Node;
unsigned Name; /* File name */
unsigned Index; /* Index of entry */
+ FileType Type; /* Type of file */
unsigned long Size; /* Size of file */
unsigned long MTime; /* Time of last modification */
};
-static FileEntry* NewFileEntry (unsigned Name, unsigned long Size, unsigned long MTime)
+static FileEntry* NewFileEntry (unsigned Name, FileType Type,
+ unsigned long Size, unsigned long MTime)
/* Create a new FileEntry, insert it into the tables and return it */
{
/* Allocate memory for the entry */
InitHashNode (&F->Node, F);
F->Name = Name;
F->Index = CollCount (&FileTab) + 1; /* First file has index #1 */
+ F->Type = Type;
F->Size = Size;
F->MTime = MTime;
const StrBuf* GetFileName (unsigned Name)
/* Get the name of a file where the name index is known */
{
- static StrBuf ErrorMsg = LIT_STRBUF_INITIALIZER ("(outside file scope)");
+ static const StrBuf ErrorMsg = LIT_STRBUF_INITIALIZER ("(outside file scope)");
const FileEntry* F;
-unsigned AddFile (const StrBuf* Name, unsigned long Size, unsigned long MTime)
+unsigned AddFile (const StrBuf* Name, FileType Type,
+ unsigned long Size, unsigned long MTime)
/* Add a new file to the list of input files. Return the index of the file in
* the table.
*/
{
/* Create a new file entry and insert it into the tables */
- FileEntry* F = NewFileEntry (GetStrBufId (Name), Size, MTime);
+ FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime);
/* Return the index */
return F->Index;
+static void WriteDep (FILE* F, FileType Types)
+/* Helper function. Writes all file names that match Types to the output */
+{
+ unsigned I;
+
+ /* Loop over all files */
+ for (I = 0; I < CollCount (&FileTab); ++I) {
+
+ const StrBuf* Filename;
+
+ /* Get the next input file */
+ const FileEntry* E = (const FileEntry*) CollAt (&FileTab, I);
+
+ /* Ignore it if it is not of the correct type */
+ if ((E->Type & Types) == 0) {
+ continue;
+ }
+
+ /* If this is not the first file, add a space */
+ if (I > 0) {
+ fputc (' ', F);
+ }
+
+ /* Print the dependency */
+ Filename = GetStrBuf (E->Name);
+ fprintf (F, "%*s", SB_GetLen (Filename), SB_GetConstBuf (Filename));
+ }
+}
+
+
+
+static void CreateDepFile (const char* Name, FileType Types)
+/* Create a dependency file with the given name and place dependencies for
+ * all files with the given types there.
+ */
+{
+ /* Open the file */
+ FILE* F = fopen (Name, "w");
+ if (F == 0) {
+ Fatal ("Cannot open dependency file `%s': %s", Name, strerror (errno));
+ }
+
+ /* Print the output file followed by a tab char */
+ fprintf (F, "%s:\t", OutFile);
+
+ /* Write out the dependencies for the output file */
+ WriteDep (F, Types);
+ fputs ("\n\n", F);
+
+ /* Write out a phony dependency for the included files */
+ WriteDep (F, Types);
+ fputs (":\n\n", F);
+
+ /* Close the file, check for errors */
+ if (fclose (F) != 0) {
+ remove (Name);
+ Fatal ("Cannot write to dependeny file (disk full?)");
+ }
+}
+
+
+
+void CreateDependencies (void)
+/* Create dependency files requested by the user */
+{
+ if (SB_NotEmpty (&DepName)) {
+ CreateDepFile (SB_GetConstBuf (&DepName),
+ FT_MAIN | FT_INCLUDE | FT_BINARY);
+ }
+ if (SB_NotEmpty (&FullDepName)) {
+ CreateDepFile (SB_GetConstBuf (&FullDepName),
+ FT_MAIN | FT_INCLUDE | FT_BINARY | FT_DBGINFO);
+ }
+}
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* An enum that describes different types of input files. The members are
+ * choosen so that it is possible to combine them to bitsets
+ */
+typedef enum {
+ FT_MAIN = 0x01, /* Main input file */
+ FT_INCLUDE = 0x02, /* Normal include file */
+ FT_BINARY = 0x04, /* Binary include file */
+ FT_DBGINFO = 0x08, /* File from debug info */
+} FileType;
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
unsigned GetFileIndex (const StrBuf* Name);
/* Return the file index for the given file name. */
-unsigned AddFile (const StrBuf* Name, unsigned long Size, unsigned long MTime);
+unsigned AddFile (const StrBuf* Name, FileType Type,
+ unsigned long Size, unsigned long MTime);
/* Add a new file to the list of input files. Return the index of the file in
* the table.
*/
void WriteFiles (void);
/* Write the list of input files to the object file */
+void CreateDependencies (void);
+/* Create dependency files requested by the user */
/* */
/* */
/* */
-/* (C) 1998-2008 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
const char* InFile = 0; /* Name of input file */
const char* OutFile = 0; /* Name of output file */
const char* ListFile = 0; /* Name of listing file */
+StrBuf DepName = STATIC_STRBUF_INITIALIZER; /* Dependency file */
+StrBuf FullDepName = STATIC_STRBUF_INITIALIZER; /* Full dependency file */
/* Default extensions */
const char ObjExt[] = ".o";/* Default object extension */
/* */
/* */
/* */
-/* (C) 1998-2008 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
+/* common */
+#include "strbuf.h"
+
+
+
/*****************************************************************************/
/* Data */
/*****************************************************************************/
extern const char* InFile; /* Name of input file */
extern const char* OutFile; /* Name of output file */
extern const char* ListFile; /* Name of listing file */
+extern StrBuf DepName; /* Name of dependencies file */
+extern StrBuf FullDepName; /* Name of full dependencies file */
/* Default extensions */
extern const char ObjExt[]; /* Default object extension */
{
printf ("Usage: %s [options] file\n"
"Short options:\n"
- " -D name[=value]\tDefine a symbol\n"
- " -I dir\t\tSet an include directory search path\n"
- " -U\t\t\tMark unresolved symbols as import\n"
- " -V\t\t\tPrint the assembler version\n"
- " -W n\t\t\tSet warning level n\n"
- " -g\t\t\tAdd debug info to object file\n"
- " -h\t\t\tHelp (this text)\n"
- " -i\t\t\tIgnore case of symbols\n"
- " -l\t\t\tCreate a listing if assembly was ok\n"
- " -mm model\t\tSet the memory model\n"
- " -o name\t\tName the output file\n"
- " -s\t\t\tEnable smart mode\n"
- " -t sys\t\tSet the target system\n"
- " -v\t\t\tIncrease verbosity\n"
+ " -D name[=value]\t\tDefine a symbol\n"
+ " -I dir\t\t\tSet an include directory search path\n"
+ " -U\t\t\t\tMark unresolved symbols as import\n"
+ " -V\t\t\t\tPrint the assembler version\n"
+ " -W n\t\t\t\tSet warning level n\n"
+ " -g\t\t\t\tAdd debug info to object file\n"
+ " -h\t\t\t\tHelp (this text)\n"
+ " -i\t\t\t\tIgnore case of symbols\n"
+ " -l\t\t\t\tCreate a listing if assembly was ok\n"
+ " -mm model\t\t\tSet the memory model\n"
+ " -o name\t\t\tName the output file\n"
+ " -s\t\t\t\tEnable smart mode\n"
+ " -t sys\t\t\tSet the target system\n"
+ " -v\t\t\t\tIncrease verbosity\n"
"\n"
"Long options:\n"
- " --auto-import\t\tMark unresolved symbols as import\n"
- " --bin-include-dir dir\tSet a search path for binary includes\n"
- " --cpu type\t\tSet cpu type\n"
- " --debug-info\t\tAdd debug info to object file\n"
- " --feature name\tSet an emulation feature\n"
- " --forget-inc-paths\tForget include search paths\n"
- " --help\t\tHelp (this text)\n"
- " --ignore-case\t\tIgnore case of symbols\n"
- " --include-dir dir\tSet an include directory search path\n"
- " --listing\t\tCreate a listing if assembly was ok\n"
- " --list-bytes n\tMaximum number of bytes per listing line\n"
- " --macpack-dir dir\tSet a macro package directory\n"
- " --memory-model model\tSet the memory model\n"
- " --pagelength n\tSet the page length for the listing\n"
- " --smart\t\tEnable smart mode\n"
- " --target sys\t\tSet the target system\n"
- " --verbose\t\tIncrease verbosity\n"
- " --version\t\tPrint the assembler version\n",
+ " --auto-import\t\t\tMark unresolved symbols as import\n"
+ " --bin-include-dir dir\t\tSet a search path for binary includes\n"
+ " --cpu type\t\t\tSet cpu type\n"
+ " --create-dep name\t\tCreate a make dependency file\n"
+ " --create-full-dep name\tCreate a full make dependency file\n"
+ " --debug-info\t\t\tAdd debug info to object file\n"
+ " --feature name\t\tSet an emulation feature\n"
+ " --forget-inc-paths\t\tForget include search paths\n"
+ " --help\t\t\tHelp (this text)\n"
+ " --ignore-case\t\t\tIgnore case of symbols\n"
+ " --include-dir dir\t\tSet an include directory search path\n"
+ " --listing\t\t\tCreate a listing if assembly was ok\n"
+ " --list-bytes n\t\tMaximum number of bytes per listing line\n"
+ " --macpack-dir dir\t\tSet a macro package directory\n"
+ " --memory-model model\t\tSet the memory model\n"
+ " --pagelength n\t\tSet the page length for the listing\n"
+ " --smart\t\t\tEnable smart mode\n"
+ " --target sys\t\t\tSet the target system\n"
+ " --verbose\t\t\tIncrease verbosity\n"
+ " --version\t\t\tPrint the assembler version\n",
ProgName);
}
+static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name)
+/* Handle an option that remembers a file name for later */
+{
+ /* Cannot have the option twice */
+ if (SB_NotEmpty (Name)) {
+ AbEnd ("Cannot use option `%s' twice", Opt);
+ }
+ /* Remember the file name for later */
+ SB_CopyStr (Name, Arg);
+ SB_Terminate (Name);
+}
+
+
+
static void DefineSymbol (const char* Def)
/* Define a symbol from the command line */
{
+static void OptCreateDep (const char* Opt, const char* Arg)
+/* Handle the --create-dep option */
+{
+ FileNameOption (Opt, Arg, &DepName);
+}
+
+
+
+static void OptCreateFullDep (const char* Opt attribute ((unused)),
+ const char* Arg)
+/* Handle the --create-full-dep option */
+{
+ FileNameOption (Opt, Arg, &FullDepName);
+}
+
+
+
static void OptDebugInfo (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Add debug info to the object file */
{ "--auto-import", 0, OptAutoImport },
{ "--bin-include-dir", 1, OptBinIncludeDir },
{ "--cpu", 1, OptCPU },
+ { "--create-dep", 1, OptCreateDep },
+ { "--create-full-dep", 1, OptCreateFullDep },
{ "--debug-info", 0, OptDebugInfo },
{ "--feature", 1, OptFeature },
{ "--forget-inc-paths", 0, OptForgetIncPaths },
/* If we didn't have any errors, check the pseudo insn stacks */
if (ErrorCount == 0) {
- CheckPseudo ();
+ CheckPseudo ();
}
/* If we didn't have any errors, check the unnamed labels */
SegDump ();
}
- /* If we didn't have any errors, create the object and listing files */
+ /* If we didn't have any errors, create the object, listing and
+ * dependency files
+ */
if (ErrorCount == 0) {
- CreateObjFile ();
- if (Listing) {
- CreateListing ();
- }
+ CreateObjFile ();
+ if (Listing) {
+ CreateListing ();
+ }
+ CreateDependencies ();
}
/* Close the input file */
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#include <sys/types.h> /* EMX needs this */
+#include <sys/stat.h>
/* common */
#include "assertion.h"
#include "error.h"
#include "expr.h"
#include "feature.h"
+#include "filetab.h"
#include "global.h"
#include "incpath.h"
#include "instr.h"
/* Include a binary file */
{
StrBuf Name = STATIC_STRBUF_INITIALIZER;
+ struct stat StatBuf;
long Start = 0L;
long Count = -1L;
long Size;
if (PathName == 0 || (F = fopen (PathName, "rb")) == 0) {
/* Not found or cannot open, print an error and bail out */
ErrorSkip ("Cannot open include file `%m%p': %s", &Name, strerror (errno));
+ xfree (PathName);
+ goto ExitPoint;
}
+ /* Remember the new file name */
+ SB_CopyStr (&Name, PathName);
+
/* Free the allocated memory */
xfree (PathName);
-
- /* If we had an error before, bail out now */
- if (F == 0) {
- goto ExitPoint;
- }
}
/* Get the size of the file */
fseek (F, 0, SEEK_END);
Size = ftell (F);
+ /* Stat the file and remember the values. There a race condition here,
+ * since we cannot use fileno() (non standard identifier in standard
+ * header file), and therefore not fstat. When using stat with the
+ * file name, there's a risk that the file was deleted and recreated
+ * while it was open. Since mtime and size are only used to check
+ * if a file has changed in the debugger, we will ignore this problem
+ * here.
+ */
+ SB_Terminate (&Name);
+ if (stat (SB_GetConstBuf (&Name), &StatBuf) != 0) {
+ Fatal ("Cannot stat input file `%m%p': %s", &Name, strerror (errno));
+ }
+
+ /* Add the file to the input file table */
+ AddFile (&Name, FT_BINARY, Size, StatBuf.st_mtime);
+
/* If a count was not given, calculate it now */
if (Count < 0) {
- Count = Size - Start;
- if (Count < 0) {
- /* Nothing to read - flag this as a range error */
+ Count = Size - Start;
+ if (Count < 0) {
+ /* Nothing to read - flag this as a range error */
ErrorSkip ("Range error");
goto Done;
}
/*****************************************************************************/
/* InputFile functions */
/*****************************************************************************/
-
+
static void IFMarkStart (CharSource* S)
}
/* Add the file to the input file table and remember the index */
- FileIdx = AddFile (SB_InitFromString (&NameBuf, Name), Buf.st_size, Buf.st_mtime);
+ FileIdx = AddFile (SB_InitFromString (&NameBuf, Name),
+ (FCount == 0)? FT_MAIN : FT_INCLUDE,
+ Buf.st_size, Buf.st_mtime);
/* Create a new input source variable and initialize it */
S = xmalloc (sizeof (*S));