home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.shrubbery.net
/
2015-02-07.ftp.shrubbery.net.tar
/
ftp.shrubbery.net
/
pub
/
foad
/
foad-0.3.tar.gz
/
foad-0.3.tar
/
foad-0.3
/
parser.y
< prev
next >
Wrap
Text File
|
2001-09-06
|
7KB
|
384 lines
%{
#include "foad.h"
#include <sys/stat.h>
extern char *progname, /* program's name */
*c_bcc,
*c_from,
*c_cc,
*c_to;
extern s_addresses bcc,
from,
cc,
to;
extern int debug,
negate;
#define YYDEBUG 1 /* include debugging */
#define YYERROR_VERBOSE 1
#define Y_DEBUG (debug > 1)
%}
/* declarations */
%union {
char *cptr;
}
%token <cptr> T_BCC T_BCC_CONT
%token <cptr> T_FROM
%token <cptr> T_CC T_CC_CONT
%token <cptr> T_TO T_TO_CONT
%token T_CONT T_LINE
/* grammar */
%start headers
%%
headers: stmts
{
}
;
stmts: stmt
| stmts stmt
;
stmt: bcc_stmt
| from_stmt
| to_stmt
| cc_stmt
| lines
| '\n'
;
lines: line
| lines line
;
line: T_LINE '\n'
{
if (Y_DEBUG)
fprintf(stderr, "%s: parser line\n", progname);
}
| T_CONT '\n'
{
if (Y_DEBUG)
fprintf(stderr, "%s: parser continue\n", progname);
}
;
bcc_stmt: bcc_bits
| bcc_stmt bcc_bits
;
bcc_bits: T_BCC '\n'
{
if (c_bcc)
append(&c_bcc, ",");
append(&c_bcc, $1);
if (Y_DEBUG)
fprintf(stderr, "%s: parser BCC: %s\n", progname, $1);
free($1);
}
| T_BCC_CONT '\n'
{
append(&c_bcc, $1);
if (Y_DEBUG)
fprintf(stderr, "%s: parser BCC continue: %s\n", progname, $1);
free($1);
}
;
from_stmt: T_FROM '\n'
{
append(&c_from, $1);
if (Y_DEBUG)
fprintf(stderr, "%s: parser FROM: %s\n", progname, $1);
free($1);
}
;
cc_stmt: cc_bits
| cc_stmt cc_bits
;
cc_bits: T_CC '\n'
{
if (c_cc)
append(&c_cc, ",");
append(&c_cc, $1);
if (Y_DEBUG)
fprintf(stderr, "%s: parser CC: %s\n", progname, $1);
free($1);
}
| T_CC_CONT '\n'
{
append(&c_cc, $1);
if (Y_DEBUG)
fprintf(stderr, "%s: parser CC continue: %s\n", progname, $1);
free($1);
}
;
to_stmt: to_bits
| to_stmt to_bits
;
to_bits: T_TO '\n'
{
if (c_to)
append(&c_to, ",");
append(&c_to, $1);
if (Y_DEBUG)
fprintf(stderr, "%s: parser TO: %s\n", progname, $1);
free($1);
}
| T_TO_CONT '\n'
{
append(&c_to, $1);
if (Y_DEBUG)
fprintf(stderr, "%s: parser TO continue: %s\n", progname, $1);
free($1);
}
;
%%
/* C */
/*
function: int read_header()
description: use the parser to read the mail headers from stdin, then
split() them
returns: non-zero on parser error
*/
int
read_header(void)
{
extern FILE *yyin;
int val = 0;
yyin = stdin;
val = yyparse();
if (debug) {
if (c_from)
fprintf(stderr, " c_from = %s\n", c_from);
if (c_to)
fprintf(stderr, " c_to = %s\n", c_to);
if (c_cc)
fprintf(stderr, " c_cc = %s\n", c_cc);
if (c_bcc)
fprintf(stderr, " c_bcc = %s\n", c_bcc);
}
if (! val) {
split(c_from, &from);
split(c_to, &to);
split(c_cc, &cc);
split(c_bcc, &bcc);
}
return(val);
}
/*
function: int append(dest string **, string *)
description: append string to the of dest string
returns: NULL on error
*/
int
append(char **dst, char *s)
{
char *new;
int len;
if (s == NULL)
return(0);
while (*s == ' ' || *s == '\t') { s++; }
if (*dst == NULL)
len = strlen(s) + 2;
else
len = strlen(*dst) + strlen(s) + 2;
if ((new = malloc(len)) == NULL) {
fprintf(stderr, "%s: malloc failure: %s\n", progname, strerror(errno));
exit(1 ^ negate);
}
bzero(new, len);
if (*dst != NULL)
strcpy(new, *dst);
strcat(new, s);
free(*dst);
*dst = new;
return(0);
}
/*
function: int lappend(linked list *, node *)
description: append a linked list node to linked list
returns: NULL on error
*/
int
lappend(struct s_addresses *dst, node *n)
{
node *next;
if (dst->next == NULL) {
dst->next = n;
} else {
next = dst->next;
while (next) {
if (next->next == NULL) {
next->next = n;
break;
} else
next = next->next;
}
}
return(0);
}
/*
function: int split(header string *, per-header linked list *)
description: split a header (from/to/cc/bcc) into the address portion
only and add it to the linked list (for the header)
returns: exit on error
*/
int
split(char *a, s_addresses *dst)
{
char *comma,
*left,
*quote;
int end;
node *new = NULL;
if (a == NULL)
return(0);
/* string quoted "strings" */
for (;;) {
if ((quote = index(a, '"')) == NULL)
break;
if ((comma = index(quote + 1, '"')) == NULL) {
fprintf(stderr, "%s: apparent address format error, unmatched \"s:"
" %s\n", progname, a);
exit(1 ^ negate);
}
strcpy(quote, comma + 1);
}
/* string quoted (strings) */
for (;;) {
if ((quote = index(a, '(')) == NULL)
break;
if ((comma = index(quote + 1, ')')) == NULL) {
fprintf(stderr, "%s: apparent address format error, unmatched ()s:"
" %s\n", progname, a);
exit(1 ^ negate);
}
strcpy(quote, comma + 1);
}
/* strip ' ;' or ': ;' constructs */
left = a;
for (;;) {
if ((comma = index(left, ';')) == NULL)
break;
quote = comma;
/* backup until we find a ':' */
while (quote > a && *(quote - 1) != ':') {
quote--;
}
if (quote > a && *(quote - 1) == ':') {
/* strip ": ;" */
strcpy(quote, comma);
*quote = ',';
left = quote;
} else {
/* strip ";" */
strcpy(comma, comma + 1);
left = comma;
}
}
/* strip spaces at EOL and before commas */
end = strlen(a) - 1;
while (*(a + end) == ' ' || *(a + end) == '\t') {
*(a + end) = '\0';
end--;
}
left = a;
while ((comma = index(left, ',')) != NULL) {
quote = comma;
while (*(quote - 1) == ' ' || *(quote - 1) == '\t') {
quote--;
}
if (*quote == ' ' || *quote == '\t')
strcpy(quote, comma);
left = quote + 1;
}
/* split *a into individual addresses */
end = 0;
for (;;) {
/* skip leading space */
while (*a == ' ' || *a == '\t') { a++; }
if (a == NULL)
break;
/* new space */
if (new == NULL) {
if ((new = malloc(sizeof(node))) == NULL) {
fprintf(stderr, "%s: malloc failure: %s\n", progname,
strerror(errno));
exit(1 ^ negate);
}
bzero((void *) new, sizeof(node));
}
/* should be left with addresses separated by commas */
if ((comma = index(a, ',')) != NULL) {
*comma = '\0';
} else {
comma = a + strlen(a);
end = 1;
}
if (*(comma - 1) == '>') {
*(comma - 1) = '\0';
if ((left = strrchr(a, '<')) == NULL) {
fprintf(stderr, "%s: apparent address format error: %s\n",
progname, a);
exit(1 ^ negate);
}
left++;
if (comma - left <= 0)
goto SKIP;
} else if ((left = strrchr(a, ' ')) != NULL) {
left++;
}
if (left == NULL)
left = a;
if (strlen(left) == 0)
goto SKIP;
if (debug > 1)
fprintf(stderr, "%s: split() adding: %s\n", progname, left);
new->addr = strdup(left);
lappend(dst, new); new = NULL;
SKIP: if (end)
break;
a = comma + 1;
}
if (new)
free(new);
return(0);
}