version 1.1, 1995/10/18 08:45:59 |
version 1.2, 1996/02/03 12:12:26 |
|
|
%{ |
%{ |
/* |
/* |
* Copyright (c) 1983, 1993 |
* Copyright (c) 1993 Michael A. Cooper |
* The Regents of the University of California. All rights reserved. |
* Copyright (c) 1993 Regents of the University of California. |
|
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* modification, are permitted provided that the following conditions |
|
|
*/ |
*/ |
|
|
#ifndef lint |
#ifndef lint |
/* from: static char sccsid[] = "@(#)gram.y 8.1 (Berkeley) 6/9/93"; */ |
static char RCSid[] = |
static char *rcsid = "$Id$"; |
"$Id$"; |
|
|
|
static char *sccsid = "@(#)gram.y 5.2 (Berkeley) 85/06/21"; |
|
|
|
static char copyright[] = |
|
"@(#) Copyright (c) 1983 Regents of the University of California.\n\ |
|
All rights reserved.\n"; |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
|
/* |
|
* Tell defs.h not to include y.tab.h |
|
*/ |
|
#ifndef yacc |
|
#define yacc |
|
#endif |
|
|
#include "defs.h" |
#include "defs.h" |
|
|
|
static struct namelist *addnl(), *subnl(), *andnl(); |
struct cmd *cmds = NULL; |
struct cmd *cmds = NULL; |
struct cmd *last_cmd; |
struct cmd *last_cmd; |
struct namelist *last_n; |
struct namelist *last_n; |
struct subcmd *last_sc; |
struct subcmd *last_sc; |
|
int parendepth = 0; |
|
|
static char *makestr __P((char *)); |
|
|
|
%} |
%} |
|
|
%term EQUAL 1 |
%term ARROW 1 |
%term LP 2 |
%term COLON 2 |
%term RP 3 |
%term DCOLON 3 |
%term SM 4 |
%term NAME 4 |
%term ARROW 5 |
%term STRING 5 |
%term COLON 6 |
%term INSTALL 6 |
%term DCOLON 7 |
%term NOTIFY 7 |
%term NAME 8 |
%term EXCEPT 8 |
%term STRING 9 |
%term PATTERN 9 |
%term INSTALL 10 |
%term SPECIAL 10 |
%term NOTIFY 11 |
%term CMDSPECIAL 11 |
%term EXCEPT 12 |
%term OPTION 12 |
%term PATTERN 13 |
|
%term SPECIAL 14 |
|
%term OPTION 15 |
|
|
|
%union { |
%union { |
int intval; |
opt_t optval; |
char *string; |
char *string; |
struct subcmd *subcmd; |
struct subcmd *subcmd; |
struct namelist *namel; |
struct namelist *namel; |
} |
} |
|
|
%type <intval> OPTION, options |
%type <optval> OPTION, options |
%type <string> NAME, STRING |
%type <string> NAME, STRING |
%type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd |
%type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, CMDSPECIAL, cmdlist, cmd |
%type <namel> namelist, names, opt_namelist |
%type <namel> namelist, names, opt_namelist nlist |
|
|
%% |
%% |
|
|
|
|
| file command |
| file command |
; |
; |
|
|
command: NAME EQUAL namelist = { |
command: NAME '=' namelist = { |
(void) lookup($1, INSERT, $3); |
(void) lookup($1, INSERT, $3); |
} |
} |
| namelist ARROW namelist cmdlist = { |
| namelist ARROW namelist cmdlist = { |
insert(NULL, $1, $3, $4); |
insert((char *)NULL, $1, $3, $4); |
} |
} |
| NAME COLON namelist ARROW namelist cmdlist = { |
| NAME COLON namelist ARROW namelist cmdlist = { |
insert($1, $3, $5, $6); |
insert($1, $3, $5, $6); |
} |
} |
| namelist DCOLON NAME cmdlist = { |
| namelist DCOLON NAME cmdlist = { |
append(NULL, $1, $3, $4); |
append((char *)NULL, $1, $3, $4); |
} |
} |
| NAME COLON namelist DCOLON NAME cmdlist = { |
| NAME COLON namelist DCOLON NAME cmdlist = { |
append($1, $3, $5, $6); |
append($1, $3, $5, $6); |
|
|
| error |
| error |
; |
; |
|
|
namelist: NAME = { |
namelist: nlist { |
|
$$ = $1; |
|
} |
|
| nlist '-' nlist { |
|
$$ = subnl($1, $3); |
|
} |
|
| nlist '+' nlist { |
|
$$ = addnl($1, $3); |
|
} |
|
| nlist '&' nlist { |
|
$$ = andnl($1, $3); |
|
} |
|
; |
|
|
|
nlist: NAME = { |
$$ = makenl($1); |
$$ = makenl($1); |
} |
} |
| LP names RP = { |
| '(' names ')' = { |
$$ = $2; |
$$ = $2; |
} |
} |
; |
; |
|
|
} |
} |
; |
; |
|
|
cmd: INSTALL options opt_namelist SM = { |
cmd: INSTALL options opt_namelist ';' = { |
register struct namelist *nl; |
register struct namelist *nl; |
|
|
$1->sc_options = $2 | options; |
$1->sc_options = $2 | options; |
|
|
} |
} |
$$ = $1; |
$$ = $1; |
} |
} |
| NOTIFY namelist SM = { |
| NOTIFY namelist ';' = { |
if ($2 != NULL) |
if ($2 != NULL) |
$1->sc_args = expand($2, E_VARS); |
$1->sc_args = expand($2, E_VARS); |
$$ = $1; |
$$ = $1; |
} |
} |
| EXCEPT namelist SM = { |
| EXCEPT namelist ';' = { |
if ($2 != NULL) |
if ($2 != NULL) |
$1->sc_args = expand($2, E_ALL); |
$1->sc_args = expand($2, E_ALL); |
$$ = $1; |
$$ = $1; |
} |
} |
| PATTERN namelist SM = { |
| PATTERN namelist ';' = { |
struct namelist *nl; |
struct namelist *nl; |
char *cp, *re_comp(); |
char *cp, *re_comp(); |
|
|
|
|
$1->sc_args = expand($2, E_VARS); |
$1->sc_args = expand($2, E_VARS); |
$$ = $1; |
$$ = $1; |
} |
} |
| SPECIAL opt_namelist STRING SM = { |
| SPECIAL opt_namelist STRING ';' = { |
if ($2 != NULL) |
if ($2 != NULL) |
$1->sc_args = expand($2, E_ALL); |
$1->sc_args = expand($2, E_ALL); |
$1->sc_name = $3; |
$1->sc_name = $3; |
$$ = $1; |
$$ = $1; |
} |
} |
|
| CMDSPECIAL opt_namelist STRING ';' = { |
|
if ($2 != NULL) |
|
$1->sc_args = expand($2, E_ALL); |
|
$1->sc_name = $3; |
|
$$ = $1; |
|
} |
; |
; |
|
|
options: /* VOID */ = { |
options: /* VOID */ = { |
|
|
int yylineno = 1; |
int yylineno = 1; |
extern FILE *fin; |
extern FILE *fin; |
|
|
int |
|
yylex() |
yylex() |
{ |
{ |
static char yytext[INMAX]; |
static char yytext[INMAX]; |
|
|
goto again; |
goto again; |
|
|
case '=': /* EQUAL */ |
case '=': /* EQUAL */ |
return(EQUAL); |
case ';': /* SM */ |
|
case '+': |
|
case '&': |
|
return(c); |
|
|
case '(': /* LP */ |
case '(': /* LP */ |
return(LP); |
++parendepth; |
|
return(c); |
|
|
case ')': /* RP */ |
case ')': /* RP */ |
return(RP); |
--parendepth; |
|
return(c); |
|
|
case ';': /* SM */ |
|
return(SM); |
|
|
|
case '-': /* -> */ |
case '-': /* -> */ |
if ((c = getc(fin)) == '>') |
if ((c = getc(fin)) == '>') |
return(ARROW); |
return(ARROW); |
ungetc(c, fin); |
(void) ungetc(c, fin); |
c = '-'; |
c = '-'; |
break; |
break; |
|
|
|
|
case ':': /* : or :: */ |
case ':': /* : or :: */ |
if ((c = getc(fin)) == ':') |
if ((c = getc(fin)) == ':') |
return(DCOLON); |
return(DCOLON); |
ungetc(c, fin); |
(void) ungetc(c, fin); |
return(COLON); |
return(COLON); |
} |
} |
cp1 = yytext; |
cp1 = yytext; |
|
|
if (c == '\\') { |
if (c == '\\') { |
if ((c = getc(fin)) != EOF) { |
if ((c = getc(fin)) != EOF) { |
if (any(c, quotechars)) |
if (any(c, quotechars)) |
c |= QUOTE; |
*cp1++ = QUOTECHAR; |
} else { |
} else { |
*cp1++ = '\\'; |
*cp1++ = '\\'; |
break; |
break; |
|
|
*cp1++ = c; |
*cp1++ = c; |
c = getc(fin); |
c = getc(fin); |
if (c == EOF || any(c, " \"'\t()=;:\n")) { |
if (c == EOF || any(c, " \"'\t()=;:\n")) { |
ungetc(c, fin); |
(void) ungetc(c, fin); |
break; |
break; |
} |
} |
} |
} |
*cp1 = '\0'; |
*cp1 = '\0'; |
if (yytext[0] == '-' && yytext[2] == '\0') { |
if (yytext[0] == '-' && yytext[1] == CNULL) |
|
return '-'; |
|
if (yytext[0] == '-' && parendepth <= 0) { |
|
opt_t opt = 0; |
|
static char ebuf[BUFSIZ]; |
|
|
switch (yytext[1]) { |
switch (yytext[1]) { |
case 'b': |
case 'o': |
yylval.intval = COMPARE; |
if (parsedistopts(&yytext[2], &opt, TRUE)) { |
return(OPTION); |
(void) sprintf(ebuf, |
|
"Bad distfile options \"%s\".", |
|
&yytext[2]); |
|
yyerror(ebuf); |
|
} |
|
break; |
|
|
case 'R': |
/* |
yylval.intval = REMOVE; |
* These options are obsoleted by -o. |
return(OPTION); |
*/ |
|
case 'b': opt = DO_COMPARE; break; |
|
case 'R': opt = DO_REMOVE; break; |
|
case 'v': opt = DO_VERIFY; break; |
|
case 'w': opt = DO_WHOLE; break; |
|
case 'y': opt = DO_YOUNGER; break; |
|
case 'h': opt = DO_FOLLOW; break; |
|
case 'i': opt = DO_IGNLNKS; break; |
|
case 'q': opt = DO_QUIET; break; |
|
case 'x': opt = DO_NOEXEC; break; |
|
case 'N': opt = DO_CHKNFS; break; |
|
case 'O': opt = DO_CHKREADONLY; break; |
|
case 's': opt = DO_SAVETARGETS; break; |
|
case 'r': opt = DO_NODESCEND; break; |
|
|
case 'v': |
default: |
yylval.intval = VERIFY; |
(void) sprintf(ebuf, "Unknown option \"%s\".", yytext); |
return(OPTION); |
yyerror(ebuf); |
|
|
case 'w': |
|
yylval.intval = WHOLE; |
|
return(OPTION); |
|
|
|
case 'y': |
|
yylval.intval = YOUNGER; |
|
return(OPTION); |
|
|
|
case 'h': |
|
yylval.intval = FOLLOW; |
|
return(OPTION); |
|
|
|
case 'i': |
|
yylval.intval = IGNLNKS; |
|
return(OPTION); |
|
} |
} |
|
|
|
yylval.optval = opt; |
|
return(OPTION); |
} |
} |
if (!strcmp(yytext, "install")) |
if (!strcmp(yytext, "install")) |
c = INSTALL; |
c = INSTALL; |
|
|
c = PATTERN; |
c = PATTERN; |
else if (!strcmp(yytext, "special")) |
else if (!strcmp(yytext, "special")) |
c = SPECIAL; |
c = SPECIAL; |
|
else if (!strcmp(yytext, "cmdspecial")) |
|
c = CMDSPECIAL; |
else { |
else { |
yylval.string = makestr(yytext); |
yylval.string = makestr(yytext); |
return(NAME); |
return(NAME); |
|
|
return(c); |
return(c); |
} |
} |
|
|
int |
/* |
any(c, str) |
* XXX We should use strchr(), but most versions can't handle |
|
* some of the characters we use. |
|
*/ |
|
extern int any(c, str) |
register int c; |
register int c; |
register char *str; |
register char *str; |
{ |
{ |
|
|
/* |
/* |
* Insert or append ARROW command to list of hosts to be updated. |
* Insert or append ARROW command to list of hosts to be updated. |
*/ |
*/ |
void |
|
insert(label, files, hosts, subcmds) |
insert(label, files, hosts, subcmds) |
char *label; |
char *label; |
struct namelist *files, *hosts; |
struct namelist *files, *hosts; |
struct subcmd *subcmds; |
struct subcmd *subcmds; |
{ |
{ |
register struct cmd *c, *prev, *nc; |
register struct cmd *c, *prev, *nc; |
register struct namelist *h; |
register struct namelist *h, *lasth; |
|
|
|
debugmsg(DM_CALL, "insert(%s, %x, %x, %x) start, files = %s", |
|
label == NULL ? "(null)" : label, |
|
files, hosts, subcmds, getnlstr(files)); |
|
|
files = expand(files, E_VARS|E_SHELL); |
files = expand(files, E_VARS|E_SHELL); |
hosts = expand(hosts, E_ALL); |
hosts = expand(hosts, E_ALL); |
for (h = hosts; h != NULL; free(h), h = h->n_next) { |
for (h = hosts; h != NULL; lasth = h, h = h->n_next, |
|
free((char *)lasth)) { |
/* |
/* |
* Search command list for an update to the same host. |
* Search command list for an update to the same host. |
*/ |
*/ |
|
|
* Insert new command to update host. |
* Insert new command to update host. |
*/ |
*/ |
nc = ALLOC(cmd); |
nc = ALLOC(cmd); |
if (nc == NULL) |
|
fatal("ran out of memory\n"); |
|
nc->c_type = ARROW; |
nc->c_type = ARROW; |
nc->c_name = h->n_name; |
nc->c_name = h->n_name; |
nc->c_label = label; |
nc->c_label = label; |
nc->c_files = files; |
nc->c_files = files; |
nc->c_cmds = subcmds; |
nc->c_cmds = subcmds; |
|
nc->c_flags = 0; |
nc->c_next = c; |
nc->c_next = c; |
if (prev == NULL) |
if (prev == NULL) |
cmds = nc; |
cmds = nc; |
|
|
* Append DCOLON command to the end of the command list since these are always |
* Append DCOLON command to the end of the command list since these are always |
* executed in the order they appear in the distfile. |
* executed in the order they appear in the distfile. |
*/ |
*/ |
void |
|
append(label, files, stamp, subcmds) |
append(label, files, stamp, subcmds) |
char *label; |
char *label; |
struct namelist *files; |
struct namelist *files; |
|
|
register struct cmd *c; |
register struct cmd *c; |
|
|
c = ALLOC(cmd); |
c = ALLOC(cmd); |
if (c == NULL) |
|
fatal("ran out of memory\n"); |
|
c->c_type = DCOLON; |
c->c_type = DCOLON; |
c->c_name = stamp; |
c->c_name = stamp; |
c->c_label = label; |
c->c_label = label; |
|
|
/* |
/* |
* Error printing routine in parser. |
* Error printing routine in parser. |
*/ |
*/ |
void |
|
yyerror(s) |
yyerror(s) |
char *s; |
char *s; |
{ |
{ |
++nerrs; |
error("Error in distfile: line %d: %s", yylineno, s); |
fflush(stdout); |
|
fprintf(stderr, "rdist: line %d: %s\n", yylineno, s); |
|
} |
} |
|
|
/* |
/* |
* Return a copy of the string. |
* Return a copy of the string. |
*/ |
*/ |
static char * |
char * |
makestr(str) |
makestr(str) |
char *str; |
char *str; |
{ |
{ |
register char *cp, *s; |
char *cp; |
|
|
str = cp = malloc(strlen(s = str) + 1); |
cp = strdup(str); |
if (cp == NULL) |
if (cp == NULL) |
fatal("ran out of memory\n"); |
fatalerr("ran out of memory"); |
while (*cp++ = *s++) |
|
; |
return(cp); |
return(str); |
|
} |
} |
|
|
/* |
/* |
|
|
{ |
{ |
register struct namelist *nl; |
register struct namelist *nl; |
|
|
|
debugmsg(DM_CALL, "makenl(%s)", name == NULL ? "null" : name); |
|
|
nl = ALLOC(namelist); |
nl = ALLOC(namelist); |
if (nl == NULL) |
|
fatal("ran out of memory\n"); |
|
nl->n_name = name; |
nl->n_name = name; |
nl->n_next = NULL; |
nl->n_next = NULL; |
|
|
return(nl); |
return(nl); |
} |
} |
|
|
|
|
/* |
/* |
|
* Is the name p in the namelist nl? |
|
*/ |
|
static int |
|
innl(nl, p) |
|
struct namelist *nl; |
|
char *p; |
|
{ |
|
for ( ; nl; nl = nl->n_next) |
|
if (!strcmp(p, nl->n_name)) |
|
return(1); |
|
return(0); |
|
} |
|
|
|
/* |
|
* Join two namelists. |
|
*/ |
|
static struct namelist * |
|
addnl(n1, n2) |
|
struct namelist *n1, *n2; |
|
{ |
|
struct namelist *nl, *prev; |
|
|
|
n1 = expand(n1, E_VARS); |
|
n2 = expand(n2, E_VARS); |
|
for (prev = NULL, nl = NULL; n1; n1 = n1->n_next, prev = nl) { |
|
nl = makenl(n1->n_name); |
|
nl->n_next = prev; |
|
} |
|
for (; n2; n2 = n2->n_next) |
|
if (!innl(nl, n2->n_name)) { |
|
nl = makenl(n2->n_name); |
|
nl->n_next = prev; |
|
prev = nl; |
|
} |
|
return(prev); |
|
} |
|
|
|
/* |
|
* Copy n1 except for elements that are in n2. |
|
*/ |
|
static struct namelist * |
|
subnl(n1, n2) |
|
struct namelist *n1, *n2; |
|
{ |
|
struct namelist *nl, *prev; |
|
|
|
n1 = expand(n1, E_VARS); |
|
n2 = expand(n2, E_VARS); |
|
for (prev = NULL; n1; n1 = n1->n_next) |
|
if (!innl(n2, n1->n_name)) { |
|
nl = makenl(n1->n_name); |
|
nl->n_next = prev; |
|
prev = nl; |
|
} |
|
return(prev); |
|
} |
|
|
|
/* |
|
* Copy all items of n1 that are also in n2. |
|
*/ |
|
static struct namelist * |
|
andnl(n1, n2) |
|
struct namelist *n1, *n2; |
|
{ |
|
struct namelist *nl, *prev; |
|
|
|
n1 = expand(n1, E_VARS); |
|
n2 = expand(n2, E_VARS); |
|
for (prev = NULL; n1; n1 = n1->n_next) |
|
if (innl(n2, n1->n_name)) { |
|
nl = makenl(n1->n_name); |
|
nl->n_next = prev; |
|
prev = nl; |
|
} |
|
return(prev); |
|
} |
|
|
|
/* |
* Make a sub command for lists of variables, commands, etc. |
* Make a sub command for lists of variables, commands, etc. |
*/ |
*/ |
struct subcmd * |
extern struct subcmd * |
makesubcmd(type) |
makesubcmd(type) |
int type; |
int type; |
{ |
{ |
register struct subcmd *sc; |
register struct subcmd *sc; |
|
|
sc = ALLOC(subcmd); |
sc = ALLOC(subcmd); |
if (sc == NULL) |
|
fatal("ran out of memory\n"); |
|
sc->sc_type = type; |
sc->sc_type = type; |
sc->sc_args = NULL; |
sc->sc_args = NULL; |
sc->sc_next = NULL; |
sc->sc_next = NULL; |
sc->sc_name = NULL; |
sc->sc_name = NULL; |
|
|
return(sc); |
return(sc); |
} |
} |