1/* VMS DEC C wrapper. 2 Copyright (C) 2001, 2003 Free Software Foundation, Inc. 3 Contributed by Douglas B. Rupp (rupp@gnat.com). 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to 19the Free Software Foundation, 51 Franklin Street, Fifth Floor, 20Boston, MA 02110-1301, USA. */ 21 22/* This program is a wrapper around the VMS DEC C compiler. 23 It translates Unix style command line options into corresponding 24 VMS style qualifiers and then spawns the DEC C compiler. */ 25 26#include "config.h" 27#include "system.h" 28#include "coretypes.h" 29#include "tm.h" 30 31#undef PATH_SEPARATOR 32#undef PATH_SEPARATOR_STR 33#define PATH_SEPARATOR ',' 34#define PATH_SEPARATOR_STR "," 35 36/* These can be set by command line arguments */ 37static int verbose = 0; 38static int save_temps = 0; 39 40static int comp_arg_max = -1; 41static const char **comp_args = 0; 42static int comp_arg_index = -1; 43static char *objfilename = 0; 44 45static char *system_search_dirs = (char *) ""; 46static char *search_dirs; 47 48static char *default_defines = (char *) ""; 49static char *defines; 50 51/* Translate a Unix syntax directory specification into VMS syntax. 52 If indicators of VMS syntax found, return input string. */ 53static char *to_host_dir_spec (char *); 54 55/* Translate a Unix syntax file specification into VMS syntax. 56 If indicators of VMS syntax found, return input string. */ 57static char *to_host_file_spec (char *); 58 59/* Add a translated arg to the list to be passed to DEC CC. */ 60static void addarg (const char *); 61 62/* Preprocess the number of args in P_ARGC and contained in ARGV. 63 Look for special flags, etc. that must be handled first. */ 64static void preprocess_args (int *, char **); 65 66/* Process the number of args in P_ARGC and contained in ARGV. Look 67 for special flags, etc. that must be handled for the VMS compiler. */ 68static void process_args (int *, char **); 69 70/* Action routine called by decc$to_vms */ 71static int translate_unix (char *, int); 72 73/* Add the argument contained in STR to the list of arguments to pass to the 74 compiler. */ 75 76static void 77addarg (const char *str) 78{ 79 int i; 80 81 if (++comp_arg_index >= comp_arg_max) 82 { 83 const char **new_comp_args 84 = (const char **) xcalloc (comp_arg_max + 1000, sizeof (char *)); 85 86 for (i = 0; i <= comp_arg_max; i++) 87 new_comp_args [i] = comp_args [i]; 88 89 if (comp_args) 90 free (comp_args); 91 92 comp_arg_max += 1000; 93 comp_args = new_comp_args; 94 } 95 96 comp_args [comp_arg_index] = str; 97} 98 99static void 100preprocess_args (int *p_argc, char *argv[]) 101{ 102 int i; 103 104 for (i = 1; i < *p_argc; i++) 105 { 106 if (strcmp (argv[i], "-o") == 0) 107 { 108 char *buff, *ptr; 109 110 i++; 111 ptr = to_host_file_spec (argv[i]); 112 objfilename = xstrdup (ptr); 113 buff = concat ("/obj=", ptr, NULL); 114 addarg (buff); 115 } 116 } 117} 118 119static void 120process_args (int *p_argc, char *argv[]) 121{ 122 int i; 123 124 for (i = 1; i < *p_argc; i++) 125 { 126 if (strlen (argv[i]) < 2) 127 continue; 128 129 if (strncmp (argv[i], "-I", 2) == 0) 130 { 131 char *ptr; 132 int new_len, search_dirs_len; 133 134 ptr = to_host_dir_spec (&argv[i][2]); 135 new_len = strlen (ptr); 136 search_dirs_len = strlen (search_dirs); 137 138 search_dirs = xrealloc (search_dirs, search_dirs_len + new_len + 2); 139 if (search_dirs_len > 0) 140 strcat (search_dirs, PATH_SEPARATOR_STR); 141 strcat (search_dirs, ptr); 142 } 143 else if (strncmp (argv[i], "-D", 2) == 0) 144 { 145 char *ptr; 146 int new_len, defines_len; 147 148 ptr = &argv[i][2]; 149 new_len = strlen (ptr); 150 defines_len = strlen (defines); 151 152 defines = xrealloc (defines, defines_len + new_len + 4); 153 if (defines_len > 0) 154 strcat (defines, ","); 155 156 strcat (defines, "\""); 157 strcat (defines, ptr); 158 strcat (defines, "\""); 159 } 160 else if (strcmp (argv[i], "-v") == 0) 161 verbose = 1; 162 else if (strcmp (argv[i], "-g0") == 0) 163 addarg ("/nodebug"); 164 else if (strcmp (argv[i], "-O0") == 0) 165 addarg ("/noopt"); 166 else if (strncmp (argv[i], "-g", 2) == 0) 167 addarg ("/debug"); 168 else if (strcmp (argv[i], "-E") == 0) 169 addarg ("/preprocess"); 170 else if (strcmp (argv[i], "-save-temps") == 0) 171 save_temps = 1; 172 } 173} 174 175/* The main program. Spawn the VMS DEC C compiler after fixing up the 176 Unix-like flags and args to be what VMS DEC C wants. */ 177 178typedef struct dsc {unsigned short len, mbz; char *adr; } Descr; 179 180int 181main (int argc, char **argv) 182{ 183 int i; 184 char cwdev [128], *devptr; 185 int devlen; 186 char *cwd = getcwd (0, 1024); 187 188 devptr = strchr (cwd, ':'); 189 devlen = (devptr - cwd) + 1; 190 strncpy (cwdev, cwd, devlen); 191 cwdev [devlen] = '\0'; 192 193 search_dirs = xstrdup (system_search_dirs); 194 defines = xstrdup (default_defines); 195 196 addarg ("cc"); 197 preprocess_args (&argc , argv); 198 process_args (&argc , argv); 199 200 if (strlen (search_dirs) > 0) 201 { 202 addarg ("/include=("); 203 addarg (search_dirs); 204 addarg (")"); 205 } 206 207 if (strlen (defines) > 0) 208 { 209 addarg ("/define=("); 210 addarg (defines); 211 addarg (")"); 212 } 213 214 for (i = 1; i < argc; i++) 215 { 216 int arg_len = strlen (argv[i]); 217 218 if (strcmp (argv[i], "-o") == 0) 219 i++; 220 else if (strcmp (argv[i], "-v" ) == 0 221 || strcmp (argv[i], "-E") == 0 222 || strcmp (argv[i], "-c") == 0 223 || strncmp (argv[i], "-g", 2 ) == 0 224 || strncmp (argv[i], "-O", 2 ) == 0 225 || strcmp (argv[i], "-save-temps") == 0 226 || (arg_len > 2 && strncmp (argv[i], "-I", 2) == 0) 227 || (arg_len > 2 && strncmp (argv[i], "-D", 2) == 0)) 228 ; 229 230 /* Unix style file specs and VMS style switches look alike, so assume 231 an arg consisting of one and only one slash, and that being first, is 232 really a switch. */ 233 else if ((argv[i][0] == '/') && (strchr (&argv[i][1], '/') == 0)) 234 addarg (argv[i]); 235 else 236 { 237 /* Assume filename arg */ 238 char buff [256], *ptr; 239 240 ptr = to_host_file_spec (argv[i]); 241 arg_len = strlen (ptr); 242 243 if (ptr[0] == '[') 244 sprintf (buff, "%s%s", cwdev, ptr); 245 else if (strchr (ptr, ':')) 246 sprintf (buff, "%s", ptr); 247 else 248 sprintf (buff, "%s%s", cwd, ptr); 249 250 ptr = xstrdup (buff); 251 addarg (ptr); 252 } 253 } 254 255 addarg (NULL); 256 257 if (verbose) 258 { 259 int i; 260 261 for (i = 0; i < comp_arg_index; i++) 262 printf ("%s ", comp_args [i]); 263 264 putchar ('\n'); 265 } 266 267 { 268 int i; 269 int len = 0; 270 271 for (i = 0; comp_args[i]; i++) 272 len = len + strlen (comp_args[i]) + 1; 273 274 { 275 char *allargs = (char *) alloca (len + 1); 276 Descr cmd; 277 int status; 278 int status1 = 1; 279 280 for (i = 0; i < len + 1; i++) 281 allargs [i] = 0; 282 283 for (i = 0; comp_args [i]; i++) 284 { 285 strcat (allargs, comp_args [i]); 286 strcat (allargs, " "); 287 } 288 289 cmd.adr = allargs; 290 cmd.len = len; 291 cmd.mbz = 0; 292 293 i = LIB$SPAWN (&cmd, 0, 0, 0, 0, 0, &status); 294 295 if ((i & 1) != 1) 296 { 297 LIB$SIGNAL (i); 298 exit (1); 299 } 300 301 if ((status & 1) == 1 && (status1 & 1) == 1) 302 exit (0); 303 304 exit (1); 305 } 306 } 307} 308 309static char new_host_filespec [255]; 310static char new_host_dirspec [255]; 311static char filename_buff [256]; 312 313static int 314translate_unix (char *name, int type ATTRIBUTE_UNUSED) 315{ 316 strcpy (filename_buff, name); 317 return 0; 318} 319 320static char * 321to_host_dir_spec (char *dirspec) 322{ 323 int len = strlen (dirspec); 324 325 strcpy (new_host_dirspec, dirspec); 326 327 if (strchr (new_host_dirspec, ']') || strchr (new_host_dirspec, ':')) 328 return new_host_dirspec; 329 330 while (len > 1 && new_host_dirspec [len-1] == '/') 331 { 332 new_host_dirspec [len-1] = 0; 333 len--; 334 } 335 336 decc$to_vms (new_host_dirspec, translate_unix, 1, 2); 337 strcpy (new_host_dirspec, filename_buff); 338 339 return new_host_dirspec; 340 341} 342 343static char * 344to_host_file_spec (char *filespec) 345{ 346 strcpy (new_host_filespec, ""); 347 if (strchr (filespec, ']') || strchr (filespec, ':')) 348 strcpy (new_host_filespec, filespec); 349 else 350 { 351 decc$to_vms (filespec, translate_unix, 1, 1); 352 strcpy (new_host_filespec, filename_buff); 353 } 354 355 return new_host_filespec; 356} 357