Merge of the izt changes.
[fw/sdcc] / src / SDCCmain.c
index c47d9109a0a6a5dac3b8b645bb4c552afe832b81..3c53bb8fb1ab67ee11a4150d4914632f60e1cc1b 100644 (file)
 #include "spawn.h"
 #endif
 
-/* This is a bit messy.  We cant include unistd.h as it defines
-   'link' which we also use.
-*/
-int access(const char *path, int mode);
+// This is a bit messy because we define link ourself
+#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+
+#include <unistd.h>
+
+#else
+// No unistd.h in Borland C++
+extern int access(const char *, int);
 #define X_OK 1
-int unlink(const char *path);
-
-extern void            initSymt                ();
-extern void            initMem                 ();
-extern void            initExpr                ();
-extern void             initiCode               ();
-extern void             initCSupport            ();
-extern void             initPeepHole            ();
-extern void            createObject    ();
-extern int             yyparse                 ();
-extern void             glue ();
-extern struct value    *constVal(char *s);
-extern double            floatFromVal(struct value *);
-extern int              fatalError ;
+
+#endif
+
+//REMOVE ME!!!
+extern int yyparse();
+
 FILE  *srcFile         ;/* source file          */
 FILE  *cdbFile = NULL  ;/* debugger information output file */
 char  *fullSrcFileName ;/* full name for the source file */
@@ -71,10 +67,12 @@ int nlibPaths = 0;
 char *relFiles[128];
 int nrelFiles = 0;
 bool verboseExec = FALSE;
-//extern int wait (int *);
 char    *preOutName;
 
+/* Far functions, far data */
 #define OPTION_LARGE_MODEL "-model-large"
+/* Far functions, near data */
+#define OPTION_MEDIUM_MODEL "-model-medium"
 #define OPTION_SMALL_MODEL "-model-small"
 #define OPTION_FLAT24_MODEL "-model-flat24"
 #define OPTION_STACK_AUTO  "-stack-auto"
@@ -115,6 +113,7 @@ char    *preOutName;
 #define OPTION_NOPEEP      "-no-peep"
 #define OPTION_ASMPEEP     "-peep-asm"
 #define OPTION_DEBUG       "-debug"
+#define OPTION_NODEBUG    "-nodebug"
 #define OPTION_VERSION     "-version"
 #define OPTION_STKAFTRDATA "-stack-after-data"
 #define OPTION_PREPROC_ONLY "-preprocessonly"
@@ -122,28 +121,51 @@ char    *preOutName;
 #define OPTION_HELP         "-help"
 #define OPTION_CALLEE_SAVES "-callee-saves"
 #define OPTION_NOREGPARMS   "-noregparms"
-
+#define OPTION_NOSTDLIB     "-nostdlib"
+#define OPTION_NOSTDINC     "-nostdinc"
+#define OPTION_VERBOSE      "-verbose"
+#define OPTION_ANSIINT     "-ansiint"
 static const char *_preCmd[] = {
     "sdcpp", "-Wall", "-lang-c++", "-DSDCC=1", 
-    "-I" SDCC_INCLUDE_DIR, "$l", "$1", "$2", NULL
+    "$l", "-I" SDCC_INCLUDE_DIR, "$1", "$2", NULL
 };
 
-extern PORT mcs51_port;
-extern PORT z80_port;
-extern PORT gbz80_port;
-extern PORT avr_port;
-
 PORT *port;
 
 static PORT *_ports[] = {
-    &mcs51_port,
-    &z80_port,
+#if !OPT_DISABLE_MCS51
+   &mcs51_port,
+#endif
+#if !OPT_DISABLE_GBZ80
     &gbz80_port,
-    &avr_port
+#endif
+#if !OPT_DISABLE_Z80
+    &z80_port,
+#endif
+#if !OPT_DISABLE_AVR
+    &avr_port,
+#endif
+#if !OPT_DISABLE_DS390
+    &ds390_port,
+#endif
+#if !OPT_DISABLE_PIC
+    &pic14_port,
+#endif
+#if !OPT_DISABLE_I186
+   &i186_port,
+#endif
+#if !OPT_DISABLE_TLCS900H
+   &tlcs900h_port,
+#endif
 };
 
 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
 
+/**
+   remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
+ */
+extern void             pic14glue();
+
 /** Sets the port to the one given by the command line option.
     @param             The name minus the option (eg 'mcs51')
     @return            0 on success.
@@ -162,7 +184,18 @@ static int _setPort(const char *name)
     exit(1);
 }
 
-static void _buildCmdLine(char *into, char **args, const char **cmds, 
+static void _validatePorts(void)
+{
+    int i;
+    for (i=0; i<NUM_PORTS; i++) {
+       if (_ports[i]->magic != PORT_MAGIC) {
+           printf("Error: port %s is incomplete.\n", _ports[i]->target);
+           wassert(0);
+       }
+    }
+}
+
+void buildCmdLine(char *into, char **args, const char **cmds, 
                          const char *p1, const char *p2, 
                          const char *p3, const char **list)
 {
@@ -179,6 +212,8 @@ static void _buildCmdLine(char *into, char **args, const char **cmds,
        /* See if it has a '$' anywhere - if not, just copy */
        if ((p = strchr(from, '$'))) {
            strncpy(into, from, p - from);
+           /* NULL terminate it */
+           into[p-from] = '\0';
            from = p+2;
            p++;
            switch (*p) {
@@ -230,8 +265,11 @@ void       printVersionInfo ()
             "SDCC : ");
     for (i=0; i<NUM_PORTS; i++)
        fprintf(stderr, "%s%s", i==0 ? "" : "/", _ports[i]->target);
-
-    fprintf(stderr, " %s `"
+    fprintf(stderr, " %s"
+#ifdef SDCC_SUB_VERSION_STR
+           "/" SDCC_SUB_VERSION_STR
+#endif
+           " ` "
 #ifdef __CYGWIN32__
                " (CYGWIN32)\n"
 #else
@@ -241,6 +279,7 @@ void        printVersionInfo ()
                " (UNIX) \n"
 # endif
 #endif
+
            , VersionString
            );
 }
@@ -272,7 +311,7 @@ void        printUsage ()
                 "PreProcessor Options :-\n"
                 "\t-Dmacro             -       Define Macro\n"          
                 "\t-Ipath              -       Include \"*.h\" path\n"
-                "Note: this is a complete list of options see docs for details\n",
+                "Note: this is NOT a complete list of options see docs for details\n",
                 _ports[0]->target
                 );             
        exit (0);
@@ -322,6 +361,10 @@ static void setDefaultOptions()
     options.idata_loc = 0x80;
     options.genericPtr = 1;   /* default on */
     options.nopeep    = 0;
+    options.model = port->general.default_model;
+    options.nostdlib=0;
+    options.nostdinc=0;
+    options.verbose=0;
 
     /* now for the optimizations */
     /* turn on the everything */
@@ -396,8 +439,9 @@ static void processFile (char *s)
     /* if the extention is type .rel or .r or .REL or .R 
        addtional object file will be passed to the linker */
     if (strcmp(fext,".r") == 0 || strcmp(fext,".rel") == 0 ||
-       strcmp(fext,".R") == 0 || strcmp(fext,".REL") == 0) {
-       
+       strcmp(fext,".R") == 0 || strcmp(fext,".REL") == 0 ||
+       strcmp(fext, port->linker.rel_ext) == 0)
+       {
        relFiles[nrelFiles++] = s;
        return ;
     }
@@ -439,6 +483,14 @@ static void _addToList(const char **list, const char *str)
     *(++list) = NULL;
 }
 
+static void _setModel(int model, const char *sz)
+{
+    if (port->general.supported_models & model)
+       options.model = model;
+    else
+       werror(W_UNSUPPORTED_MODEL, sz, port->target);
+}
+
 /*-----------------------------------------------------------------*/
 /* parseCmdLine - parses the command line and sets the options     */
 /*-----------------------------------------------------------------*/
@@ -466,17 +518,22 @@ int   parseCmdLine ( int argc, char **argv )
            }
 
            if (strcmp(&argv[i][1],OPTION_LARGE_MODEL) == 0) {
-               options.model = MODEL_LARGE;
+               _setModel(MODEL_LARGE, argv[i]);
+                continue;
+           }
+
+           if (strcmp(&argv[i][1],OPTION_MEDIUM_MODEL) == 0) {
+               _setModel(MODEL_MEDIUM, argv[i]);
                 continue;
            }
            
            if (strcmp(&argv[i][1],OPTION_SMALL_MODEL) == 0) {
-               options.model = MODEL_SMALL;
+               _setModel(MODEL_SMALL, argv[i]);
                 continue;
            }
            
            if (strcmp(&argv[i][1],OPTION_FLAT24_MODEL) == 0) {
-               options.model = MODEL_FLAT24;
+               _setModel(MODEL_FLAT24, argv[i]);
                 continue;
            }
            
@@ -607,6 +664,11 @@ int   parseCmdLine ( int argc, char **argv )
                 continue;
            }
 
+           if (strcmp(&argv[i][1],OPTION_NODEBUG) == 0) {
+               options.nodebug = 1;            
+                continue;
+           }
+
            if (strcmp(&argv[i][1],OPTION_NOREGPARMS) == 0) {
                options.noregparms = 1;         
                 continue;
@@ -758,6 +820,26 @@ int   parseCmdLine ( int argc, char **argv )
                 continue;
            }
 
+           if (strcmp(&argv[i][1],OPTION_NOSTDLIB) == 0) {
+               options.nostdlib=1;
+               continue;
+           }
+
+           if (strcmp(&argv[i][1],OPTION_NOSTDINC) == 0) {
+               options.nostdinc=1;
+               continue;
+           }
+
+           if (strcmp(&argv[i][1],OPTION_VERBOSE) == 0) {
+               options.verbose=1;
+               continue;
+           }
+           
+           if (strcmp(&argv[i][1],OPTION_ANSIINT) == 0) {
+               options.ANSIint=1;
+               continue;
+           }       
+
            if (!port->parseOption(&argc, argv, &i))
            {
                werror(W_UNKNOWN_OPTION,argv[i]);
@@ -915,21 +997,30 @@ int   parseCmdLine ( int argc, char **argv )
                noAssemble = 1;
                break;
 
+           case 'V':
+             verboseExec = TRUE;
+             break;
+
            case 'v':
-#if FEATURE_VERBOSE_EXEC
-               verboseExec = TRUE;
-#else
                printVersionInfo();
                exit(0);
-#endif
                break;
 
                /* preprocessor options */              
+           case 'M':
+             {
+               preProcOnly=1;
+               _addToList(preArgv, "-M");
+               break;
+             }
+           case 'C':
+             {
+               _addToList(preArgv, "-C");
+               break;
+             }
            case 'd':
            case 'D':
            case 'I':
-           case 'M':
-           case 'C':
            case 'A':
            case 'U':
                {
@@ -945,8 +1036,6 @@ int   parseCmdLine ( int argc, char **argv )
                    
                    if ( argv[i][1] == 'Y' )
                        argv[i][1] = 'I';
-                   if (argv[i][1] == 'M')
-                       preProcOnly = 1;
 
                    sprintf(buffer, "-%c%s", sOpt, rest);
                    _addToList(preArgv, buffer);
@@ -974,7 +1063,7 @@ int   parseCmdLine ( int argc, char **argv )
        options.xstack_loc = options.xdata_loc ;
 
     /* if debug option is set the open the cdbFile */
-    if (/* options.debug && */ srcFileName) {
+    if (!options.nodebug && srcFileName) {
        sprintf(cdbfnbuf,"%s.cdb",srcFileName);
        if ((cdbFile = fopen(cdbfnbuf,"w")) == NULL)
            werror(E_FILE_OPEN_ERR,cdbfnbuf);
@@ -989,7 +1078,17 @@ int   parseCmdLine ( int argc, char **argv )
 /*-----------------------------------------------------------------*/
 /* my_system - will call a program with arguments                  */
 /*-----------------------------------------------------------------*/
+
+#if defined(_MSC_VER)
+
+char *try_dir[]= {NULL};                       // TODO : Fill in some default search list
+
+#else
+
 char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
+
+#endif
+
 int my_system (const char *cmd, char **cmd_argv)
 {    
     char *dir, *got= NULL; int i= 0;
@@ -1027,18 +1126,22 @@ int my_system (const char *cmd, char **cmd_argv)
         free(dir);
         i++;
     }
-#if FEATURE_VERBOSE_EXEC
+
     if (verboseExec) {
        char **pCmd = cmd_argv;
+       printf ("+ ");
        while (*pCmd) {
            printf("%s ", *pCmd);
            pCmd++;
        }
        printf("\n");
     }
-#endif
+
     if (got)
+               {
       i= spawnv(P_WAIT,got,cmd_argv) == -1;
+               free(got) ;
+               }
     else
       i= spawnvp(P_WAIT,cmd,cmd_argv) == -1;
     if (i) {
@@ -1104,34 +1207,43 @@ static void linkEdit (char **envp)
     for (i=0; linkOptions[i] ; i++)
        fprintf(lnkfile,"%s\n",linkOptions[i]);
 
-    /* standard library path */
-    switch(options.model)
-    {
-        case MODEL_SMALL:
-                   c = "small";
-                   break;
-               case MODEL_LARGE:
-                   c = "large";
-                   break;
-               case MODEL_FLAT24:
-                   c = "flat24";
-                   break;
-        default:
-            werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
-            c = "unknown";
-            break;
-    }
-    fprintf (lnkfile,"-k %s/%s\n",SDCC_LIB_DIR/*STD_LIB_PATH*/,c);
-           
     /* other library paths if specified */
     for (i = 0 ; i < nlibPaths ; i++ )
        fprintf (lnkfile,"-k %s\n",libPaths[i]);
-        
-    /* standard library files */
-    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);
+
+    /* standard library path */
+    if (!options.nostdlib) {
+      if (IS_DS390_PORT) {
+       c="ds390";
+      } else {
+       switch(options.model)
+         {
+         case MODEL_SMALL:
+           c = "small";
+           break;
+         case MODEL_LARGE:
+           c = "large";
+           break;
+         case MODEL_FLAT24:
+           c = "flat24";
+           break;
+         default:
+           werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
+           c = "unknown";
+           break;
+         }
+      }
+      fprintf (lnkfile,"-k %s/%s\n",SDCC_LIB_DIR/*STD_LIB_PATH*/,c);
+      
+      /* standard library files */
+      if (strcmp(port->target, "ds390")==0) {
+       fprintf (lnkfile,"-l %s\n",STD_DS390_LIB);
+      }
+      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);
+    }
 
     /* additional libraries if any */
     for (i = 0 ; i < nlibFiles; i++)
@@ -1147,9 +1259,10 @@ static void linkEdit (char **envp)
     fprintf (lnkfile,"\n-e\n");
     fclose(lnkfile);
 
-    _buildCmdLine(buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
+    buildCmdLine(buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
 
-    /* call the linker */
+    if (options.verbose)
+      printf ("sdcc: Calling linker...\n");
     if (my_system(argv[0], argv)) {
        perror("Cannot exec linker");
        exit(1);
@@ -1171,7 +1284,7 @@ static void assemble (char **envp)
 {
     char *argv[128];  /* assembler arguments */
 
-    _buildCmdLine(buffer, argv, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
+    buildCmdLine(buffer, argv, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
 
     if (my_system(argv[0], argv)) {
        perror("Cannot exec assember");
@@ -1213,6 +1326,12 @@ static int preProcess (char **envp)
            case MODEL_SMALL:
                _addToList(preArgv, "-DSDCC_MODEL_SMALL");
                break;
+           case MODEL_COMPACT:
+               _addToList(preArgv, "-DSDCC_MODEL_COMPACT");
+               break;
+           case MODEL_MEDIUM:
+               _addToList(preArgv, "-DSDCC_MODEL_MEDIUM");
+               break;
            case MODEL_FLAT24:
                _addToList(preArgv, "-DSDCC_MODEL_FLAT24");
                break;
@@ -1229,9 +1348,12 @@ static int preProcess (char **envp)
        if (!preProcOnly)
            preOutName = strdup(tmpnam(NULL));
 
-       _buildCmdLine(buffer, argv, _preCmd, fullSrcFileName, 
+       buildCmdLine(buffer, argv, _preCmd, fullSrcFileName, 
                      preOutName, srcFileName, preArgv);
 
+       if (options.verbose)
+         printf ("sdcc: Calling preprocessor...\n");
+
        if (my_system(argv[0], argv)) {
            unlink (preOutName);
            perror("Cannot exec Preprocessor");
@@ -1256,6 +1378,8 @@ static int preProcess (char **envp)
 
 static void _findPort(int argc, char **argv)
 {
+    _validatePorts();
+
     argc--;
     while (argc) {
        if (!strncmp(*argv, "-m", 2)) {
@@ -1278,7 +1402,7 @@ int main ( int argc, char **argv , char **envp)
 {
     /* turn all optimizations off by default */
     memset(&optimize,0,sizeof(struct optimize));
-    
+
     /*printVersionInfo ();*/
 
     _findPort(argc, argv);
@@ -1298,25 +1422,48 @@ int main ( int argc, char **argv , char **envp)
        printUsage();
        exit(0);
     }
-
        
-    if (srcFileName)
-       preProcess(envp) ;
-
     if (srcFileName) {
+       preProcess(envp) ;
 
        initSymt();
        initiCode();
        initCSupport ();
        initPeepHole();
+
+       if (options.verbose)
+         printf ("sdcc: Generating code...\n");
+
        yyparse();
 
-       if (!fatalError) {
+       if (!fatalError) 
+       {
+/* 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
+         if(IS_PIC_PORT)
+           pic14glue();
+         else
+#endif
            glue();
+           if (fatalError)
+           {
+               return 1;
+           }
            if (!options.c1mode)
+           {
+               if (options.verbose)
+                 printf ("sdcc: Calling assembler...\n");
+
                assemble(envp);
-       } else {
-           exit(-1);
+           }
+       }
+       else 
+       {
+           return 1;
         }
        
     }
@@ -1328,8 +1475,12 @@ int main ( int argc, char **argv , char **envp)
        !fatalError      &&
        !noAssemble      &&
        !options.c1mode  &&
-       (srcFileName || nrelFiles))
-       linkEdit (envp);
+       (srcFileName || nrelFiles)) {
+       if (port->linker.do_link)
+           port->linker.do_link();
+       else
+         linkEdit (envp);
+    }
 
     if (yyin && yyin != stdin)
        fclose(yyin);
@@ -1338,6 +1489,7 @@ int main ( int argc, char **argv , char **envp)
         unlink(preOutName);
         free(preOutName);
     }
+
     return 0;
     
 }