1 /* CC65 main program */
9 #include "../common/version.h"
24 /*****************************************************************************/
26 /*****************************************************************************/
30 /* Names of the target systems sorted by target name */
31 static const char* TargetNames [] = {
47 /*****************************************************************************/
49 /*****************************************************************************/
53 static void usage (int ExitCode)
55 fputs ("Usage: cc65 [options] file\n"
56 "\t-d\t\tDebug mode\n"
57 "\t-g\t\tAdd debug info to object files\n"
58 "\t-h\t\tPrint this help\n"
59 "\t-j\t\tDefault characters are signed\n"
60 "\t-o name\t\tName the output file\n"
61 "\t-tx\t\tSet target system x\n"
62 "\t-v\t\tVerbose mode\n"
63 "\t-A\t\tStrict ANSI mode\n"
64 "\t-Cl\t\tMake local variables static\n"
65 "\t-Dsym[=defn]\tDefine a symbol\n"
66 "\t-I path\t\tSet include directory\n"
67 "\t-O\t\tOptimize code\n"
68 "\t-Oi\t\tOptimize code, inline more code\n"
69 "\t-Or\t\tEnable register variables\n"
70 "\t-Os\t\tInline some known functions\n"
71 "\t-T\t\tInclude source as comment\n"
72 "\t-V\t\tPrint version number\n"
73 "\t-W\t\tSuppress warnings\n",
80 static char* GetArg (int* ArgNum, char* argv [], unsigned Len)
81 /* Get an option argument */
83 char* Arg = argv [*ArgNum];
84 if (Arg [Len] != '\0') {
85 /* Argument appended */
88 /* Separate argument */
89 Arg = argv [*ArgNum + 1];
91 /* End of arguments */
92 fprintf (stderr, "Option requires an argument: %s\n", argv [*ArgNum]);
102 /* Define a CBM system */
103 static void cbmsys (const char* sys)
105 AddNumericMacro ("__CBM__", 1);
106 AddNumericMacro (sys, 1);
111 static int MapSys (const char* Name)
112 /* Map a target name to a system code. Return -1 in case of an error */
116 /* Check for a numeric target */
117 if (isdigit (*Name)) {
118 int Target = atoi (Name);
119 if (Target >= 0 && Target < TGT_COUNT) {
124 /* Check for a target string */
125 for (I = 0; I < TGT_COUNT; ++I) {
126 if (strcmp (TargetNames [I], Name) == 0) {
136 /* Define a target system */
137 static void SetSys (const char* Sys)
139 switch (Target = MapSys (Sys)) {
145 AddNumericMacro ("__ATARI__", 1);
161 cbmsys ("__PLUS4__");
165 cbmsys ("__CBM610__");
173 AddNumericMacro ("__NES__", 1);
177 AddNumericMacro ("__APPLE2__", 1);
181 /* Do not handle as a CBM system */
182 AddNumericMacro ("__GEOS__", 1);
186 fputs ("Unknown system type\n", stderr);
187 usage (EXIT_FAILURE);
193 static void InvSym (const char* Def)
194 /* Print an error about an invalid macro definition and die */
196 fprintf (stderr, "Invalid macro definition: `%s'\n", Def);
202 static void DefineSym (const char* Def)
203 /* Define a symbol on the command line */
207 /* The symbol must start with a character or underline */
208 if (Def [0] != '_' && !isalpha (Def [0])) {
212 /* Check the symbol name */
213 while (isalnum (*P) || *P == '_') {
217 /* Do we have a value given? */
222 /* No value given. Define the macro with the value 1 */
223 AddNumericMacro (Def, 1);
225 /* We have a value, P points to the '=' character. Since the argument
226 * is const, create a copy and replace the '=' in the copy by a zero
230 unsigned Len = strlen (Def)+1;
231 char* S = xmalloc (Len);
232 memcpy (S, Def, Len);
236 /* Define this as a macro */
239 /* Release the allocated memory */
246 int main (int argc, char **argv)
253 /* Initialize the output file name */
258 /* Parse the command line */
259 for (i = 1; i < argc; i++) {
260 if (*(argp = argv[i]) == '-') {
263 case 'd': /* debug mode */
269 usage (EXIT_SUCCESS);
281 strcpy (out_name, GetArg (&i, argv, 2));
285 SetSys (GetArg (&i, argv, 2));
308 DefineSym (GetArg (&i, argv, 2));
312 AddIncludePath (GetArg (&i, argv, 2), INC_SYS | INC_USER);
321 sscanf (p, "%lx", (long*) &OptDisable);
341 fprintf (stderr, "cc65 V%u.%u.%u\n",
342 VER_MAJOR, VER_MINOR, VER_PATCH);
350 fprintf (stderr, "Invalid option %s\n", argp);
351 usage (EXIT_FAILURE);
355 fprintf (stderr, "additional file specs ignored\n");
357 fin = xstrdup (argp);
358 inp = fopen (fin, "r");
360 Fatal (FAT_CANNOT_OPEN_INPUT, strerror (errno));
366 fprintf (stderr, "%s: No input files\n", argv [0]);
370 /* Create the output file name. We should really have
371 * some checks for string overflow, but I'll drop this because of the
372 * additional code size it would need (as in other places). Sigh.
374 if (out_name [0] == '\0') {
375 /* No output name given, create default */
376 strcpy (out_name, fin);
377 if ((p = strrchr (out_name, '.'))) {
380 strcat (out_name, ".s");
386 /* Create the output file if we didn't had any errors */
387 if (ErrorCount == 0 || Debug) {
391 /* Optimize the output if requested */
397 F = fopen (out_name, "w");
399 Fatal (FAT_CANNOT_OPEN_OUTPUT, strerror (errno));
402 /* Write the output to the file */
405 /* Close the file, check for errors */
406 if (fclose (F) != 0) {
408 Fatal (FAT_CANNOT_WRITE_OUTPUT);
412 /* Return an apropriate exit code */
413 return (ErrorCount > 0)? EXIT_FAILURE : EXIT_SUCCESS;