undo Johan's changes for the moment
[fw/sdcc] / src / SDCCmain.c
index be3101f9266bc5132a4ac2c28b480a2d0db2129b..69cfb2ebf09066c2c02cea4182dd54bb33a7e384 100644 (file)
    what you give them.   Help stamp out software-hoarding!  
 -------------------------------------------------------------------------*/
 
+//#define USE_SYSTEM_SYSTEM_CALLS
+
 #include "common.h"
 #include <ctype.h>
+#include "newalloc.h"
+#include "SDCCerr.h"
 
 #if NATIVE_WIN32
 #include <process.h>
 #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,9 +71,16 @@ int nlibPaths = 0;
 char *relFiles[128];
 int nrelFiles = 0;
 bool verboseExec = FALSE;
-//extern int wait (int *);
 char    *preOutName;
 
+// In MSC VC6 default search path for exe's to path for this
+
+#if defined(_MSC_VER)
+
+char DefaultExePath[_MAX_PATH] ;
+
+#endif
+
 /* Far functions, far data */
 #define OPTION_LARGE_MODEL "-model-large"
 /* Far functions, near data */
@@ -126,29 +133,15 @@ 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
 };
 
-#if !OPT_DISABLE_MCS51
-extern PORT mcs51_port;
-#endif
-#if !OPT_DISABLE_GBZ80
-extern PORT gbz80_port;
-#endif
-#if !OPT_DISABLE_Z80
-extern PORT z80_port;
-#endif
-#if !OPT_DISABLE_AVR
-extern PORT avr_port;
-#endif
-#if !OPT_DISABLE_DS390
-extern PORT ds390_port;
-#endif
-
-
 PORT *port;
 
 static PORT *_ports[] = {
@@ -167,10 +160,24 @@ static PORT *_ports[] = {
 #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.
@@ -189,6 +196,71 @@ static int _setPort(const char *name)
     exit(1);
 }
 
+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);
+       }
+    }
+}
+
+#ifdef USE_SYSTEM_SYSTEM_CALLS
+void buildCmdLine(char *into, const char **cmds, 
+                         const char *p1, const char *p2, 
+                         const char *p3, const char **list)
+{
+    const char *p, *from;
+
+    *into = '\0';
+
+    while (*cmds) {
+
+       from = *cmds;
+       cmds++;
+
+       /* See if it has a '$' anywhere - if not, just copy */
+       if ((p = strchr(from, '$'))) {
+           strncat(into, from, p - from);
+           /* seperate it */
+           strcat(into, " ");
+           from = p+2;
+           p++;
+           switch (*p) {
+           case '1':
+               if (p1)
+                   strcat(into, p1);
+               break;
+           case '2':
+               if (p2)
+                   strcat(into, p2);
+               break;
+           case '3':
+               if (p3)
+                   strcat(into, p3);
+               break;
+           case 'l': {
+               const char **tmp = list;
+               if (tmp) {
+                   while (*tmp) {
+                       strcat(into, *tmp);
+                       strcat(into, " ");
+                       tmp++;
+                   }
+               }
+               break;
+           }
+           default:
+               assert(0);
+           }
+       }
+       strcat(into, from); // this includes the ".asm" from "$1.asm"
+       strcat(into, " ");
+    }
+}
+#else
 void buildCmdLine(char *into, char **args, const char **cmds, 
                          const char *p1, const char *p2, 
                          const char *p3, const char **list)
@@ -247,6 +319,7 @@ void buildCmdLine(char *into, char **args, const char **cmds,
     }
     *args = NULL;
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* printVersionInfo - prints the version info                     */
@@ -356,6 +429,9 @@ static void setDefaultOptions()
     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 */
@@ -408,7 +484,7 @@ static void processFile (char *s)
        
        /* get rid of the "." */
        strtok(buffer,".");
-       ALLOC_ATOMIC(srcFileName,strlen(buffer)+1);
+       srcFileName = Safe_calloc(strlen(buffer)+1);
        strcpy(srcFileName,buffer);
 
        /* get rid of any path information 
@@ -421,7 +497,7 @@ static void processFile (char *s)
               *(fext-1) != '/'   &&
               *(fext-1) != ':')
            fext--;
-       ALLOC_ATOMIC(moduleName,strlen(fext)+1);
+       moduleName = Safe_calloc(strlen(fext)+1);
        strcpy(moduleName,fext);
        
        return ;
@@ -811,6 +887,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]);
@@ -968,13 +1064,13 @@ 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 */              
@@ -1049,14 +1145,79 @@ int   parseCmdLine ( int argc, char **argv )
 /*-----------------------------------------------------------------*/
 /* my_system - will call a program with arguments                  */
 /*-----------------------------------------------------------------*/
-char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
+
+#if defined(_MSC_VER)
+
+char *try_dir[]= {DefaultExePath, NULL};                       // TODO : Fill in some default search list
+
+#else
+
+//char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
+char *try_dir[]= {NULL};
+
+#endif
+
+#ifdef USE_SYSTEM_SYSTEM_CALLS
+int my_system (const char *cmd)
+{    
+  int argsStart, e, i=0;
+  char *cmdLine=NULL;
+
+  argsStart=strstr(cmd, " ")-cmd;
+  
+  // try to find the command in predefined path's
+  while (try_dir[i]) {
+    cmdLine = (char*)malloc(strlen(try_dir[i])+strlen(cmd)+10);
+    strcpy(cmdLine, try_dir[i]); // the path
+    strcat(cmdLine, "/");
+    strncat(cmdLine, cmd, argsStart); // the command
+#if NATIVE_WIN32
+    strcat(cmdLine, ".exe");
+    /* Mung slashes into backslashes to keep WIndoze happy. */
+    {
+      char *r=cmdLine;
+      while (*r) {
+       if (*r == '/') {
+         *r = '\\';
+       }
+       r++;
+      }
+    }
+#endif
+    if (access(cmdLine, X_OK) == 0) {
+      // the arguments
+      strcat(cmdLine, cmd+argsStart);
+      break;
+    }
+    free(cmdLine);
+    cmdLine=NULL;
+    i++;
+  }
+  
+  if (verboseExec) {
+    printf ("+ %s\n", cmdLine ? cmdLine : cmd);
+  }
+  
+  if (cmdLine) {
+    // command found in predefined path
+    e=system(cmdLine);
+    free(cmdLine);
+  } else {
+    // trust on $PATH
+    e=system(cmd);
+  }
+  return e;
+}
+
+#else
+
 int my_system (const char *cmd, char **cmd_argv)
 {    
     char *dir, *got= NULL; int i= 0;
 
     while (!got && try_dir[i])
     {
-        dir= (char*)malloc(strlen(try_dir[i])+strlen(cmd)+10);
+        dir= (char*)Safe_malloc(strlen(try_dir[i])+strlen(cmd)+10);
         strcpy(dir, try_dir[i]);
         strcat(dir, "/");
         strcat(dir, cmd);
@@ -1087,18 +1248,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) {
@@ -1108,6 +1273,7 @@ int my_system (const char *cmd, char **cmd_argv)
     
     return 0;
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* linkEdit : - calls the linkage editor  with options             */
@@ -1115,7 +1281,9 @@ int my_system (const char *cmd, char **cmd_argv)
 static void linkEdit (char **envp)
 {
     FILE *lnkfile ;
+#ifndef USE_SYSTEM_SYSTEM_CALLS
     char *argv[128];
+#endif
     char *segName, *c;
 
     int i;
@@ -1164,41 +1332,43 @@ static void linkEdit (char **envp)
     for (i=0; linkOptions[i] ; i++)
        fprintf(lnkfile,"%s\n",linkOptions[i]);
 
-    /* standard library path */
-    if (strcmp(port->target,"ds390")==0) {
-      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);
-           
     /* other library paths if specified */
     for (i = 0 ; i < nlibPaths ; i++ )
        fprintf (lnkfile,"-k %s\n",libPaths[i]);
-        
-    /* standard library files */
-    if (strcmp(port->target, "ds390")==0) {
-      fprintf (lnkfile,"-l %s\n",STD_DS390_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);
     }
-    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++)
@@ -1214,14 +1384,23 @@ static void linkEdit (char **envp)
     fprintf (lnkfile,"\n-e\n");
     fclose(lnkfile);
 
-    buildCmdLine(buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
+    if (options.verbose)
+      printf ("sdcc: Calling linker...\n");
 
-    /* call the linker */
+#ifdef USE_SYSTEM_SYSTEM_CALLS
+    buildCmdLine(buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
+    if (my_system(buffer)) {
+      exit(1);
+    }
+#else
+    buildCmdLine(buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
     if (my_system(argv[0], argv)) {
        perror("Cannot exec linker");
        exit(1);
     }
 
+#endif
+
     if (strcmp(srcFileName,"temp") == 0) {
        /* rename "temp.cdb" to "firstRelFile.cdb" */
        char *f = strtok(strdup(relFiles[0]),".");
@@ -1236,14 +1415,21 @@ static void linkEdit (char **envp)
 /*-----------------------------------------------------------------*/
 static void assemble (char **envp)
 {
+#ifdef USE_SYSTEM_SYSTEM_CALLS
+    buildCmdLine(buffer, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
+    if (my_system(buffer)) {
+      exit(1);
+    }
+#else
     char *argv[128];  /* assembler arguments */
 
     buildCmdLine(buffer, argv, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
 
     if (my_system(argv[0], argv)) {
-       perror("Cannot exec assember");
+       perror("Cannot exec assembler");
        exit(1);
     }
+#endif
 }
 
 
@@ -1253,7 +1439,9 @@ static void assemble (char **envp)
 /*-----------------------------------------------------------------*/
 static int preProcess (char **envp)
 {
+#ifndef USE_SYSTEM_SYSTEM_CALLS
     char *argv[128];
+#endif
     char procDef[128];
 
     preOutName = NULL;
@@ -1302,6 +1490,16 @@ static int preProcess (char **envp)
        if (!preProcOnly)
            preOutName = strdup(tmpnam(NULL));
 
+       if (options.verbose)
+         printf ("sdcc: Calling preprocessor...\n");
+
+#ifdef USE_SYSTEM_SYSTEM_CALLS
+       buildCmdLine(buffer, _preCmd, fullSrcFileName, 
+                     preOutName, srcFileName, preArgv);
+       if (my_system(buffer)) {
+         exit(1);
+       }
+#else
        buildCmdLine(buffer, argv, _preCmd, fullSrcFileName, 
                      preOutName, srcFileName, preArgv);
 
@@ -1311,6 +1509,7 @@ static int preProcess (char **envp)
            exit(1);
        }
 
+#endif
        if (preProcOnly)
            exit(0);
     }
@@ -1329,6 +1528,8 @@ static int preProcess (char **envp)
 
 static void _findPort(int argc, char **argv)
 {
+    _validatePorts();
+
     argc--;
     while (argc) {
        if (!strncmp(*argv, "-m", 2)) {
@@ -1359,6 +1560,28 @@ int main ( int argc, char **argv , char **envp)
     if (port->init)
        port->init();
 
+#if defined(_MSC_VER)
+
+      {
+      int i ;
+
+      // Create a default exe search path from the path to the sdcc command
+
+      strcpy(DefaultExePath,argv[0]) ;
+
+      for(i = strlen(DefaultExePath) ; i > 0 ; i--)
+       if (DefaultExePath[i] == '\\')
+         {
+         DefaultExePath[i] = '\0' ;
+         break ;
+         }
+
+      if (i == 0)
+       DefaultExePath[0] = '\0' ;
+      }
+
+#endif
+
     setDefaultOptions();
     parseCmdLine(argc,argv);
 
@@ -1372,22 +1595,46 @@ int main ( int argc, char **argv , char **envp)
        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 {
+           }
+       }
+       else 
+       {
            return 1;
         }
        
@@ -1404,7 +1651,7 @@ int main ( int argc, char **argv , char **envp)
        if (port->linker.do_link)
            port->linker.do_link();
        else
-           linkEdit (envp);
+         linkEdit (envp);
     }
 
     if (yyin && yyin != stdin)
@@ -1417,4 +1664,4 @@ int main ( int argc, char **argv , char **envp)
 
     return 0;
     
-}
+  }