aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/msp430/msp430-devices.c
diff options
context:
space:
mode:
authorJozef Lawrynowicz <jozef.l@mittosystems.com>2019-11-04 11:01:03 +0000
committerJozef Lawrynowicz <jozefl@gcc.gnu.org>2019-11-04 11:01:03 +0000
commitd7eabfd452f6f447ca8f3a955e7a4b531884fadb (patch)
tree7654a0733dcf2cd4ab85896373c854912bda4b7c /gcc/config/msp430/msp430-devices.c
parentb76f4e6c06bd494d2383c4c16d1e1a034da74641 (diff)
downloadgcc-d7eabfd452f6f447ca8f3a955e7a4b531884fadb.zip
gcc-d7eabfd452f6f447ca8f3a955e7a4b531884fadb.tar.gz
gcc-d7eabfd452f6f447ca8f3a955e7a4b531884fadb.tar.bz2
MSP430: Add new methods of finding external MCU data file
MCU data file can now be specified with an environment variable or installed into a toolchain subdirectory. 2019-11-04 Jozef Lawrynowicz <jozef.l@mittosystems.com> gcc/ * config/msp430/driver-msp430.c (msp430_get_linker_devices_include_path): New spec function. * config/msp430/msp430-devices.c (msp430_dirname): New function. (extract_devices_dir_from_exec_prefix): New function. (extract_devices_dir_from_collect_gcc): New function. (msp430_check_env_var_for_devices): New function. (msp430_check_path_for_devices): Use xstrdup instead of ASTRDUP. (parse_devices_csv): Call msp430_check_env_var_for_devices if devices.csv was not found using other methods. * config/msp430/msp430-devices.h (msp430_check_env_var_for_devices): New prototype. (msp430_dirname): Likewise. * config/msp430/msp430.c (msp430_register_pre_includes): New function. * config/msp430/msp430.h (EXTRA_SPEC_FUNCTIONS): Add msp430_get_linker_devices_include_path. (TARGET_EXTRA_PRE_INCLUDES): Define. * doc/invoke.texi: Document new ways of searching for support files. gcc/testsuite/ * gcc.target/msp430/devices/csv-using-env-var.c: New test. * gcc.target/msp430/devices/csv-using-installed.c: New test. * gcc.target/msp430/devices/csv-using-option.c: New test. * gcc.target/msp430/devices/devices-main.c: New test source file. * gcc.target/msp430/devices/msp430-devices.h: New test. * gcc.target/msp430/msp430.exp (msp430_device_permutations_runtest): Add special cases for csv-using* tests. Define TESTING_HARD_DATA when running tests that use hard-coded device data. (get_installed_device_data_path): New. (msp430_hide_installed_devices_data): New. (msp430_restore_installed_devices_data): New. (msp430_test_installed_device_data): New. (msp430_install_device_data): New. From-SVN: r277772
Diffstat (limited to 'gcc/config/msp430/msp430-devices.c')
-rw-r--r--gcc/config/msp430/msp430-devices.c133
1 files changed, 129 insertions, 4 deletions
diff --git a/gcc/config/msp430/msp430-devices.c b/gcc/config/msp430/msp430-devices.c
index 537d438..600a111 100644
--- a/gcc/config/msp430/msp430-devices.c
+++ b/gcc/config/msp430/msp430-devices.c
@@ -37,7 +37,7 @@ extern struct t_msp430_mcu_data hard_msp430_mcu_data[605];
/* Set to the full path to devices.csv if it is found by searching the -I and
-L paths. */
-char * derived_devices_csv_loc = NULL;
+char *derived_devices_csv_loc = NULL;
/* This is to canonicalize the directory separators in the path.
On Windows we could have a mix of '/' and '\' in the path. */
@@ -52,6 +52,128 @@ canonicalize_path_dirsep (char **path)
t_path[i] = DIR_SEPARATOR;
}
+/* This function returns the enclosing directory of PATH.
+ It is inconsequential whether PATH ends in a dirsep or not.
+ It modifies the string pointed to by PATH. */
+char *
+msp430_dirname (char *path)
+{
+ int last_elem = strlen (path) - 1;
+ int i = last_elem - (IS_DIR_SEPARATOR (path[last_elem]) ? 1 : 0);
+ for (; i >= 0; i--)
+ {
+ if (IS_DIR_SEPARATOR (path[i]))
+ {
+ path[i] = '\0';
+ return path;
+ }
+ }
+ return path;
+}
+
+/* devices.csv path from the toolchain root. */
+static const char rest_of_devices_path[] = "/msp430-elf/include/devices/";
+
+/* "The default value of GCC_EXEC_PREFIX is prefix/lib/gcc". Strip lib/gcc
+ from GCC_EXEC_PREFIX to get the path to the installed toolchain. */
+static void
+extract_devices_dir_from_exec_prefix (char **devices_loc)
+{
+ const char *temp;
+ char *gcc_exec_prefix = *devices_loc;
+ int len = strlen (gcc_exec_prefix);
+
+ /* Copied from gcc.c. */
+ if (len > (int) sizeof ("/lib/gcc/") - 1
+ && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
+ {
+ temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
+ if (IS_DIR_SEPARATOR (*temp)
+ && filename_ncmp (temp + 1, "lib", 3) == 0
+ && IS_DIR_SEPARATOR (temp[4])
+ && filename_ncmp (temp + 5, "gcc", 3) == 0)
+ {
+ len -= sizeof ("/lib/gcc/") - 1;
+ /* Keep the '/' from the beginning of /lib/gcc. */
+ gcc_exec_prefix[len + 1] = (char) 0;
+ *devices_loc = concat (gcc_exec_prefix, rest_of_devices_path, NULL);
+ return;
+ }
+ }
+}
+
+/* Given the path to the GCC executable, return the path to the installed
+ device data in "$TOOLCHAIN_ROOT/msp430-elf/include/devices".
+ Assumes the GCC executable is in "$TOOLCHAIN_ROOT/<somedir>/". */
+static void
+extract_devices_dir_from_collect_gcc (char **devices_loc)
+{
+ char *t_devices_loc = *devices_loc;
+ /* Go up a directory to the toolchain root. */
+ t_devices_loc = msp430_dirname (msp430_dirname (t_devices_loc));
+ t_devices_loc = concat (t_devices_loc, rest_of_devices_path, NULL);
+ *devices_loc = t_devices_loc;
+}
+
+/* The path to the MSP430-GCC support files can be specified with the
+ environment variable "MSP430_GCC_INCLUDE_DIR", or installed into the
+ toolchain in the msp430-elf/include/devices subdirectory.
+ We use the GCC_EXEC_PREFIX or COLLECT_GCC environment variables as a starting
+ point for the location of the toolchain, and work out the path to the
+ installed device data from there.
+ Return 0 and set LOCAL_DEVICES_CSV_LOC if we find devices.csv. Return 1
+ if devices.csv wasn't found. */
+int
+msp430_check_env_var_for_devices (char **local_devices_csv_loc)
+{
+ const int num_vars = 3;
+ const char dirsep[2] = { DIR_SEPARATOR, 0 };
+ /* Both GCC_EXEC_PREFIX and COLLECT_GCC should always be set to the format we
+ expect, as they are required for correct operation of the toolchain.
+ So if they are wrong the user will probably have bigger problems.
+ GCC_EXEC_PREFIX is only defined in the driver, whilst COLLECT_GCC is only
+ defined in the compiler proper, so we need both. */
+ const char *env_vars[num_vars] = {
+ "MSP430_GCC_INCLUDE_DIR", "GCC_EXEC_PREFIX", "COLLECT_GCC" };
+ enum msp430_include_vars {
+ MSP430_GCC_INCLUDE_DIR,
+ GCC_EXEC_PREFIX,
+ COLLECT_GCC
+ };
+ FILE *devices_csv_file = NULL;
+ int i;
+
+ for (i = MSP430_GCC_INCLUDE_DIR; i <= COLLECT_GCC; i++)
+ {
+ char *t_devices_loc;
+ char *val = getenv (env_vars[i]);
+ if (val == NULL)
+ continue;
+ t_devices_loc = xstrdup (val);
+
+ if (i == MSP430_GCC_INCLUDE_DIR)
+ {
+ if (!IS_DIR_SEPARATOR (t_devices_loc[strlen (t_devices_loc) - 1]))
+ t_devices_loc = concat (t_devices_loc, dirsep, NULL);
+ }
+ else if (i == GCC_EXEC_PREFIX)
+ extract_devices_dir_from_exec_prefix (&t_devices_loc);
+ else if (i == COLLECT_GCC)
+ extract_devices_dir_from_collect_gcc (&t_devices_loc);
+
+ t_devices_loc = concat (t_devices_loc, "devices.csv", NULL);
+ devices_csv_file = fopen (t_devices_loc, "r");
+ if (devices_csv_file != NULL)
+ {
+ fclose (devices_csv_file);
+ *local_devices_csv_loc = t_devices_loc;
+ canonicalize_path_dirsep (local_devices_csv_loc);
+ return 0;
+ }
+ }
+ return 1;
+}
+
/* Spec function which searches the paths passed to the -I and -L options for
the "devices.csv" file. If it is found then the -mdevices-csv-loc option is
placed on the command line so the compiler knows the location of the
@@ -69,7 +191,7 @@ msp430_check_path_for_devices (int argc, const char **argv)
return NULL;
for (i = 0; i < argc; i++)
{
- char *inc_path = ASTRDUP (argv[i]);
+ char *inc_path = xstrdup (argv[i]);
canonicalize_path_dirsep (&inc_path);
if (!IS_DIR_SEPARATOR (inc_path[strlen (inc_path) - 1]))
inc_path = concat (inc_path, dirsep, NULL);
@@ -274,8 +396,11 @@ parse_devices_csv (const char * mcu_name)
/* Otherwise check if the path to devices.csv was found another way. */
else if (derived_devices_csv_loc != NULL)
return parse_devices_csv_1 (derived_devices_csv_loc, mcu_name);
- /* devices.csv was not found. */
- return 2;
+ /* Otherwise we need to use environment variables to try and find it. */
+ if (msp430_check_env_var_for_devices (&derived_devices_csv_loc))
+ /* devices.csv was not found. */
+ return 2;
+ return parse_devices_csv_1 (derived_devices_csv_loc, mcu_name);
}
/* Main entry point to load the MCU data for the given -mmcu into