diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/SDCCsystem.c | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/SDCCsystem.c')
| -rw-r--r-- | src/SDCCsystem.c | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/src/SDCCsystem.c b/src/SDCCsystem.c new file mode 100644 index 0000000..a340045 --- /dev/null +++ b/src/SDCCsystem.c @@ -0,0 +1,408 @@ +/*------------------------------------------------------------------------- + SDCCsystem - SDCC system & pipe functions + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +#ifdef _WIN32 +/* avoid DATADIR definition clash :-( */ +#undef DATADIR +#include <windows.h> +#undef TRUE +#undef FALSE +#include <stdio.h> +#include <io.h> +#include <fcntl.h> +#else +#include <unistd.h> +#endif +#include <string.h> +#include <ctype.h> +#include "SDCCglobl.h" +#include "SDCCutil.h" +#include "dbuf_string.h" +#include "SDCCsystem.h" +#include "newalloc.h" + + +set *binPathSet = NULL; /* set of binary paths */ + + +/*! + * get command and arguments from command line + */ + +static void +split_command (const char *cmd_line, char **command, char **params) +{ + const char *p, *cmd_start; + char delim; + char *str; + unsigned len; + + /* skip leading spaces */ + for (p = cmd_line; isspace (*p); p++) + ; + + /* get command */ + switch (*p) + { + case '\'': + case '"': + delim = *p; + cmd_start = ++p; + break; + + default: + delim = ' '; + cmd_start = p; + } + + if (delim == ' ') + { + while (*p != '\0' && !isspace (*p)) + p++; + } + else + { + while (*p != '\0' && *p != delim) + p++; + } + + if (command != NULL) + { + len = p - cmd_start; + str = Safe_alloc (len + 1); + strncpy (str, cmd_start, len); + str[len] = '\0'; + *command = str; + } + + p++; + + /* skip spaces before parameters */ + while (isspace (*p)) + p++; + + /* get parameters */ + if (params != NULL) + *params = Safe_strdup (p); +} + + +/*! + * find the command: + * 1) if the command is specified by path, try it + * 2) try to find the command in predefined path's + * 3) trust on $PATH + */ + +#ifdef _WIN32 +/* WIN32 version */ + +/* + * I don't like this solution, but unfortunately cmd.exe and command.com + * don't accept something like this: + * "program" "argument" + * Cmd.exe accepts the following: + * ""program" "argument"" + * but command.com doesn't. + * The following is accepted by both: + * program "argument" + * + * So the most portable WIN32 solution is to use GetShortPathName() for + * program to get rid of spaces, so that quotes are not needed :-( + * Using spawnvp() instead of system() is more portable cross platform approach, + * but then also a substitute for _popen() should be developed... + */ + +#define EXE_EXT ".exe" + +/*! + * merge command and parameters to command line + */ + +static const char * +merge_command (const char *command, const char *params) +{ + struct dbuf_s dbuf; + + /* allocate extra space for ' ' and '\0' */ + dbuf_init (&dbuf, strlen (command) + strlen (params) + 2); + + dbuf_append_str (&dbuf, command); + dbuf_append (&dbuf, " ", 1); + dbuf_append_str (&dbuf, params); + + return dbuf_detach_c_str (&dbuf); +} + + +/*! + * check if path/command exist by converting it to short file name + * if it exists, compose with args and return it + */ + +static const char * +compose_command_line (const char *path, const char *command, const char *args) +{ + unsigned len; + struct dbuf_s cmdPath; + char shortPath[PATH_MAX]; + + dbuf_init (&cmdPath, PATH_MAX); + + if (path != NULL) + dbuf_makePath (&cmdPath, path, command); + else + dbuf_append_str (&cmdPath, command); + + /* Try if cmdPath or cmdPath.exe exist by converting it to the short path name */ + len = GetShortPathName (dbuf_c_str (&cmdPath), shortPath, sizeof shortPath); + assert (len < sizeof shortPath); + if (0 == len) + { + dbuf_append_str (&cmdPath, EXE_EXT); + len = GetShortPathName (dbuf_c_str (&cmdPath), shortPath, sizeof shortPath); + assert (len < sizeof shortPath); + } + if (0 != len) + { + /* compose the command line */ + return merge_command (shortPath, args); + } + else + { + /* path/command not found */ + return NULL; + } +} + + +static const char * +get_path (const char *cmd) +{ + const char *cmdLine; + char *command; + char *args; + char *path; + + /* get the command */ + split_command (cmd, &command, &args); + + if (NULL == (cmdLine = compose_command_line(NULL, command, args))) + { + /* not an absolute path: try to find the command in predefined binary paths */ + if (NULL != (path = (char *)setFirstItem (binPathSet))) + { + while (NULL == (cmdLine = compose_command_line (path, command, args)) && + NULL != (path = (char *)setNextItem (binPathSet))) + ; + } + + if (NULL == cmdLine) + { + /* didn't found the command in predefined binary paths: try with PATH */ + char *envPath; + + if (NULL != (envPath = getenv("PATH"))) + { + /* make a local copy; strtok() will modify it */ + envPath = Safe_strdup (envPath); + + if (NULL != (path = strtok (envPath, ";"))) + { + while (NULL == (cmdLine = compose_command_line (path, command, args)) && + NULL != (path = strtok (NULL, ";"))) + ; + } + + Safe_free (envPath); + } + } + + /* didn't found it; probably this won't help neither :-( */ + if (NULL == cmdLine) + cmdLine = merge_command (command, args); + } + + Safe_free(command); + Safe_free(args); + + return cmdLine; +} + +#else +/* *nix version */ + +/*! + * merge command and parameters to command line + */ + +static const char * +merge_command (const char *command, const char *params) +{ + struct dbuf_s dbuf; + char *s = shell_escape (command); + + /* allocate extra space for ' ' and '\0' */ + dbuf_init (&dbuf, strlen (command) + strlen (params) + 2); + + dbuf_append_str (&dbuf, s); + dbuf_append (&dbuf, " ", 1); + dbuf_append_str (&dbuf, params); + + return dbuf_detach_c_str (&dbuf); +} + + +/*! + * check if the path is relative or absolute (if contains the dir separator) + */ + +static int +has_path (const char *path) +{ + return dbuf_splitPath (path, NULL, NULL); +} + + +static const char * +get_path (const char *cmd) +{ + const char *cmdLine = NULL; + char *command; + char *args; + char *path; + + /* get the command */ + split_command (cmd, &command, &args); + + if (!has_path (command)) + { + /* try to find the command in predefined binary paths */ + if (NULL != (path = (char *)setFirstItem (binPathSet))) + { + do + { + struct dbuf_s dbuf; + const char *cmdPath; + + dbuf_init (&dbuf, PATH_MAX); + dbuf_makePath (&dbuf, path, command); + cmdPath = dbuf_detach (&dbuf); + + /* Try if cmdPath */ + if (0 == access (cmdPath, X_OK)) + { + /* compose the command line */ + cmdLine = merge_command (cmdPath, args); + break; + } + } while (NULL != (path = (char *)setNextItem (binPathSet))); + } + if (NULL == cmdLine) + cmdLine = merge_command (command, args); + + Safe_free (command); + Safe_free (args); + + return cmdLine; + } + else + { + /* + * the command is defined with absolute path: + * just return it + */ + Safe_free (command); + Safe_free (args); + + return Safe_strdup (cmd); + } +} +#endif + + +/*! + * call an external program with arguements + */ + +int +sdcc_system (const char *cmd) +{ + int e; + const char *cmdLine = get_path (cmd); + + assert (NULL != cmdLine); + + if (options.verboseExec) + printf ("+ %s\n", cmdLine); + + e = system (cmdLine); + + if (options.verboseExec && e) + printf ("+ %s returned errorcode %d\n", cmdLine, e); + + dbuf_free (cmdLine); + + return e; +} + + +/*! + * pipe an external program with arguements + */ + +#ifdef _WIN32 +#define sdcc_popen_read(cmd) _popen ((cmd), "rt") +int +sdcc_pclose (FILE *fp) +{ + return _pclose (fp); +} +#else +#define sdcc_popen_read(cmd) popen ((cmd), "r") +int +sdcc_pclose (FILE *fp) +{ + return pclose (fp); +} +#endif + +FILE * +sdcc_popen (const char *cmd) +{ + FILE *fp; + const char *cmdLine = get_path (cmd); + + assert (NULL != cmdLine); + + if (options.verboseExec) + { + printf ("+ %s\n", cmdLine); + } + + fp = sdcc_popen_read (cmdLine); + dbuf_free (cmdLine); + + return fp; +} |
