Fixed several problems
[fw/sdcc] / src / SDCCmain.c
index 8ebfa26c9991001428ae22a83086c1cb5d245648..fbf69c0ac70884d5f25b0b7ea4d5a13aa724e813 100644 (file)
    You are forbidden to forbid anyone else to use, share and improve
    what you give them.   Help stamp out software-hoarding!  
 -------------------------------------------------------------------------*/
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <ctype.h>
 
+#include "common.h"
+#include <ctype.h>
 #include "spawn.h"
-#include "SDCCglobl.h"
-#include "config.h"
+
+/* 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);
+#define X_OK 1
+int unlink(const char *path);
 
 extern void            initSymt                ();
 extern void            initMem                 ();
@@ -47,8 +50,7 @@ FILE  *cdbFile = NULL  ;/* debugger information output file */
 char  *fullSrcFileName ;/* full name for the source file */
 char  *srcFileName     ;/* source file name with the .c stripped */
 char  *moduleName      ;/* module name is srcFilename stripped of any path */
-char *preArgv[128]        ;/* pre-processor arguments  */
-int   preArgc  = 0        ;/* pre-processor argument count     */
+const char *preArgv[128]          ;/* pre-processor arguments  */
 int   currRegBank = 0 ;
 struct optimize optimize ;
 struct options  options ;
@@ -56,7 +58,7 @@ char *VersionString = SDCC_VERSION_STR /*"Version 2.1.8a"*/;
 short preProcOnly = 0;
 short noAssemble = 0;
 char *linkOptions[128];
-char *asmOptions[128];
+const char *asmOptions[128];
 char *libFiles[128] ;
 int nlibFiles = 0;
 char *libPaths[128] ;
@@ -112,15 +114,111 @@ char    *preOutName;
 #define OPTION_HELP         "-help"
 #define OPTION_CALLEE_SAVES "-callee-saves"
 #define OPTION_NOREGPARMS   "-noregparms"
+
+static const char *_preCmd[] = {
+    "sdcpp", "-version", "-Wall", "-lang-c++", "-DSDCC=1", 
+    "-I" SDCC_INCLUDE_DIR, "$l", "$1", "$2", NULL
+};
+
+extern PORT mcs51_port;
+extern PORT z80_port;
+
+PORT *port;
+
+static PORT *_ports[] = {
+    &mcs51_port,
+    &z80_port
+};
+
+#define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
+
+/** Sets the port to the one given by the command line option.
+    @param             The name minus the option (eg 'mcs51')
+    @return            0 on success.
+*/
+static int _setPort(const char *name)
+{
+    int i;
+    for (i=0; i<NUM_PORTS; i++) {
+       if (!strcmp(_ports[i]->target, name)) {
+           port = _ports[i];
+           return 0;
+       }
+    }
+    /* Error - didnt find */
+    return 1;
+}
+
+static void _buildCmdLine(char *into, char **args, const char **cmds, 
+                         const char *p1, const char *p2, 
+                         const char *p3, const char **list)
+{
+    const char *p, *from;
+
+    while (*cmds) {
+       *args = into;
+       args++;
+
+       from = *cmds;
+       cmds++;
+       *into = '\0';
+
+       /* See if it has a '$' anywhere - if not, just copy */
+       if ((p = strchr(from, '$'))) {
+           strncpy(into, from, p - from);
+           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) {
+                       strcpy(into, *tmp);
+                       into += strlen(into)+1;
+                       *args = into;
+                       args++;
+                       tmp++;
+                   }
+               }
+               break;
+           }
+           default:
+               assert(0);
+           }
+       }
+       strcat(into, from);
+       if (strlen(into) == 0)
+           args--;
+       into += strlen(into)+1;
+    }
+    *args = NULL;
+}
+
 /*-----------------------------------------------------------------*/
 /* printVersionInfo - prints the version info                     */
 /*-----------------------------------------------------------------*/
 void   printVersionInfo ()
 {
+    int i;
     
+    fprintf (stderr,
+            "SDCC : ");
+    for (i=0; i<NUM_PORTS; i++)
+       fprintf(stderr, "%s%s", i==0 ? "" : "/", _ports[i]->target);
 
-       fprintf (stderr                                 ,
-               "SDCC : MCU 8051 %s "
+    fprintf(stderr, " %s `"
 #ifdef __CYGWIN32__
                " (CYGWIN32)\n"
 #else
@@ -130,8 +228,8 @@ void        printVersionInfo ()
                " (UNIX) \n"
 # endif
 #endif
-                , VersionString
-                   );
+           , VersionString
+           );
 }
 
 /*-----------------------------------------------------------------*/
@@ -143,6 +241,8 @@ void        printUsage ()
        fprintf (stderr,
                 "Usage : [options] filename\n"
                 "Options :-\n"
+                "\t-m<proc>             -     Target processor <proc>.  Default %s\n"
+                "\t                           Try --version for supported values of <proc>\n"
                 "\t--model-large        -     Large Model\n"
                 "\t--model-small        -     Small Model (default)\n"
                 "\t--stack-auto         -     Stack automatic variables\n"
@@ -159,7 +259,9 @@ 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 a complete list of options see docs for details\n",
+                _ports[0]->target
+                );             
        exit (0);
 }
 
@@ -197,11 +299,6 @@ static void setDefaultOptions()
        preArgv[i] = linkOptions [i] =
            asmOptions[i] = relFiles[i] = libFiles[i] =
            libPaths[i] = NULL ;
-    preArgv[preArgc++] = "-version";
-    preArgv[preArgc++] = "-Wall";
-    preArgv[preArgc++] = "-lang-c++";
-    preArgv[preArgc++] = "-DSDCC=1";
-    preArgv[preArgc++] = "-I" SDCC_INCLUDE_DIR ;
 
     /* first the options part */
     options.stack_loc = 0; /* stack pointer initialised to 0 */
@@ -222,6 +319,8 @@ static void setDefaultOptions()
     optimize.label4 = 1;    
     optimize.loopInvariant = 1;
     optimize.loopInduction = 1;
+
+    port->setDefaultOptions();
 }
 
 /*-----------------------------------------------------------------*/
@@ -300,6 +399,18 @@ static void processFile (char *s)
   
 }
 
+static void _addToList(const char **list, const char *str)
+{
+    /* This is the bad way to do things :) */
+    while (*list)
+       list++;
+    *list = strdup(str);
+    if (!*list) {
+       werror(E_OUT_OF_MEM,__FILE__, 0);
+       exit (1);
+    }
+    *(++list) = NULL;
+}
 
 /*-----------------------------------------------------------------*/
 /* parseCmdLine - parses the command line and sets the options     */
@@ -605,7 +716,8 @@ int   parseCmdLine ( int argc, char **argv )
                 continue;
            }
 
-           werror(W_UNKNOWN_OPTION,argv[i]);
+           if (!port->parseOption(&argc, argv))
+               werror(W_UNKNOWN_OPTION,argv[i]);
        }      
 
        /* these are undocumented options */
@@ -675,7 +787,10 @@ int   parseCmdLine ( int argc, char **argv )
                break;
 
            case 'm':
-               werror(W_UNSUPP_OPTION,"-mL/-mS","use --model-large/--model-small instead");
+               /* Used to select the port */
+               if (_setPort(argv[i] + 2)) {
+                   werror(W_UNSUPP_OPTION,"-m","Unrecognised processor");
+               }
                break;
            
            case 'a'    : 
@@ -737,9 +852,9 @@ int   parseCmdLine ( int argc, char **argv )
                    /* assembler options */
                    if (argv[i][2] == 'a') {
                        if (argv[i][3])
-                           parseWithComma(asmOptions,&argv[i][3]);
+                           parseWithComma((char **)asmOptions,&argv[i][3]);
                        else
-                           parseWithComma(asmOptions,argv[++i]);
+                           parseWithComma((char **)asmOptions,argv[++i]);
                        
                    } else {
                        werror(W_UNKNOWN_OPTION,argv[i]);                      
@@ -778,36 +893,27 @@ int   parseCmdLine ( int argc, char **argv )
                    else
                        rest = &argv[i][2] ;
                    
-                   /* increase allocation for preprocessor argv 
-                      if (!(preArgv = realloc(preArgv,(preArgc+1)*sizeof(char **)))) {
-                      werror (E_OUT_OF_MEM);
-                      exit (1);
-                      } */
                    if ( argv[i][1] == 'Y' )
                        argv[i][1] = 'I';
                    if (argv[i][1] == 'M')
                        preProcOnly = 1;
 
-                   if (!(preArgv[preArgc] = GC_malloc(strlen(rest)+3))) {
-                       werror(E_OUT_OF_MEM,__FILE__,strlen(rest)+3);                   
-                       exit (1);
-                   }
-                   
-                   sprintf(preArgv[preArgc],"-%c%s",sOpt,rest);
-                   preArgc++ ;
+                   sprintf(buffer, "-%c%s", sOpt, rest);
+                   _addToList(preArgv, buffer);
                }
                break ;
 
            default:
-               werror(W_UNKNOWN_OPTION,argv[i]);               
+               if (!port->parseOption(&argc, argv))
+                   werror(W_UNKNOWN_OPTION,argv[i]);
            }
            continue ;
        }
 
-       /* no option must be a filename */
-       processFile(argv[i]);
-
-
+       if (!port->parseOption(&argc, argv)) {
+           /* no option must be a filename */
+           processFile(argv[i]);
+       }
     }  
 
     /* set up external stack location if not explicitly specified */
@@ -824,6 +930,7 @@ int   parseCmdLine ( int argc, char **argv )
            fprintf(cdbFile,"M:%s\n",moduleName);
        }
     }
+    port->finaliseOptions();
     return 0;
 }
 
@@ -871,7 +978,8 @@ int my_system (const char *cmd, char **cmd_argv)
 static void linkEdit (char **envp)
 {
     FILE *lnkfile ;
-    char *lnkArgs[4];
+    char *argv[128];
+
     int i;
     if (!srcFileName)
        srcFileName = "temp";
@@ -935,13 +1043,10 @@ static void linkEdit (char **envp)
     fprintf (lnkfile,"\n-e\n");
     fclose(lnkfile);
 
-    /* call the linker */
-    lnkArgs[0] = "aslink";
-    lnkArgs[1] = "-nf";
-    lnkArgs[2] = srcFileName;
-    lnkArgs[3] = NULL;
+    _buildCmdLine(buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
 
-    if (my_system("aslink",lnkArgs)) {
+    /* call the linker */
+    if (my_system(argv[0], argv)) {
        perror("Cannot exec linker");
        exit(1);
     }
@@ -960,62 +1065,48 @@ static void linkEdit (char **envp)
 /*-----------------------------------------------------------------*/
 static void assemble (char **envp)
 {
-    char *asmArgs[128];  /* assembler arguments */
-    int i = 2;
+    char *argv[128];  /* assembler arguments */
 
-    asmArgs[0] = "asx8051";
-    
-/*     if (options.debug) */
-    asmArgs[1] = "-plosgffc" ;
-/*     else */
-/*     asmArgs[1] = "-plosgff"; */
-
-    /* add the extra options if any */
-    for (; asmOptions[i-2] ; i++)
-       asmArgs[i] = asmOptions[i-2];
-
-    /* create the assembler file name */
-    sprintf (buffer, srcFileName);
-    strcat (buffer, ".asm");
-    asmArgs[i++] = buffer;
-
-    asmArgs[i] = 0; /* end of args */
+    _buildCmdLine(buffer, argv, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
 
-    if (my_system("asx8051",asmArgs)) {
-       perror("Cannot exec linker");
+    if (my_system(argv[0], argv)) {
+       perror("Cannot exec assember");
        exit(1);
     }
 }
 
 
+
 /*-----------------------------------------------------------------*/
 /* preProcess - spawns the preprocessor with arguments            */
 /*-----------------------------------------------------------------*/
 static int preProcess (char **envp)
 {
-        
+    char *argv[128];
+
+    preOutName = NULL;
+
     /* if using external stack define the macro */
     if ( options.useXstack )
-       preArgv[preArgc++] = "-DSDCC_USE_XSTACK" ;
+       _addToList(preArgv, "-DSDCC_USE_XSTACK");
     
     /* set the macro for stack autos   */
     if ( options.stackAuto )
-       preArgv[preArgc++] = "-DSDCC_STACK_AUTO";
+       _addToList(preArgv, "-DSDCC_STACK_AUTO");
     
     /* set the macro for large model   */
     if ( options.model )
-       preArgv[preArgc++] = "-DSDCC_MODEL_LARGE" ;
+       _addToList(preArgv, "-DSDCC_MODEL_LARGE");
     else
-       preArgv[preArgc++] = "-DSDCC_MODEL_SMALL" ;
+       _addToList(preArgv, "-DSDCC_MODEL_SMALL");
     
-    preArgv[preArgc++] = fullSrcFileName ;
     if (!preProcOnly)
-       preArgv[preArgc++] = preOutName = strdup(tmpnam(NULL));
-    preArgv[preArgc] = NULL;
+       preOutName = strdup(tmpnam(NULL));
 
-    preArgv[0] = "sdcpp";
+    _buildCmdLine(buffer, argv, _preCmd, fullSrcFileName, 
+                 preOutName, srcFileName, preArgv);
 
-    if (my_system("sdcpp",preArgv)) {
+    if (my_system(argv[0], argv)) {
        unlink (preOutName);
        perror("Cannot exec Preprocessor");
        exit(1);
@@ -1033,6 +1124,21 @@ static int preProcess (char **envp)
     return 0;
 }
 
+static void _findPort(int argc, char **argv)
+{
+    argc--;
+    while (argc) {
+       if (!strncmp(*argv, "-m", 2)) {
+           _setPort(*argv + 2);
+           return;
+       }
+       argv++;
+       argc--;
+    }
+    /* Use the first in the list */
+    port = _ports[0];
+}
+
 /* 
  * main routine
  * initialises and calls the parser
@@ -1045,8 +1151,9 @@ int main ( int argc, char **argv , char **envp)
     
     /*printVersionInfo ();*/
 
+    _findPort(argc, argv);
     setDefaultOptions();
-    parseCmdLine (argc,argv);
+    parseCmdLine(argc,argv);
 
     /* if no input then printUsage & exit */
     if (!srcFileName && !nrelFiles) {