1 /* VMS archive wrapper.
2 Copyright (C) 2011-2024 Free Software Foundation, Inc.
3 Contributed by AdaCore.
5 This file is part of GCC.
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)
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.
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/>. */
23 #include <sys/types.h>
29 #include "libiberty.h"
31 #define FATAL_EXIT_CODE (44 | 0x10000000)
33 /* Librarian arguments. */
34 static int lib_arg_max
= 0;
35 static const char **lib_args
;
36 static int lib_arg_index
= -1;
38 /* Set for r/c/x/v command. */
39 static int replace_mode
= 0;
40 static int create_mode
= 0;
41 static int extract_mode
= 0;
42 static int verbose_mode
= 0;
44 static char modecmd
[32];
45 static char libname
[256];
47 #define TEMP_FILE "arXXXXXX"
48 #define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
50 #define SUFFIX_LEN (sizeof(SUFFIX) - 1)
52 static char *to_host_file_spec (char *filespec
);
53 static int is_regular_file (char *name
);
56 static char new_host_filespec
[255];
57 static char filename_buff
[256];
60 translate_unix (char *name
, int type
)
62 strcpy (filename_buff
, name
);
68 to_host_file_spec (char *filespec
)
71 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
75 strcpy (filename_buff
, filespec
);
76 decc$
to_vms (filespec
, translate_unix
, 1, 1);
77 strcpy (new_host_filespec
, filename_buff
);
78 return new_host_filespec
;
85 /* Check to see if the file named in NAME is a regular file, i.e. not a
89 is_regular_file (char *name
)
94 ret
= stat (name
, &statbuf
);
95 return !ret
&& S_ISREG (statbuf
.st_mode
);
98 /* Add the argument contained in STR to the list of arguments to pass to the
102 addarg (const char *str
)
104 if (++lib_arg_index
>= lib_arg_max
)
107 lib_args
= XRESIZEVEC (const char *, lib_args
, lib_arg_max
);
110 lib_args
[lib_arg_index
] = str
;
116 printf ("usage: ar -r [-cv] archive file...\n");
117 printf (" ar -c [-rv] archive file...\n");
118 printf (" ar -x [-v] archive [module...]\n");
122 main (int argc
, char *argv
[])
127 int outlen
, maxoutlen
= 4000;
128 char temp_filename
[] = TEMP_FILE SUFFIX
;
134 fprintf (stderr
, "ar: no command or archive\n");
135 exit (FATAL_EXIT_CODE
);
138 if (argv
[1][0] != '-')
140 int arglen
= strlen (argv
[1]);
142 /* Compatibility mode. */
143 for (i
= 0; i
< arglen
; i
++)
145 if (argv
[1][i
] == 'r')
149 else if (argv
[1][i
] == 'c')
153 else if (argv
[1][i
] == 'x')
157 else if (argv
[1][i
] == 'v')
163 fprintf (stderr
, "ar: unknown command '%c'\n", argv
[1][i
]);
164 exit (FATAL_EXIT_CODE
);
173 for (i
= 1; i
< argc
; i
++)
175 if (argv
[i
][0] != '-')
180 else if (strcmp (argv
[i
], "-r") == 0)
184 else if (strcmp (argv
[i
], "-c") == 0)
188 else if (strcmp (argv
[i
], "-x") == 0)
192 else if (strcmp (argv
[i
], "-v") == 0)
196 else if (strcmp (argv
[i
], "--help") == 0)
203 fprintf (stderr
, "ar: unknown option %s\n", argv
[i
]);
204 exit (FATAL_EXIT_CODE
);
213 char *lname
= argv
[nexti
];
216 /* Next argument is the archive name. */
217 if (is_regular_file (lname
))
219 addarg (xstrdup (to_host_file_spec (lname
)));
223 /* If not found, try with .olb instead of .a. */
224 lnamelen
= strlen (lname
);
227 && strcmp (&lname
[lnamelen
- 2], ".a") == 0)
231 nlibname
= (char *)alloca (lnamelen
+ 3);
232 strcpy (nlibname
, lname
);
233 strcpy (&nlibname
[lnamelen
- 2], ".olb");
234 if (is_regular_file (nlibname
))
236 addarg (xstrdup (to_host_file_spec (nlibname
)));
241 fprintf (stderr
, "ar: file '%s' doesn't exist\n", lname
);
242 exit (FATAL_EXIT_CODE
);
246 strcpy (libname
, to_host_file_spec (argv
[nexti
]));
250 /* Build command mode. */
253 strcat (modecmd
, "/replace");
255 if (!is_regular_file (libname
) || !replace_mode
)
257 /* Really create if the archive doesn't exist. */
258 strcat (modecmd
, "/create");
261 else if (extract_mode
)
266 strcat (modecmd
, "/extract=(*");
269 strcat (modecmd
, "/extract=(");
273 for (i
= nexti
; i
< argc
; i
++)
277 /* Convert to module name (remove extension) and quote it. */
278 char *module
= argv
[i
];
279 int module_len
= strlen (module
);
280 char *newarg
= (char *)xmalloc (module_len
+ 3);
284 memcpy (newarg
+ 1, module
, module_len
);
288 && strcmp (&module
[module_len
- 4], ".obj") == 0)
298 /* Add the filename. */
299 addarg (xstrdup (to_host_file_spec (argv
[i
])));
306 /* Create the command file name. */
307 strcpy (temp_filename
, TEMP_FILE SUFFIX
);
308 comfd
= mkstemps (temp_filename
, SUFFIX_LEN
);
309 comfile
= fdopen (comfd
, "w");
311 /* Write the command file.
312 We need to split to command into severals ones if it is too long. */
314 for (iarg
= 0; iarg
<= lib_arg_index
; iarg
++)
318 fprintf (comfile
, "$ library %s %s -\n", modecmd
, libname
);
319 if (create_mode
&& iarg
== 0)
320 strcpy (modecmd
, "/replace");
323 fprintf (comfile
, "%s", lib_args
[iarg
]);
324 outlen
+= strlen (lib_args
[iarg
]) + 2;
326 if (outlen
> maxoutlen
|| iarg
== lib_arg_index
)
328 /* Will write a new command. */
329 fprintf (comfile
, "\n");
334 /* Continuation line. */
335 fprintf (comfile
, ",-\n");
341 sprintf (command
, "@%s", temp_filename
);
343 status
= system (command
);
345 remove (temp_filename
);