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
21 # include <lib-lib/lib-lib.h>
26 static buffer_t *buffer_merge(buffer_t *A, buffer_t **B)
33 static inline int to_control(int c) {
34 return (toupper((unsigned char)c) - 'A' + 1) & 0x7f;
37 static buffer_t *buffer_escape(buffer_t *buf, const char *s, ssize_t len)
45 buffer_addch(buf, to_control(s[1]));
46 buffer_add(buf, s + 2, len - 2);
51 int i = (hexval(s[1]) << 4) | hexval(s[2]);
54 buffer_add(buf, s + 3, len - 3);
60 case '0': case '1': case '2': case '3':
62 int i = (octval(s[0]) << 6) | (octval(s[1]) << 3) | octval(s[2]);
65 buffer_add(buf, s + 3, len - 3);
71 case 'e': buffer_addch(buf, '\e'); return buf;
72 case 'f': buffer_addch(buf, '\f'); return buf;
73 case 'n': buffer_addch(buf, '\n'); return buf;
74 case 'r': buffer_addch(buf, '\r'); return buf;
75 case 't': buffer_addch(buf, '\t'); return buf;
76 case 'v': buffer_addch(buf, '\v'); return buf;
82 buffer_add(buf, s, len);
86 static void substvar(buffer_t *buf, const segment seg)
92 if (m_strncpy(var, sizeof(var), seg.s, seg.len) <= 0)
95 if ((res = getenv(var))) {
96 buffer_addstr(buf, res);
99 if (mutt_option_value(var, tmp, sizeof(tmp))) {
100 buffer_addstr(buf, tmp);
107 %token_type { segment }
109 %extra_argument { struct rcstate *state }
111 /****************************************************************************/
113 /****************************************************************************/
115 escnl ::= BSLASH NL . { state->linenum++; }
119 sp ::= sp escnl SPACE .
121 non_nl ::= ATOM|SPACE|BQUOTE|BSLASH|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|SQUOTE|RBRACE .
123 non_nl_star ::= non_nl_star non_nl .
125 to_eol_aux ::= NL . { state->linenum++; }
126 to_eol_aux ::= SHARP non_nl_star NL . { state->linenum++; }
127 to_eol ::= to_eol_aux .
128 to_eol ::= sp to_eol_aux .
130 /****************************************************************************/
131 /* Our macro tokens */
132 /****************************************************************************/
135 %type svar { segment }
136 svar(Z) ::= DOLLAR ATOM(B) . { Z = B; }
137 svar(Z) ::= DOLLAR LBRACE ATOM(B) RBRACE . { Z = B; }
139 /* '-quoted tokens */
140 %type sqtok { buffer_t* }
141 %destructor sqtok { buffer_delete(&$$); }
142 sqtok(Z) ::= . { Z = buffer_new(); }
143 sqtok(Z) ::= sqtok(A) escnl . { Z = A; }
144 sqtok(Z) ::= sqtok(A) BSLASH BSLASH|SQUOTE(B) . { buffer_addch(Z = A, *B.s); }
145 sqtok(Z) ::= sqtok(A) BSLASH ATOM|SPACE|BQUOTE|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|RBRACE(B) . {
146 buffer_addch(Z = A, '\\');
147 buffer_add(Z, B.s, B.len);
149 sqtok(Z) ::= sqtok(A) ATOM|SPACE|BQUOTE|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|RBRACE(B) . {
150 buffer_add(Z = A, B.s, B.len);
153 /* `-quoted tokens */
154 %type bqtok { buffer_t* }
155 %destructor bqtok { buffer_delete(&$$); }
156 bqtok(Z) ::= . { Z = buffer_new(); }
157 bqtok(Z) ::= bqtok(A) escnl . { Z = A; }
158 bqtok(Z) ::= bqtok(A) BSLASH non_nl(B) . { Z = buffer_escape(A, B.s, B.len); }
159 bqtok(Z) ::= bqtok(A) svar(B) . { substvar(Z = A, B); }
160 bqtok(Z) ::= bqtok(A) ATOM|SPACE|SHARP|EQUAL|LBRACE|RBRACE|SQUOTE|DQUOTE(B) . {
161 buffer_add(Z = A, B.s, B.len);
164 /* "-quoted tokens */
165 %type dqtok { buffer_t* }
166 %destructor dqtok { buffer_delete(&$$); }
167 dqtok(Z) ::= . { Z = buffer_new(); }
168 dqtok(Z) ::= dqtok(A) escnl . { Z = A; }
169 dqtok(Z) ::= dqtok(A) BSLASH non_nl(B) . { Z = buffer_escape(A, B.s, B.len); }
170 dqtok(Z) ::= dqtok(A) svar(B) . { substvar(Z = A, B); }
171 dqtok(Z) ::= dqtok(A) ATOM|SPACE|SHARP|EQUAL|LBRACE|RBRACE|SQUOTE(B) . {
172 buffer_add(Z = A, B.s, B.len);
174 dqtok(Z) ::= dqtok(A) BQUOTE bqtok(B) BQUOTE . { /* XXX */ buffer_merge(Z = A, &B); }
176 /* unquoted tokens */
177 %type uqtok { buffer_t* }
178 %destructor uqtok { buffer_delete(&$$); }
179 uqtok(Z) ::= BSLASH non_nl(A) . { buffer_add(Z = buffer_new(), A.s, A.len); }
180 uqtok(Z) ::= svar(A) . { substvar(Z = buffer_new(), A); }
181 uqtok(Z) ::= ATOM|EQUAL|LBRACE|RBRACE(A) . { buffer_add(Z = buffer_new(), A.s, A.len); }
182 uqtok(Z) ::= SQUOTE sqtok(A) SQUOTE . { Z = A; }
183 uqtok(Z) ::= DQUOTE dqtok(A) DQUOTE . { Z = A; }
184 uqtok(Z) ::= BQUOTE bqtok(A) BQUOTE . { /* XXX */ Z = A; }
186 /* token accumulator: NEVER USE DIRECTLY */
187 %type tokaux { buffer_t* }
188 %destructor tokaux { abort(); }
189 tokaux(Z) ::= uqtok(A) . { Z = A; }
190 tokaux(Z) ::= tokaux(A) escnl . { Z = A; }
191 tokaux(Z) ::= tokaux(A) uqtok(B) . { Z = buffer_merge(A, &B); }
193 %type token { buffer_t* }
194 %destructor token { buffer_delete(&$$); }
195 token(Z) ::= sp tokaux(A) . { Z = A; }
198 /****************************************************************************/
200 /****************************************************************************/
202 %type simple_list { string_list_t * }
203 %destructor simple_list { string_list_wipe(&$$); }
205 simple_list(L) ::= simple_list(A) token(B) . {
207 L = string_item_new();
208 L->data = buffer_unwrap(&B);
217 /****************************************************************************/
218 /* Entry point : the rc lines */
219 /****************************************************************************/
223 rclines ::= rclines rcline .
226 rcline ::= BIND token token token to_eol .
227 rcline ::= EXEC simple_list to_eol .
228 rcline ::= MACRO token token token to_eol .
229 rcline ::= MACRO token token token token to_eol .
230 rcline ::= PUSH token to_eol .
231 rcline ::= SCORE token token to_eol .
232 rcline ::= UNSCORE simple_list to_eol .
236 %type atok { buffer_t* }
237 %destructor atok { buffer_delete(&$$); }
238 atok(Z) ::= ATOM|SHARP|DQUOTE|EQUAL|LBRACE|SQUOTE|RBRACE(A) . {
239 buffer_add(Z = buffer_new(), A.s, A.len);
241 atok(Z) ::= SPACE(A) . {
242 buffer_add(Z = buffer_new(), A.s, A.len);
244 atok(Z) ::= atok(A) escnl . { Z = A; }
245 atok(Z) ::= atok(A) BSLASH non_nl(B) . { Z = buffer_escape(A, B.s, B.len); }
246 atok(Z) ::= atok(A) svar(B) . { substvar(Z = A, B); }
247 atok(Z) ::= atok(A) BQUOTE bqtok(B) BQUOTE . { /* XXX */ buffer_merge(Z = A, &B); }
249 rcline ::= ALIAS token SPACE atok to_eol .
254 rcline ::= COLOR token token token to_eol .
255 rcline ::= COLOR token token token token to_eol .
256 rcline ::= UNCOLOR token simple_list to_eol .
257 rcline ::= MONO token token to_eol .
258 rcline ::= MONO token token token to_eol .
259 rcline ::= UNMONO token simple_list to_eol .
264 rcline ::= ACCOUNT_HOOK token token to_eol .
265 rcline ::= APPEND_HOOK token token to_eol .
266 rcline ::= CHARSET_HOOK token token to_eol .
267 rcline ::= CLOSE_HOOK token token to_eol .
268 rcline ::= CRYPT_HOOK token token to_eol .
269 rcline ::= FCC_HOOK token token to_eol .
270 rcline ::= FCC_SAVE_HOOK token token to_eol .
271 rcline ::= FOLDER_HOOK token token to_eol .
272 rcline ::= ICONV_HOOK token token to_eol .
273 rcline ::= MBOX_HOOK token token to_eol .
274 rcline ::= MESSAGE_HOOK token token to_eol .
275 rcline ::= OPEN_HOOK token token to_eol .
276 rcline ::= PGP_HOOK token token to_eol .
277 rcline ::= REPLY_HOOK token token to_eol .
278 rcline ::= SAVE_HOOK token token to_eol .
279 rcline ::= SEND2_HOOK token token to_eol .
280 rcline ::= SEND_HOOK token token to_eol .
282 rcline ::= UNHOOK token to_eol .
285 /* {{{ buffy related */
288 mailboxes ::= mailboxes token(A) . {
290 char buf[_POSIX_PATH_MAX];
294 m_strcpy(buf, sizeof(buf), A->data);
295 mutt_expand_path(buf, sizeof(buf));
296 i = buffy_lookup(buf);
298 tmp = p_new(BUFFY, 1);
299 tmp->path = m_strdup(buf);
300 buffy_array_append(&Incoming, tmp);
302 tmp = Incoming.arr[i];
307 tmp->newly_created = 0;
311 rcline ::= MAILBOXES mailboxes to_eol .
314 unmailboxes ::= unmailboxes token(A) . {
316 if (A->data[0] == '*' && A->len == 1) {
317 buffy_array_wipe(&Incoming);
319 char buf[_POSIX_PATH_MAX];
323 m_strcpy(buf, sizeof(buf), A->data);
324 mutt_expand_path(buf, sizeof(buf));
325 i = buffy_lookup(buf);
326 tmp = buffy_array_take(&Incoming, i);
332 rcline ::= UNMAILBOXES unmailboxes to_eol .
335 /* {{{ lists (alternative_order, auto_view, hdr_order, mime_lookup */
337 rcline ::= ALTERNATIVE_ORDER simple_list(L) to_eol . {
338 string_list_append(&AlternativeOrderList, string_list_rev(L));
340 rcline ::= AUTO_VIEW simple_list(L) to_eol . {
341 string_list_append(&AutoViewList, string_list_rev(L));
343 rcline ::= HDR_ORDER simple_list(L) to_eol . {
344 string_list_append(&HeaderOrderList, string_list_rev(L));
346 rcline ::= MIME_LOOKUP simple_list(L) to_eol . {
347 string_list_append(&MimeLookupList, string_list_rev(L));
352 /* vim: set indentexpr= cin: */