xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/avr/driver-avr.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* Subroutines for the gcc driver.
2    Copyright (C) 2009-2015 Free Software Foundation, Inc.
3    Contributed by Georg-Johann Lay <avr@gjlay.de>
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "diagnostic.h"
25 #include "tm.h"
26 
27 // Remove -nodevicelib from the command line if not needed
28 #define X_NODEVLIB "%<nodevicelib"
29 
30 static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
31 
32 static const char specfiles_doc_url[] =
33   "http://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html";
34 
35 
36 static const char*
37 avr_diagnose_devicespecs_error (const char *mcu, const char *filename)
38 {
39   error ("cannot access device-specs for %qs expected at %qs",
40          mcu, filename);
41 
42   // Inform about natively supported devices and cores.
43 
44   if (strncmp (mcu, "avr", strlen ("avr")))
45     avr_inform_devices ();
46 
47   avr_inform_core_architectures ();
48 
49   inform (input_location, "you can provide your own specs files, "
50           "see <%s> for details", specfiles_doc_url);
51 
52   return X_NODEVLIB;
53 }
54 
55 
56 /* Implement spec function `device-specs-file´.
57 
58    Compose -specs=<specs-file-name>%s.  If everything went well then argv[0]
59    is the inflated (absolute) specs directory and argv[1] is a device or
60    core name as supplied by -mmcu=*.  When building GCC the path might
61    be relative.  */
62 
63 const char*
64 avr_devicespecs_file (int argc, const char **argv)
65 {
66   char *specfile_name;
67   const char *mmcu = NULL;
68 
69 #ifdef DEBUG_SPECS
70   if (verbose_flag)
71     fnotice (stderr, "Running spec function '%s' with %d args\n\n",
72              __FUNCTION__, argc);
73 #endif
74 
75   switch (argc)
76     {
77     case 0:
78       fatal_error (input_location,
79                    "bad usage of spec function %qs", "device-specs-file");
80       return X_NODEVLIB;
81 
82     case 1:
83       if (0 == strcmp ("device-specs", argv[0]))
84         {
85           /* FIXME:  This means "device-specs%s" from avr.h:DRIVER_SELF_SPECS
86              has not been resolved to a path.  That case can occur when the
87              c++ testsuite is run from the build directory.  DejaGNU's
88              libgloss.exp:get_multilibs runs $compiler without -B, i.e.runs
89              xgcc without specifying a prefix.  Without any prefix, there is
90              no means to find out where the specs files might be located.
91              get_multilibs runs xgcc --print-multi-lib, hence we don't actually
92              need information form a specs file and may skip it here.  */
93           return X_NODEVLIB;
94         }
95 
96       mmcu = AVR_MMCU_DEFAULT;
97       break;
98 
99     default:
100       mmcu = argv[1];
101 
102       // Allow specifying the same MCU more than once.
103 
104       for (int i = 2; i < argc; i++)
105         if (0 != strcmp (mmcu, argv[i]))
106           {
107             error ("specified option %qs more than once", "-mmcu");
108             return X_NODEVLIB;
109           }
110 
111       break;
112     }
113 
114   specfile_name = concat (argv[0], dir_separator_str, "specs-", mmcu, NULL);
115 
116 #ifdef DEBUG_SPECS
117   if (verbose_flag)
118     fnotice (stderr, "'%s': mmcu='%s'\n'%s': specfile='%s'\n\n",
119              __FUNCTION__, mmcu, __FUNCTION__, specfile_name);
120 #endif
121 
122   // Filter out silly -mmcu= arguments like "foo bar".
123 
124   for (const char *s = mmcu; *s; s++)
125     if (!ISALNUM (*s)
126         && '-' != *s
127         && '_' != *s)
128       {
129         error ("strange device name %qs after %qs: bad character %qc",
130                mmcu, "-mmcu=", *s);
131         return X_NODEVLIB;
132       }
133 
134   if (/* When building / configuring the compiler we might get a relative path
135          as supplied by "-B.".  Assume that the specs file exists and MCU is
136          a core, not a proper device then, i.e. we have "-mmcu=avr*".  */
137       (0 == strncmp (mmcu, "avr", strlen ("avr"))
138        && specfile_name[0] == '.')
139       /* vanilla */
140       || (IS_ABSOLUTE_PATH (specfile_name)
141           && !access (specfile_name, R_OK)))
142     {
143       return concat ("-specs=device-specs", dir_separator_str, "specs-", mmcu,
144                      // Use '%s' instead of the expanded specfile_name.  This
145                      // is the easiest way to handle pathes containing spaces.
146                      "%s",
147 #if defined (WITH_AVRLIBC)
148                      " %{mmcu=avr*:" X_NODEVLIB "} %{!mmcu=*:" X_NODEVLIB "}",
149 #else
150                      " " X_NODEVLIB,
151 #endif
152                      NULL);
153     }
154 
155   return avr_diagnose_devicespecs_error (mmcu, specfile_name);
156 }
157