Commit f49d4057 f49d4057c49022a646c8dbe2d203e8c374bb7427 by Sergey Poznyakoff

Fixes in wordsplit. Use wordsplit instead of vartab in movemail.

Eventually this will lead to vartab fading out until it is removed
in some point in the future.  Wordsplit provides a much better
variable substitution mechanism.

* include/mailutils/wordsplit.h (mu_wordsplit) <ws_getvar>: Change
signature.
<ws_closure>: New member.
(MU_WRDSF_CLOSURE): New flag.
* libmailutils/string/wordsplit.c (mu_wordsplit_init): Initialize
ws_closure to NULL, unless MU_WRDSF_CLOSURE is set.
Do not modify ws_wordn if MU_WRDSF_DOOFFS is set.
(wsnode_remove): Clear _WSNF_JOIN on the previous node if the node
being deleted is the last one in chain.
(expvar): Pass ws_closure as 3rd argument to ws_getvar.
Insert a NULL node if the variable is not defined.

* movemail/movemail.c: Use wordsplit instead of vartab. Note a side
effect: the "source:*" and "dest:*" variables are now written as
"source_*" and "dest_*", correspondingly.
(movemail_getvar_closure): New structure.
(DCL_VTX): Remove macro and its uses.
(get_url_part, movemail_getvar): New functions.
(set_program_id): Rewrite using wordsplit.
...@@ -35,8 +35,9 @@ struct mu_wordsplit ...@@ -35,8 +35,9 @@ struct mu_wordsplit
35 __attribute__ ((__format__ (__printf__, 1, 2))); 35 __attribute__ ((__format__ (__printf__, 1, 2)));
36 36
37 const char **ws_env; 37 const char **ws_env;
38 char *(*ws_getvar) (const char *, size_t); 38 const char *(*ws_getvar) (const char *, size_t, void *);
39 39 void *ws_closure;
40
40 const char *ws_input; 41 const char *ws_input;
41 size_t ws_len; 42 size_t ws_len;
42 size_t ws_endp; 43 size_t ws_endp;
...@@ -103,6 +104,9 @@ struct mu_wordsplit ...@@ -103,6 +104,9 @@ struct mu_wordsplit
103 /* Handle C escapes */ 104 /* Handle C escapes */
104 #define MU_WRDSF_CESCAPES 0x1000000 105 #define MU_WRDSF_CESCAPES 0x1000000
105 106
107 /* ws_closure is set */
108 #define MU_WRDSF_CLOSURE 0x2000000
109
106 #define MU_WRDSF_DEFFLAGS \ 110 #define MU_WRDSF_DEFFLAGS \
107 (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | \ 111 (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | \
108 MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS | MU_WRDSF_CESCAPES) 112 MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS | MU_WRDSF_CESCAPES)
......
...@@ -151,9 +151,10 @@ mu_wordsplit_init (struct mu_wordsplit *wsp, const char *input, size_t len, ...@@ -151,9 +151,10 @@ mu_wordsplit_init (struct mu_wordsplit *wsp, const char *input, size_t len,
151 wsp->ws_wordc = 0; 151 wsp->ws_wordc = 0;
152 wsp->ws_wordn = 0; 152 wsp->ws_wordn = 0;
153 } 153 }
154 if (wsp->ws_flags & MU_WRDSF_DOOFFS)
155 wsp->ws_wordn += wsp->ws_offs;
156 154
155 if (!(wsp->ws_flags & MU_WRDSF_CLOSURE))
156 wsp->ws_closure = NULL;
157
157 wsp->ws_endp = 0; 158 wsp->ws_endp = 0;
158 wsp->ws_errno = 0; 159 wsp->ws_errno = 0;
159 wsp->ws_head = wsp->ws_tail = NULL; 160 wsp->ws_head = wsp->ws_tail = NULL;
...@@ -311,7 +312,11 @@ wsnode_remove (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node) ...@@ -311,7 +312,11 @@ wsnode_remove (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node)
311 312
312 p = node->prev; 313 p = node->prev;
313 if (p) 314 if (p)
314 p->next = node->next; 315 {
316 p->next = node->next;
317 if (!node->next)
318 p->flags &= ~_WSNF_JOIN;
319 }
315 else 320 else
316 wsp->ws_head = node->next; 321 wsp->ws_head = node->next;
317 322
...@@ -666,7 +671,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, ...@@ -666,7 +671,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len,
666 { 671 {
667 size_t i = 0; 672 size_t i = 0;
668 const char *defstr = NULL; 673 const char *defstr = NULL;
669 char *value; 674 const char *value;
670 const char *vptr; 675 const char *vptr;
671 struct mu_wordsplit_node *newnode; 676 struct mu_wordsplit_node *newnode;
672 const char *start = str - 1; 677 const char *start = str - 1;
...@@ -738,7 +743,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, ...@@ -738,7 +743,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len,
738 return _wsplt_nomem (wsp); 743 return _wsplt_nomem (wsp);
739 } 744 }
740 else if (wsp->ws_flags & MU_WRDSF_GETVAR) 745 else if (wsp->ws_flags & MU_WRDSF_GETVAR)
741 value = wsp->ws_getvar (str, i); 746 value = wsp->ws_getvar (str, i, wsp->ws_closure);
742 else if (wsp->ws_flags & MU_WRDSF_UNDEF) 747 else if (wsp->ws_flags & MU_WRDSF_UNDEF)
743 { 748 {
744 wsp->ws_errno = MU_WRDSE_UNDEF; 749 wsp->ws_errno = MU_WRDSE_UNDEF;
...@@ -822,6 +827,14 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, ...@@ -822,6 +827,14 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len,
822 memcpy (newnode->v.word, start, size); 827 memcpy (newnode->v.word, start, size);
823 newnode->v.word[size] = 0; 828 newnode->v.word[size] = 0;
824 } 829 }
830 else
831 {
832 if (wsnode_new (wsp, &newnode))
833 return 1;
834 wsnode_insert (wsp, newnode, *ptail, 0);
835 *ptail = newnode;
836 newnode->flags = _WSNF_NULL;
837 }
825 return 0; 838 return 0;
826 } 839 }
827 840
......
...@@ -650,70 +650,98 @@ _compare_uidls (const void *item, const void *value) ...@@ -650,70 +650,98 @@ _compare_uidls (const void *item, const void *value)
650 650
651 return strcmp (a->uidl, b->uidl); 651 return strcmp (a->uidl, b->uidl);
652 } 652 }
653
654 struct movemail_getvar_closure
655 {
656 const char *source_name;
657 const char *dest_name;
658 mu_url_t source_url;
659 mu_url_t dest_url;
660 };
653 661
654 #define __cat2__(a,b) a ## b 662 #define SEQ(s, n, l) \
655 #define DCL_VTX(what) \ 663 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0)
656 static int \
657 __cat2__(_vtx_,what) (const char *name, void *data, char **p) \
658 { \
659 mu_url_t url = data; \
660 int rc = __cat2__(mu_url_aget_,what) (url, p); \
661 if (rc == MU_ERR_NOENT) \
662 { \
663 *p = strdup (""); \
664 return 0; \
665 } \
666 return rc; \
667 }
668 664
669 DCL_VTX (host) 665 static const char *
670 DCL_VTX (user) 666 get_url_part (mu_url_t url, const char *name, size_t nlen)
671 DCL_VTX (path) 667 {
668 int rc = MU_ERR_NOENT;
669 const char *s;
670
671 if (!url)
672 return NULL;
673 if (SEQ ("user", name, nlen))
674 rc = mu_url_sget_user (url, &s);
675 else if (SEQ ("host", name, nlen))
676 rc = mu_url_sget_host (url, &s);
677 else if (SEQ ("port", name, nlen))
678 rc = mu_url_sget_portstr (url, &s);
679 else if (SEQ ("path", name, nlen))
680 rc = mu_url_sget_path (url, &s);
681
682 if (rc)
683 return NULL;
684 return s;
685 }
686
687 static const char *
688 movemail_getvar (const char *name, size_t nlen, void *data)
689 {
690 struct movemail_getvar_closure *pc = data;
691
692 if (SEQ ("progname", name, nlen))
693 return mu_program_name;
694 if (SEQ ("source", name, nlen))
695 return pc->source_name;
696 if (SEQ ("dest", name, nlen))
697 return pc->dest_name;
698
699 if (nlen > 7 && memcmp ("source_", name, 7) == 0)
700 return get_url_part (pc->source_url, name + 7, nlen - 7);
701 if (nlen > 5 && memcmp ("dest_", name, 5) == 0)
702 return get_url_part (pc->dest_url, name + 5, nlen - 5);
703
704 return NULL;
705 }
672 706
673 static void 707 static void
674 set_program_id (const char *source_name, const char *dest_name) 708 set_program_id (const char *source_name, const char *dest_name)
675 { 709 {
676 int rc; 710 int rc;
677 mu_vartab_t vtab; 711 struct mu_wordsplit ws;
678 char *id; 712 struct movemail_getvar_closure clos;
679 mu_url_t url; 713
680 714 clos.source_name = source_name;
681 mu_vartab_create (&vtab); 715 clos.dest_name = dest_name;
682 mu_vartab_define (vtab, "progname", mu_program_name, 1); 716 rc = mu_mailbox_get_url (source, &clos.source_url);
683 mu_vartab_define (vtab, "source", source_name, 1);
684 rc = mu_mailbox_get_url (source, &url);
685 if (rc) 717 if (rc)
686 mu_diag_output (MU_DIAG_INFO, 718 mu_diag_output (MU_DIAG_INFO,
687 _("cannot obtain source mailbox URL: %s"), 719 _("cannot obtain source mailbox URL: %s"),
688 mu_strerror (rc)); 720 mu_strerror (rc));
689 else 721 rc = mu_mailbox_get_url (dest, &clos.dest_url);
690 {
691 mu_vartab_define_exp (vtab, "source:user", _vtx_user, NULL, url);
692 mu_vartab_define_exp (vtab, "source:host", _vtx_host, NULL, url);
693 mu_vartab_define_exp (vtab, "source:path", _vtx_path, NULL, url);
694 }
695
696 mu_vartab_define (vtab, "dest", dest_name, 1);
697 rc = mu_mailbox_get_url (dest, &url);
698 if (rc) 722 if (rc)
699 mu_diag_output (MU_DIAG_INFO, 723 mu_diag_output (MU_DIAG_INFO,
700 _("cannot obtain destination mailbox URL: %s"), 724 _("cannot obtain destination mailbox URL: %s"),
701 mu_strerror (rc)); 725 mu_strerror (rc));
702 else 726
727 ws.ws_getvar = movemail_getvar;
728 ws.ws_closure = &clos;
729 if (mu_wordsplit (program_id_option, &ws,
730 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
731 MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE))
703 { 732 {
704 mu_vartab_define_exp (vtab, "dest:user", _vtx_user, NULL, url); 733 mu_error (_("cannot expand line `%s': %s"), program_id_option,
705 mu_vartab_define_exp (vtab, "dest:host", _vtx_host, NULL, url); 734 mu_wordsplit_strerror (&ws));
706 mu_vartab_define_exp (vtab, "dest:path", _vtx_path, NULL, url); 735 return;
707 } 736 }
708 737
709 rc = mu_vartab_expand (vtab, program_id_option, &id);
710 mu_vartab_destroy (&vtab);
711 /* mu_asprintf (&id, "%s: %s", mu_program_name, s);
712 free (s);*/
713 /* FIXME: Don't use mu_set_program_name here, because it 738 /* FIXME: Don't use mu_set_program_name here, because it
714 plays wise with its argument. We need a mu_set_diag_prefix 739 plays wise with its argument. We need a mu_set_diag_prefix
715 function. */ 740 function. */
716 mu_program_name = id; 741 mu_program_name = ws.ws_wordv[0];
742 ws.ws_wordv[0] = NULL;
743 ws.ws_wordc = 0;
744 mu_wordsplit_free (&ws);
717 } 745 }
718 746
719 int 747 int
......