home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume1 / 8710 / 19 < prev    next >
Internet Message Format  |  1990-07-13  |  22KB

  1. Path: uunet!seismo!sundc!pitstop!sun!amdcad!ames!necntc!ncoast!allbery
  2. From: david@ms.uky.edu (David Herron -- Resident E-mail Hack)
  3. Newsgroups: comp.sources.misc
  4. Subject: RFC822 parser in Yacc
  5. Message-ID: <4959@ncoast.UUCP>
  6. Date: 29 Oct 87 04:10:48 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Organization: U of Ky, Math. Sciences, Lexington KY
  9. Lines: 918
  10. Approved: allbery@ncoast.UUCP
  11. X-Archive: comp.sources.misc/8710/19
  12.  
  13. Brandon,
  14.  
  15. Enclosed is something I've received about 30 requests for.  Rich felt
  16. it wasn't "clean" enough just yet to go through sources.unix -- so here
  17. it is.  The intention is that someone take it and insert it into some
  18. program or some such and have it go through comp.sources.unix that
  19. way.
  20.  
  21. Note that while it isn't truly mine, that the heredity is fully
  22. documented and nobody is making restricting claims on the source.
  23. In fact, I think everybody involved would URGE this to be incorporated
  24. into something larger.  I personally would like to see a fancier 
  25. version of this be sent through sources.unix just to ensure that
  26. a more "pure" form of the grammar be in the archives, aside from
  27. this being used in some larger program.
  28.  
  29.  
  30.     -- David
  31.  
  32. #! /bin/sh
  33. : This is a shell archive, meaning:
  34. : 1. Remove everything above the '#! /bin/sh' line.
  35. : 2. Save the resulting text in a file.
  36. : 3. Execute the file with /bin/sh '(not csh)' to create the files:
  37. :    'README'
  38. :    'README.old'
  39. :    'NOTES'
  40. :    'Makefile'
  41. :    'addr.c'
  42. :    'addr.h'
  43. :    'atest.c'
  44. :    'rfc822.y'
  45. : This archive created: 'Tue Oct 27 17:50:49 1987
  46. '
  47. : By:    'David Herron -- Resident E-mail Hack ()'
  48. export PATH; PATH=/bin:$PATH
  49. echo shar: extracting "'README'" '(1347 characters)'
  50. if test -f 'README'
  51. then
  52.     echo shar: will not over-write existing file "'README'"
  53. else
  54. sed 's/^X//'  >'README' <<'SHAR_EOF'
  55. XThese files make up a YACC grammar for parsing RFC822 addresses which
  56. XI received a long time ago from
  57. X
  58. X    From: Daniel Karrenberg <dfk@unido.uucp>
  59. X
  60. XThey kind of hung around a long time gathering mold until someone posted
  61. Xa request for a LEX parser for RFC822.  Well, I mentioned this thing
  62. Xand the responses just took off.  Rich Salz contributed a few changes.
  63. X(mainly, it seems, improving portability).  For my part, I've gone
  64. Xover the grammar with a fine-tooth comb to check if it matches the spec.
  65. XThe results of that are in NOTES.
  66. X
  67. X    Date: Tue, 13 Oct 87 14:22:11 edt
  68. X    From: Rich Salz <rsalz@PINEAPPLE.BBN.COM>
  69. X    To: david%ms.uky.edu@HARVARD.HARVARD.EDU
  70. X    Subject: rfc822 parser
  71. X
  72. X    Here's my changes, basically, a rewrite.  Do what you will -- I suppose my
  73. X    name should go in there, in case I put in any bugs...
  74. X
  75. XOne thing this stuff doesn't do is parse a whole message. (or even
  76. Xjust the headers).  It only parses addresses.  It should be simple
  77. Xenough to wrap a header-parser around this address-parser, probably
  78. Xin the same grammar.
  79. X
  80. XI personally am slightly displeased that it will group all the comment
  81. Xtext into one thing.  That's not a very nice thing to do, and shouldn't
  82. Xreally be necessary ...  But it's sat here long enough without my doing
  83. Xanything with it ... :-)
  84. X
  85. X
  86. X
  87. X    -- David Herron <david@ms.uky.edu>
  88. X       Tue Oct 27 17:49:58 EST 1987
  89. SHAR_EOF
  90. if test 1347 -ne "`wc -c < 'README'`"
  91. then
  92.     echo shar: error transmitting "'README'" '(should have been 1347 characters)'
  93. fi
  94. fi # end of overwriting check
  95. echo shar: extracting "'README.old'" '(3100 characters)'
  96. if test -f 'README.old'
  97. then
  98.     echo shar: will not over-write existing file "'README.old'"
  99. else
  100. sed 's/^X//'  >'README.old' <<'SHAR_EOF'
  101. X[ This is the original information I received along with these
  102. X  files ... David ]
  103. X
  104. X
  105. XReceived: from  by .ukma.UUCP id a028381; 1 Apr 86 10:23 EST
  106. XReceived: From UKMA.BITNET By UKMA.BITNET ; 01 Apr 86 15:22:19 GMT
  107. XMessage-Id: <8604010817.AA27744@unido.uucp>
  108. XReceived: by unido.uucp; Tue, 1 Apr 86 10:17:13 -0200
  109. XTo: david@UKMA
  110. XSubject: Re: BSMTP & sendmail
  111. XIn-Reply-To: Your message of Thu, 27 Mar 86 11:46:58 EST.
  112. X             <8603271918.AA28476@unido.uucp>
  113. XDate: 01 Apr 86 10:17:09 N (Tue)
  114. XFrom: Daniel Karrenberg <dfk@unido.uucp>
  115. X
  116. X
  117. X  > I assume you've tried to use simple and found it disgusting?
  118. X
  119. XI tried to fully understand it, but .......
  120. X
  121. X  > I used simple and friends with sendmail for quite awhile and could never
  122. X  > get it to work well.  I wasn't using it for sending BSMTP tho, but I
  123. X  > assume that it was just a matter of saying the right incantations into
  124. X  > the configuration.  (Currently I'm using it with mmdf -- it works a
  125. X  > little better with mmdf).
  126. X
  127. XSending BSMTP is not the problem. Receiving is the dificult part.
  128. X
  129. X  > I've been considering doing up a set of programs for sending and
  130. X  > recieving BSMTP but not using simple.  But I've got too many other
  131. X  > pressing matters.
  132. X
  133. XVery similar to my situation !
  134. X
  135. X  > I would like to have the RFC-822 grammer you mentioned (please?).
  136. X
  137. XSure, see below. Please feel invited to send comments and suggestions.
  138. XIf you go ahead with a BSMTP server please let me know. If there are
  139. Xcode conversion problems I could send it in tarmail format.
  140. X
  141. X
  142. XRegards
  143. X
  144. X-Daniel  <dfk@unido.uucp> , <dfk@unido.bitnet>
  145. X
  146. X
  147. X
  148. X--------------  Original README
  149. X
  150. X
  151. X                                       Tue Apr  1 09:52:46 MET DST 1986
  152. X
  153. XThis is an RFC822 addressparser. The grammer and scanner are based on work
  154. Xdone by Bill Nesheim of Cornell:
  155. X
  156. X  > -------
  157. X  > Date:     Thu, 13 Feb 86 16:31:51 EST
  158. X  > From:     <bill%bullwinkle@crnlcs.bitnet>
  159. X  > To:       dfk@unido.uucp
  160. X  > Subject:  Re:  damail.c
  161. X  > -------
  162. X  >
  163. X  > I've spooled a tar file of damail to you via bitnet.
  164. X  >                 Bill
  165. X  >
  166. X  > (ps: go ahead and give it to whoever wants it.  It's not great, but it
  167. X  > works well enough.)
  168. X
  169. XI have generalized it to accept -hopefully- full RFC822 syntax and store
  170. Xthe pieces in a reasonable datastructure for processing. The rationale for
  171. Xthis is not to do any string shoving in the mailer proper. I have had to
  172. Xunderstand too much Mail software that munged address strings in too many
  173. Xplaces.
  174. X
  175. XHowever I haven't written a program using this parser yet because I have
  176. Xlittle time for this 'hobby'.
  177. X
  178. XOne thing it doesn't handle very well are ()-comments. Since they are
  179. Xessentially white space, they are skipped by the scanner. If there is
  180. Xmore than one of this kind in any given address, they will be concatenated
  181. Xin the adderss structure. This makes it impossible to reconstruct a
  182. Xcommented address string from the parsed version exactly.
  183. X
  184. XThere is a program to test the parser: tparse.c
  185. X
  186. XIt has been run on VAX, NS32016 and 68000 CPUs.
  187. X
  188. XPleas feel invited to send comments, suggestions and fixes!
  189. X
  190. X
  191. X- Daniel  <dfk@unido.bitnet>, <dfk@unido.uucp>
  192. SHAR_EOF
  193. if test 3100 -ne "`wc -c < 'README.old'`"
  194. then
  195.     echo shar: error transmitting "'README.old'" '(should have been 3100 characters)'
  196. fi
  197. fi # end of overwriting check
  198. echo shar: extracting "'NOTES'" '(893 characters)'
  199. if test -f 'NOTES'
  200. then
  201.     echo shar: will not over-write existing file "'NOTES'"
  202. else
  203. sed 's/^X//'  >'NOTES' <<'SHAR_EOF'
  204. XObservations while going over this grammar.
  205. X
  206. X1. An embedded '\n' will muck things up.  In yylex(), an embedded '\n'
  207. X   will bring you through the default: of the second switch(), and
  208. X   since isspace('\n') fails we'll continue picking up characters
  209. X   for the current ATOM.  But an eol is supposed to end the current 
  210. X   token.
  211. X2. An address like "a@b.[1.2.3.4].c" is allowed, and looking in the
  212. X   actual spec, it's supposed to be allowed.  This is moderately
  213. X   strange ...
  214. X3. A not-very major no-no ... In this grammar, a "mailbox" can be
  215. X   an "addr_spec", a "route_addr", or a "phrase route_addr".  Strict
  216. X   interpretation of the spec says that it can't be just a "route_addr".
  217. X4. At first glance, the code for addr_lel would allow '\n' to
  218. X   seperate addresses, which is plain wrong.  Fortunately, EOL really
  219. X   just means the end of the buffer ...
  220. X
  221. X
  222. X-- David Herron <david@ms.uky.edu>
  223. SHAR_EOF
  224. if test 893 -ne "`wc -c < 'NOTES'`"
  225. then
  226.     echo shar: error transmitting "'NOTES'" '(should have been 893 characters)'
  227. fi
  228. fi # end of overwriting check
  229. echo shar: extracting "'Makefile'" '(291 characters)'
  230. if test -f 'Makefile'
  231. then
  232.     echo shar: will not over-write existing file "'Makefile'"
  233. else
  234. sed 's/^X//'  >'Makefile' <<'SHAR_EOF'
  235. X##
  236. XCFLAGS    = -O
  237. XOBJS    = addr.o rfc822.o
  238. XSRCS    = addr.c rfc822.c atest.c
  239. X
  240. Xall:        atest
  241. X
  242. Xatest:        $(OBJS) atest.c
  243. X    $(CC) -o atest $(CFLAGS) atest.c $(OBJS)
  244. X
  245. Xrfc822.o:    rfc822.c
  246. X$(OBJS):    addr.h
  247. X
  248. Xclean:
  249. X    rm -f a.out foo core tags lint rfc822.c atest *.o y.*
  250. X
  251. Xlint:        all
  252. X    exec lint -hba $(SRCS) >lint 
  253. SHAR_EOF
  254. if test 291 -ne "`wc -c < 'Makefile'`"
  255. then
  256.     echo shar: error transmitting "'Makefile'" '(should have been 291 characters)'
  257. fi
  258. fi # end of overwriting check
  259. echo shar: extracting "'addr.c'" '(1489 characters)'
  260. if test -f 'addr.c'
  261. then
  262.     echo shar: will not over-write existing file "'addr.c'"
  263. else
  264. sed 's/^X//'  >'addr.c' <<'SHAR_EOF'
  265. X#include <stdio.h>
  266. X#include "addr.h"
  267. X
  268. X
  269. X
  270. X#ifdef    NEED_BZERO
  271. X/*
  272. X**  I forget what bzero is called for SystemV, so...
  273. X*/
  274. Xbzero(p, i)
  275. X    register char    *p;
  276. X    register int     i;
  277. X{
  278. X    while (--i >= 0)
  279. X    *p++ = '\0';
  280. X}
  281. X#endif    /* NEED_BZERO */
  282. X
  283. X
  284. X/*
  285. X**  Create and initialize a new address.
  286. X*/
  287. XAddr *
  288. XnewAddr()
  289. X{
  290. X    register Addr    *ap;
  291. X
  292. X    if ((ap = (Addr *)malloc((MALLOCT)sizeof *ap)) == NULL) {
  293. X    perror("Addr alloc");
  294. X    exit(1);
  295. X    }
  296. X    bzero((char *)ap, sizeof *ap);
  297. X    return(ap);
  298. X}
  299. X
  300. X
  301. X/*
  302. X**  Append addresslist "addr" to addresslist "head".
  303. X*/
  304. XappAddr(head, addr)
  305. X    Addr        **head;
  306. X    Addr         *addr;
  307. X{
  308. X    register Addr    *ap;
  309. X
  310. X    if (*head) {
  311. X    for (ap = *head; ap->next; ap = ap->next)
  312. X        ;
  313. X    ap->next = addr;
  314. X    }
  315. X    else
  316. X    *head = addr;
  317. X}
  318. X
  319. X
  320. X
  321. X/*
  322. X**  Create and initialize a new domain.
  323. X*/
  324. XDom *
  325. XnewDom()
  326. X{
  327. X    register Dom    *dp;
  328. X
  329. X    if ((dp = (Dom *)malloc((MALLOCT)sizeof *dp)) == NULL) {
  330. X    perror("Dom alloc");
  331. X    exit(1);
  332. X    }
  333. X    bzero((char *)dp, sizeof *dp);
  334. X    dp->top = dp->sub;
  335. X    return(dp);
  336. X}
  337. X
  338. X
  339. X/*
  340. X**  Append domainlist "dom" to domainlist "head".
  341. X*/
  342. XappDom(head, dom)
  343. X    Dom            **head;
  344. X    Dom            *dom;
  345. X{
  346. X    register Dom    *dp;
  347. X
  348. X    if (*head) {
  349. X    for (dp = *head; dp->next; dp = dp->next)
  350. X        ;
  351. X    dp->next = dom;
  352. X    }
  353. X    else
  354. X    *head = dom;
  355. X}
  356. X
  357. X
  358. X/*
  359. X**  Prepend domainlist "dom" before domainlist "head".
  360. X*/
  361. XprepDom(head, dom)
  362. X    Dom            **head;
  363. X    Dom             *dom;
  364. X{
  365. X    register Dom     *dp;
  366. X
  367. X    for (dp = dom; dp->next; dp = dp->next)
  368. X    ;
  369. X    dp->next = *head;
  370. X    *head = dom;
  371. X}
  372. SHAR_EOF
  373. if test 1489 -ne "`wc -c < 'addr.c'`"
  374. then
  375.     echo shar: error transmitting "'addr.c'" '(should have been 1489 characters)'
  376. fi
  377. fi # end of overwriting check
  378. echo shar: extracting "'addr.h'" '(1198 characters)'
  379. if test -f 'addr.h'
  380. then
  381.     echo shar: will not over-write existing file "'addr.h'"
  382. else
  383. sed 's/^X//'  >'addr.h' <<'SHAR_EOF'
  384. X/*
  385. X** Mail address data structures
  386. X*/
  387. X
  388. X#undef    NEED_BZERO
  389. X#define NSUBDOM        20          /* # of subdomain names in domain */
  390. X
  391. Xtypedef unsigned int MALLOCT;        /* Parameter to malloc        */
  392. X
  393. X/*
  394. X**  An address.
  395. X*/
  396. Xtypedef struct _addr {
  397. X    struct _addr    *next;        /* next address in list        */
  398. X    struct _dom        *route;        /* route icl. destination domain */
  399. X    struct _dom        *destdom;    /* destination domain        */
  400. X    char        *localp;    /* RFC local part        */
  401. X    char        *name;        /* Comment name            */
  402. X    char        *group;        /* Group (List) phrase        */
  403. X    char        *comment;    /* () comment phrase        */
  404. X    char        *error;        /* error text if not NULL    */
  405. X} Addr;
  406. X
  407. X
  408. X/*
  409. X**  A domain.
  410. X*/
  411. Xtypedef struct _dom {
  412. X    struct _dom        *next;        /* next domain (f.i. in route)    */
  413. X    char        *sub[NSUBDOM];    /* subdomain strins        */
  414. X    char        **top;        /* toplevel domain        */
  415. X} Dom;
  416. X
  417. X
  418. Xextern Addr    *newAddr();        /* Create a new address        */
  419. Xextern Dom    *newDom();        /* Create a new domain        */
  420. Xextern Addr    *adrlist;
  421. Xextern Addr    *errlist;
  422. Xextern char    *malloc();
  423. Xextern char    *strcpy();
  424. Xextern char    *strncpy();
  425. Xextern char    *strcat();
  426. X
  427. X/* SHUT UP! */
  428. X#define Strcpy        (void)strcpy
  429. X#define Strncpy        (void)strncpy
  430. X#define Strcat        (void)strcat
  431. X#define Sprintf        (void)sprintf
  432. SHAR_EOF
  433. if test 1198 -ne "`wc -c < 'addr.h'`"
  434. then
  435.     echo shar: error transmitting "'addr.h'" '(should have been 1198 characters)'
  436. fi
  437. fi # end of overwriting check
  438. echo shar: extracting "'atest.c'" '(1121 characters)'
  439. if test -f 'atest.c'
  440. then
  441.     echo shar: will not over-write existing file "'atest.c'"
  442. else
  443. sed 's/^X//'  >'atest.c' <<'SHAR_EOF'
  444. X/*
  445. X**  Checkout program for rfc822-address parser
  446. X**  Takes address-lines from stdin up to EOF or empty line.
  447. X**  Writes results to stdout, errors to stderr.
  448. X*/
  449. X#include <stdio.h>
  450. X#include "addr.h"
  451. X
  452. X
  453. Xstatic void
  454. Xprtroute(dp)
  455. X    register Dom    *dp;
  456. X{
  457. X    register char    **p;
  458. X
  459. X    for (; dp; dp = dp->next) {
  460. X    printf("\t");
  461. X    for (p = dp->sub; p != dp->top; p++)
  462. X        printf("%s.", *p);
  463. X    printf("%s\n", *p);
  464. X    }
  465. X}
  466. X
  467. X
  468. Xmain()
  469. X{
  470. X    register Addr    *ap;
  471. X    register int     i;
  472. X    char         line[100];
  473. X
  474. X    while (gets(line) && *line) {
  475. X    parseit(line);
  476. X    for (i = 0; i < 2; i++)
  477. X        for (ap = i ? adrlist : errlist; ap; ap = ap->next) {
  478. X        if (ap->error)
  479. X            printf("error:\t%s\n", ap->error);
  480. X        if (ap->name)
  481. X            printf("name:\t%s\n", ap->name);
  482. X        if (ap->comment)
  483. X            printf("comment:\t%s\n", ap->comment);
  484. X        if (ap->group)
  485. X            printf("group:\t%s\n", ap->group);
  486. X        if (ap->localp)
  487. X            printf("localp:\t%s\n", ap->localp);
  488. X        if (ap->destdom) {
  489. X            printf("destdom:\n");
  490. X            prtroute(ap->destdom);
  491. X        }
  492. X        if (ap->route) {
  493. X            printf("route:\n");
  494. X            prtroute(ap->route);
  495. X        }
  496. X        printf("\n");
  497. X        }
  498. X    }
  499. X    exit(0);
  500. X}
  501. SHAR_EOF
  502. if test 1121 -ne "`wc -c < 'atest.c'`"
  503. then
  504.     echo shar: error transmitting "'atest.c'" '(should have been 1121 characters)'
  505. fi
  506. fi # end of overwriting check
  507. echo shar: extracting "'rfc822.y'" '(6772 characters)'
  508. if test -f 'rfc822.y'
  509. then
  510.     echo shar: will not over-write existing file "'rfc822.y'"
  511. else
  512. sed 's/^X//'  >'rfc822.y' <<'SHAR_EOF'
  513. X%{
  514. X#include "addr.h"
  515. X
  516. Xstatic char    *errstr;
  517. Xstatic char    *comstr;
  518. Xstatic char    *cp;
  519. Xstatic char     errbuf[256];
  520. Xstatic char     combuf[256];
  521. Xstatic int     iseol;
  522. X
  523. XAddr        *adrlist;
  524. XAddr        *errlist;
  525. X%}
  526. X
  527. X%union {
  528. X   char     yChar;
  529. X   char    *yString;
  530. X   Dom    *yDom;
  531. X   Addr    *yAddr;
  532. X}
  533. X
  534. X%token    EOL ATOM LIT_DOMAIN QUOTED_STRING
  535. X
  536. X%type    <yString>    word domain_ref sub_domain local_part phrase
  537. X%type    <yDom>        domain route_list route
  538. X%type    <yAddr>        addr_spec route_addr mailbox mbox_list group address
  539. X
  540. X%start    addr_list
  541. X
  542. X%%
  543. Xaddr_list:    addr_lel
  544. X       | addr_list addr_lel
  545. X       ;
  546. X
  547. Xaddr_lel: address EOL {
  548. X        $1->comment = comstr;
  549. X        $1->error = errstr;
  550. X        comstr = NULL;
  551. X        errstr = NULL;
  552. X        appAddr(&adrlist, $1);
  553. X    }
  554. X    | address ',' {
  555. X        $1->comment = comstr;
  556. X        $1->error = errstr;
  557. X        comstr = NULL;
  558. X        errstr = NULL;
  559. X        appAddr(&adrlist, $1);
  560. X    }
  561. X    | error {
  562. X        register Addr    *ap;
  563. X
  564. X        ap = newAddr();
  565. X        Sprintf(errbuf, "after \"%s\", before \"%s\"\n", $<yString>1, cp);
  566. X        errstr = newstring2(errstr, errbuf);
  567. X        ap->error = errstr;
  568. X        errstr = NULL;
  569. X        comstr = NULL;
  570. X        appAddr(&errlist, ap);
  571. X    }
  572. X    ;
  573. X
  574. Xaddress: mailbox {
  575. X        $$ = $1;
  576. X    }
  577. X    | group {
  578. X        $$ = $1;
  579. X    }
  580. X    ;
  581. X
  582. Xgroup    : phrase ':' mbox_list ';' {
  583. X        register Addr    *a;
  584. X
  585. X        for (a = $3; a; a = a->next)
  586. X        a->group = $1;
  587. X        $$ = $3;
  588. X    }
  589. X    ;
  590. X
  591. Xmbox_list: mailbox {
  592. X        $$ = $1;
  593. X    }
  594. X    | mbox_list ',' mailbox {
  595. X        $3->comment = comstr;
  596. X        $3->error = errstr;
  597. X        comstr = NULL;
  598. X        errstr = NULL;
  599. X        appAddr(&($1), $3);
  600. X        $$ = $1;
  601. X    }
  602. X    ;
  603. X
  604. Xmailbox: addr_spec {
  605. X        $$ = $1;
  606. X    }
  607. X    | route_addr {
  608. X        $$ = $1;
  609. X    }
  610. X    | phrase route_addr {
  611. X        $2->name = $1;
  612. X        $$ = $2;
  613. X    }
  614. X    ;
  615. X
  616. Xphrase    : word {
  617. X        $$ = $1;
  618. X    }
  619. X    | phrase word {
  620. X        $$ = newstring3($1, " ", $2);
  621. X        free($1);
  622. X        free($2);
  623. X       }
  624. X       ;
  625. X
  626. Xroute_addr: '<' addr_spec '>' {
  627. X       $$ = $2;
  628. X       }
  629. X       | '<' route addr_spec '>' {
  630. X       prepDom(&($3->route), $2);
  631. X       $$ = $3;
  632. X       }
  633. X       ;
  634. X
  635. Xroute    : route_list ':' {
  636. X        $$ = $1;
  637. X    }
  638. X    ;
  639. X
  640. Xroute_list: '@' domain {
  641. X        $$ = $2;
  642. X    }
  643. X    | route_list ',' '@' domain {
  644. X        appDom(&($1), $4);
  645. X        $$ = $1;
  646. X    }
  647. X    ;
  648. X
  649. Xaddr_spec: local_part '@' domain {
  650. X        register Addr    *ap;
  651. X
  652. X        $$ = ap = newAddr();
  653. X        ap->localp = $1;
  654. X        ap->destdom = $3;
  655. X        ap->route = $3;
  656. X    }
  657. X    | local_part {
  658. X        register Addr    *ap;
  659. X
  660. X        $$ = ap = newAddr();
  661. X        ap->localp = $1;
  662. X        ap->destdom = NULL;
  663. X    }
  664. X    ;
  665. X
  666. X
  667. Xlocal_part: word {
  668. X        $$ = $1;
  669. X        }
  670. X        | local_part '.' word {
  671. X        $$ = newstring3($1, ".", $3);
  672. X        free($1);
  673. X        free($3);
  674. X        }
  675. X        | local_part '%' word {
  676. X        $$ = newstring3($1, "%", $3);
  677. X        free($1);
  678. X        free($3);
  679. X        }
  680. X        ;
  681. X
  682. Xdomain    : sub_domain {
  683. X        register Dom    *dp;
  684. X
  685. X        dp = newDom();
  686. X        dp->sub[0] = $1;
  687. X        dp->top = dp->sub;
  688. X        $$ = dp;
  689. X    }
  690. X    | domain '.' sub_domain {
  691. X        ($1->top)++;
  692. X        *($1->top) = $3;
  693. X        $$ = $1;
  694. X    }
  695. X    ;
  696. X
  697. Xsub_domain: domain_ref {
  698. X        $$ = $1;
  699. X    }
  700. X    | LIT_DOMAIN {
  701. X        $$ = yylval.yString;
  702. X    }
  703. X    ;
  704. X
  705. Xdomain_ref: ATOM {
  706. X        $$ = yyval.yString;
  707. X    }
  708. X    ;
  709. X
  710. Xword    : ATOM {
  711. X        $$ = yylval.yString;
  712. X    }
  713. X    | QUOTED_STRING {
  714. X        $$ = yylval.yString;
  715. X    }
  716. X    ;
  717. X
  718. X%%
  719. X
  720. X#include <stdio.h>
  721. X#include <ctype.h>
  722. X
  723. X#define ERROR    -2
  724. X
  725. X
  726. Xstatic char *
  727. Xnewstring3(a, b, c)
  728. X    char    *a;
  729. X    char    *b;
  730. X    char    *c;
  731. X{
  732. X    char    *p;
  733. X    char    *q;
  734. X    int         i;
  735. X
  736. X    i = strlen(a) + strlen(b) + strlen(c) + 1;
  737. X    if ((p = malloc((MALLOCT)i)) == NULL) {
  738. X    perror("newstring3 (malloc)");
  739. X    exit(1);
  740. X    }
  741. X    q = p + strlen(strcpy(p, a));
  742. X    q += strlen(strcpy(q, b));
  743. X    Strcpy(q, c);
  744. X    return(q);
  745. X}
  746. X
  747. X
  748. Xstatic char *
  749. Xnewstring2(a, b)
  750. X    char        *a;
  751. X    char        *b;
  752. X{
  753. X    char        *p;
  754. X    int             i;
  755. X
  756. X    i = strlen(a) + strlen(b) + 1;
  757. X    if ((p = malloc((MALLOCT)i)) == NULL) {
  758. X    perror("newstring2 (malloc)");
  759. X    exit(1);
  760. X    }
  761. X    Strcpy(p, a);
  762. X    Strcat(p, b);
  763. X    return(p);
  764. X}
  765. X
  766. X
  767. Xstatic void
  768. Xyyerror(s)
  769. X    char    *s;
  770. X{
  771. X   switch(yychar) {
  772. X       default:
  773. X       Sprintf(errbuf, "%s: \"%c\" unexpected\n", s, yylval.yChar);
  774. X       errstr = newstring2(errstr, errbuf);
  775. X       break;
  776. X       case LIT_DOMAIN:
  777. X       case QUOTED_STRING:
  778. X       case ATOM:
  779. X       Sprintf(errbuf, "%s: \"%s\" unexpected\n", s, yylval.yString);
  780. X       errstr = newstring2(errstr, errbuf);
  781. X       break;
  782. X       case 0: /* EOF */
  783. X       Sprintf(errbuf, "%s: unexpected EOF\n", s);
  784. X       errstr = newstring2(errstr, errbuf);
  785. X       break;
  786. X   }
  787. X
  788. X}
  789. X
  790. X
  791. Xparseit(line)
  792. X    char    *line;
  793. X{
  794. X    cp = line;
  795. X    adrlist = NULL;
  796. X    errlist = NULL;
  797. X    (void)yyparse();
  798. X}
  799. X
  800. X
  801. Xyylex()
  802. X{
  803. X    register char    *p;
  804. X    register int     paren_count;
  805. X
  806. X    while (isascii(*cp) && (isspace(*cp) || (*cp == '('))) {
  807. X    if (*cp == '(') {
  808. X        for (paren_count = 1, p = cp + 1; paren_count; p++) {
  809. X        if (*p == '\0')
  810. X            return(EOF);
  811. X        if (*p == '(')
  812. X            paren_count++;
  813. X        else if( *p == ')')
  814. X            paren_count--;
  815. X        }
  816. X        Strncpy(combuf, cp + 1, (p - 2) - cp);
  817. X        if (comstr == NULL) {
  818. X        if ((comstr = malloc((MALLOCT)(strlen(combuf) + 1))) == NULL) {
  819. X            perror("malloc failure");
  820. X            exit(1);
  821. X        }
  822. X        Strcpy(comstr, combuf);
  823. X        }
  824. X        else
  825. X        comstr = newstring3(comstr, ", ", combuf);
  826. X        cp = p;
  827. X    }
  828. X    else
  829. X        cp++;
  830. X    }
  831. X
  832. X    if (!isascii(*cp))
  833. X    return(ERROR);
  834. X
  835. X    switch (*cp) {
  836. X    case '\0':
  837. X        if (iseol) {
  838. X        iseol = 0;
  839. X        return(EOF);
  840. X        }
  841. X        iseol = 1;
  842. X        return(EOL);
  843. X    case ',':
  844. X    case ':':
  845. X    case ';':
  846. X    case '.':
  847. X    case '@':
  848. X    case '%':
  849. X    case '<':
  850. X    case '>':
  851. X        yylval.yChar = *cp;
  852. X        return(*cp++);
  853. X    case '[':       /* LIT_DOMAIN */
  854. X        for (p = cp; *++p && *p != ']'; )
  855. X        ;
  856. X        if (*p == '\0')
  857. X        return(EOF);
  858. X        if ((yylval.yString = malloc((MALLOCT)(p - cp + 2))) == NULL) {
  859. X        fprintf(stderr,"not enough memory\n");
  860. X        return(ERROR);
  861. X        }
  862. X        Strncpy(yylval.yString, cp, p - cp + 1);
  863. X        yylval.yString[p - cp + 2] = '\0';
  864. X        cp = ++p;
  865. X        return(LIT_DOMAIN);
  866. X    case '"':       /* QUOTED_STRING */
  867. X        for (p = cp; *++p && *p != '"'; )
  868. X        ;
  869. X        if (*p == '\0')
  870. X        return(EOF);
  871. X        if ((yylval.yString = malloc((MALLOCT)(p - cp + 2))) == NULL) {
  872. X        fprintf(stderr,"not enough memory\n");
  873. X        return(ERROR);
  874. X        }
  875. X        Strncpy(yylval.yString, cp, p - cp + 1);
  876. X        yylval.yString[p - cp + 2] = '\0';
  877. X        cp = ++p;
  878. X        return(QUOTED_STRING);
  879. X    }
  880. X    for (p = cp; ; p++)
  881. X    switch (*p) {
  882. X        case 'a':
  883. X        case 'A':
  884. X        if ((p[1] == 't' || p[1] == 'T') && isspace(p[2])) {
  885. X            yylval.yChar = '@';
  886. X            cp = p + 2;
  887. X            return('@');
  888. X        }
  889. X        break;
  890. X        case ',':
  891. X        case ':':
  892. X        case ';' :
  893. X        case '.':
  894. X        case '@':
  895. X        case '%':
  896. X        case '<':
  897. X        case '>':
  898. X        case '(':
  899. X        case ')':
  900. X        case '[':
  901. X        case '"':
  902. X        case '\0':
  903. X        goto out;
  904. X        default:
  905. X        if (isspace(*p))
  906. X            goto out;
  907. X    }
  908. Xout:
  909. X    if ((yylval.yString = malloc((MALLOCT)(p - cp + 1))) == NULL) {
  910. X    fprintf(stderr,"not enough memory\n");
  911. X    return(ERROR);
  912. X    }
  913. X    Strncpy(yylval.yString, cp, p - cp);
  914. X    yylval.yString[p - cp] = '\0';
  915. X    cp = p;
  916. X    return(ATOM);
  917. X}
  918. SHAR_EOF
  919. if test 6772 -ne "`wc -c < 'rfc822.y'`"
  920. then
  921.     echo shar: error transmitting "'rfc822.y'" '(should have been 6772 characters)'
  922. fi
  923. fi # end of overwriting check
  924. :    End of shell archive
  925. exit 0
  926. -- 
  927. <---- David Herron,  Local E-Mail Hack,  david@ms.uky.edu, david@ms.uky.csnet
  928. <----                    {rutgers,uunet,cbosgd}!ukma!david, david@UKMA.BITNET
  929. <---- I thought that time was this neat invention that kept everything
  930. <---- from happening at once.  Why doesn't this work in practice?
  931.