home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / ease / part01 next >
Encoding:
Internet Message Format  |  1987-02-10  |  48.8 KB

  1. Subject:  v08i053:  Ease, a language for writing sendmail.cf files, Part01/04
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: ksb@j.cc.purdue.edu
  6. Mod.sourbes: Volume 8, Issue 53
  7. Archive-name: ease/Part01
  8.  
  9. The Ease language is a high-level specification format for sendmail's
  10. configuration file.  The motivation for its development was to fulfill
  11. a goal of providing a readable and easily modifiable sendmail
  12. configuration file format.  Ease fulfills this goal by shielding the
  13. programmer from the cryptic configuration specification required by
  14. sendmail and providing a high-level language with which the programmer
  15. may specify all modifications to a configuration file.  The development
  16. of Ease coincided with the development of an Ease translator, et, which
  17. translates a configuration file written in Ease to an equivalent file
  18. of the standard format accepted by sendmail.
  19.  
  20. Please let Kevin Braunsdorf, "ksb@j.cc.purdue.edu" know if you make any
  21. modifications to Ease; he's taking care of this now (the original
  22. author has since left Purdue) and we'd really like to keep the released
  23. version exactly in step with our local version in order to make
  24. supporting this a lot easier.
  25.  
  26. Thanks,
  27.     "Wombat" <rsk@j.cc.purdue.edu>
  28.  
  29. #    This is a shell archive.
  30. #    Remove everything above and including the cut line.
  31. #    Then run the rest of the file through sh.
  32. #----cut here-----cut here-----cut here-----cut here----#
  33. #!/bin/sh
  34. # shar:    Shell Archiver
  35. #    Run the following text with /bin/sh to create:
  36. #    doc
  37. #    src
  38. mkdir doc
  39. chdir doc
  40. cat << \SHAR_EOF > ap1
  41. .DS C
  42. \s+5\fBAppendix A\fR
  43.  
  44.  
  45. \fBPre-Declared Macros\fR\s-5
  46. .DE
  47. .sp 5
  48. .TS 
  49. center box;
  50. c|c|c
  51. l|l|l.
  52. \fBEase\fR Macro    Raw Equivalent    Meaning*
  53. =
  54. \fIm_odate\fR    a    The origination date in Arpanet format
  55. \fIm_adate\fR    b    The current date in Arpanet format
  56. \fIm_hops\fR    c    The hop count
  57. \fIm_udate\fR    d    The date in UNIX (ctime) format
  58. \fIm_smtp\fR    e    The SMTP entry message
  59. \fIm_saddr\fR    f    The sender (from) address
  60. \fIm_sreladdr\fR    g    The sender address relative to the recipient
  61. \fIm_rhost\fR    h    The recipient host
  62. \fIm_qid\fR    i    The queue id
  63. \fIm_oname\fR    j    The official domain name for this site
  64. \fIm_ufrom\fR    l    The format of the UNIX from line
  65. \fIm_daemon\fR    n    The name of the daemon (for error messages)
  66. \fIm_addrops\fR    o    The set of "operators" in addresses
  67. \fIm_pid\fR    p    Sendmail's pid
  68. \fIm_defaddr\fR    q    The default format of sender address
  69. \fIm_protocol\fR    r    Protocol used
  70. \fIm_shostname\fR    s    Sender's host name
  71. \fIm_ctime\fR    t    A numeric representation of the current time
  72. \fIm_ruser\fR    u    The recipient user
  73. \fIm_version\fR    v    The version number of sendmail
  74. \fIm_sitename\fR    w    The hostname of this site
  75. \fIm_sname\fR    x    The full name of the sender
  76. \fIm_stty\fR    y    The id of the sender's tty
  77. \fIm_rhdir\fR    z    The home directory of the recipient
  78. .TE
  79. .FS
  80. *  Taken from pages 15 and 16 of the Installation and Operation Guide
  81. for Sendmail (UNIX Programmer's Manual, Volume 2c), by Eric Allman.
  82. .FE
  83. SHAR_EOF
  84. if test 1384 -ne "`wc -c ap1`"
  85. then
  86. echo shar: error transmitting ap1 '(should have been 1384 characters)'
  87. fi
  88. cat << \SHAR_EOF > ap2
  89. .DS C
  90. \s+5\fBAppendix B\fR
  91.  
  92.  
  93. \fBSendmail Options\fR\s-5
  94. .DE
  95. .sp 2
  96. .PP
  97. For a complete description of Sendmail's options and their values, refer to 
  98. Appendix B of the Installation and Operation Guide for Sendmail (UNIX
  99. Programmer's Manual, Volume 2c), by Eric Allman.
  100. .sp 2
  101. .TS 
  102. center box;
  103. c|c
  104. l|l.
  105. Sendmail Option (\fBEase\fR)    Sendmail Option (Raw)    Special Values
  106. =
  107. \fIo_alias\fR    A    
  108. \fIo_ewait\fR    a    
  109. \fIo_bsub\fR    B    
  110. \fIo_qwait\fR    c    
  111. \fIo_delivery\fR  (special values below)    d  (special values below)
  112.      \fId_interactive\fR         i 
  113.      \fId_background\fR        b 
  114.      \fId_queue\fR        q
  115. \fIo_rebuild\fR    D
  116. \fIo_handling\fR  (special values below)    e  (special values below)
  117.      \fIh_print\fR         p 
  118.      \fIh_exit\fR         q
  119.      \fIh_mail\fR         m
  120.      \fIh_write\fR         w
  121.      \fIh_mailz\fR         e
  122. \fIo_tmode\fR    F    
  123. \fIo_usave\fR    f    
  124. \fIo_gid\fR    g    
  125. \fIo_fsmtp\fR    H    
  126. \fIo_skipd\fR    i    
  127. \fIo_slog\fR    L    
  128. \fIo_rsend\fR    m    
  129. \fIo_dnet\fR    N    
  130. \fIo_hformat\fR    o    
  131. \fIo_qdir\fR    Q    
  132. \fIo_tread\fR    r    
  133. \fIo_flog\fR    S    
  134. \fIo_safe\fR    s    
  135. \fIo_qtimeout\fR    T    
  136. \fIo_timezone\fR    t    
  137. \fIo_dmuid\fR    u    
  138. \fIo_verbose\fR    v    
  139. \fIo_wizpass\fR    W    
  140. \fIo_loadq\fR    x    
  141. \fIo_loadnc\fR    X    
  142. .TE
  143. SHAR_EOF
  144. if test 1153 -ne "`wc -c ap2`"
  145. then
  146. echo shar: error transmitting ap2 '(should have been 1153 characters)'
  147. fi
  148. cat << \SHAR_EOF > ap3
  149. .DS C
  150. \s+5\fBAppendix C\fR
  151.  
  152.  
  153. \fBMailer Flags\fR\s-5
  154. .DE
  155. .sp 5
  156. .PP
  157. For a complete description of mailer flags, refer to 
  158. Appendix C of the Installation and Operation Guide for Sendmail (UNIX
  159. Programmer's Manual, Volume 2c), by Eric Allman.
  160. .sp 5
  161. .TS 
  162. center box;
  163. c|c
  164. l|l.
  165. Mailer Flag (\fBEase\fR)    Mailer Flag (Raw)
  166. =
  167. \fIf_ffrom\fR    f
  168. \fIf_rfrom\fR    r
  169. \fIf_noreset\fR    S
  170. \fIf_noufrom\fR    n
  171. \fIf_locm\fR    l
  172. \fIf_strip\fR    s 
  173. \fIf_mult\fR    m
  174. \fIf_from\fR    F
  175. \fIf_date\fR    D
  176. \fIf_mesg\fR    M
  177. \fIf_full\fR    x    
  178. \fIf_return\fR    P    
  179. \fIf_upperu\fR    u    
  180. \fIf_upperh\fR    h    
  181. \fIf_arpa\fR    A    
  182. \fIf_ufrom\fR    U    
  183. \fIf_expensive\fR    e    
  184. \fIf_dot\fR    X    
  185. \fIf_llimit\fR    L    
  186. \fIf_retsmtp\fR    p    
  187. \fIf_smtp\fR    I    
  188. \fIf_addrw\fR    C    
  189. .TE
  190. SHAR_EOF
  191. if test 689 -ne "`wc -c ap3`"
  192. then
  193. echo shar: error transmitting ap3 '(should have been 689 characters)'
  194. fi
  195. cat << \SHAR_EOF > cover
  196. .DA
  197. .sp 15
  198. .nr PS 14
  199. .ps 14
  200. .DS C
  201.  
  202. .DE
  203. .sp 10
  204. .nr PS 36
  205. .ps 36
  206. .DS C
  207. \fBEase:\fR
  208. .DE
  209. .sp 5
  210. .nr PS 22
  211. .ps 22
  212. .DS C
  213. A Configuration Language
  214.   
  215. for Sendmail
  216. .DE
  217. .sp 13
  218. .nr PS 14
  219. .ps 14
  220. .DS C
  221. by
  222.  
  223. \fIJames S. Schoner\fR
  224. \fIPurdue University Computing Center\fR
  225. .DE
  226. SHAR_EOF
  227. if test 262 -ne "`wc -c cover`"
  228. then
  229. echo shar: error transmitting cover '(should have been 262 characters)'
  230. fi
  231. cat << \SHAR_EOF > ease.paper
  232. .LP
  233. .TL
  234. Ease: A Configuration Language
  235. for Sendmail
  236. .AU
  237. James S. Schoner
  238. .AI
  239. Purdue University Computing Center
  240. West Lafayette, Indiana  47907
  241. .sp 2
  242. .I
  243. .ce
  244. ABSTRACT
  245. .R
  246. .PP
  247. The rapid expansion of computer networks and ensuing variation among mailing
  248. address formats have made address interpretation an increasingly
  249. complex task.  In the UNIX* 4.2BSD operating system, a program named 
  250. \fIsendmail\fR was introduced which provided a
  251. general internetwork mail routing facility.  This facility has significantly
  252. diminished the complexity of handling address interpretation.
  253. .PP
  254. \fISendmail\fR's address interpretation is based on a rewriting
  255. system composed of
  256. a number of rewriting rules (or productions) arranged as part of a 
  257. configuration file.  Unfortunately, the syntactical format of a
  258. configuration file for \fIsendmail\fR is both terse and rigid, making it
  259. rather difficult to modify.  The standard format certainly serves its 
  260. purpose, but, as 
  261. the need to change these configurations increases in frequency, a more 
  262. readable format (i.e., one that is similar to the format 
  263. of modern programming languages) is required to permit reasonably 
  264. quick modifications to the configuration.  As a solution to this problem, 
  265. \fBEase\fR 
  266. provides a level of abstraction which eliminates most of the current
  267. syntactic hindrances
  268. faced by programmers who must reconfigure \fIsendmail\fR's 
  269. address parsing scheme.  
  270. .PP
  271. As a high-level specification format, \fBEase\fR is proving to be an 
  272. excellent alternative to \fIsendmail\fR's cryptic 
  273. configuration file syntax.  The syntactic structures of \fBEase\fR 
  274. are patterned after modern language constructs, making the language
  275. easy to learn and easy to remember.  The format of the address rewriting
  276. rule is perhaps the most significant syntactical improvement.  It was 
  277. undoubtedly
  278. the most needed improvement.  Nevertheless, every element of a configuration 
  279. file is structurally enhanced through the use of \fBEase\fR. 
  280. .FS
  281. *  UNIX is a trademark of AT&T Bell Laboratories.
  282. .FE
  283. .sp 2
  284. .NH
  285. Introduction
  286. .PP
  287. The \fBEase\fR language is a high-level specification format for \fIsendmail\fR's
  288. configuration file.  The motivation for its development
  289. was to fulfill a goal of providing a readable and easily modifiable 
  290. \fIsendmail\fR configuration file format.  \fBEase\fR fulfills this goal by
  291. shielding the programmer from the cryptic configuration specification required
  292. by \fIsendmail\fR and providing a high-level language with which the programmer
  293. may specify all modifications to a configuration file.  The development 
  294. of Ease coincided with
  295. the development of an \fBEase\fR translator, \fIet\fR,
  296. which translates a configuration file written 
  297. in \fBEase\fR to an
  298. equivalent file of the standard format accepted by \fIsendmail\fR.
  299. .NH
  300. Ease in Profile
  301. .PP
  302. As will be seen in the next section, the syntax of \fBEase\fR is quite
  303. readable and easy to learn.  In order to acquire a relevant perspective
  304. on this issue,
  305. the reader is advised to examine a raw configuration file for \fIsendmail\fR (the 
  306. output
  307. of the \fBEase\fR translator, \fIet\fR, will do nicely).  The raw syntax, while
  308. quite fitting for quick translation, can prove to be a programmer's nightmare.  
  309. .PP
  310. Undoubtedly, one of the more prominent features of \fBEase\fR is the ability 
  311. to attach
  312. names to address fields.  When address field names are well-chosen, a distinct,
  313. self-documenting quality becomes a visible part of the address rewriting 
  314. rules.  Ostensibly, address field names provide a new level of semantic 
  315. abstraction.  A brief comparison of the formats can be accomplished by examining
  316. the following equivalent representations of an address pattern:
  317. .DS
  318.     user_path@host_name            (\fBEase\fR format)
  319.     $+@$-                    (raw format)
  320. .DE
  321. In the above, \*Quser_path\*U represents a field of one or more address
  322. tokens, and \*Qhost_name\*U represents one address token exactly.  These
  323. token fields are represented by \*Q$+\*U and \*Q$-\*U in the raw format.  Clearly, 
  324. the \fBEase\fR format is preferable, not only for increased readability, but 
  325. structural comprehension as well.
  326. .PP
  327. Other features of \fBEase\fR include ruleset naming, long identifiers for 
  328. macros and classes, flow-of-control structures, and free formatting.  In
  329. addition, the C language preprocessor (cpp) can be used for file inclusion
  330. and conditionally defined code constructs.  The next section describes
  331. the \fBEase\fR language in complete detail.
  332. .NH
  333. Ease Syntax*
  334. .FS
  335. *  \fINo attempt is made to describe the complete semantic meaning 
  336. associated with all of the constructs of a sendmail configuration file.  Items 
  337. not covered in this document include the semantic distinction among rulesets, 
  338. the special uses of
  339. pre-defined macros, and the method of building configuration files.  To
  340. obtain this information, the reader is advised to refer to
  341. the Installation and Operation Guide for Sendmail (UNIX
  342. Programmer's Manual, Volume 2c), by Eric Allman.\fR
  343. .FE
  344. .PP
  345. At its highest level, \fBEase\fR can be viewed as a collection of 
  346. block-structures, where each block begins with a keyword and is followed by
  347. zero or more related definitions and/or declarations.  There are ten distinct 
  348. block types.  The following is 
  349. a list containing all ten block keywords and the block type it denotes.
  350. .TS
  351. center;
  352. l l .
  353. \fIbind\fR    -ruleset identifier bindings
  354. \fImacro\fR    -macro definitions
  355. \fIclass\fR    -class definitions
  356. \fIoptions\fR    -\fIsendmail\fR option definitions
  357. \fIprecedence\fR    -precedence definitions
  358. \fItrusted\fR    -trusted users
  359. \fIheader\fR    -mail header definitions
  360. \fImailer\fR    -mailer definitions
  361. \fIfield\fR    -address field definitions
  362. \fIruleset\fR    -address rewriting rules
  363. .TE
  364. .sp 1
  365. In general,
  366. .TS
  367. center ;
  368. l .
  369.  
  370. * Letters are distinguished by case,
  371.  
  372. T{
  373. * An \fBEase\fR identifier is defined to be a letter, followed by zero or 
  374. more letters, digits, underscores (_), or dashes (-),
  375. T}
  376.  
  377. T{
  378. * A literal newline or double quotation (") character may be included in 
  379. any quoted string by preceding the character with a backslash (\\\\\), and
  380. T}
  381.  
  382. T{
  383. * \fBEase\fR source is preprocessed by the C language preprocessor (cpp),
  384. thus source comments (i.e., text enclosed by \*Q/*\*U and \*Q*/\*U) may appear 
  385. anywhere as part of \fBEase\fR whitespace.
  386. T}
  387. .TE
  388. .PP
  389. For notational convenience, this document specifies all reserved
  390. words of the \fBEase\fR language in italics.  In addition, quantities
  391. enclosed in angle brackets (<..>) represent arbitrary 
  392. identifiers, strings, or numbers.  
  393. .NH 2
  394. Ruleset Identifier Bindings
  395. .PP
  396. A ruleset (a set of rewriting rules) is identified solely by an integer 
  397. in \fIsendmail\fR's
  398. configuration file.  \fBEase\fR, however, allows each ruleset to be named with
  399. a meaningful identifier.  Since a special numeric association for each 
  400. ruleset is required by the address parsing scheme of \fIsendmail\fR, a \fIbind\fR
  401. block must be present in any \fBEase\fR file which defines one or more 
  402. rulesets.  A
  403. \fIbind\fR block consists of the keyword \fIbind\fR, followed by zero or more
  404. statements of the form:
  405. .TS
  406. center box;
  407. l .
  408. <ruleset-id> = \fIruleset\fR <ruleset-number> ;
  409. .TE
  410. The following example, 
  411. .sp 1
  412. \fIbind\fR
  413. .PP
  414. FINAL_RW = \fIruleset\fR 4;
  415. .sp 1
  416. specifies that FINAL_RW, the final rewriting ruleset, is \fIsendmail\fR's ruleset 
  417. number 4.
  418. .NH 2
  419. Macro Definitions
  420. .PP
  421. A macro is an identifier which, when referenced in the text of a program,
  422. is replaced by its value, a string of zero or more characters.  The value
  423. of a macro may include references to other macros, but not itself!  \fISendmail\fR
  424. allows a maximum of 26 user-declared macros in its configuration file.  In 
  425. addition, there are a number of pre-declared macros which have special meaning
  426. to \fIsendmail\fR (see Appendix A).  \fBEase\fR macros are defined in 
  427. \fImacro\fR blocks.  \fBEase\fR allows any macro to be declared 
  428. (which is equivalent to simply referencing it) before it is defined.  A macro
  429. identifier is replaced by its value when it is preceded by the character
  430. \*Q$\*U.  In addition, a macro reference inside a quoted string must always 
  431. include braces ({}) around the macro identifier (for delimiting purposes).  
  432. .PP
  433. A \fImacro\fR block consists of the keyword \fImacro\fR, followed by zero
  434. or more statements taking either of the following forms:
  435. .TS
  436. center box;
  437. l .
  438. <macro-identifier> = "<macro-value>" ;
  439. <macro-identifier> = \fBconditional-expression\fR ;
  440. .TE
  441. The \fBconditional-expression\fR format will be discussed 
  442. later.  
  443. .sp 1
  444. The following example,
  445. .sp 1
  446. \fImacro\fR
  447. .PP
  448. first_name = "James";
  449. .PP
  450. last_name = "Schoner";
  451. .PP
  452. whole_name = "${first_name} ${second_name}";
  453. .sp 1
  454. defines the macros first_name, last_name, and whole_name, where whole_name
  455. is the string, "James Schoner".
  456. .NH 2
  457. Class definitions
  458. .PP
  459. A class is denoted by an identifier representing a logical grouping of zero 
  460. or more names.  Classes are used to represent the range of values a token
  461. may assume in the pattern matching of an address.  Further discussion on the
  462. use of classes will be deferred until address fields are described.
  463. .PP
  464. One identifier may be used to distinctly represent both a macro
  465. and class (i.e., the set of macro identifiers and the set of class identifiers
  466. may form a non-empty intersection).  A name, or class element, may 
  467. be an identifier or any quoted word.
  468. .PP
  469. A \fIclass\fR block consists of the keyword \fIclass\fR, followed by zero
  470. or more statements taking any of the following forms:
  471. .TS
  472. center box;
  473. l .
  474. <class-identifier> = { <name1>, <name2>, <name3>, ... } ;
  475. <class-identifier> = \fIreadclass\fR ( "<file-name>" ) ;
  476. <class-identifier> = \fIreadclass\fR ( "<file-name>", "<read-format>" ) ;
  477. .TE
  478. The second and third forms cause \fIsendmail\fR to read the names of the class 
  479. from the named
  480. file.  The third form contains a read format, which should be a \fIscanf(3)\fR 
  481. pattern yielding a single string.
  482. .sp 1
  483. The following example,
  484. .sp 1
  485. \fIclass\fR
  486. .PP
  487. campus_hosts = { statistics, engineering, chemistry, physics, physics-2 } ;
  488. .PP
  489. versions     = { "1.0", "1.1", "4.0", "4.2", latest-and-greatest } ;
  490. .PP
  491. phone_hosts  = \fIreadclass\fR ( "/tmp/phonenet.list" ) ;
  492. .sp 1
  493. defines the classes campus_hosts, versions, and phone_hosts.
  494. .NH 2
  495. Sendmail option definitions
  496. .PP
  497. A number of options to the \fIsendmail\fR program may be specified in 
  498. an \fIoptions\fR
  499. block.  For a description of the various \fIsendmail\fR options and their 
  500. values, see Appendix B.  
  501. .PP
  502. An
  503. \fIoptions\fR block consists of the keyword \fIoptions\fR, followed by zero
  504. or more statements taking any of the following forms:
  505. .TS
  506. center box;
  507. l l .
  508. <option-identifier>    = "<option-value>" ;
  509. \fIo_delivery\fR    = \fBspecial-value\fR ;
  510. \fIo_handling\fR    = \fBspecial-value\fR ;
  511. .TE
  512. All but two options (\fIo_delivery\fR and \fIo_handling\fR) use the first 
  513. form.  To specify an option without a value, simply assign to it the null 
  514. string ("").  The \fBspecial-value\fR field of the second and third form
  515. refers to special values (non-quoted) which are specified in Appendix B.
  516. .sp 1
  517. The following example,
  518. .sp 1
  519. \fIoptions\fR
  520. .PP
  521. \fIo_alias\fR = "/usr/lib/aliases" ;
  522. .PP
  523. \fIo_tmode\fR = "0600" ;
  524. .PP
  525. \fIo_delivery\fR = d_background ;
  526. .sp 1
  527. sets the options \fIo_alias\fR, \fIo_tmode\fR, and \fIo_delivery\fR.
  528. .NH 2
  529. Precedence definitions
  530. .PP
  531. Message headers may contain a \*QPrecedence:\*U field describing the precedence
  532. of the message class.  Identifiers which may appear in the precedence field of
  533. a message are given precedence values in a configuration file \fIprecedence\fR 
  534. definition.  This association will be illustrated below in an example.
  535. .PP
  536. A \fIprecedence\fR block consists of the keyword \fIprecedence\fR, followed 
  537. by zero or more statements of the form:
  538. .KS
  539. .TS
  540. center box;
  541. l .
  542. <precedence-identifier> = <precedence-integer> ;
  543. .TE
  544. .KE
  545. The following example,
  546. .sp 1
  547. \fIprecedence\fR
  548. .PP
  549. special-delivery = 100;
  550. .PP
  551. junk = -100;
  552. .sp 1
  553. defines the precedence level for the names \*Qspecial-delivery\*U and 
  554. \*Qjunk\*U.  Thus, whenever the name \*Qjunk\*U appears in 
  555. a \*QPrecedence:\*U field, the corresponding message class will be set to -100.
  556. .NH 2
  557. Trusted users
  558. .PP
  559. \fISendmail\fR's \fB-f\fR flag allows trusted users to override the sender's
  560. machine address.  Trusted users are listed in \fItrusted\fR blocks.  A 
  561. \fItrusted\fR block consists of the keyword \fItrusted\fR, followed 
  562. by zero or more sets of users taking the form:
  563. .TS
  564. center box;
  565. l .
  566. { <user1>, <user2>, <user3>, ... } ;
  567. .TE
  568. The following example,
  569. .sp 1
  570. \fItrusted\fR
  571. .PP
  572. { root, uucp, network } ;
  573. .PP
  574. { acu, kcs, jss } ;
  575. .sp 1
  576. specifies that the users root, uucp, network, acu, kcs, and jss can be trusted 
  577. to use the \fIsendmail\fR flag, \fB-f\fR.
  578. .NH 2
  579. Mail header definitions
  580. .PP
  581. The format of the message headers inserted by \fIsendmail\fR is defined in one
  582. or more \fIheader\fR blocks in the configuration file.  A \fIheader\fR block
  583. consists of the keyword \fIheader\fR, followed by zero or more statements
  584. taking any of the following forms:
  585. .TS
  586. center box;
  587. l
  588. l
  589. l
  590. l
  591. l
  592. l
  593. l
  594. l
  595. l
  596. l .
  597. \fIfor\fR ( <mailer-flag1>, <mailer-flag2>, ... )
  598.        \fIdefine\fR ( "<header-title>" , \fBheader-value\fR ) ;
  599.  
  600. \fIfor\fR ( <mailer-flag1>, <mailer-flag2>, ... ) {
  601.        \fIdefine\fR ( "<header-title>" , \fBheader-value\fR ) ;
  602.        \fIdefine\fR ( "<header-title>" , \fBheader-value\fR ) ;
  603.        .
  604.        .
  605. } ;
  606.  
  607. \fIdefine\fR ( "<header-title>" , \fBheader-value\fR ) ;
  608. .TE
  609. The first form is used to define one header for one or more mailer
  610. flags.  The second form differs from the first in that more than one
  611. header may be defined for a given set of flags.  The third form is used to 
  612. define a header,
  613. regardless of mailer flags.  Refer to Appendix C for a list of \fBEase\fR 
  614. identifiers representing mailer flags.  The header title is a simple
  615. string of characters (no macro references), whereas the \fBheader-value\fR can
  616. be either a string of characters (possibly containing macro references) or 
  617. a \fBconditional-expression\fR (discussed later).
  618. .sp 1
  619. The following example,
  620. .DS
  621. \fIheader\fR
  622.  
  623.     \fIdefine\fR ( "Subject:", "") ;
  624.  
  625.     \fIfor\fR ( \fIf_return\fR )
  626.         \fIdefine\fR ( "Return-Path:", "<${\fIm_sreladdr\fR}>" ) ;
  627.  
  628.     \fIfor\fR ( \fIf_date\fR ) {
  629.         \fIdefine\fR ( "Resent-Date:", "${\fIm_odate\fR}" ) ;
  630.         \fIdefine\fR ( "Date:", "${\fIm_odate\fR}" );
  631.     } ;
  632. .DE
  633. defines a \*QSubject\*U field for all mailers, regardless of their flags, a
  634. \*QReturn-Path\*U field for mailers whose definition specifies
  635. the flag, \fIf_return\fR, and the headers, \*QResent-Date\*U and \*QDate\*U,
  636. for mailers whose definition specifies the flag, \fIf_date\fR.
  637. .NH 2
  638. Mailer Definitions
  639. .PP
  640. \fISendmail\fR's definition of a mailer (or an interface to one) occurs in a
  641. \fImailer\fR block.  A \fImailer\fR block consists of the keyword \fImailer\fR,
  642. followed by zero or more statements of the form:
  643. .TS
  644. center box;
  645. l .
  646. <mailer-identifier> { \fBmailer-spec\fR } ;
  647. .TE
  648. The field, \fBmailer-spec\fR, is a list of zero or more of the
  649. following attribute assignments (where successive assignment statements are
  650. separated by commas):
  651. .TS
  652. center ;
  653. l l 
  654. l l
  655. l l
  656. l l
  657. l l
  658. l l
  659. l l .
  660. \fIPath\fR    = \fBstring-attribute\fR
  661. \fIArgv\fR    = \fBstring-attribute\fR
  662. \fIEol\fR    = \fBstring-attribute\fR
  663. \fIMaxsize\fR    = \fBstring-attribute\fR
  664. \fIFlags\fR    = { <mailer-flag1>, <mailer-flag2>, ... } 
  665. \fISender\fR    = <sender-ruleset-id>
  666. \fIRecipient\fR    = <recipient-ruleset-id>
  667. .TE
  668. The \fBstring-attribute\fR value can take the form of a quoted string
  669. (possibly containing macro references) or a \fBconditional-expression\fR 
  670. (discussed later).
  671. .sp 1
  672. The following example,
  673. .sp 1
  674. \fImailer\fR
  675. .DS
  676.     local {
  677.         \fIPath\fR        = "/bin/mail",
  678.         \fIFlags\fR        = { \fIf_from\fR, \fIf_locm\fR },
  679.         \fISender\fR    = Sender_RW,
  680.         \fIRecipient\fR    = Recip_RW,
  681.         \fIArgv\fR        = "mail -d ${\fIm_ruser\fR}",
  682.         \fIMaxsize\fR    = "200000"
  683.     } ;
  684. .DE
  685. defines a mailer named \*Qlocal\*U.
  686. .NH 2
  687. Address field definitions
  688. .PP
  689. \fISendmail\fR's address parsing scheme treats an address as a group of tokens
  690. (an address token is precisely defined in the Arpanet protocol RFC822).  In
  691. general, \fIsendmail\fR divides an address into tokens based on a list of
  692. characters assigned as a string to the special macro \fIm_addrops\fR.  These
  693. characters will individually be considered as tokens and will separate tokens
  694. when parsing is performed. 
  695. .PP
  696. For
  697. the \fBEase\fR language, there is a distinct set of address tokens (defined
  698. below) which are used in combination to represent generic forms of 
  699. addresses.  In 
  700. addition to literal address tokens, the pattern to be matched in a rewriting 
  701. rule (often refered to as the LHS) may
  702. include field identifiers which match one of five possibilities:
  703. .DS
  704.     - zero or more tokens
  705.     - one or more tokens
  706.     - one token exactly
  707.     - one token which is an element of an aribitrary class \fBX\fR
  708.     - one token which is not an element of an aribitrary class \fBX\fR
  709. .DE
  710. A particular field type may be assigned to one or more identifiers.  Each
  711. field identifier is associated with (or defined to be) a field type in
  712. a \fIfield\fR declarations block.  A \fIfield\fR declarations block consists
  713. of the keyword \fIfield\fR, followed by zero or more field definitions of
  714. the form:
  715. .TS
  716. center box;
  717. l .
  718. \fBfield-id-list\fR : \fBfield-type\fR ;
  719. .TE
  720. A \fBfield-id-list\fR is a list of one or more identifiers, each separated by
  721. a comma.  A \fBfield-type\fR, on the other hand, is a representation of 
  722. one of the five fields 
  723. described above.  The syntax for each of the five forms follows:
  724. .DS
  725.     \fImatch\fR ( 0* )
  726.     \fImatch\fR ( 1* )
  727.     \fImatch\fR ( 1 )
  728.     \fImatch\fR ( 1 ) in <class-X>
  729.     \fImatch\fR ( 0 ) in <class-X>
  730. .DE
  731. The star in the first two forms means: "or more".  Thus, the first
  732. form would read: "match zero or more tokens".  The fourth form describes
  733. a field where one token is matched from an arbitrary class (class-X), whereas
  734. the fifth form describes a field where one token is matched if it is not of the
  735. given class (class-X).
  736. .sp 1
  737. The following example,
  738. .sp 1
  739. .DS
  740. \fIfield\fR
  741.     anypath        : \fImatch\fR ( 0* );
  742.     recipient_host    : \fImatch\fR ( 1 );
  743.     local_site        : \fImatch\fR ( 1 ) in \fIm_sitename\fR;
  744.     remote_site        : \fImatch\fR ( 0 ) in \fIm_sitename\fR;
  745. .DE
  746. defines the fields anypath, recipient_host, local_site, and remote_site.
  747. .NH 2
  748. Address rewriting rules
  749. .PP
  750. Address rewriting rules are grouped according to the function they perform.  For
  751. example, it is desirable to form a distinct group for those rewriting rules 
  752. which perform transformations on recipient addresses.
  753. .PP
  754. Sets of rewriting rules are defined in \fIruleset\fR blocks.  A \fIruleset\fR
  755. block consists of the keyword \fIruleset\fR, followed by zero or more
  756. ruleset definitions of the form:
  757. .TS
  758. center box;
  759. l .
  760. <ruleset-id> { <rewriting-rule1> <rewriting-rule2> ... }
  761. .TE
  762. The ruleset identifier, ruleset-id, must be defined in a \fIbind\fR block, as
  763. described earlier.  The rewriting rules have the form:
  764. .DS
  765.     \fIif\fR ( <match-pattern> )
  766.         <match-action> ( <rewriting-pattern> ) ;
  767. .DE
  768. where match-pattern, rewriting-pattern, and match-action are described below.
  769. .NH 3
  770. Match-patterns
  771. .PP
  772. A match-pattern is a sequence of Ease address elements representing an
  773. address format.  If the address being rewritten matches the pattern
  774. \*Qmatch-pattern\*U,
  775. then the address is reformatted using the pattern \*Qrewriting-pattern\*U, and 
  776. the corresponding
  777. action (\*Qmatch-action\*U) is performed.  The five distinct Ease address
  778. elements which may constitute a match-pattern are as follows:
  779. .TS
  780. center ;
  781. l .
  782. 1. Field Identifiers (refer to previous section)
  783. T{
  784. 2. Non-alphanumeric characters (the exception is the case for literal 
  785. double quotes, which must be preceded by a backslash (\\\\\)
  786. T}
  787. 3. Macro references
  788. 4. Quoted strings ("...")
  789. 5. \fBConditional-expressions\fR (discussed later)
  790. .TE
  791. Below are two sample match-patterns, each describing the same address format:
  792. .DS
  793.     user-id @ hostname . $arpa_suffix
  794.     user-id @ hostname ".ARPA"
  795. .DE
  796. where user-id and hostname are field identifiers, and arpa_suffix is a 
  797. user-defined macro with the value \*QARPA\*U.
  798. .NH 3
  799. Rewriting-patterns
  800. .PP
  801. A rewriting-pattern specifies the form in which to rewrite a matched 
  802. address.  The seven distinct elements which may be used to form 
  803. a rewriting-pattern are as follows:
  804. .TS
  805. center ;
  806. l .
  807.  
  808. T{
  809. 1. Non-alphanumeric characters (the exception is the case for literal
  810. double quotes, left parentheses, or right parentheses, each of which 
  811. must be preceded by a backslash (\\\\\). 
  812. T}
  813.  
  814. T{
  815. 2. A call to another ruleset.  This is used to perform rewrites
  816. on a suffix of the rewriting-pattern.  The proper use of this
  817. feature will be demonstrated by example below. 
  818. T}
  819.  
  820. 3. Quoted strings ("...").
  821.  
  822. 4. \fBConditional-expressions\fR (discussed later).
  823.  
  824. 5. A macro reference.
  825.  
  826. T{
  827. 6. A positional reference in the matched address.  A positional 
  828. reference takes the form: $<integer-position>.  For example, 
  829. $3 references the value of the third \fBEase\fR address 
  830. element in the matched address.
  831. T}
  832.  
  833. T{
  834. 7. Canonicalized host names of the form \fIcanon\fR (<id-token>),
  835. where id-token is a regular identifier, a quoted identifier (with
  836. double quotes), a macro reference yielding an identifier, or a 
  837. positional reference in the matched address.  The canonicalization of 
  838. a host name is simply a mapping to its canonical (or official) form.
  839. T}
  840.  
  841. .TE
  842. Below are two sample rewriting-patterns:
  843. .DS
  844.     $1 % $2 < @ $3 ".ARPA" >
  845.     OLDSTYLE_RW ( $1 )
  846. .DE
  847. The first form specifies an address such as a%b<@c.ARPA>, where a, b, and c
  848. represent matched identifiers or paths.  The second form specifies a call to
  849. the ruleset \*QOLDSTYLE_RW\*U, for old-style rewriting on the parameter 
  850. $1, which probably references the entire matched address.  This will become 
  851. clear in later examples.
  852. .NH 3
  853. Match-actions
  854. .PP
  855. When a ruleset is called, the address to be rewritten is compared (or matched)
  856. sequentially against the match-address of each rewriting rule.  When a
  857. match-address describes the address \fIsendmail\fR is attempting to rewrite, the
  858. address is rewritten (or reformatted) using the rule's 
  859. rewriting-pattern.  Following this rewrite, the corresponding match-action
  860. is performed.  There are four match-actions:
  861. .TS
  862. center ;
  863. l l .
  864. \fIretry\fR    T{
  865. -a standard action which causes the rewritten address
  866. to be again compared to the match-address of the current rule. 
  867. T}
  868.  
  869. \fInext\fR    T{
  870. -an action which causes the rewritten address to be
  871. compared to the match-address of the next rewriting rule of the current 
  872. ruleset.  If the end of the list is reached, the ruleset returns the 
  873. rewritten address.
  874. T}
  875.  
  876. \fIreturn\fR    T{
  877. -an action which causes an immediate return of the 
  878. ruleset with the current rewritten address.
  879. T}
  880.  
  881. \fIresolve\fR    T{
  882. -an action which specifies that the address has been
  883. completely resolved (i.e., no further rewriting is necessary).  The 
  884. \fIresolve\fR action is described in more detail below. 
  885. T}
  886. .TE
  887. .PP
  888. The match-action, \fIresolve\fR, is special in that it terminates
  889. the address rewriting altogether.  The semantic structure of \fIsendmail\fR's
  890. rewriting scheme requires that a \fIresolve\fR action appear only in the 
  891. ruleset whose numerical binding is to the number zero.  The \fIresolve\fR action
  892. must specify three parameters: \fImailer\fR, \fIhost\fR, and \fIuser\fR.  If
  893. the \fImailer\fR is local, the \fIhost\fR parameter may be omitted.  The
  894. \fImailer\fR argument must be specified as a single word, macro, or positional
  895. reference in the matched address.  The \fIhost\fR argument may be specified as 
  896. a single word or as an expression which expands to a single word (i.e.,
  897. \fIhost\fR ($1 ".ARPA")).  In addition, the \fIhost\fR argument may be a
  898. canonicalization (as described above) or a numeric internet specification.  The
  899. keyword \fIhostnum\fR is used for numeric internet specifications, as in 
  900. \fIhostnum\fR ("00.00.00.00") or \fIhostnum\fR ( $2 ).  The \fIuser\fR 
  901. specification is a rewriting-pattern, as described above.  
  902. .PP
  903. In general, the format of a \fIresolve\fR action will be as follows:
  904. .DS
  905.     \fIresolve\fR (    \fImailer\fR ( <mailer-name> ),
  906.             \fIhost\fR   ( <host-name> ),
  907.             \fIuser\fR   ( <user-address>)   );
  908. .DE
  909. Examples of the match-action statement are shown below:
  910. .DS
  911. \fIfield\fR
  912.     anypath    : \fImatch\fR (0*);
  913.     usr, path    : \fImatch\fR (1*);
  914.     hostname    : \fImatch\fR (1);
  915.     phone_host    : \fImatch\fR (1) in phonehosts;
  916. .DE
  917. .DS
  918. \fIruleset\fR
  919.  
  920.     EXAMPLE_RW {
  921.     
  922.         \fIif\fR ( anypath < path > anypath )   /* basic RFC821/822 parse */
  923.             \fIretry\fR ( $2 );
  924.         \fIif\fR ( usr " at " path )        /* \*Qat\*U -> \*Q@\*U */
  925.             \fInext\fR ( $1 @ $2 );
  926.         \fIif\fR ( @path: usr )
  927.             \fIreturn\fR ( LOCAL_RW ( < @$1 > : $2 ) );
  928.         \fIif\fR ( anypath < @phone_host".ARPA" > anypath )
  929.             \fIresolve\fR (    \fImailer\fR ( tcp ),
  930.                     \fIhost\fR ( csnet-relay ),
  931.                     \fIuser\fR ( $1 % $2 < @"csnet-relay" > $3 ) );
  932.     }
  933. .DE
  934. .PP
  935. The example above defines the ruleset \*QEXAMPLE_RW\*U, which contains four
  936. rewriting rules.  The first rewriting rule discards all tokens of an address
  937. which lie on either side of a pair of angle brackets (<>), thereby 
  938. rewriting the address as
  939. the sequence of tokens contained within the angle brackets ($2).  Following the
  940. address rewrite, the rule is applied again (\fIretry\fR).  When the first rule
  941. fails to match the address being rewritten, the second rule is applied.  
  942. .PP
  943. The second 
  944. rule simply replaces the word \*Qat\*U by the symbol \*Q@\*U.  The \*Q\fInext\fR\*U
  945. action specifies that if a match is made, a rewrite is performed and 
  946. matching continues at the next (or following) rule.  
  947. .PP
  948. The third rule illustrates
  949. the use of the \*Q\fIreturn\fR\*U action, which is executed if the 
  950. pattern \*Q@path: usr\*U
  951. describes the current format of the address being rewritten.  In this example,
  952. the \fIreturn\fR action returns the result of a call to ruleset \*QLOCAL_RW\*U,
  953. which rewrites the address \*Q<@$1>:$2\*U, where $1 and $2 are substituted
  954. with the token(s) matched respectively by \*Qpath\*U and \*Qusr\*U.
  955. .PP
  956. The fourth (and final) rule signals a resolution (and termination) of the
  957. rewriting process if the given pattern is matched.  The resolution specifies
  958. that the mailer \*Qtcp\*U will be used to deliver the message to the host
  959. \*Qcsnet-relay\*U.  The \fIuser\fR parameter specifies the final form of the address
  960. which \fIsendmail\fR has just resolved.
  961. .sp 2
  962. .PP
  963. The \fBEase\fR construct which remains to be examined is the 
  964. \fBconditional-expression\fR.  The \fBconditional-expression\fR provides a 
  965. method for
  966. constructing strings based on the condition that some test macro is (or is not)
  967. set.  The general form begins with the concatenation of a string and a
  968. \fBstring-conditional\fR:
  969. .DS
  970.     \fIconcat\fR ( <quoted-string>, \fBstring-conditional\fR )
  971.     \fIconcat\fR ( \fBstring-conditional\fR, <quoted-string> )
  972. .DE
  973. A \fBstring-conditional\fR assumes either of the following forms:
  974. .DS
  975.     \fIifset\fR ( <macro-name>, <ifset-string> )
  976.     \fIifset\fR ( <macro-name>, <ifset-string>, <notset-string> )
  977. .DE
  978. A \fBstring-conditional\fR of the first form evaluates to \*Qifset-string\*U 
  979. if the macro \*Qmacro-name\*U has been assigned a value; otherwise it
  980. evaluates to the null string.  The second form behaves similarly, except
  981. that the \fBstring-conditional\fR evaluates to \*Qnotset-string\*U, instead
  982. of the null string, if the macro \*Qmacro-name\*U has no value.
  983. .sp 1
  984. The following \fBconditional-expression\fR,
  985. .DS
  986.     \fIconcat\fR ( "New ", \fIifset\fR ( city, "York", "Jersey" ) )
  987. .DE
  988. evaluates to the string "New York", if the macro \*Qcity\*U is set.  Otherwise,
  989. the \fBconditional-expression\fR evaluates to the string "New Jersey".
  990. .NH
  991. Ease Translation
  992. .PP
  993. It is important to note that \fBEase\fR is translated by a stand-alone
  994. translator to the raw configuration file format.  No modifications were
  995. made to the \fIsendmail\fR program itself.  As a result, syntactical verification
  996. of a configuration file can be performed without invoking \fIsendmail\fR.
  997. .PP
  998. The \fBEase\fR language is translated by invoking 
  999. the C language preprocessor (cpp) with \fBEase\fR source as input, then piping
  1000. the output as input to the \fBEase\fR translator (\fIet\fR).  The \fBEase\fR
  1001. translator may be invoked on the command line in one of four ways:
  1002. .TS
  1003. center box ;
  1004. l l .
  1005. \fIet\fR  <input-file>  <output-file>    [read from a file, write to a file]
  1006. \fIet\fR  <input-file>    [read from a file, write to standard output]
  1007. \fIet\fR  -  <output-file>    [read from standard input, write to a file]
  1008. \fIet\fR    [read from standard input, write to standard output]
  1009. .TE
  1010. .NH
  1011. Conclusion
  1012. .PP
  1013. \fBEase\fR is currently in use at the Purdue University Computing 
  1014. Center.  Source code for the \fBEase\fR translator (\fIet\fR) may be
  1015. obtained on request by writing to:
  1016. .DS
  1017. U.S. Mail:
  1018.         James S. Schoner
  1019.         c/o Kevin S. Braunsdorf
  1020.         Purdue University Computing Center
  1021.         Purdue University
  1022.         West Lafayette, Indiana  47907
  1023.  
  1024. Electronic Mail:
  1025.         ksb@j.cc.purdue.edu
  1026. .DE
  1027. .PP
  1028. Much of the success of this project is attributable to the constant support 
  1029. and insight offered by Mark Shoemaker.  To him, I owe a debt of gratitude.  In 
  1030. addition, I would like to thank Kevin Smallwood, Paul Albitz, and Rich Kulawiec
  1031. for their many notable suggestions and valuable insight.
  1032. SHAR_EOF
  1033. if test 29063 -ne "`wc -c ease.paper`"
  1034. then
  1035. echo shar: error transmitting ease.paper '(should have been 29063 characters)'
  1036. fi
  1037. cat << \SHAR_EOF > Makefile
  1038. #
  1039. #    Makefile for Ease document.
  1040. #
  1041. #    James S. Schoner
  1042. #    Purdue University Computing Center
  1043. #
  1044. all:    cover mainbody apen1 apen2 apen3
  1045.     
  1046. cover: FRC
  1047.     troff -ms cover
  1048.  
  1049. mainbody:
  1050.     tbl ease.paper | troff -ms
  1051.  
  1052. apen1:
  1053.     tbl ap1 | troff -ms
  1054.  
  1055. apen2:
  1056.     tbl ap2 | troff -ms
  1057.  
  1058. apen3:
  1059.     tbl ap3 | troff -ms
  1060.  
  1061. FRC:
  1062.  
  1063. SHAR_EOF
  1064. if test 293 -ne "`wc -c Makefile`"
  1065. then
  1066. echo shar: error transmitting Makefile '(should have been 293 characters)'
  1067. fi
  1068. chdir ..
  1069. mkdir src
  1070. chdir src
  1071. cat << \SHAR_EOF > parser.y
  1072. %{
  1073. /*    $Header: /usr/src/local/etc/ease/RCS/parser.y,v 1.3 85/12/10 18:02:11 jss Exp $    */
  1074.  
  1075. /*
  1076.  *    parser.y -- EASE parser.
  1077.  *
  1078.  *            Contains code for yacc(1) which produces a parser (y.tab.c)
  1079.  *            for Ease, a specification format for sendmail configuration
  1080.  *            files.
  1081.  *
  1082.  *    author   -- James S. Schoner, Purdue University Computing Center,
  1083.  *                          West Lafayette, Indiana  47907
  1084.  *
  1085.  *    date     -- July 2, 1985
  1086.  *
  1087.  *    Copyright (c) 1985 by Purdue Research Foundation
  1088.  *
  1089.  *    All rights reserved.
  1090.  *
  1091.  */
  1092.  
  1093. #include <stdio.h>
  1094. #include "symtab.h"
  1095.  
  1096. extern void       BindID ();
  1097. extern void       EmitDef ();
  1098. extern char      *ListAppend ();
  1099. extern char       *MakeCond ();
  1100. extern char      *MakeRStr ();
  1101. extern char       *ConvOpt ();
  1102. extern char      *ConvFlg ();
  1103. extern char      *MacScan ();
  1104. extern char      *ConvMat ();
  1105. extern void       StartRuleset ();
  1106. extern char      *MakePosTok ();
  1107. extern char      *GetField ();
  1108. extern char      *Bracket ();
  1109. extern char      *MakeRSCall ();
  1110. extern char      *CheckMailer ();
  1111. extern char      *CheckRS ();
  1112. extern char      *MakeField ();
  1113. extern char       MakeMac ();
  1114. extern void       AssignType ();
  1115. extern void       RemoveSymbol ();
  1116. extern void       yyerror ();
  1117.  
  1118. extern short RMatch;        /* ruleset match flag               */
  1119.  
  1120. char *Cbuf = " ";        /* character buffer                 */
  1121. char *Mbuf = "$ ";        /* macro buffer                        */
  1122. char *Tsb;            /* pointer to temporary string buffer */
  1123. char *Flaglist;            /* pointer to header flag list          */
  1124.  
  1125. %}
  1126.  
  1127. %union {            /* value stack element type    */
  1128.     int      ival;        /* integer token            */
  1129.     char      *psb;        /* string token               */
  1130.     struct he *phe;        /* pointer to hash entry       */
  1131.     enum opts optval;    /* sendmail options           */
  1132.     enum flgs flgval;    /* mailer flags               */
  1133.     enum mats mpval;    /* mailer attribute parameters */
  1134. }
  1135.  
  1136. %start config
  1137.  
  1138. %token     <phe>    IDENT
  1139. %token  <psb>    SCONST
  1140. %token  <ival>    ICONST SEPCHAR
  1141. %token BIND MACRO CLASS OPTIONS PRECEDENCE TRUSTED HEADER RULESET MAILER
  1142. %token IF RETRY NEXT RETURN RESOLVE CONCAT IFSET FOR CANON READCLASS
  1143. %token MPATH MFLAGS MSENDER MRECIPIENT MARGV MEOL MMAXSIZE
  1144. %token AAOPT AOPT BBOPT COPT DOPT DOPTI DOPTB DOPTQ DDOPT EOPT EOPTP EOPTE 
  1145. %token EOPTM EOPTW EOPTZ FFOPT FOPT GOPT HHOPT IOPT LLOPT MOPT NNOPT OOPT QQOPT
  1146. %token ROPT SSOPT SOPT TTOPT TOPT UOPT VOPT WWOPT XOPT XXOPT
  1147. %token FFLAG RFLAG SSFLAG NFLAG LFLAG SFLAG MFLAG FFFLAG DDFLAG MMFLAG XFLAG
  1148. %token PPFLAG UFLAG HFLAG AAFLAG UUFLAG EFLAG XXFLAG LLFLAG PFLAG IIFLAG CCFLAG
  1149. %token ASGN COMMA LBRACE RBRACE LPAREN RPAREN SEMI DOLLAR MATCH IN HOSTNUM
  1150. %token DEFINE FIELD COLON STAR HOST USER
  1151.  
  1152. %type    <psb>        mval strval ifcon conval ifres elseres nameset namelist
  1153. %type    <psb>        doptid eoptid idlist fcond dlist mflags route mdefs
  1154. %type    <psb>        matchaddr matchtok action actionstmt mailerspec mtdef
  1155. %type    <psb>        rwaddr rwtok ftype reftok rword cantok resolution
  1156. %type    <psb>        userspec hword hostid dheader
  1157. %type    <ival>        anychar
  1158. %type    <phe>        cdef
  1159. %type    <optval>    optid
  1160. %type    <flgval>    flagid
  1161. %type    <mpval>        mvar
  1162.  
  1163. %left COMMA
  1164. %left LPAREN RPAREN
  1165. %nonassoc SCONST
  1166.  
  1167. %%
  1168. config        :    /* empty */
  1169.         |    config blockdef
  1170.         |    error blockdef
  1171.         ;
  1172.  
  1173. blockdef    :    BIND bindings
  1174.         |    MACRO macdefs
  1175.         |    CLASS classdefs
  1176.         |    OPTIONS optdefs
  1177.         |    PRECEDENCE precdefs
  1178.         |    TRUSTED tlist
  1179.         |    HEADER hdefs
  1180.         |    MAILER mlist
  1181.         |    RULESET rdef
  1182.         |    FIELD fdefs
  1183.         ;
  1184.  
  1185. bindings    :    /* empty */
  1186.         |    bindings IDENT ASGN RULESET ICONST SEMI {
  1187.                 BindID ($2, $5, ID_RULESET);
  1188.             }
  1189.         |    error SEMI {
  1190.                 yyerrok;
  1191.             }
  1192.         ;
  1193.  
  1194. macdefs        :    /* empty */
  1195.         |    macdefs IDENT ASGN mval SEMI {
  1196.                 EmitDef (def_macro, $2, $4, (char *) NULL);
  1197.             }
  1198.         |    error SEMI {
  1199.                 yyerrok;
  1200.             }
  1201.         ;
  1202.  
  1203. mval        :    strval                %prec COMMA {
  1204.                 $$ = $1;
  1205.             }
  1206.         |    CONCAT LPAREN conval RPAREN {
  1207.                 $$ = $3;
  1208.             }
  1209.         ;
  1210.  
  1211. strval        :    SCONST {
  1212.                 $$ = $1;
  1213.             }
  1214.         |    strval SCONST {
  1215.                 $$ = ListAppend ($1, $2, (char *) NULL);
  1216.                 free ($1);
  1217.             }
  1218.         ;
  1219.  
  1220. conval        :    strval COMMA ifcon {
  1221.                 $$ = ListAppend ($1, $3, (char *) NULL);
  1222.                 free ($1);
  1223.                 free ($3);
  1224.             }
  1225.         |    ifcon COMMA strval {
  1226.                 $$ = ListAppend ($1, $3, (char *) NULL);
  1227.                 free ($1);
  1228.                 free ($3);
  1229.             }
  1230.         |    error {
  1231.                 $$ = NULL;
  1232.             }
  1233.         ;
  1234.  
  1235. ifcon        :    IFSET LPAREN IDENT COMMA ifres RPAREN {
  1236.                 $$ = MakeCond ($3, $5);
  1237.             }
  1238.         ;
  1239.  
  1240. ifres        :    mval elseres {
  1241.                 if ($2 != NULL) {
  1242.                     $$ = ListAppend ($1, $2, "$|");
  1243.                     free ($1);
  1244.                     free ($2);
  1245.                 } else
  1246.                     $$ = $1;
  1247.             }
  1248.         |    error {
  1249.                 $$ = NULL;
  1250.             }
  1251.         ;
  1252.  
  1253. elseres        :    /* empty */ {
  1254.                 $$ = NULL;
  1255.             }
  1256.         |    COMMA mval {
  1257.                 $$ = $2;
  1258.             }
  1259.         ;
  1260.  
  1261. classdefs    :    /* empty */ 
  1262.         |    classdefs IDENT ASGN nameset {
  1263.                 EmitDef (def_class, $2, $4, (char *) NULL);
  1264.             }
  1265.         |    error
  1266.         ;
  1267.  
  1268. nameset        :    LBRACE namelist RBRACE SEMI {
  1269.                 $$ = $2;
  1270.             }
  1271.         |    LBRACE RBRACE SEMI {
  1272.                 $$ = NULL;
  1273.             }
  1274.         |    LBRACE error RBRACE SEMI {
  1275.                 $$ = NULL;
  1276.             }
  1277.         |    READCLASS LPAREN strval RPAREN SEMI {
  1278.                 $$ = MakeRStr ($3, (char *) NULL);
  1279.             }
  1280.         |    READCLASS LPAREN strval COMMA strval RPAREN SEMI {
  1281.                 $$ = MakeRStr ($3, $5);
  1282.             }
  1283.         |    READCLASS LPAREN error RPAREN SEMI {
  1284.                 $$ = NULL;
  1285.             }
  1286.         |    error SEMI {
  1287.                 $$ = NULL;
  1288.                 yyerrok;
  1289.             }
  1290.         ;
  1291.  
  1292. namelist    :    IDENT {
  1293.                 $$ = ListAppend ($1->psb, (char *) NULL, (char *) NULL);
  1294.                 RemoveSymbol ($1);
  1295.             }
  1296.         |    strval {
  1297.                 $$ = $1;
  1298.             }
  1299.         |    namelist COMMA IDENT {
  1300.                 $$ = ListAppend ($1, $3->psb, " ");
  1301.                 free ($1);
  1302.                 RemoveSymbol ($3);
  1303.             }
  1304.         |    namelist COMMA strval {
  1305.                 $$ = ListAppend ($1, $3, " ");
  1306.                 free ($1);
  1307.                 free ($3);
  1308.             }
  1309.         ;
  1310.  
  1311. optdefs        :    /* empty */
  1312.         |    optdefs optid ASGN strval SEMI {
  1313.                 EmitDef (def_option, (struct he *) NULL, ConvOpt ($2), $4);
  1314.             }
  1315.         |    optdefs DOPT ASGN doptid SEMI {
  1316.                 EmitDef (def_option, (struct he *) NULL, ConvOpt (opt_d), $4);
  1317.             }
  1318.         |    optdefs EOPT ASGN eoptid SEMI {
  1319.                 EmitDef (def_option, (struct he *) NULL, ConvOpt (opt_e), $4);
  1320.             }
  1321.         |    error SEMI {
  1322.                 yyerrok;
  1323.             }
  1324.         ;
  1325.  
  1326. optid        :    AAOPT {
  1327.                 $$ = opt_A;
  1328.             }
  1329.         |    AOPT {
  1330.                 $$ = opt_a;
  1331.             }
  1332.         |    BBOPT {
  1333.                 $$ = opt_B;
  1334.             }
  1335.         |    COPT {
  1336.                 $$ = opt_c;
  1337.             }
  1338.         |    DDOPT {
  1339.                 $$ = opt_D;
  1340.             }
  1341.         |    FFOPT {
  1342.                 $$ = opt_F;
  1343.             }
  1344.         |    FOPT {
  1345.                 $$ = opt_f;
  1346.             }
  1347.         |    GOPT {
  1348.                 $$ = opt_g;
  1349.             }
  1350.         |    HHOPT {
  1351.                 $$ = opt_H;
  1352.             }
  1353.         |    IOPT {
  1354.                 $$ = opt_i;
  1355.             }
  1356.         |    LLOPT {
  1357.                 $$ = opt_L;
  1358.             }
  1359.         |    MOPT {
  1360.                 $$ = opt_m;
  1361.             }
  1362.         |    NNOPT {
  1363.                 $$ = opt_N;
  1364.             }
  1365.         |    OOPT {
  1366.                 $$ = opt_o;
  1367.             }
  1368.         |    QQOPT {
  1369.                 $$ = opt_Q;
  1370.             }
  1371.         |    ROPT {
  1372.                 $$ = opt_r;
  1373.             }
  1374.         |    SSOPT {
  1375.                 $$ = opt_S;
  1376.             }
  1377.         |    SOPT {
  1378.                 $$ = opt_s;
  1379.             }
  1380.         |    TTOPT {
  1381.                 $$ = opt_T;
  1382.             }
  1383.         |    TOPT {
  1384.                 $$ = opt_t;
  1385.             }
  1386.         |    UOPT {
  1387.                 $$ = opt_u;
  1388.             }
  1389.         |    VOPT {
  1390.                 $$ = opt_v;
  1391.             }
  1392.         |    WWOPT {
  1393.                 $$ = opt_W;
  1394.             }
  1395.         |    XOPT {
  1396.                 $$ = opt_x;
  1397.             }
  1398.         |    XXOPT {
  1399.                 $$ = opt_X;
  1400.             }
  1401.         ;
  1402.  
  1403. doptid        :    DOPTI {
  1404.                 $$ = ConvOpt (d_opt_i);
  1405.             }
  1406.         |    DOPTB {
  1407.                 $$ = ConvOpt (d_opt_b);
  1408.             }
  1409.         |    DOPTQ {
  1410.                 $$ = ConvOpt (d_opt_q);
  1411.             }
  1412.         ;
  1413.  
  1414. eoptid        :    EOPTP {
  1415.                 $$ = ConvOpt (e_opt_p);
  1416.             }
  1417.         |    EOPTE {
  1418.                 $$ = ConvOpt (e_opt_e);
  1419.             }
  1420.         |    EOPTM {
  1421.                 $$ = ConvOpt (e_opt_m);
  1422.             }
  1423.         |    EOPTW {
  1424.                 $$ = ConvOpt (e_opt_w);
  1425.             }
  1426.         |    EOPTZ {
  1427.                 $$ = ConvOpt (e_opt_z);
  1428.             }
  1429.         ;
  1430.  
  1431. precdefs    :    /* empty */
  1432.         |    precdefs IDENT ASGN ICONST SEMI {
  1433.                 BindID ($2, $4, ID_PREC);
  1434.                 EmitDef (def_prec, $2, (char *) NULL, (char *) NULL);
  1435.             }
  1436.         ;
  1437.  
  1438. tlist        :    /* empty */
  1439.         |    tlist LBRACE IDENT idlist RBRACE SEMI {
  1440.                 EmitDef (def_trusted, (struct he *) NULL, 
  1441.                      ListAppend ($3->psb, $4, " "), (char *) NULL);
  1442.                 free ($4);
  1443.                 RemoveSymbol ($3);
  1444.             }
  1445.         |    tlist LBRACE RBRACE SEMI
  1446.         |    error SEMI {
  1447.                 yyerrok;
  1448.             }
  1449.         ;
  1450.  
  1451. hdefs        :    /* empty */
  1452.         |    hdefs FOR fcond dheader SEMI {
  1453.                 EmitDef (def_header, (struct he *) NULL, $3, $4);
  1454.             }
  1455.         |    hdefs FOR fcond LBRACE { Flaglist = $3; } 
  1456.                 dheaders RBRACE SEMI
  1457.         |    hdefs DEFINE dlist SEMI {
  1458.                 EmitDef (def_header, (struct he *) NULL, (char *) NULL, $3);
  1459.             }
  1460.         |    error SEMI {
  1461.                 yyerrok;
  1462.             }
  1463.         ;
  1464.  
  1465. fcond        :    LPAREN RPAREN {
  1466.                 $$ = NULL;
  1467.             }
  1468.         |    LPAREN mflags RPAREN {
  1469.                 $$ = $2;
  1470.             }
  1471.         |    LPAREN error RPAREN {
  1472.                 $$ = NULL;
  1473.             }
  1474.         ;
  1475.  
  1476. mflags        :    flagid {
  1477.                 $$ = ListAppend (ConvFlg ($1), (char *) NULL, (char *) NULL);
  1478.             }
  1479.         |    mflags COMMA flagid {
  1480.                 $$ = ListAppend ($1, ConvFlg($3), (char *) NULL);
  1481.                 free ($1);
  1482.             }
  1483.         ;
  1484.  
  1485. flagid        :    FFLAG {
  1486.                 $$ = flg_f;
  1487.             }
  1488.         |    RFLAG {
  1489.                 $$ = flg_r;
  1490.             }
  1491.         |    SSFLAG {
  1492.                 $$ = flg_S;
  1493.             }
  1494.         |    NFLAG {
  1495.                 $$ = flg_n;
  1496.             }
  1497.         |    LFLAG {
  1498.                 $$ = flg_l;
  1499.             }
  1500.         |    SFLAG {
  1501.                 $$ = flg_s;
  1502.             }
  1503.         |    MFLAG {
  1504.                 $$ = flg_m;
  1505.             }
  1506.         |    FFFLAG {
  1507.                 $$ = flg_F;
  1508.             }
  1509.         |    DDFLAG {
  1510.                 $$ = flg_D;
  1511.             }
  1512.         |    MMFLAG {
  1513.                 $$ = flg_M;
  1514.             }
  1515.         |    XFLAG {
  1516.                 $$ = flg_x;
  1517.             }
  1518.         |    PPFLAG {
  1519.                 $$ = flg_P;
  1520.             }
  1521.         |    UFLAG {
  1522.                 $$ = flg_u;
  1523.             }
  1524.         |    HFLAG {
  1525.                 $$ = flg_h;
  1526.             }
  1527.         |    AAFLAG {
  1528.                 $$ = flg_A;
  1529.             }
  1530.         |    UUFLAG {
  1531.                 $$ = flg_U;
  1532.             }
  1533.         |    EFLAG {
  1534.                 $$ = flg_e;
  1535.             }
  1536.         |    XXFLAG {
  1537.                 $$ = flg_X;
  1538.             }
  1539.         |    LLFLAG {
  1540.                 $$ = flg_L;
  1541.             }
  1542.         |    PFLAG {
  1543.                 $$ = flg_p;
  1544.             }
  1545.         |    IIFLAG {
  1546.                 $$ = flg_I;
  1547.             }
  1548.         |    CCFLAG {
  1549.                 $$ = flg_C;
  1550.             }
  1551.         ;
  1552.  
  1553. dheader        :    /* empty */ {
  1554.                 $$ = NULL;
  1555.             }
  1556.         |    DEFINE dlist {
  1557.                 $$ = $2;
  1558.             }
  1559.         |    error {
  1560.                 $$ = NULL;
  1561.             }
  1562.         ;
  1563.  
  1564. dheaders    :    /* empty */
  1565.         |    dheaders DEFINE dlist SEMI {
  1566.                 EmitDef (def_header, (struct he *) NULL, Flaglist, $3);
  1567.             }
  1568.         |    error
  1569.         ;
  1570.  
  1571. dlist        :    LPAREN strval COMMA mval RPAREN {
  1572.                 $$ = ListAppend ($2, MacScan ($4), " ");
  1573.                 free ($2);
  1574.                 free ($4);
  1575.             }
  1576.         |    LPAREN error RPAREN {
  1577.                 $$ = NULL;
  1578.             }
  1579.         ;
  1580.  
  1581. mlist        :    /* empty */
  1582.         |    mlist IDENT LBRACE mdefs RBRACE SEMI {
  1583.                 EmitDef (def_mailer, $2, $4, (char *) NULL);
  1584.             }
  1585.         |    mlist IDENT LBRACE RBRACE SEMI {
  1586.                 EmitDef (def_mailer, $2, (char *) NULL, (char *) NULL);
  1587.             }
  1588.         |    error SEMI {
  1589.                 yyerrok;
  1590.             }
  1591.         ;
  1592.  
  1593. mdefs        :    mtdef {
  1594.                 $$ = $1;
  1595.             }
  1596.         |    mdefs COMMA mtdef {
  1597.                 $$ = ListAppend ($1, $3, ", ");
  1598.                 free ($1);
  1599.                 free ($3);
  1600.             }
  1601.         ;    
  1602.  
  1603. mtdef        :    mvar ASGN mval {
  1604.                 $$ = ListAppend (ConvMat ($1), MacScan ($3), "=");
  1605.                 free ($3);
  1606.             }
  1607.         |    MFLAGS ASGN LBRACE mflags RBRACE {
  1608.                 $$ = ListAppend (ConvMat (mat_flags), $4, "=");
  1609.             }
  1610.         |    MSENDER ASGN IDENT {
  1611.                 $$ = ListAppend (ConvMat (mat_sender), CheckRS ($3), "=");
  1612.             }
  1613.         |    MRECIPIENT ASGN IDENT {
  1614.                 $$ = ListAppend (ConvMat (mat_recipient), CheckRS ($3), "=");
  1615.             }
  1616.         |    error {
  1617.                 $$ = NULL;
  1618.             }
  1619.         ;
  1620.  
  1621. mvar        :    MPATH {
  1622.                 $$ = mat_path;
  1623.             }
  1624.         |    MARGV {
  1625.                 $$ = mat_argv;
  1626.             }
  1627.         |    MEOL {
  1628.                 $$ = mat_eol;
  1629.             }
  1630.         |    MMAXSIZE {
  1631.                 $$ = mat_maxsize;
  1632.             }
  1633.         ;
  1634.  
  1635. rdef        :    /* empty */
  1636.         |    rdef IDENT { StartRuleset ($2); } rulelist
  1637.         ;
  1638.  
  1639. rulelist    :    LBRACE ruledefs RBRACE {
  1640.                 RMatch = FALSE;
  1641.             }
  1642.         |    error {
  1643.                 RMatch = FALSE;
  1644.             }
  1645.         ;
  1646.  
  1647. ruledefs    :    /* empty */ {
  1648.                 RMatch = TRUE;
  1649.             }
  1650.         |    ruledefs IF LPAREN matchaddr RPAREN actionstmt {
  1651.                 EmitDef (def_ruleset, (struct he *) NULL, 
  1652.                      ListAppend ($4, $6, "\t"), (char *) NULL);
  1653.             free ($4);
  1654.             free ($6);
  1655.             }
  1656.         |    error SEMI {
  1657.                 yyerrok;
  1658.             }
  1659.         ;
  1660.  
  1661. matchaddr    :    /* empty */ {
  1662.                 $$ = NULL;
  1663.             }
  1664.         |    matchaddr matchtok {
  1665.                 $$ = ListAppend ($1, $2, (char *) NULL);
  1666.                 free ($1);
  1667.             }
  1668.         |    error {
  1669.                 $$ = NULL;
  1670.             }
  1671.         ;
  1672.  
  1673. matchtok    :    IDENT {
  1674.                 $$ = GetField ($1);
  1675.             }
  1676.         |    anychar {
  1677.                 *Cbuf = $1;
  1678.                 $$ = ListAppend (Cbuf, (char *) NULL, (char *) NULL);
  1679.             }
  1680.         |    mval {
  1681.                 $$ = MacScan ($1);
  1682.             }
  1683.         |    DOLLAR IDENT {
  1684.                 Mbuf[1] = MakeMac ($2, ID_MACRO);
  1685.                 $$ = ListAppend (Mbuf, (char *) NULL, (char *) NULL);
  1686.             }
  1687.         ;
  1688.  
  1689. actionstmt    :    action LPAREN rwaddr RPAREN SEMI {
  1690.                 $$ = ListAppend ($1, $3, (char *) NULL);
  1691.                 free ($3);
  1692.             }
  1693.         |    RESOLVE LPAREN resolution RPAREN SEMI {
  1694.                 $$ = $3;
  1695.             }
  1696.         |    error SEMI {
  1697.                 $$ = NULL;
  1698.                 yyerrok;
  1699.             }
  1700.         ;
  1701.  
  1702. action        :    RETRY {
  1703.                 $$ = NULL;
  1704.             }
  1705.         |    NEXT {
  1706.                 $$ = "$:";
  1707.             }
  1708.         |    RETURN {
  1709.                 $$ = "$@";
  1710.             }
  1711.         ;
  1712.  
  1713. rwaddr        :    /* empty */ {
  1714.                 $$ = NULL;
  1715.             }
  1716.         |    rwaddr rwtok {
  1717.                 $$ = ListAppend ($1, $2, (char *) NULL);
  1718.                 free ($1);
  1719.             }
  1720.         |    rwaddr IDENT LPAREN rwaddr RPAREN {
  1721.                 $$ = ListAppend ($1, (Tsb = MakeRSCall ($2, $4)), (char *) NULL);
  1722.                 free ($1);
  1723.                 free ($4);
  1724.                 free (Tsb);
  1725.             }
  1726.         |    error {
  1727.                 $$ = NULL;
  1728.             }
  1729.         ;
  1730.  
  1731. rwtok        :    anychar {
  1732.                 *Cbuf = $1;
  1733.                 $$ = ListAppend (Cbuf, (char *) NULL, (char *) NULL);
  1734.             }
  1735.         |    mval {
  1736.                 $$ = MacScan ($1);
  1737.             }
  1738.         |    cantok {
  1739.                 $$ = $1;
  1740.             }
  1741.         |    reftok {
  1742.                 $$ = $1;
  1743.             }
  1744.         ;
  1745.  
  1746. cantok        :    CANON LPAREN IDENT RPAREN {
  1747.                 $$ = Bracket ($3->psb, TRUE);
  1748.                 RemoveSymbol ($3);
  1749.             }
  1750.         |    CANON LPAREN SCONST RPAREN {
  1751.                 $$ = Bracket (MacScan ($3), TRUE);
  1752.                 free ($3);
  1753.             }
  1754.         |    CANON LPAREN reftok RPAREN {
  1755.                 $$ = Bracket ($3, TRUE);
  1756.                 free ($3);
  1757.             }
  1758.         ;
  1759.  
  1760. reftok        :    DOLLAR IDENT {
  1761.                 Mbuf[1] = MakeMac ($2, ID_MACRO);
  1762.                 $$ = ListAppend (Mbuf, (char *) NULL, (char *) NULL);
  1763.             }
  1764.         |    DOLLAR ICONST {
  1765.                 $$ = ListAppend (MakePosTok ($2), (char *) NULL, (char *) NULL);
  1766.             }
  1767.         ;
  1768.  
  1769. anychar        :    SEPCHAR {
  1770.                 $$ = $1;
  1771.             }
  1772.         |    COLON {
  1773.                 $$ = ':';
  1774.             }
  1775.         |    STAR {
  1776.                 $$ = '*';
  1777.             }
  1778.         |    SEMI {
  1779.                 $$ = ';';
  1780.             }
  1781.         |    LBRACE {
  1782.                 $$ = '{';
  1783.             }
  1784.         |    RBRACE {
  1785.                 $$ = '}';
  1786.             }
  1787.         |    COMMA {
  1788.                 $$ = ',';
  1789.             }
  1790.         |    ASGN {
  1791.                 $$ = '=';
  1792.             }
  1793.         ;
  1794.  
  1795. resolution    :    mailerspec COMMA route {
  1796.                 $$ = ListAppend ($1, $3, (char *) NULL);
  1797.                 free ($1);
  1798.                 free ($3);
  1799.             }
  1800.         |    error {
  1801.                 $$ = NULL;
  1802.             }
  1803.         ;
  1804.  
  1805. mailerspec    :    MAILER LPAREN rword RPAREN {
  1806.                 $$ = ListAppend ("$#", $3, (char *) NULL);
  1807.             }
  1808.         ;
  1809.  
  1810. route        :    HOST LPAREN hword RPAREN COMMA userspec {
  1811.                 $$ = ListAppend (Tsb = ListAppend ("$@", $3, (char *) NULL),
  1812.                          $6, (char *) NULL);
  1813.                 free (Tsb);
  1814.                 free ($6);
  1815.             }
  1816.         |    userspec {
  1817.                 $$ = $1;
  1818.             }
  1819.         ;
  1820.  
  1821. hword        :    hostid {
  1822.                 $$ = $1;
  1823.             }
  1824.         |    HOSTNUM LPAREN reftok RPAREN {
  1825.                 $$ = Bracket ($3, FALSE);
  1826.                 free ($3);
  1827.             }
  1828.         ;
  1829.  
  1830. hostid        :    /* empty */ {
  1831.                 $$ = NULL;
  1832.             }
  1833.         |    hostid IDENT {
  1834.                 $$ = ListAppend ($1, $2->psb, (char *) NULL);
  1835.                 RemoveSymbol ($2);
  1836.                 free ($1);
  1837.             }
  1838.         |    hostid rwtok {
  1839.                 $$ = ListAppend ($1, $2, (char *) NULL);
  1840.                 free ($1);
  1841.             }
  1842.         ;
  1843.  
  1844. userspec    :    USER LPAREN rwaddr RPAREN {
  1845.                 $$ = ListAppend ("$:", $3, (char *) NULL);
  1846.                 free ($3);
  1847.             }
  1848.         ;
  1849.  
  1850. rword        :    IDENT {
  1851.                 $$ = CheckMailer ($1);
  1852.             }
  1853.         |    reftok {
  1854.                 $$ = $1;
  1855.             }
  1856.         ;
  1857.  
  1858. fdefs        :    /* empty */
  1859.         |    fdefs IDENT idlist COLON ftype SEMI {
  1860.                 AssignType (ListAppend ($2->psb, $3, " "), $5);
  1861.                 free ($3);
  1862.             }
  1863.         |    error SEMI {
  1864.                 yyerrok;
  1865.             }
  1866.         ;
  1867.  
  1868. idlist        :    /* empty */ {
  1869.                 $$ = NULL;
  1870.             }
  1871.         |    idlist COMMA IDENT {
  1872.                 $$ = ListAppend ($1, $3->psb, " ");
  1873.                 free ($1);
  1874.             }
  1875.         ;
  1876.  
  1877. ftype        :    MATCH LPAREN ICONST RPAREN cdef {
  1878.                 $$ = ListAppend (MakeField ($3, $5, FALSE), 
  1879.                              (char *) NULL, (char *) NULL);
  1880.             }
  1881.         |    MATCH LPAREN ICONST STAR RPAREN {
  1882.                 $$ = ListAppend (MakeField ($3, (struct he *) NULL, TRUE), 
  1883.                          (char *) NULL, (char *) NULL);
  1884.             }
  1885.         |    error {
  1886.                 $$ = NULL;
  1887.             }
  1888.         ;
  1889.  
  1890. cdef        :    /* empty */ {
  1891.                 $$ = NULL;
  1892.             }
  1893.         |    IN IDENT {
  1894.                 $$ = $2;
  1895.             }
  1896.         ;
  1897. SHAR_EOF
  1898. if test 14482 -ne "`wc -c parser.y`"
  1899. then
  1900. echo shar: error transmitting parser.y '(should have been 14482 characters)'
  1901. fi
  1902. chdir ..
  1903. #    End of shell archive
  1904. exit 0
  1905.  
  1906.