New target "hc08" for the Motorola 68hc08 family of micros
[fw/sdcc] / src / SDCCmain.c
index cb5029eaa5b220a23028a014bdf504319f6a38ea..2002576ff8f922d86aa5f5941096b1e10f4e6133 100644 (file)
    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
 #include <signal.h>
 #include "common.h"
 #include <ctype.h>
@@ -117,6 +123,7 @@ char buffer[PATH_MAX * 2];
 #define OPTION_ICODE_IN_ASM    "--i-code-in-asm"
 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
 #define OPTION_MSVC_ERROR_STYLE "--vc"
+#define OPTION_USE_STDOUT "--use-stdout"
 
 static const OPTION
 optionsTable[] = {
@@ -175,7 +182,7 @@ optionsTable[] = {
     { 0,    OPTION_PEEP_FILE,       NULL, "<file> use this extra peep-hole file" },
     { 0,    OPTION_LIB_PATH,        NULL, "<path> use this path to search for libraries" },
     { 0,    "--int-long-reent",     &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
-    { 0,    "--float-reent",        &options.float_rent, "Use reenterant calls on the floar support functions" },
+    { 0,    "--float-reent",        &options.float_rent, "Use reenterant calls on the float support functions" },
     { 0,    OPTION_OUT_FMT_IHX,     NULL, NULL },
     { 0,    "--out-fmt-s19",        &options.out_fmt, NULL },
     { 0,    "--cyclomatic",         &options.cyclomatic, NULL },
@@ -217,11 +224,14 @@ optionsTable[] = {
     { 0,    OPTION_ICODE_IN_ASM,    &options.iCodeInAsm, "include i-code as comments in the asm file"},
     { 0,    OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
     { 0,    OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
-    /* End of options */
-#if 0 /* 10jun03 !OPT_DISABLE_PIC16 */
-    { 0,    "--no-movff",          &options.no_movff, "disable generating MOVFF opcode in PIC16 port"},
+    { 0,    OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
+#if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
+    { 0,    "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
+#endif
+#if !OPT_DISABLE_PIC16
     { 0,    "--gen-banksel",       &options.gen_banksel, "enable the generation of banksel assembler directives in PIC16 port"},
 #endif
+    /* End of options */
     { 0,    NULL }
 };
 
@@ -294,17 +304,11 @@ static PORT *_ports[] =
 #if !OPT_DISABLE_DS400
   &ds400_port, 
 #endif 
+  &hc08_port,
 };
 
 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
 
-#if !OPT_DISABLE_PIC
-extern void picglue ();
-#endif
-#if !OPT_DISABLE_PIC16
-extern void pic16glue();
-#endif
-
 /** Sets the port to the one given by the command line option.
     @param    The name minus the option (eg 'mcs51')
     @return     0 on success.
@@ -399,7 +403,7 @@ _findProcessor (int argc, char **argv)
 /* printVersionInfo - prints the version info        */
 /*-----------------------------------------------------------------*/
 void
-printVersionInfo ()
+printVersionInfo (void)
 {
   int i;
 
@@ -452,7 +456,7 @@ printOptions(const OPTION *optionsTable)
 /* printUsage - prints command line syntax         */
 /*-----------------------------------------------------------------*/
 void
-printUsage ()
+printUsage (void)
 {
     int i;
     printVersionInfo();
@@ -482,10 +486,16 @@ void
 setParseWithComma (set **dest, char *src)
 {
   char *p;
+  int length;
 
   /* skip the initial white spaces */
   while (isspace(*src))
     src++;
+  
+  /* skip the trailing white spaces */
+  length = strlen(src);
+  while (length && isspace(src[length-1]))
+    src[--length] = '\0';
 
   for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
     addSet(dest, Safe_strdup(p));
@@ -1269,6 +1279,8 @@ parseCmdLine (int argc, char **argv)
        werror (E_FILE_OPEN_ERR, scratchFileName);
     }
   MSVC_style(options.vc_err_style);
+  if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
+
   return 0;
 }
 
@@ -1292,23 +1304,33 @@ linkEdit (char **envp)
       exit (1);
     }
 
-  /* now write the options.  JCF: added option 'y' */
-  fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
-
-  /* if iram size specified */
-  if (options.iram_size)
-    fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
-
-  /* if xram size specified */
-  if (options.xram_size_set)
-    fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
-
-  /* if code size specified */
-  if (options.code_size)
-    fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
-
-  if (options.debug)
-    fprintf (lnkfile, "-z\n");
+   if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
+   {
+         fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
+          (options.out_fmt ? 's' : 'i'), dstFileName);
+   }
+   else /*For all the other ports.  Including pics???*/
+   {
+         fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
+   }
+
+   if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
+   {
+         /* if iram size specified */
+         if (options.iram_size)
+               fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
+
+         /* if xram size specified */
+         if (options.xram_size_set)
+               fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
+
+         /* if code size specified */
+         if (options.code_size)
+               fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
+
+         if (options.debug)
+               fprintf (lnkfile, "-z\n");
+   }
 
 #define WRITE_SEG_LOC(N, L) \
     segName = Safe_strdup(N); \
@@ -1316,28 +1338,44 @@ linkEdit (char **envp)
     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
     if (segName) { Safe_free(segName); }
 
-  /* code segment start */
-  WRITE_SEG_LOC (CODE_NAME, options.code_loc);
+   if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
+   {
 
-  /* data segment start */
-  if(options.data_loc){ /*JCF: If zero, the linker chooses the best place for data*/
-         WRITE_SEG_LOC (DATA_NAME, options.data_loc);
-  }
+         /* code segment start */
+         WRITE_SEG_LOC (CODE_NAME, options.code_loc);
 
-  /* xdata start */
-  WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
+         /* data segment start. If zero, the linker chooses
+      the best place for data*/
+         if(options.data_loc){
+                 WRITE_SEG_LOC (DATA_NAME, options.data_loc);
+         }
 
-  /* indirect data */
-  if (IDATA_NAME) {
-    WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
-  }
+         /* xdata start */
+         WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
+
+         /* indirect data */
+         if (IDATA_NAME) {
+               WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
+         }
 
-  /* bit segment start */
-  WRITE_SEG_LOC (BIT_NAME, 0);
+         /* bit segment start */
+         WRITE_SEG_LOC (BIT_NAME, 0);
 
-  /* JCF: stack start */
-  if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
-       WRITE_SEG_LOC ("SSEG", options.stack_loc);
+         /* stack start */
+         if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
+               WRITE_SEG_LOC ("SSEG", options.stack_loc);
+         }
+   }
+   else /*For the z80, gbz80*/
+   {
+       WRITE_SEG_LOC ("_CODE", options.code_loc);
+       WRITE_SEG_LOC ("_DATA", options.data_loc);
+   }
+  
+  /* If the port has any special linker area declarations, get 'em */
+  if (port->extraAreas.genExtraAreaLinkOptions)
+  {
+       port->extraAreas.genExtraAreaLinkOptions(lnkfile);
   }
 
   /* add the extra linker options */
@@ -1346,87 +1384,150 @@ linkEdit (char **envp)
   /* other library paths if specified */
   for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
     fprintf (lnkfile, "-k %s\n", s);
-
+  
   /* standard library path */
-  if (!options.nostdlib)
+    if (!options.nostdlib)
     {
-      switch (options.model)
-       {
-       case MODEL_SMALL:
-         c = "small";
-         break;
-       case MODEL_LARGE:
-         c = "large";
-         break;
-       case MODEL_FLAT24:
-         /* c = "flat24"; */
-           if (TARGET_IS_DS390)
-           {
-               c = "ds390";
-           }
-           else if (TARGET_IS_DS400)
-           {
-               c = "ds400";
-           }
-           else
-           {
-               fprintf(stderr, 
-                       "Add support for your FLAT24 target in %s @ line %d\n",
-                       __FILE__, __LINE__);
-               exit(-1);
-           }
-         break;
-       case MODEL_PAGE0:
-         c = "xa51";
-         break;
-       default:
-         werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
-         c = "unknown";
-         break;
-       }
-      for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
-        mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
+        if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
+        {
+            switch (options.model)
+            {
+                case MODEL_SMALL:
+                    c = "small";
+                    break;
+                case MODEL_LARGE:
+                    c = "large";
+                    break;
+                case MODEL_FLAT24:
+                    /* c = "flat24"; */
+                    if (TARGET_IS_DS390)
+                    {
+                        c = "ds390";
+                    }
+                    else if (TARGET_IS_DS400)
+                    {
+                        c = "ds400";
+                    }
+                    else
+                    {
+                        fprintf(stderr, 
+                               "Add support for your FLAT24 target in %s @ line %d\n",
+                               __FILE__, __LINE__);
+                        exit(-1);
+                    }
+                       break;
+                   case MODEL_PAGE0:
+                       c = "xa51";
+                       break;
+                   default:
+                       werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
+                       c = "unknown";
+                       break;
+               }
+        }
+        else /*for the z80, gbz80*/
+        {
+            if (TARGET_IS_HC08)
+                c = "hc08";
+            else if (TARGET_IS_Z80)
+                c = "z80";
+            else
+                c = "gbz80";
+        }
+        for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
+            mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
+
 
       /* standard library files */
 #if !OPT_DISABLE_DS390
-      if (options.model == MODEL_FLAT24)
-       {
-           if (TARGET_IS_DS390)
-           {
-               fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
-           }
-           else if (TARGET_IS_DS400)
-           {
-               fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
-           }
-           else
-           {
-               fprintf(stderr, 
-                       "Add support for your FLAT24 target in %s @ line %d\n",
-                       __FILE__, __LINE__);
-               exit(-1);
-           }
-       }
+        if (options.model == MODEL_FLAT24)
+        {
+            if (TARGET_IS_DS390)
+            {
+                fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
+            }
+            else if (TARGET_IS_DS400)
+            {
+                fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
+            }
+            else
+            {
+                fprintf(stderr, 
+                    "Add support for your FLAT24 target in %s @ line %d\n",
+                    __FILE__, __LINE__);
+                exit(-1);
+            }
+        }
 #endif
 
 #if !OPT_DISABLE_XA51 
 #ifdef STD_XA51_LIB
-      if (options.model == MODEL_PAGE0)
-       {
-         fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
-       }
+        if (options.model == MODEL_PAGE0)
+        {
+            fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
+        }
 #endif
 #endif
-      fprintf (lnkfile, "-l %s\n", STD_LIB);
-      fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
-      fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
-      fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
+        if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
+              || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
+        { /*Why the z80 port is not using the standard libraries?*/
+            fprintf (lnkfile, "-l %s\n", STD_LIB);
+            fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
+            fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
+            fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
+        }
+        else if (TARGET_IS_HC08)
+        {
+            fprintf (lnkfile, "-l hc08\n");
+        }
+        else if (TARGET_IS_Z80)
+        {
+            fprintf (lnkfile, "-l z80\n");
+        }
+        else if (TARGET_IS_GBZ80)
+        {
+            fprintf (lnkfile, "-l gbz80\n");
+        }
     }
 
   /* additional libraries if any */
   for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
     fprintf (lnkfile, "-l %s\n", s);
 
+  /*For the z80 and gbz80 ports, try to find where crt0.o is...
+  It is very important for this file to be first on the linking proccess
+  so the areas are set in the correct order, expecially _GSINIT*/
+  if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
+      !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
+  {
+      char crt0path[PATH_MAX];
+      FILE * crt0fp;
+      for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
+      {
+          sprintf (crt0path, "%s%s%s%scrt0.o",
+             s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
+          
+          crt0fp=fopen(crt0path, "r");
+          if(crt0fp!=NULL)/*Found it!*/
+          {
+              fclose(crt0fp);
+              #ifdef __CYGWIN__
+              {
+                 /*The CYGWIN version of the z80-gbz80 linker is getting confused with
+                 windows paths, so convert them to the CYGWIN format*/
+                 char posix_path[PATH_MAX];
+                 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
+                 cygwin_conv_to_full_posix_path(crt0path, posix_path);
+                 strcpy(crt0path, posix_path);
+              }
+              #endif
+              fprintf (lnkfile, "%s\n", crt0path);
+              break;
+          }
+      }
+      if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
+  }
+
   /* put in the object files */
   if (fullSrcFileName)
     fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
@@ -1475,11 +1576,11 @@ linkEdit (char **envp)
        /* VR 030517 - gplink needs linker options to set the linker script,*/
        buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, NULL, linkOptionsSet);
 
-       buildCmdLine2 (buffer, buffer2, sizeof(buffer));
+       buildCmdLine2 (buffer, sizeof(buffer), buffer2);
     }
   else
     {
-      buildCmdLine2 (buffer, port->linker.mcmd, sizeof(buffer));
+      buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
     }
 
 /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
@@ -1566,7 +1667,7 @@ assemble (char **envp)
                      options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
                      asmOptionsSet);
     } else {
-       buildCmdLine2 (buffer, port->assembler.mcmd, sizeof(buffer));
+       buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
     }
 
     if (my_system (buffer)) {
@@ -1672,7 +1773,7 @@ preProcess (char **envp)
       if (options.verbose)
        printf ("sdcc: Calling preprocessor...\n");
 
-      buildCmdLine2 (buffer, _preCmd, sizeof(buffer));
+      buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
 
       if (preProcOnly) {
         if (my_system (buffer)) {
@@ -1726,6 +1827,7 @@ setBinPaths(const char *argv0)
 }
 
 /* Set system include path */
+static void
 setIncludePath(void)
 {
   char *p;
@@ -1981,29 +2083,15 @@ main (int argc, char **argv, char **envp)
         exit (1);
       }
 
-      if (TARGET_IS_PIC) {
-        /* TSD PIC port hack - if the PIC port option is enabled
-           and SDCC is used to generate PIC code, then we will
-           generate .asm files in gpasm's format instead of SDCC's
-           assembler's format
-        */
-#if !OPT_DISABLE_PIC
-        picglue ();
-#endif
-
-      } else
-      if(TARGET_IS_PIC16) {
-       /* PIC16 port misc improvements Vangelis Rokas - 6-May-2003
-         Generate .asm files for gpasm (just like PIC target) but use
-         pic16glue()
-       */
-      
-#if !OPT_DISABLE_PIC16
-       pic16glue();
-#endif
-      } else {
-        glue ();
-      }
+      if (port->general.do_glue != NULL)
+        (*port->general.do_glue)();
+      else
+        {
+          /* this shouldn't happen */
+          assert(FALSE);
+          /* in case of NDEBUG */
+          glue();
+        }
 
       if (!options.c1mode && !noAssemble)
         {