Wed Apr 15 14:33:07 1992 Steve Chamberlain (sac@thepub.cygnus.com)
* arsup.c, arsup.h, arparse.y, arlex.l: support for archive scripting language.
This commit is contained in:
parent
4a11eef2eb
commit
c0cc691258
|
@ -36,6 +36,10 @@ alloca.c
|
||||||
am29k-pinsn.c
|
am29k-pinsn.c
|
||||||
ar.1
|
ar.1
|
||||||
ar.c
|
ar.c
|
||||||
|
arlex.l
|
||||||
|
arsup.c
|
||||||
|
arsup.h
|
||||||
|
arparse.y
|
||||||
binutils.texi
|
binutils.texi
|
||||||
bucomm.c
|
bucomm.c
|
||||||
bucomm.h
|
bucomm.h
|
||||||
|
|
426
binutils/ar.c
426
binutils/ar.c
|
@ -29,18 +29,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
#include "bucomm.h"
|
#include "bucomm.h"
|
||||||
#include "aout/ar.h"
|
#include "aout/ar.h"
|
||||||
#include "../bfd/libbfd.h"
|
#include "../bfd/libbfd.h"
|
||||||
|
#include "arsup.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef USG
|
||||||
|
#include <time.h>
|
||||||
|
#else
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#define BUFSIZE 8192
|
#define BUFSIZE 8192
|
||||||
/* PROTO (void, open_inarch, (char *archive_filename)); */
|
|
||||||
#ifdef __STDC__
|
|
||||||
static void open_inarch(char *archive_filename);
|
|
||||||
#else
|
|
||||||
static void open_inarch();
|
|
||||||
#endif /* __STDC__ */
|
|
||||||
|
|
||||||
PROTO(void, map_over_members, (void (*function) (), char **files, int count));
|
void EXFUN(open_inarch,(char *archive_filename));
|
||||||
|
|
||||||
|
|
||||||
PROTO(void, print_contents, (bfd * member));
|
PROTO(void, print_contents, (bfd * member));
|
||||||
PROTO(void, extract_file, (bfd * abfd));
|
PROTO(void, extract_file, (bfd * abfd));
|
||||||
PROTO(void, delete_members, (char **files_to_delete));
|
PROTO(void, delete_members, (char **files_to_delete));
|
||||||
|
@ -56,6 +57,7 @@ char *program_name = NULL;
|
||||||
bfd bogus_archive;
|
bfd bogus_archive;
|
||||||
bfd *inarch; /* The input arch we're manipulating */
|
bfd *inarch; /* The input arch we're manipulating */
|
||||||
|
|
||||||
|
int mri_mode;
|
||||||
/* This flag distinguishes between ar and ranlib:
|
/* This flag distinguishes between ar and ranlib:
|
||||||
1 means this is 'ranlib'; 0 means this is 'ar'.
|
1 means this is 'ranlib'; 0 means this is 'ar'.
|
||||||
-1 means if we should use argv[0] to decide. */
|
-1 means if we should use argv[0] to decide. */
|
||||||
|
@ -113,6 +115,52 @@ enum pos {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int interactive = 0;
|
||||||
|
void
|
||||||
|
DEFUN_VOID(mri_emul)
|
||||||
|
{
|
||||||
|
interactive = isatty(fileno(stdin)) ;
|
||||||
|
yyparse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If count is 0, then function is called once on each entry. if nonzero,
|
||||||
|
count is the length of the files chain; function is called on each entry
|
||||||
|
whose name matches one in files
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
DEFUN(map_over_members,(function, files, count),
|
||||||
|
void (*function) () AND
|
||||||
|
char **files AND
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
bfd *head;
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
for (head = inarch->next; head; head = head->next)
|
||||||
|
function(head);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
This may appear to be a baroque way of accomplishing what we want.
|
||||||
|
however we have to iterate over the filenames in order to notice where
|
||||||
|
a filename is requested but does not exist in the archive. Ditto
|
||||||
|
mapping over each file each time -- we want to hack multiple
|
||||||
|
references.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (; count > 0; files++, count--) {
|
||||||
|
boolean found = false;
|
||||||
|
for (head = inarch->next; head; head = head->next)
|
||||||
|
if ((head->filename != NULL) &&
|
||||||
|
(!strcmp(*files, head->filename))) {
|
||||||
|
found = true;
|
||||||
|
function(head);
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
fprintf(stderr, "No entry %s in archive.\n", *files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean operation_alters_arch = false;
|
boolean operation_alters_arch = false;
|
||||||
|
@ -126,196 +174,207 @@ main(argc, argv)
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
{
|
{
|
||||||
char *arg_ptr;
|
char *arg_ptr;
|
||||||
char c;
|
char c;
|
||||||
enum {
|
enum {
|
||||||
none = 0, delete, replace, print_table,
|
none = 0, delete, replace, print_table,
|
||||||
print_files, extract, move, quick_append
|
print_files, extract, move, quick_append
|
||||||
} operation = none;
|
} operation = none;
|
||||||
int arg_index;
|
int arg_index;
|
||||||
char **files;
|
char **files;
|
||||||
char *inarch_filename;
|
char *inarch_filename;
|
||||||
char *temp;
|
char *temp;
|
||||||
|
|
||||||
bfd_init();
|
|
||||||
|
|
||||||
|
bfd_init();
|
||||||
|
verbose = 1;
|
||||||
#ifdef GNU960
|
#ifdef GNU960
|
||||||
check_v960( argc, argv );
|
check_v960( argc, argv );
|
||||||
default_target = bfd_make_targ_name(BFD_COFF_FORMAT,HOST_BYTE_ORDER_BIG_P);
|
default_target = bfd_make_targ_name(BFD_COFF_FORMAT,HOST_BYTE_ORDER_BIG_P);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
program_name = argv[0];
|
program_name = argv[0];
|
||||||
|
|
||||||
temp = strrchr(program_name, '/');
|
temp = strrchr(program_name, '/');
|
||||||
if (temp == (char *) NULL)
|
if (temp == (char *) NULL)
|
||||||
temp = program_name; /* shouldn't happen, but... */
|
temp = program_name; /* shouldn't happen, but... */
|
||||||
else
|
else
|
||||||
++temp;
|
++temp;
|
||||||
if (is_ranlib > 0 || (is_ranlib < 0 && strcmp(temp, "ranlib") == 0)) {
|
if (is_ranlib > 0 || (is_ranlib < 0 && strcmp(temp, "ranlib") == 0)) {
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
bfd_fatal("Too few command arguments.");
|
bfd_fatal("Too few command arguments.");
|
||||||
ranlib_only(argv[1]);
|
ranlib_only(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argc == 2 && strcmp(argv[1],"-M") == 0) {
|
||||||
if (argc < 3)
|
mri_emul();
|
||||||
bfd_fatal("Too few command arguments.");
|
exit(0);
|
||||||
|
}
|
||||||
arg_ptr = argv[1];
|
if (argc < 3)
|
||||||
|
bfd_fatal("Too few command arguments.");
|
||||||
if (*arg_ptr == '-')
|
|
||||||
++arg_ptr; /* compatibility */
|
arg_ptr = argv[1];
|
||||||
|
|
||||||
while (c = *arg_ptr++) {
|
if (*arg_ptr == '-')
|
||||||
switch (c) {
|
++arg_ptr; /* compatibility */
|
||||||
case 'd':
|
|
||||||
case 'm':
|
while (c = *arg_ptr++) {
|
||||||
case 'p':
|
switch (c) {
|
||||||
case 'q':
|
case 'd':
|
||||||
case 'r':
|
case 'm':
|
||||||
case 't':
|
case 'p':
|
||||||
case 'x':
|
case 'q':
|
||||||
if (operation != none)
|
case 'r':
|
||||||
fatal("two different operation switches specified");
|
case 't':
|
||||||
switch (c) {
|
case 'x':
|
||||||
case 'd':
|
if (operation != none)
|
||||||
operation = delete;
|
fatal("two different operation switches specified");
|
||||||
operation_alters_arch = true;
|
switch (c) {
|
||||||
break;
|
case 'd':
|
||||||
case 'm':
|
operation = delete;
|
||||||
operation = move;
|
operation_alters_arch = true;
|
||||||
operation_alters_arch = true;
|
break;
|
||||||
break;
|
case 'm':
|
||||||
case 'p':
|
operation = move;
|
||||||
operation = print_files;
|
operation_alters_arch = true;
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'p':
|
||||||
operation = quick_append;
|
operation = print_files;
|
||||||
operation_alters_arch = true;
|
break;
|
||||||
break;
|
case 'q':
|
||||||
case 'r':
|
operation = quick_append;
|
||||||
operation = replace;
|
operation_alters_arch = true;
|
||||||
operation_alters_arch = true;
|
break;
|
||||||
break;
|
case 'r':
|
||||||
case 't':
|
operation = replace;
|
||||||
operation = print_table;
|
operation_alters_arch = true;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 't':
|
||||||
operation = extract;
|
operation = print_table;
|
||||||
break;
|
break;
|
||||||
}
|
case 'x':
|
||||||
case 'l':
|
operation = extract;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
}
|
||||||
silent_create = 1;
|
case 'l':
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'c':
|
||||||
preserve_dates = 1;
|
silent_create = 1;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 'o':
|
||||||
write_armap = true;
|
preserve_dates = 1;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 's':
|
||||||
newer_only = 1;
|
write_armap = true;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'u':
|
||||||
verbose = 1;
|
newer_only = 1;
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'v':
|
||||||
postype = pos_after;
|
verbose = 1;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'a':
|
||||||
postype = pos_before;
|
postype = pos_after;
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'b':
|
||||||
postype = pos_before;
|
postype = pos_before;
|
||||||
break;
|
break;
|
||||||
default:
|
case 'i':
|
||||||
fatal("invalid option %c", c);
|
postype = pos_before;
|
||||||
}
|
break;
|
||||||
|
case 'M':
|
||||||
|
|
||||||
|
mri_mode = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("invalid option %c", c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mri_mode) {
|
||||||
|
mri_emul();
|
||||||
|
}
|
||||||
|
else {
|
||||||
if ((operation == none || operation == print_table)
|
if ((operation == none || operation == print_table)
|
||||||
&& write_armap == true)
|
&& write_armap == true)
|
||||||
ranlib_only(argv[2]);
|
ranlib_only(argv[2]);
|
||||||
|
|
||||||
if (operation == none)
|
if (operation == none)
|
||||||
fatal("no operation specified");
|
fatal("no operation specified");
|
||||||
|
|
||||||
if (newer_only && operation != replace)
|
if (newer_only && operation != replace)
|
||||||
fatal("'u' only meaningful with 'r' option.");
|
fatal("'u' only meaningful with 'r' option.");
|
||||||
|
|
||||||
arg_index = 2;
|
arg_index = 2;
|
||||||
|
|
||||||
if (postype != pos_default)
|
if (postype != pos_default)
|
||||||
posname = argv[arg_index++];
|
posname = argv[arg_index++];
|
||||||
|
|
||||||
inarch_filename = argv[arg_index++];
|
inarch_filename = argv[arg_index++];
|
||||||
|
|
||||||
if (arg_index < argc) {
|
if (arg_index < argc) {
|
||||||
files = argv + arg_index;
|
files = argv + arg_index;
|
||||||
while (arg_index < argc)
|
while (arg_index < argc)
|
||||||
if (!strcmp(argv[arg_index++], "__.SYMDEF")) {
|
if (!strcmp(argv[arg_index++], "__.SYMDEF")) {
|
||||||
ignore_symdef = 1;
|
ignore_symdef = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
files = NULL;
|
files = NULL;
|
||||||
|
|
||||||
if (operation == quick_append) {
|
if (operation == quick_append) {
|
||||||
if (files != NULL)
|
if (files != NULL)
|
||||||
do_quick_append(inarch_filename, files);
|
do_quick_append(inarch_filename, files);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
open_inarch(inarch_filename);
|
open_inarch(inarch_filename);
|
||||||
/*
|
/*
|
||||||
If we have no archive, and we've been asked to replace then create one
|
If we have no archive, and we've been asked to replace then create one
|
||||||
*/
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
if (operation == replace && inarch == &bogus_archive) {
|
if (operation == replace && inarch == &bogus_archive) {
|
||||||
silent_create = 1;
|
silent_create = 1;
|
||||||
do_quick_append(inarch_filename, 0);
|
do_quick_append(inarch_filename, 0);
|
||||||
open_inarch(inarch_filename);
|
open_inarch(inarch_filename);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
|
|
||||||
case print_table:
|
case print_table:
|
||||||
map_over_members(print_descr, files, argc - 3);
|
map_over_members(print_descr, files, argc - 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case print_files:
|
case print_files:
|
||||||
map_over_members(print_contents, files, argc - 3);
|
map_over_members(print_contents, files, argc - 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case extract:
|
case extract:
|
||||||
map_over_members(extract_file, files, argc - 3);
|
map_over_members(extract_file, files, argc - 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case delete:
|
case delete:
|
||||||
if (files != NULL)
|
if (files != NULL)
|
||||||
delete_members(files);
|
delete_members(files);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case move:
|
case move:
|
||||||
if (files != NULL)
|
if (files != NULL)
|
||||||
move_members(files);
|
move_members(files);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case replace:
|
case replace:
|
||||||
if (files != NULL || write_armap)
|
if (files != NULL || write_armap)
|
||||||
replace_members(files);
|
replace_members(files);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Shouldn't happen! */
|
/* Shouldn't happen! */
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Sorry; this option not implemented.\n");
|
fprintf(stderr, "Sorry; this option not implemented.\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (0);
|
return (0);
|
||||||
} /* main() */
|
} /* main() */
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -332,7 +391,7 @@ char *file;
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
open_inarch(archive_filename)
|
open_inarch(archive_filename)
|
||||||
char *archive_filename;
|
char *archive_filename;
|
||||||
{
|
{
|
||||||
|
@ -346,7 +405,8 @@ open_inarch(archive_filename)
|
||||||
if (!operation_alters_arch) {
|
if (!operation_alters_arch) {
|
||||||
fprintf (stderr, "%s: %s not found.\n", program_name,
|
fprintf (stderr, "%s: %s not found.\n", program_name,
|
||||||
archive_filename);
|
archive_filename);
|
||||||
exit (1);
|
maybequit();
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
if (!silent_create)
|
if (!silent_create)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -390,47 +450,6 @@ open_inarch(archive_filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
If count is 0, then function is called once on each entry. if nonzero,
|
|
||||||
count is the length of the files chain; function is called on each entry
|
|
||||||
whose name matches one in files
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
map_over_members(function, files, count)
|
|
||||||
void (*function) ();
|
|
||||||
char **files;
|
|
||||||
int count;
|
|
||||||
{
|
|
||||||
bfd *head;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (count == 0) {
|
|
||||||
for (head = inarch->next; head; head = head->next)
|
|
||||||
function(head);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
This may appear to be a baroque way of accomplishing what we want.
|
|
||||||
however we have to iterate over the filenames in order to notice where
|
|
||||||
a filename is requested but does not exist in the archive. Ditto
|
|
||||||
mapping over each file each time -- we want to hack multiple
|
|
||||||
references.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (; count > 0; files++, count--) {
|
|
||||||
boolean found = false;
|
|
||||||
for (head = inarch->next; head; head = head->next)
|
|
||||||
if ((head->filename != NULL) &&
|
|
||||||
(!strcmp(*files, head->filename))) {
|
|
||||||
found = true;
|
|
||||||
function(head);
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
fprintf(stderr, "No entry %s in archive.\n", *files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -502,7 +521,7 @@ extract_file(abfd)
|
||||||
ostream = 0;
|
ostream = 0;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
/* Seems like an abstraction violation, eh? Well it's OK! */
|
/* Seems like an abstraction violation, eh? Well it's OK! */
|
||||||
ostream = fopen(abfd->filename, "wb");
|
ostream = fopen(abfd->filename, FOPEN_WB);
|
||||||
if (!ostream) {
|
if (!ostream) {
|
||||||
perror(abfd->filename);
|
perror(abfd->filename);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -520,7 +539,7 @@ extract_file(abfd)
|
||||||
/* See comment above; this saves disk arm motion */
|
/* See comment above; this saves disk arm motion */
|
||||||
if (!ostream) {
|
if (!ostream) {
|
||||||
/* Seems like an abstraction violation, eh? Well it's OK! */
|
/* Seems like an abstraction violation, eh? Well it's OK! */
|
||||||
ostream = fopen(abfd->filename, "wb");
|
ostream = fopen(abfd->filename, FOPEN_WB);
|
||||||
if (!ostream) {
|
if (!ostream) {
|
||||||
perror(abfd->filename);
|
perror(abfd->filename);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -580,7 +599,7 @@ do_quick_append(archive_filename, files_to_append)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ofile = fopen(archive_filename, "a+b");
|
ofile = fopen(archive_filename, FOPEN_AUB);
|
||||||
if (ofile == NULL) {
|
if (ofile == NULL) {
|
||||||
perror(program_name);
|
perror(program_name);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -621,7 +640,7 @@ do_quick_append(archive_filename, files_to_append)
|
||||||
|
|
||||||
BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
|
BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
|
||||||
|
|
||||||
ifile = fopen(*files_to_append, "rb");
|
ifile = fopen(*files_to_append, FOPEN_RB);
|
||||||
if (ifile == NULL)
|
if (ifile == NULL)
|
||||||
bfd_perror(program_name);
|
bfd_perror(program_name);
|
||||||
|
|
||||||
|
@ -940,5 +959,8 @@ void
|
||||||
print_descr(abfd)
|
print_descr(abfd)
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
{
|
{
|
||||||
print_arelt_descr(abfd, verbose);
|
print_arelt_descr(stdout,abfd, verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
%{
|
||||||
|
/* arlex.l - Strange script language lexer */
|
||||||
|
|
||||||
|
/* Copyright (C) 1992 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GNU Binutils.
|
||||||
|
|
||||||
|
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 of the License, 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Contributed by Steve Chamberlain
|
||||||
|
sac@cygnus.com
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define DONTDECLARE_MALLOC
|
||||||
|
#include <ansidecl.h>
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include "arparse.h"
|
||||||
|
int linenumber;
|
||||||
|
%}
|
||||||
|
%%
|
||||||
|
|
||||||
|
"ADDLIB" { return ADDLIB; }
|
||||||
|
"ADDMOD" { return ADDMOD; }
|
||||||
|
"CLEAR" { return CLEAR; }
|
||||||
|
"CREATE" { return CREATE; }
|
||||||
|
"DELETE" { return DELETE; }
|
||||||
|
"DIRECTORY" { return DIRECTORY; }
|
||||||
|
"END" { return END; }
|
||||||
|
"EXTRACT" { return EXTRACT; }
|
||||||
|
"FULLDIR" { return FULLDIR; }
|
||||||
|
"HELP" { return HELP; }
|
||||||
|
"LIST" { return LIST; }
|
||||||
|
"OPEN" { return OPEN; }
|
||||||
|
"REPLACE" { return REPLACE; }
|
||||||
|
"VERBOSE" { return VERBOSE; }
|
||||||
|
"SAVE" { return SAVE; }
|
||||||
|
"addlib" { return ADDLIB; }
|
||||||
|
"addmod" { return ADDMOD; }
|
||||||
|
"clear" { return CLEAR; }
|
||||||
|
"create" { return CREATE; }
|
||||||
|
"delete" { return DELETE; }
|
||||||
|
"directory" { return DIRECTORY; }
|
||||||
|
"end" { return END; }
|
||||||
|
"extract" { return EXTRACT; }
|
||||||
|
"fulldir" { return FULLDIR; }
|
||||||
|
"help" { return HELP; }
|
||||||
|
"list" { return LIST; }
|
||||||
|
"open" { return OPEN; }
|
||||||
|
"replace" { return REPLACE; }
|
||||||
|
"verbose" { return VERBOSE; }
|
||||||
|
"save" { return SAVE; }
|
||||||
|
"+\n" { linenumber ++; }
|
||||||
|
"(" { return '('; }
|
||||||
|
")" { return ')'; }
|
||||||
|
"," { return ','; }
|
||||||
|
[A-Za-z0-9/$:.\-]+ {
|
||||||
|
yylval.name = strdup(yytext);
|
||||||
|
return FILENAME;
|
||||||
|
}
|
||||||
|
"*".* { }
|
||||||
|
";".* { }
|
||||||
|
" " { }
|
||||||
|
"\n" { linenumber ++; return NEWLINE; }
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
%{
|
||||||
|
/* arparse.y - Stange script language parser */
|
||||||
|
|
||||||
|
/* Copyright (C) 1992 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GNU Binutils.
|
||||||
|
|
||||||
|
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 of the License, 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Contributed by Steve Chamberlain
|
||||||
|
sac@cygnus.com
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define DONTDECLARE_MALLOC
|
||||||
|
#include "bfd.h"
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include "arsup.h"
|
||||||
|
extern int interactive;
|
||||||
|
extern bfd *inarch;
|
||||||
|
extern int verbose;
|
||||||
|
void (*command)();
|
||||||
|
FILE *listing;
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union {
|
||||||
|
char *name;
|
||||||
|
struct list *list ;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
%token NEWLINE
|
||||||
|
%token VERBOSE
|
||||||
|
%token <name> FILENAME
|
||||||
|
%token ADDLIB
|
||||||
|
%token LIST
|
||||||
|
%token ADDMOD
|
||||||
|
%token CLEAR
|
||||||
|
%token CREATE
|
||||||
|
%token DELETE
|
||||||
|
%token DIRECTORY
|
||||||
|
%token END
|
||||||
|
%token EXTRACT
|
||||||
|
%token FULLDIR
|
||||||
|
%token HELP
|
||||||
|
%token QUIT
|
||||||
|
%token REPLACE
|
||||||
|
%token SAVE
|
||||||
|
%token OPEN
|
||||||
|
|
||||||
|
%type <list> modulelist
|
||||||
|
%type <list> modulename
|
||||||
|
%type <name> optional_filename
|
||||||
|
%%
|
||||||
|
|
||||||
|
start:
|
||||||
|
{ prompt(); } session
|
||||||
|
;
|
||||||
|
|
||||||
|
session:
|
||||||
|
session command_line
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
command_line:
|
||||||
|
command NEWLINE { prompt(); }
|
||||||
|
|
||||||
|
command:
|
||||||
|
open_command
|
||||||
|
| create_command
|
||||||
|
| verbose_command
|
||||||
|
| directory_command
|
||||||
|
| addlib_command
|
||||||
|
| clear_command
|
||||||
|
| addmod_command
|
||||||
|
| save_command
|
||||||
|
| replace_command
|
||||||
|
| delete_command
|
||||||
|
| list_command
|
||||||
|
| END { return 0; }
|
||||||
|
| error
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
replace_command:
|
||||||
|
REPLACE modulename
|
||||||
|
{ ar_replace($2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
clear_command:
|
||||||
|
CLEAR
|
||||||
|
{ ar_clear(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
delete_command:
|
||||||
|
DELETE modulename
|
||||||
|
{ ar_delete($2); }
|
||||||
|
;
|
||||||
|
addmod_command:
|
||||||
|
ADDMOD modulename
|
||||||
|
{ ar_addmod($2); }
|
||||||
|
;
|
||||||
|
|
||||||
|
list_command:
|
||||||
|
LIST
|
||||||
|
{ ar_list(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
save_command:
|
||||||
|
SAVE
|
||||||
|
{ ar_save(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
open_command:
|
||||||
|
OPEN FILENAME
|
||||||
|
{ ar_open($2,0); }
|
||||||
|
;
|
||||||
|
|
||||||
|
create_command:
|
||||||
|
CREATE FILENAME
|
||||||
|
{ ar_open($2,1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
addlib_command:
|
||||||
|
ADDLIB FILENAME modulelist
|
||||||
|
{ ar_addlib($2,$3); }
|
||||||
|
;
|
||||||
|
directory_command:
|
||||||
|
DIRECTORY FILENAME modulelist optional_filename
|
||||||
|
{ ar_directory($2, $3, $4); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
optional_filename:
|
||||||
|
FILENAME
|
||||||
|
{ $$ = $1; }
|
||||||
|
| { $$ = 0; }
|
||||||
|
;
|
||||||
|
|
||||||
|
modulelist:
|
||||||
|
'(' modulename ')'
|
||||||
|
{ $$ = $2; }
|
||||||
|
|
|
||||||
|
{ $$ = 0; }
|
||||||
|
;
|
||||||
|
|
||||||
|
modulename:
|
||||||
|
modulename optcomma FILENAME
|
||||||
|
{ struct list *n = (struct list *) malloc(sizeof(struct list));
|
||||||
|
n->next = $1;
|
||||||
|
n->name = $3;
|
||||||
|
$$ = n;
|
||||||
|
}
|
||||||
|
| { $$ = 0; }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
optcomma:
|
||||||
|
','
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
verbose_command:
|
||||||
|
VERBOSE
|
||||||
|
{ verbose = !verbose; }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
yyerror(x)
|
||||||
|
char *x;
|
||||||
|
{
|
||||||
|
extern int linenumber;
|
||||||
|
printf("Synax error in archive script, line %d\n", linenumber + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,382 @@
|
||||||
|
/* arsup.c - Archive support for MRI compatibility */
|
||||||
|
|
||||||
|
/* Copyright (C) 1992 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GNU Binutils.
|
||||||
|
|
||||||
|
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 of the License, 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Contributed by Steve Chamberlain
|
||||||
|
sac@cygnus.com
|
||||||
|
|
||||||
|
This file looks after requests from arparse.y, to provide the MRI
|
||||||
|
style librarian command syntax + 1 word LIST
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "arsup.h"
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include "bucomm.h"
|
||||||
|
extern bfd *inarch;
|
||||||
|
extern int verbose;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN(map_over_list,(function, list),
|
||||||
|
void (*function) () AND
|
||||||
|
struct list *list)
|
||||||
|
|
||||||
|
{
|
||||||
|
bfd *head;
|
||||||
|
|
||||||
|
if (list == 0) {
|
||||||
|
for (head = inarch->next; head; head = head->next){
|
||||||
|
function(head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
This may appear to be a baroque way of accomplishing what we want.
|
||||||
|
however we have to iterate over the filenames in order to notice where
|
||||||
|
a filename is requested but does not exist in the archive. Ditto
|
||||||
|
mapping over each file each time -- we want to hack multiple
|
||||||
|
references.
|
||||||
|
*/
|
||||||
|
struct list *ptr = list;
|
||||||
|
|
||||||
|
for (ptr = list; ptr; ptr=ptr->next)
|
||||||
|
{
|
||||||
|
boolean found = false;
|
||||||
|
bfd *prev = inarch;
|
||||||
|
for (head = inarch->next; head; head = head->next)
|
||||||
|
{
|
||||||
|
if ((head->filename != NULL) &&
|
||||||
|
(!strcmp(ptr->name, head->filename)))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
function(head, prev);
|
||||||
|
|
||||||
|
}
|
||||||
|
prev = head;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
fprintf(stderr, "No entry %s in archive.\n", ptr->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FILE *outfile;
|
||||||
|
void
|
||||||
|
DEFUN(ar_directory_doer,(abfd),
|
||||||
|
bfd *abfd)
|
||||||
|
{
|
||||||
|
print_arelt_descr(outfile, abfd, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN(ar_directory,(ar_name, list, output),
|
||||||
|
char *ar_name AND
|
||||||
|
struct list *list AND
|
||||||
|
char *output)
|
||||||
|
{
|
||||||
|
open_inarch(ar_name);
|
||||||
|
if (output) {
|
||||||
|
outfile = fopen(output,"w");
|
||||||
|
if (outfile == 0) {
|
||||||
|
outfile =stdout;
|
||||||
|
fprintf(stderr,"Can't open file %s\n", output);
|
||||||
|
output = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
outfile = stdout;
|
||||||
|
|
||||||
|
map_over_list(ar_directory_doer, list);
|
||||||
|
bfd_close(inarch);
|
||||||
|
if (output)
|
||||||
|
fclose(outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN_VOID(prompt)
|
||||||
|
{
|
||||||
|
extern int interactive;
|
||||||
|
if (interactive)
|
||||||
|
{
|
||||||
|
printf("AR >");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN_VOID(maybequit)
|
||||||
|
{
|
||||||
|
if (!interactive)
|
||||||
|
exit(9);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bfd *obfd;
|
||||||
|
char *real_name ;
|
||||||
|
void
|
||||||
|
DEFUN(ar_open,(name, t),
|
||||||
|
char *name AND
|
||||||
|
int t)
|
||||||
|
|
||||||
|
{
|
||||||
|
char *tname = malloc(strlen(name)+10);
|
||||||
|
real_name = name;
|
||||||
|
sprintf(tname, "%s-tmp", name);
|
||||||
|
obfd = bfd_openw(tname, NULL);
|
||||||
|
|
||||||
|
if (!obfd) {
|
||||||
|
fprintf(stderr,"%s: Can't open output archive %s\n", program_name,
|
||||||
|
tname);
|
||||||
|
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!t) {
|
||||||
|
bfd **ptr;
|
||||||
|
bfd *element;
|
||||||
|
bfd *ibfd;
|
||||||
|
ibfd = bfd_openr(name, NULL);
|
||||||
|
if (bfd_check_format(ibfd, bfd_archive) != true) {
|
||||||
|
fprintf(stderr,"%s: file %s is not an archive\n", program_name,
|
||||||
|
name);
|
||||||
|
maybequit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr = &(obfd->archive_head);
|
||||||
|
element = bfd_openr_next_archived_file(ibfd, NULL);
|
||||||
|
|
||||||
|
while (element) {
|
||||||
|
*ptr = element;
|
||||||
|
ptr = &element->next;
|
||||||
|
element = bfd_openr_next_archived_file(ibfd, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bfd_set_format(obfd, bfd_archive);
|
||||||
|
|
||||||
|
obfd->has_armap = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN(ar_addlib_doer, (abfd, prev),
|
||||||
|
bfd *abfd AND
|
||||||
|
bfd *prev)
|
||||||
|
{
|
||||||
|
/* Add this module to the output bfd */
|
||||||
|
|
||||||
|
prev->next = abfd->next;
|
||||||
|
abfd->next = obfd->archive_head;
|
||||||
|
obfd->archive_head = abfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN(ar_addlib, (name, list),
|
||||||
|
char *name AND
|
||||||
|
struct list *list)
|
||||||
|
{
|
||||||
|
if (!obfd) {
|
||||||
|
fprintf(stderr, "%s: no output archive specified yet\n", program_name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (open_inarch(name) ) {
|
||||||
|
map_over_list(ar_addlib_doer, list);
|
||||||
|
}
|
||||||
|
/* Don't close the bfd, since it will make the elements disasppear */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN(ar_addmod, (list),
|
||||||
|
struct list *list)
|
||||||
|
{
|
||||||
|
if (!obfd) {
|
||||||
|
fprintf(stderr, "%s: no open output archive\n", program_name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (list) {
|
||||||
|
bfd *abfd = bfd_openr(list->name, NULL);
|
||||||
|
if (!abfd) {
|
||||||
|
fprintf(stderr,"%s: can't open file %s\n", program_name,
|
||||||
|
list->name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
abfd->next = obfd->archive_head;
|
||||||
|
obfd->archive_head = abfd;
|
||||||
|
}
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN_VOID(ar_clear)
|
||||||
|
{
|
||||||
|
if (obfd)
|
||||||
|
obfd->archive_head = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN(ar_delete, (list),
|
||||||
|
struct list *list)
|
||||||
|
{
|
||||||
|
if (!obfd) {
|
||||||
|
fprintf(stderr, "%s: no open output archive\n", program_name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (list) {
|
||||||
|
/* Find this name in the archive */
|
||||||
|
bfd *member = obfd->archive_head;
|
||||||
|
bfd **prev = &(obfd->archive_head);
|
||||||
|
int found = 0;
|
||||||
|
while (member) {
|
||||||
|
if (strcmp(member->filename, list->name) == 0) {
|
||||||
|
*prev = member->next;
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev = &(member->next);
|
||||||
|
}
|
||||||
|
member = member->next;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
fprintf(stderr,"%s: can't find module file %s\n", program_name,
|
||||||
|
list->name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN_VOID(ar_save)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!obfd) {
|
||||||
|
fprintf(stderr, "%s: no open output archive\n", program_name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bfd_close(obfd);
|
||||||
|
unlink(real_name);
|
||||||
|
link(obfd->filename, real_name);
|
||||||
|
unlink(obfd->filename);
|
||||||
|
obfd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFUN(ar_replace, (list),
|
||||||
|
struct list *list)
|
||||||
|
{
|
||||||
|
if (!obfd) {
|
||||||
|
fprintf(stderr, "%s: no open output archive\n", program_name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (list) {
|
||||||
|
/* Find this name in the archive */
|
||||||
|
bfd *member = obfd->archive_head;
|
||||||
|
bfd **prev = &(obfd->archive_head);
|
||||||
|
int found = 0;
|
||||||
|
while (member)
|
||||||
|
{
|
||||||
|
if (strcmp(member->filename, list->name) == 0)
|
||||||
|
{
|
||||||
|
/* Found the one to replace */
|
||||||
|
bfd *abfd = bfd_openr(list->name, 0);
|
||||||
|
if (!abfd)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: can't open file %s\n", program_name, list->name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*prev = abfd;
|
||||||
|
abfd->next = member->next;
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev = &(member->next);
|
||||||
|
}
|
||||||
|
member = member->next;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
bfd *abfd = bfd_openr(list->name, 0);
|
||||||
|
fprintf(stderr,"%s: can't find module file %s\n", program_name,
|
||||||
|
list->name);
|
||||||
|
if (!abfd)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: can't open file %s\n", program_name, list->name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*prev = abfd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And I added this one */
|
||||||
|
void
|
||||||
|
DEFUN_VOID(ar_list)
|
||||||
|
{
|
||||||
|
if (!obfd)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: no open output archive\n", program_name);
|
||||||
|
maybequit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bfd *abfd;
|
||||||
|
outfile = stdout;
|
||||||
|
verbose =1 ;
|
||||||
|
printf("Current open archive is %s\n", obfd->filename);
|
||||||
|
for (abfd = obfd->archive_head;
|
||||||
|
abfd != (bfd *)NULL;
|
||||||
|
abfd = abfd->next)
|
||||||
|
{
|
||||||
|
ar_directory_doer(abfd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void EXFUN( map_over_members, (void (*function) (), char **files, int count));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct list {
|
||||||
|
char *name;
|
||||||
|
struct list *next;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
void EXFUN(maybequit,(void));
|
||||||
|
void EXFUN(prompt,(void));
|
||||||
|
void EXFUN(ar_clear,(void));
|
||||||
|
void EXFUN(ar_replace,(struct list *));
|
||||||
|
void EXFUN(ar_delete,(struct list *));
|
||||||
|
void EXFUN(ar_save, (void));
|
||||||
|
void EXFUN(ar_list, (void));
|
||||||
|
void EXFUN(ar_open, (char *, int));
|
||||||
|
void EXFUN(ar_directory,(char *, struct list *, char *));
|
||||||
|
void EXFUN(ar_addmod, (struct list *));
|
||||||
|
void EXFUN(ar_addlib, (char *, struct list *));
|
||||||
|
int interactive;
|
||||||
|
|
||||||
|
int yyparse();
|
Loading…
Reference in New Issue