/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * Copyright © 2006 Pierre Habouzit */ %include { # include "mutt.h" # include "parse.h" static buffer_t *buffer_merge(buffer_t *A, buffer_t **B) { buffer_addbuf(A, *B); buffer_delete(B); return A; } static inline int to_control(int c) { return (toupper((unsigned char)c) - 'A' + 1) & 0x7f; } static buffer_t *buffer_escape(buffer_t *buf, const char *s, ssize_t len) { assert (len > 0); switch (*s) { case 'c': case 'C': if (len < 2) break; buffer_addch(buf, to_control(s[1])); buffer_add(buf, s + 2, len - 2); return buf; case 'x': if (len >= 3) { int i = (hexval(s[1]) << 4) | hexval(s[2]); if (i >= 0) { buffer_addch(buf, i); buffer_add(buf, s + 3, len - 3); return buf; } } break; case '0': case '1': case '2': case '3': if (len >= 3) { int i = (octval(s[0]) << 6) | (octval(s[1]) << 3) | octval(s[2]); if (i >= 0) { buffer_addch(buf, i); buffer_add(buf, s + 3, len - 3); return buf; } } break; case 'e': buffer_addch(buf, '\e'); return buf; case 'f': buffer_addch(buf, '\f'); return buf; case 'n': buffer_addch(buf, '\n'); return buf; case 'r': buffer_addch(buf, '\r'); return buf; case 't': buffer_addch(buf, '\t'); return buf; case 'v': buffer_addch(buf, '\v'); return buf; default: break; } buffer_add(buf, s, len); return buf; } } %token_prefix RCTK_ %token_type { segment } %start_symbol rc /****************************************************************************/ /* Often used */ /****************************************************************************/ spaces ::= SPACE . spaces ::= spaces SPACE . non_nl ::= ATOM|SPACE|BANG|BQUOTE|BSLASH|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|PIPE|QUOTE|RBRACE|TILDE . non_nl_star ::= . non_nl_star ::= non_nl_star non_nl . to_eol ::= NL . to_eol ::= SHARP non_nl_star NL . to_eol ::= spaces SHARP non_nl_star NL . /****************************************************************************/ /* Our macro tokens */ /****************************************************************************/ %type sqtok { buffer_t* } sqtok(C) ::= . { C = buffer_new(); } sqtok(C) ::= sqtok(A) BSLASH BSLASH|QUOTE(B) . { buffer_addch(C = A, *B.s); } sqtok(C) ::= sqtok(A) BSLASH ATOM|SPACE|BANG|BQUOTE|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|PIPE|RBRACE|TILDE(B) . { buffer_addch(C = A, '\\'); buffer_add(C, B.s, B.len); } sqtok(C) ::= sqtok(A) ATOM|SPACE|BANG|BQUOTE|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|PIPE|RBRACE|TILDE(B) . { buffer_add(C = A, B.s, B.len); } %type dqtok { buffer_t* } dqtok(C) ::= . { C = buffer_new(); } dqtok(C) ::= dqtok(A) BSLASH non_nl(T) . { C = buffer_escape(A, T.s, T.len); } dqtok(C) ::= dqtok(A) ATOM|SPACE|BANG|SHARP|EQUAL|LBRACE|PIPE|RBRACE|TILDE(T) . { buffer_add(C = A, T.s, T.len); } %type tok { buffer_t* } tok(R) ::= ATOM|BANG|EQUAL|PIPE|TILDE(T) . { R = buffer_new(); buffer_add(R, T.s, T.len); } tok(R) ::= BSLASH non_nl(T) . { R = buffer_new(); buffer_add(R, T.s, T.len); } tok(R) ::= QUOTE sqtok(T) QUOTE . { R = T; } tok(R) ::= DQUOTE dqtok(T) DQUOTE . { R = T; } %type token_acc { buffer_t* } token_acc(A) ::= tok(T) . { A = T; } token_acc(C) ::= token_acc(A) tok(B) . { C = buffer_merge(A, &B); } %type token { buffer_t* } token(R) ::= spaces token_acc(T) . { R = T; } /****************************************************************************/ /* list of tokens */ /****************************************************************************/ %type simple_list { string_list_t * } simple_list ::= . simple_list(L) ::= simple_list(A) token(B) . { string_list_t **last = string_list_last(&A); *last = string_item_new(); (*last)->data = buffer_unwrap(&B); L = A; } /****************************************************************************/ /* Entry point : the rc lines */ /****************************************************************************/ rc ::= rclines . rclines ::= . rclines ::= rclines rcline . rcline ::= to_eol . rcline ::= ALT_ORDER simple_list(L) to_eol . { string_list_append(&AlternativeOrderList, L); } /* vim: set indentexpr= cin: */