2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * Copyright © 2006 Pierre Habouzit
24 static buffer_t *buffer_merge(buffer_t *A, buffer_t **B)
31 static inline int to_control(int c) {
32 return (toupper((unsigned char)c) - 'A' + 1) & 0x7f;
35 static buffer_t *buffer_escape(buffer_t *buf, const char *s, ssize_t len)
43 buffer_addch(buf, to_control(s[1]));
44 buffer_add(buf, s + 2, len - 2);
49 int i = (hexval(s[1]) << 4) | hexval(s[2]);
52 buffer_add(buf, s + 3, len - 3);
58 case '0': case '1': case '2': case '3':
60 int i = (octval(s[0]) << 6) | (octval(s[1]) << 3) | octval(s[2]);
63 buffer_add(buf, s + 3, len - 3);
69 case 'e': buffer_addch(buf, '\e'); return buf;
70 case 'f': buffer_addch(buf, '\f'); return buf;
71 case 'n': buffer_addch(buf, '\n'); return buf;
72 case 'r': buffer_addch(buf, '\r'); return buf;
73 case 't': buffer_addch(buf, '\t'); return buf;
74 case 'v': buffer_addch(buf, '\v'); return buf;
80 buffer_add(buf, s, len);
84 static void substvar(buffer_t *buf, const segment seg) {
89 if (m_strncpy(var, sizeof(var), seg.s, seg.len) <= 0)
92 if ((res = getenv(var))) {
93 buffer_addstr(buf, res);
96 if (mutt_option_value(var, tmp, sizeof(tmp))) {
97 buffer_addstr(buf, tmp);
104 %token_type { segment }
106 %extra_argument { struct rcstate *state }
108 /****************************************************************************/
110 /****************************************************************************/
112 escnl ::= BSLASH NL . { state->linenum++; }
116 sp ::= sp escnl SPACE .
118 non_nl ::= ATOM|SPACE|BQUOTE|BSLASH|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|QUOTE|RBRACE .
120 non_nl_star ::= non_nl_star non_nl .
122 to_eol_aux ::= NL . { state->linenum++; }
123 to_eol_aux ::= SHARP non_nl_star NL . { state->linenum++; }
124 to_eol ::= to_eol_aux .
125 to_eol ::= sp to_eol_aux .
127 /****************************************************************************/
128 /* Our macro tokens */
129 /****************************************************************************/
131 %type svar { segment }
132 svar(Z) ::= DOLLAR ATOM(B) . { Z = B; }
133 svar(Z) ::= DOLLAR LBRACE ATOM(B) RBRACE . { Z = B; }
135 /* '-quoted tokens */
136 %type sqtok { buffer_t* }
137 %destructor sqtok { buffer_delete(&$$); }
138 sqtok(Z) ::= . { Z = buffer_new(); }
139 sqtok(Z) ::= sqtok(A) escnl . { Z = A; }
140 sqtok(Z) ::= sqtok(A) BSLASH BSLASH|QUOTE(B) . { buffer_addch(Z = A, *B.s); }
141 sqtok(Z) ::= sqtok(A) BSLASH ATOM|SPACE|BQUOTE|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|RBRACE(B) . {
142 buffer_addch(Z = A, '\\');
143 buffer_add(Z, B.s, B.len);
145 sqtok(Z) ::= sqtok(A) ATOM|SPACE|BQUOTE|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|RBRACE(B) . {
146 buffer_add(Z = A, B.s, B.len);
149 /* "-quoted tokens */
150 %type dqtok { buffer_t* }
151 %destructor dqtok { buffer_delete(&$$); }
152 dqtok(Z) ::= . { Z = buffer_new(); }
153 dqtok(Z) ::= dqtok(A) escnl . { Z = A; }
154 dqtok(Z) ::= dqtok(A) BSLASH non_nl(B) . { Z = buffer_escape(A, B.s, B.len); }
155 dqtok(Z) ::= dqtok(A) ATOM|SPACE|SHARP|EQUAL|LBRACE|RBRACE(B) . {
156 buffer_add(Z = A, B.s, B.len);
158 dqtok(Z) ::= dqtok(A) svar(B) . { substvar(Z = A, B); }
160 /* unquoted tokens */
161 %type uqtok { buffer_t* }
162 %destructor uqtok { buffer_delete(&$$); }
163 uqtok(Z) ::= ATOM|EQUAL|LBRACE|RBRACE(A) . { buffer_add(Z = buffer_new(), A.s, A.len); }
164 uqtok(Z) ::= BSLASH non_nl(A) . { buffer_add(Z = buffer_new(), A.s, A.len); }
165 uqtok(Z) ::= QUOTE sqtok(A) QUOTE . { Z = A; }
166 uqtok(Z) ::= DQUOTE dqtok(A) DQUOTE . { Z = A; }
167 uqtok(Z) ::= svar(B) . { substvar(Z = buffer_new(), B); }
169 /* token accumulator */
170 %type token { buffer_t* }
171 %destructor token { buffer_delete(&$$); }
172 token(Z) ::= uqtok(A) . { Z = A; }
173 token(Z) ::= token(A) escnl . { Z = A; }
174 token(Z) ::= token(A) uqtok(B) . { Z = buffer_merge(A, &B); }
176 /****************************************************************************/
178 /****************************************************************************/
180 %type simple_list { string_list_t * }
181 %destructor simple_list { string_list_wipe(&$$); }
183 simple_list(L) ::= simple_list(A) sp token(B) . {
184 L = string_item_new();
185 L->data = buffer_unwrap(&B);
190 /****************************************************************************/
191 /* Entry point : the rc lines */
192 /****************************************************************************/
196 rclines ::= rclines rcline .
198 rcline ::= ALTERNATIVE_ORDER simple_list(L) to_eol . {
199 string_list_append(&AlternativeOrderList, string_list_rev(L));
201 rcline ::= AUTO_VIEW simple_list(L) to_eol . {
202 string_list_append(&AutoViewList, string_list_rev(L));
204 rcline ::= HDR_ORDER simple_list(L) to_eol . {
205 string_list_append(&HeaderOrderList, string_list_rev(L));
207 rcline ::= MIME_LOOKUP simple_list(L) to_eol . {
208 string_list_append(&MimeLookupList, string_list_rev(L));
212 /* vim: set indentexpr= cin: */