improvements, fixes, parser progress, ...
[apps/madmutt.git] / rcparser.y
index b63ab9a..114c043 100644 (file)
  */
 
 %include {
+#   include <lib-lib/lib-lib.h>
 #   include "mutt.h"
 #   include "parse.h"
+#   include "buffy.h"
 
     static buffer_t *buffer_merge(buffer_t *A, buffer_t **B)
     {
@@ -37,7 +39,7 @@
         assert (len > 0);
 
         switch (*s) {
-          case 'c': case 'C':
+          case 'c': case 'Z':
             if (len < 2)
                 break;
             buffer_addch(buf, to_control(s[1]));
         buffer_add(buf, s, len);
         return buf;
     }
+
+    static void substvar(buffer_t *buf, const segment seg)
+    {
+        const char *res;
+        char tmp[STRING];
+        char var[STRING];
+
+        if (m_strncpy(var, sizeof(var), seg.s, seg.len) <= 0)
+            return;
+
+        if ((res = getenv(var))) {
+            buffer_addstr(buf, res);
+            return;
+        }
+        if (mutt_option_value(var, tmp, sizeof(tmp))) {
+            buffer_addstr(buf, tmp);
+        }
+    }
 }
 
+%name rcparse
 %token_prefix RCTK_
 %token_type  { segment }
 %start_symbol rc
+%extra_argument { struct rcstate *state }
 
 /****************************************************************************/
 /* Often used                                                               */
 /****************************************************************************/
 
-spaces ::= SPACE .
-spaces ::= spaces SPACE .
+escnl ::= BSLASH NL .                      { state->linenum++; }
+
+sp ::= SPACE .
+sp ::= sp SPACE .
+sp ::= sp escnl SPACE .
 
-non_nl ::= ATOM|SPACE|BANG|BQUOTE|BSLASH|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|PIPE|QUOTE|RBRACE|TILDE .
+non_nl ::= ATOM|SPACE|BQUOTE|BSLASH|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|SQUOTE|RBRACE .
 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 .
-
+to_eol_aux ::= NL .                        { state->linenum++; }
+to_eol_aux ::= SHARP non_nl_star NL .      { state->linenum++; }
+to_eol ::= to_eol_aux .
+to_eol ::= sp to_eol_aux .
 
 /****************************************************************************/
 /* Our macro tokens                                                         */
 /****************************************************************************/
+/*                                                                       {{{*/
 
+%type svar { segment }
+svar(Z) ::= DOLLAR ATOM(B) .               { Z = B; }
+svar(Z) ::= DOLLAR LBRACE ATOM(B) RBRACE . { Z = B; }
+
+/* '-quoted 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);
+%destructor sqtok  { buffer_delete(&$$); }
+sqtok(Z) ::= .                                 { Z = buffer_new(); }
+sqtok(Z) ::= sqtok(A) escnl .                  { Z = A; }
+sqtok(Z) ::= sqtok(A) BSLASH BSLASH|SQUOTE(B) . { buffer_addch(Z = A, *B.s); }
+sqtok(Z) ::= sqtok(A) BSLASH ATOM|SPACE|BQUOTE|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|RBRACE(B) . {
+    buffer_addch(Z = A, '\\');
+    buffer_add(Z, 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);
+sqtok(Z) ::= sqtok(A) ATOM|SPACE|BQUOTE|SHARP|DOLLAR|DQUOTE|EQUAL|LBRACE|RBRACE(B) . {
+    buffer_add(Z = 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);
+/* `-quoted tokens */
+%type bqtok { buffer_t* }
+%destructor bqtok { buffer_delete(&$$); }
+bqtok(Z) ::= .                             { Z = buffer_new(); }
+bqtok(Z) ::= bqtok(A) escnl .              { Z = A; }
+bqtok(Z) ::= bqtok(A) BSLASH non_nl(B) .   { Z = buffer_escape(A, B.s, B.len); }
+bqtok(Z) ::= bqtok(A) svar(B) .            { substvar(Z = A, B); }
+bqtok(Z) ::= bqtok(A) ATOM|SPACE|SHARP|EQUAL|LBRACE|RBRACE|SQUOTE|DQUOTE(B)  . {
+    buffer_add(Z = A, B.s, B.len);
 }
 
-%type tok   { buffer_t* }
-tok(R) ::= ATOM|BANG|EQUAL|PIPE|TILDE(T) . {
-    R = buffer_new();
-    buffer_add(R, T.s, T.len);
+/* "-quoted tokens */
+%type dqtok { buffer_t* }
+%destructor dqtok { buffer_delete(&$$); }
+dqtok(Z) ::= .                             { Z = buffer_new(); }
+dqtok(Z) ::= dqtok(A) escnl .              { Z = A; }
+dqtok(Z) ::= dqtok(A) BSLASH non_nl(B) .   { Z = buffer_escape(A, B.s, B.len); }
+dqtok(Z) ::= dqtok(A) svar(B) .            { substvar(Z = A, B); }
+dqtok(Z) ::= dqtok(A) ATOM|SPACE|SHARP|EQUAL|LBRACE|RBRACE|SQUOTE(B)  . {
+    buffer_add(Z = A, B.s, B.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; }
+dqtok(Z) ::= dqtok(A) BQUOTE bqtok(B) BQUOTE . { /* XXX */ buffer_merge(Z = A, &B); }
 
-%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); }
+/* unquoted tokens */
+%type uqtok { buffer_t* }
+%destructor uqtok { buffer_delete(&$$); }
+uqtok(Z) ::= BSLASH non_nl(A) .            { buffer_add(Z = buffer_new(), A.s, A.len); }
+uqtok(Z) ::= svar(A) .                     { substvar(Z = buffer_new(), A); }
+uqtok(Z) ::= ATOM|EQUAL|LBRACE|RBRACE(A) . { buffer_add(Z = buffer_new(), A.s, A.len); }
+uqtok(Z) ::= SQUOTE sqtok(A) SQUOTE .      { Z = A; }
+uqtok(Z) ::= DQUOTE dqtok(A) DQUOTE .      { Z = A; }
+uqtok(Z) ::= BQUOTE bqtok(A) BQUOTE .      { /* XXX */ Z = A; }
 
-%type token { buffer_t* }
-token(R) ::= spaces token_acc(T) . { R = T; }
+/* token accumulator: NEVER USE DIRECTLY */
+%type tokaux { buffer_t* }
+%destructor tokaux { abort(); }
+tokaux(Z) ::= uqtok(A) .                   { Z = A; }
+tokaux(Z) ::= tokaux(A) escnl .            { Z = A; }
+tokaux(Z) ::= tokaux(A) uqtok(B) .         { Z = buffer_merge(A, &B); }
 
+%type token { buffer_t* }
+%destructor token { buffer_delete(&$$); }
+token(Z) ::= sp tokaux(A) .                 { Z = A; }
 
+/*                                                                       }}}*/
 /****************************************************************************/
 /* list of tokens                                                           */
 /****************************************************************************/
 
 %type simple_list { string_list_t * }
-simple_list    ::= .
+%destructor simple_list { string_list_wipe(&$$); }
+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;
+    if (B->len) {
+        L = string_item_new();
+        L->data = buffer_unwrap(&B);
+        L->next = A;
+    } else {
+        L = A;
+        buffer_delete(&B);
+    }
 }
 
 
@@ -164,9 +223,130 @@ rclines ::= .
 rclines ::= rclines rcline .
 
 rcline ::= to_eol .
-rcline ::= ALT_ORDER simple_list(L) to_eol . {
-    string_list_append(&AlternativeOrderList, L);
+rcline ::= BIND token token token to_eol .
+rcline ::= EXEC simple_list to_eol .
+rcline ::= MACRO token token token to_eol .
+rcline ::= MACRO token token token token to_eol .
+rcline ::= PUSH token to_eol .
+rcline ::= SCORE token token to_eol .
+rcline ::= UNSCORE simple_list to_eol .
+
+/* {{{ alias */
+
+%type atok { buffer_t* }
+%destructor atok { buffer_delete(&$$); }
+atok(Z) ::= ATOM|SHARP|DQUOTE|EQUAL|LBRACE|SQUOTE|RBRACE(A) . {
+    buffer_add(Z = buffer_new(), A.s, A.len);
+}
+atok(Z) ::= SPACE(A) . {
+    buffer_add(Z = buffer_new(), A.s, A.len);
+}
+atok(Z) ::= atok(A) escnl .              { Z = A; }
+atok(Z) ::= atok(A) BSLASH non_nl(B) .   { Z = buffer_escape(A, B.s, B.len); }
+atok(Z) ::= atok(A) svar(B) .            { substvar(Z = A, B); }
+atok(Z) ::= atok(A) BQUOTE bqtok(B) BQUOTE . { /* XXX */ buffer_merge(Z = A, &B); }
+
+rcline ::= ALIAS token SPACE atok to_eol .
+
+/* }}} */
+/* {{{ colors */
+
+rcline ::= COLOR token token token to_eol .
+rcline ::= COLOR token token token token to_eol .
+rcline ::= UNCOLOR token simple_list to_eol .
+rcline ::= MONO token token to_eol .
+rcline ::= MONO token token token to_eol .
+rcline ::= UNMONO token simple_list to_eol .
+
+/* }}} */
+/* {{{ hooks */
+
+rcline ::= ACCOUNT_HOOK token token to_eol .
+rcline ::= APPEND_HOOK token token to_eol .
+rcline ::= CHARSET_HOOK token token to_eol .
+rcline ::= CLOSE_HOOK token token to_eol .
+rcline ::= CRYPT_HOOK token token to_eol .
+rcline ::= FCC_HOOK token token to_eol .
+rcline ::= FCC_SAVE_HOOK token token to_eol .
+rcline ::= FOLDER_HOOK token token to_eol .
+rcline ::= ICONV_HOOK token token to_eol .
+rcline ::= MBOX_HOOK token token to_eol .
+rcline ::= MESSAGE_HOOK token token to_eol .
+rcline ::= OPEN_HOOK token token to_eol .
+rcline ::= PGP_HOOK token token to_eol .
+rcline ::= REPLY_HOOK token token to_eol .
+rcline ::= SAVE_HOOK token token to_eol .
+rcline ::= SEND2_HOOK token token to_eol .
+rcline ::= SEND_HOOK token token to_eol .
+
+rcline ::= UNHOOK token to_eol .
+
+/* }}} */
+/* {{{ buffy related  */
+
+mailboxes ::= .
+mailboxes ::= mailboxes token(A) . {
+    if (A->len) {
+        char buf[_POSIX_PATH_MAX];
+        BUFFY *tmp;
+        int i;
+
+        m_strcpy(buf, sizeof(buf), A->data);
+        mutt_expand_path(buf, sizeof(buf));
+        i = buffy_lookup(buf);
+        if (i < 0) {
+            tmp = p_new(BUFFY, 1);
+            tmp->path = m_strdup(buf);
+            buffy_array_append(&Incoming, tmp);
+        } else {
+            tmp = Incoming.arr[i];
+        }
+
+        tmp->new = 0;
+        tmp->notified = 1;
+        tmp->newly_created = 0;
+    }
+    buffer_delete(&A);
+}
+rcline ::= MAILBOXES mailboxes to_eol .
+
+unmailboxes ::= .
+unmailboxes ::= unmailboxes token(A) . {
+    if (A->len) {
+        if (A->data[0] == '*' && A->len == 1) {
+            buffy_array_wipe(&Incoming);
+        } else {
+            char buf[_POSIX_PATH_MAX];
+            BUFFY *tmp;
+            int i;
+
+            m_strcpy(buf, sizeof(buf), A->data);
+            mutt_expand_path(buf, sizeof(buf));
+            i = buffy_lookup(buf);
+            tmp = buffy_array_take(&Incoming, i);
+            buffy_delete(&tmp);
+        }
+    }
+    buffer_delete(&A);
+}
+rcline ::= UNMAILBOXES unmailboxes to_eol .
+
+/* }}} */
+/* {{{ lists (alternative_order, auto_view, hdr_order, mime_lookup */
+
+rcline ::= ALTERNATIVE_ORDER simple_list(L) to_eol . {
+    string_list_append(&AlternativeOrderList, string_list_rev(L));
+}
+rcline ::= AUTO_VIEW         simple_list(L) to_eol . {
+    string_list_append(&AutoViewList, string_list_rev(L));
+}
+rcline ::= HDR_ORDER         simple_list(L) to_eol . {
+    string_list_append(&HeaderOrderList, string_list_rev(L));
+}
+rcline ::= MIME_LOOKUP       simple_list(L) to_eol . {
+    string_list_append(&MimeLookupList, string_list_rev(L));
 }
 
+/* }}} */
 
 /* vim: set indentexpr= cin: */