templates
author Myhailo Danylenko <isbear@ukrpost.net>
Fri, 20 Jul 2012 17:55:10 +0300
changeset 33 ce47dc7fc6c0
permissions -rw-r--r--
Add use-gslice and templates
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
33
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     1
# HG changeset patch
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     2
# Parent 456d832740146c5c9a0428c9ca0a1a0c431481b0
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     3
[work-in-progress] Use templates for statusbars
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     4
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     5
diff -r 456d83274014 mcabber/CMakeLists.txt
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     6
--- a/mcabber/CMakeLists.txt	Fri Jul 20 17:29:53 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     7
+++ b/mcabber/CMakeLists.txt	Fri Jul 20 17:30:20 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     8
@@ -154,8 +154,8 @@
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
     9
 
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    10
 ## Define targets
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    11
 set ( mcabber_SUBSYSTEMS
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    12
-	caps commands compl events hbuf help histolog hooks
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    13
-	modules nohtml otr pgp roster screen settings utf8 utils
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    14
+	caps commands compl events hbuf help histolog hooks modules
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    15
+	nohtml otr parser pgp roster screen settings templates utf8 utils
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    16
 	xmpp xmpp_helper xmpp_iq xmpp_iqrequest xmpp_muc xmpp_s10n )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    17
 if ( NOT MODULES_ENABLE )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    18
 	list ( APPEND mcabber_SUBSYSTEMS extcmd fifo )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    19
diff -r 456d83274014 mcabber/mcabber/parser.c
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    20
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    21
+++ b/mcabber/mcabber/parser.c	Fri Jul 20 17:30:20 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    22
@@ -0,0 +1,853 @@
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    23
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    24
+/* Copyright 2012 Myhailo Danylenko
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    25
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    26
+ * This file is part of mcabber
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    27
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    28
+ * mcabber is free software: you can redistribute it and/or
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    29
+ * modify it under the terms of the GNU General Public License as published
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    30
+ * by the Free Software Foundation, either version 2 of the License, or
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    31
+ * (at your option) any later version.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    32
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    33
+ * This program is distributed in the hope that it will be useful,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    34
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    35
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    36
+ * GNU General Public License for more details.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    37
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    38
+ * You should have received a copy of the GNU General Public License
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    39
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>. */
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    40
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    41
+#include <glib.h>
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    42
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    43
+#include <ctype.h>   // is*
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    44
+#include <stdlib.h>  // strtol
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    45
+#include <string.h>  // strchr
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    46
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    47
+#include "parser.h"
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    48
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    49
+#include "config.h"
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    50
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    51
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    52
+//  Private types
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    53
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    54
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    55
+typedef enum {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    56
+	in_string,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    57
+	in_escape,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    58
+	in_var,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    59
+	in_plainvarstart,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    60
+	in_plainvar,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    61
+	in_prevarname,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    62
+	in_varnamestart,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    63
+	in_varname,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    64
+	in_varchop,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    65
+	in_varstrip,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    66
+	in_varstripchop,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    67
+	in_varslash,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    68
+	in_varmatch,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    69
+	in_varpresubst,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    70
+	in_varsubst,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    71
+	in_varcolon,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    72
+	in_varminus,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    73
+	in_varplus,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    74
+	in_varpos,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    75
+	in_postvarpos,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    76
+	in_varlen,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    77
+	in_varsubstring,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    78
+	in_varend,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    79
+	in_evalstart,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    80
+	in_mathexpand,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    81
+	in_dblparen_eol,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    82
+	nostate,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    83
+} tmpl_parser_state_t;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    84
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    85
+const static char * const tmpl_statenames [ ] = {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    86
+	"in string",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    87
+	"in escape",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    88
+	"in var",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    89
+	"in plainvarstart",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    90
+	"in plainvar",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    91
+	"in prevarname",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    92
+	"in varnamestart",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    93
+	"in varname",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    94
+	"in varchop",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    95
+	"in varstrip",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    96
+	"in varstripchop",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    97
+	"in varslash",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    98
+	"in varmatch",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
    99
+	"in varpresubst",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   100
+	"in varsubst",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   101
+	"in varcolon",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   102
+	"in varminus",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   103
+	"in varplus",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   104
+	"in varpos",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   105
+	"in postvarpos",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   106
+	"in varlen",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   107
+	"in varsubstring",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   108
+	"in varend",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   109
+	"in evalstart",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   110
+	"in mathexpand",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   111
+	"in dblparen eol",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   112
+	"wrong state",
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   113
+};
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   114
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   115
+typedef enum {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   116
+	no_eol         =  0x0,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   117
+	brace_eol      =  0x1,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   118
+	slash_eol      =  0x2,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   119
+	colon_eol      =  0x4,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   120
+	paren_eol      =  0x8,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   121
+	dblparen_eol   = 0x10,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   122
+	balance_parens = 0x20,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   123
+} tmpl_parser_flags_t;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   124
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   125
+typedef enum {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   126
+	no_operation,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   127
+	expand_var,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   128
+	value_length,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   129
+} tmpl_var_operation_t;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   130
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   131
+typedef enum {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   132
+	no_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   133
+	noempty_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   134
+	paren_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   135
+	plus_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   136
+	minus_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   137
+	remainder_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   138
+	division_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   139
+	multiplication_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   140
+} tmpl_math_op_t;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   141
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   142
+typedef enum {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   143
+	in_preargument,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   144
+	in_hexoctzero,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   145
+	in_number,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   146
+	in_variable,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   147
+	in_postparen,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   148
+	in_op,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   149
+} tmpl_math_state_t;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   150
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   151
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   152
+//  Code
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   153
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   154
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   155
+GQuark tmpl_gerror_quark ( void )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   156
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   157
+	return g_quark_from_static_string ( "tmpl_gerror_quark" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   158
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   159
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   160
+// match tmpl_glob ( string, pattern, greedy, right-to-left )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   161
+// Performs matching of given pattern against given string,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   162
+// returns first substring in input, that matched. In pattern,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   163
+// there are currently two tokens recognized: '*' and '?'.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   164
+const gchar *tmpl_glob ( const char *str, gsize length, const char *pat, gsize patlen, gboolean rtl, gsize *ret_len )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   165
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   166
+	*ret_len = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   167
+	if ( rtl ) { // rtl
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   168
+		const char *p           = pat + patlen - 1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   169
+		const char *s           = str + length - 1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   170
+		const char *matchend    = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   171
+		const char *patrollback = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   172
+		const char *strrollback = s;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   173
+		while ( p >= pat && s >= str ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   174
+			if ( *p == '*' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   175
+				if ( matchend == NULL && patrollback != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   176
+					matchend = strrollback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   177
+				patrollback = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   178
+				strrollback = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   179
+				p --;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   180
+			} else if ( *p == '?' || *p == *s ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   181
+				if ( patrollback == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   182
+					patrollback = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   183
+					strrollback = s;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   184
+				}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   185
+				p --;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   186
+				s --;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   187
+			} else if ( patrollback != NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   188
+				p =    patrollback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   189
+				s = -- strrollback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   190
+			} else {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   191
+				s --;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   192
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   193
+		}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   194
+		// now s, p or both have finished run
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   195
+		if ( s >= str && patrollback == NULL ) // s remains and final star
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   196
+			s = str - 1; // value at the end of loop
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   197
+		if ( p >= pat ) { // p remains
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   198
+			while ( *p == '*' && p >= pat ) // ignore empty stars
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   199
+				p --;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   200
+			if ( p >= pat ) // symbols remain in pattern, no match
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   201
+				return NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   202
+		}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   203
+		if ( matchend == NULL && patrollback != NULL ) // no stars
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   204
+			matchend = strrollback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   205
+		if ( matchend != NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   206
+			*ret_len = matchend - s;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   207
+			return s + 1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   208
+		} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   209
+			return NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   210
+	} else { // ltr
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   211
+		const char * const  pe          = pat + patlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   212
+		const char * const  se          = str + length;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   213
+		const char         *p           = pat;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   214
+		const char         *s           = str;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   215
+		const char         *matchstart  = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   216
+		const char         *patrollback = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   217
+		const char         *strrollback = s;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   218
+		while ( p < pe && s < se ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   219
+			if ( *p == '*' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   220
+				if ( matchstart == NULL && patrollback != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   221
+					matchstart = strrollback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   222
+				patrollback = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   223
+				strrollback = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   224
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   225
+			} else if ( *p == '?' || *p == *s ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   226
+				if ( patrollback == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   227
+					patrollback = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   228
+					strrollback = s;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   229
+				}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   230
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   231
+				s ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   232
+			} else if ( patrollback != NULL ) { // start/nomatch-recovery eat
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   233
+				p =    patrollback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   234
+				s = ++ strrollback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   235
+			} else { // star-eat
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   236
+				s ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   237
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   238
+		}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   239
+		// now s, p or both have finished run
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   240
+		if ( s < se && patrollback == NULL ) // s remains and final star
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   241
+				s = se;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   242
+		if ( p < pe ) { // p remains
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   243
+			while ( *p == '*' && p < pe ) // ignore empty stars
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   244
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   245
+			if ( p < pe ) // symbols remain in pattern, no match
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   246
+				return NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   247
+		}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   248
+		if ( matchstart == NULL && patrollback != NULL ) // no stars
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   249
+			matchstart = strrollback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   250
+		if ( matchstart != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   251
+			*ret_len = s - matchstart;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   252
+		return matchstart;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   253
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   254
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   255
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   256
+// match tmpl_greedy_glob ( string, pattern, right-to-left )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   257
+// The same as above, but greedy.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   258
+const gchar *tmpl_greedy_glob ( const char *str, gsize length, const char *pat, gsize patlen, gboolean rtl, gsize *ret_len )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   259
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   260
+	const char * const  pe = pat + patlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   261
+	const char         *p  = pat;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   262
+	while ( p < pe ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   263
+		if ( *p == '*' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   264
+			gsize       llen = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   265
+			const char *left = tmpl_glob ( str, length, pat, p - pat, FALSE, &llen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   266
+			if ( left != NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   267
+				gsize       rlen  = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   268
+				const char *right = tmpl_glob ( left + llen, str + length - ( left + llen ), p + 1, pe - p - 1, TRUE, &rlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   269
+				if ( right != NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   270
+					*ret_len = right + rlen - left;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   271
+					return left;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   272
+				}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   273
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   274
+			return NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   275
+		}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   276
+		p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   277
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   278
+	return tmpl_glob ( str, length, pat, patlen, rtl, ret_len );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   279
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   280
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   281
+// - + * / % ( )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   282
+static gssize tmpl_math_expand_internal ( const char *str, gsize length, tmpl_variable_callback_t get_val, gpointer udata, GError **error, tmpl_math_op_t bound, gsize *proc_len )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   283
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   284
+	g_assert ( error != NULL && *error == NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   285
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   286
+	gssize             result   = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   287
+	const char *       p        = str;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   288
+	const char * const e        = str + length;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   289
+	tmpl_math_state_t   state    = in_preargument;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   290
+	const char *       varname  = NULL;  // variable name start
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   291
+	gsize              base     = 10;    // number base
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   292
+	gboolean           invert   = FALSE; // number change sign
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   293
+	gboolean           errstate = bound >= noempty_op; // indicates erroneous state
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   294
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   295
+	// process first argument
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   296
+	while ( p < e && *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   297
+		if ( state == in_preargument ) { // initial space-skipping state
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   298
+			if ( isspace ( *p ) )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   299
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   300
+			else if ( *p == '-' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   301
+				invert = ! invert;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   302
+				errstate = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   303
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   304
+			} else if ( *p == '+' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   305
+				errstate = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   306
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   307
+			} else if ( *p == '(' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   308
+				gsize processed = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   309
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   310
+				result = tmpl_math_expand_internal ( p, e - p, get_val, udata, error, paren_op, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   311
+				if ( *error == NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   312
+					state = in_postparen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   313
+				errstate  = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   314
+				p        += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   315
+			} else if ( *p == '0' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   316
+				result   = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   317
+				errstate = FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   318
+				state    = in_hexoctzero;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   319
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   320
+			} else if ( isdigit ( *p ) ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   321
+				result   = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   322
+				base     = 10;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   323
+				state    = in_number;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   324
+			} else if ( isalpha ( *p ) || *p == '_' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   325
+				state    = in_variable;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   326
+				errstate = FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   327
+				varname  = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   328
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   329
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   330
+				g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EMATHWRONGARG, "Wrong symbol in math argument" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   331
+		} else if ( state == in_hexoctzero ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   332
+			if ( *p == 'x' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   333
+				errstate = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   334
+				base     = 16;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   335
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   336
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   337
+				base = 8;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   338
+			state  = in_number;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   339
+		} else if ( state == in_number ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   340
+			short d = -1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   341
+			if ( *p == '0' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   342
+				d = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   343
+			else if ( *p == '1' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   344
+				d = 1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   345
+			else if ( *p == '2' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   346
+				d = 2;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   347
+			else if ( *p == '3' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   348
+				d = 3;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   349
+			else if ( *p == '4' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   350
+				d = 4;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   351
+			else if ( *p == '5' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   352
+				d = 5;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   353
+			else if ( *p == '6' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   354
+				d = 6;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   355
+			else if ( *p == '7' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   356
+				d = 7;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   357
+			else if ( base <= 8 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   358
+				;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   359
+			else if ( *p == '8' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   360
+				d = 8;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   361
+			else if ( *p == '9' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   362
+				d = 9;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   363
+			else if ( base <= 10 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   364
+				;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   365
+			else if ( *p == 'a' || *p == 'A' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   366
+				d = 10;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   367
+			else if ( *p == 'b' || *p == 'B' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   368
+				d = 11;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   369
+			else if ( *p == 'c' || *p == 'C' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   370
+				d = 12;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   371
+			else if ( *p == 'd' || *p == 'D' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   372
+				d = 13;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   373
+			else if ( *p == 'e' || *p == 'E' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   374
+				d = 14;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   375
+			else if ( *p == 'f' || *p == 'F' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   376
+				d = 15;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   377
+			if ( d >= 0 ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   378
+				errstate = FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   379
+				result   = result * base + d;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   380
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   381
+			} else if ( ! errstate )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   382
+				state = in_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   383
+			else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   384
+				g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EMATHWRONGNUMBER, "Too short math number" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   385
+		} else if ( state == in_variable ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   386
+			if ( ! ( isalnum ( *p ) || *p == '_' ) ) { // XXX vars with '-' have to be expanded earlier
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   387
+				gsize        vlen  = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   388
+				const char * value = get_val ( varname, p - varname, udata, &vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   389
+				// TODO control recursion level
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   390
+				result = tmpl_math_expand_internal ( value, vlen, get_val, udata, error, no_op, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   391
+				if ( *error == NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   392
+					state = in_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   393
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   394
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   395
+		} else if ( state == in_postparen ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   396
+			if ( *p == ')' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   397
+				errstate = FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   398
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   399
+				state    = in_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   400
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   401
+				g_assert_not_reached ();
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   402
+		} else if ( state == in_op )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   403
+			break;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   404
+		else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   405
+			g_assert_not_reached ();
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   406
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   407
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   408
+	if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   409
+		// in_preargument - empty argument, possibly +-+- - 0 / errstate
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   410
+		// in_hexoctzero  - 0                             - 0
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   411
+		// in_number      - 0, 0x, 01, 0x1, 1             - failure at 0x (errstate), invert
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   412
+		// in_variable    - varname                       - get var, invert
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   413
+		// in_postparen   - eof                           - failure (errstate)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   414
+		// in_op          - ok                            - invert, continue parsing
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   415
+		if ( errstate )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   416
+			g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EMATHWRONGSTATE, "Wrong state at the end of first math argument parsing" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   417
+		else {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   418
+			if ( state == in_op ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   419
+				if ( invert )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   420
+					result = - result;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   421
+			
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   422
+				// process operator+second argument pairs
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   423
+				while ( p < e && *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   424
+					tmpl_math_op_t op = no_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   425
+					if ( isspace ( *p ) )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   426
+						p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   427
+					else if ( *p == '+' ) // set op
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   428
+						op = plus_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   429
+					else if ( *p == '-' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   430
+						op = minus_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   431
+					else if ( *p == '/' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   432
+						op = division_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   433
+					else if ( *p == '*' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   434
+						op = multiplication_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   435
+					else if ( *p == '%' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   436
+						op = remainder_op;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   437
+					else if ( *p == ')' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   438
+						if ( bound < paren_op )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   439
+							g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EMATHUNBALPAREN, "Unbalanced parens in math expression" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   440
+						else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   441
+							break;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   442
+					} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   443
+						g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EMATHWRONGOP, "Wrong math operator '%c'", *p );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   444
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   445
+					if ( op != no_op ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   446
+						// lower priority operator, returning result
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   447
+						if ( op < bound )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   448
+							break;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   449
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   450
+						p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   451
+						gsize  processed = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   452
+						gssize arg       = tmpl_math_expand_internal ( p, e - p, get_val, udata, error, op, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   453
+						if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   454
+							if ( op == plus_op )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   455
+								result += arg;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   456
+							else if ( op == minus_op )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   457
+								result -= arg;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   458
+							else if ( op == division_op )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   459
+								result /= arg;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   460
+							else if ( op == multiplication_op )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   461
+								result *= arg;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   462
+							else if ( op == remainder_op )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   463
+								result %= arg;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   464
+							else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   465
+								g_assert_not_reached ();
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   466
+						}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   467
+						p += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   468
+					}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   469
+				}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   470
+			} else if ( state == in_variable ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   471
+				gsize        vlen  = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   472
+				const char * value = get_val ( varname, p - varname, udata, &vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   473
+				result = tmpl_math_expand_internal ( value, vlen, get_val, udata, error, no_op, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   474
+				if ( *error == NULL && invert )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   475
+					result = - result;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   476
+			} else if ( invert )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   477
+				result = - result;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   478
+			// XXX may add long conditional with g_assert here, but I'm lazy
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   479
+		}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   480
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   481
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   482
+	// return result
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   483
+	if ( proc_len != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   484
+		*proc_len = p - str;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   485
+	return result;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   486
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   487
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   488
+// result tmpl_math_expand ( plainexpanded string, callback )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   489
+// Performs mathematical expansion on given string.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   490
+// Note, that it does not perform variable/quote/etc expansion,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   491
+// if you want it, you should do that first.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   492
+gssize tmpl_math_expand ( const char *str, gsize length, tmpl_variable_callback_t get_val, gpointer udata, GError **ret_err )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   493
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   494
+	g_return_val_if_fail ( ret_err == NULL || *ret_err == NULL, -1 ); // XXX
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   495
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   496
+	GError * error  = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   497
+	gssize   result = tmpl_math_expand_internal ( str, length, get_val, udata, &error, no_op, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   498
+	if ( error != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   499
+		g_propagate_error ( ret_err, error );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   500
+	return result;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   501
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   502
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   503
+// expansion tmpl_expand ( template, callback )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   504
+// Parse template, substitute shell-like expressions:
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   505
+// * $var ${var}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   506
+// * ${var##pat} ${var#pat} ${var%%pat} ${var%pat}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   507
+// * ${var/pat} ${var/pat/repl} ${var//pat/repl} ${var/%pat/repl} ${var/#pat/repl}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   508
+// * ${var:+tmpl} ${var:-tmpl}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   509
+// * ${var:uint} ${var:uint:uint}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   510
+// * ${#var} ${!var} ${!var[operation]}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   511
+// * \n \t \e \$ \\ \X
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   512
+// Callback will be called to obtain variable values.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   513
+// Variable name should be: /^[[:alnum:]][[:alnum:]_-]*$/
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   514
+// For pattern rules see tmpl_glob ().
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   515
+static gchar *tmpl_expand_internal ( const char *template, gsize len, tmpl_variable_callback_t get_val, gpointer udata, gsize *ret_len, GError **error, tmpl_parser_flags_t flags, gsize *proc_len )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   516
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   517
+	g_assert ( error != NULL && *error == NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   518
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   519
+	if ( template == NULL || len == 0 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   520
+		return NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   521
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   522
+	GString            *result     = g_string_new ( NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   523
+	const char         *p          = template;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   524
+	const char * const  e          = template + len;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   525
+	tmpl_parser_state_t  state      = in_string;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   526
+	const char         *a1s        = p;     // string, varname
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   527
+	const gchar        *value      = NULL;  // variable value
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   528
+	gsize               vlen       = 0;     // variable value length
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   529
+	tmpl_var_operation_t operation  = no_operation;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   530
+	gchar              *pattern    = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   531
+	gsize               plen       = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   532
+	gboolean            rtl        = FALSE; // strip/chop
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   533
+	gboolean            greedy     = FALSE; // strip/chop
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   534
+	gboolean            multiglob  = FALSE; // replace
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   535
+	gsize               parencount = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   536
+	gssize              subsoffset = -1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   537
+	gssize              subslength = -1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   538
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   539
+	while ( p < e && *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   540
+		if ( state == in_string ) { // nothing special
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   541
+			if ( *p == '\\' ) { // escape next char
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   542
+				g_string_append_len ( result, a1s, p - a1s );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   543
+				state = in_escape;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   544
+			} else if ( *p == '$' ) { // start variable
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   545
+				g_string_append_len ( result, a1s, p - a1s );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   546
+				state = in_var;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   547
+			} else if ( flags & balance_parens && *p == '(' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   548
+				parencount ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   549
+			} else if ( *p == ')' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   550
+				if ( flags & balance_parens && parencount > 0 ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   551
+					parencount --;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   552
+				} else if ( flags & dblparen_eol ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   553
+					g_string_append_len ( result, a1s, p - a1s );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   554
+					state = in_dblparen_eol;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   555
+				} else if ( flags & balance_parens )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   556
+					g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EUNBALPAREN, "Unbalanced parentheses" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   557
+			} else if ( ( flags & brace_eol && *p == '}' ) ||
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   558
+			            ( flags & slash_eol && *p == '/' ) ||
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   559
+						( flags & colon_eol && parencount == 0 && *p == ':' ) )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   560
+				break;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   561
+			p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   562
+		} else if ( state == in_escape ) { // escape (on escaped char)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   563
+			if ( *p == 'n' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   564
+				g_string_append_c ( result, '\n' );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   565
+			else if ( *p == 't' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   566
+				g_string_append_c ( result, '\t' );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   567
+			else if ( *p == 'e' ) // for some experimentation with colors...
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   568
+				g_string_append_c ( result, '\033' );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   569
+			else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   570
+				g_string_append_c ( result, *p );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   571
+			p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   572
+			state = in_string;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   573
+			a1s   = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   574
+		} else if ( state == in_var ) { // some variable
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   575
+			if ( *p == '{' ) { // enclosed variable
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   576
+				state = in_prevarname;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   577
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   578
+			} else if ( *p == '(' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   579
+				state = in_evalstart;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   580
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   581
+			} else // unenclosed variable
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   582
+				state = in_plainvarstart;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   583
+		} else if ( state == in_plainvarstart ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   584
+			if ( isalpha ( *p ) || *p == '_' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   585
+				state = in_plainvar;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   586
+				a1s   = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   587
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   588
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   589
+				g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EWRONGVARNAME, "Wrong symbol at the start of variable name" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   590
+		} else if ( state == in_plainvar ) { // unenclosed variable
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   591
+			if ( ! ( isalnum ( *p ) || *p == '-' || *p == '_' ) ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   592
+				gsize        vlen  = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   593
+				const gchar *value = get_val ( a1s, p - a1s, udata, &vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   594
+				g_string_append_len ( result, value, vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   595
+				state = in_string;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   596
+				a1s   = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   597
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   598
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   599
+		} else if ( state == in_prevarname ) { // allow ! and # at varname start
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   600
+			if ( *p == '!' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   601
+				operation = expand_var;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   602
+				p++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   603
+			} else if ( *p == '#' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   604
+				operation = value_length;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   605
+				p++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   606
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   607
+				operation = no_operation;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   608
+			state = in_varnamestart;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   609
+		} else if ( state == in_varnamestart ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   610
+			if ( isalpha ( *p ) || *p == '_' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   611
+				state = in_varname;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   612
+				a1s   = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   613
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   614
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   615
+				g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EWRONGVARNAME, "Wrong symbol at start of variable name" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   616
+		} else if ( state == in_varname ) { // enclosed variable name
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   617
+			if ( ! ( isalnum ( *p ) || *p == '-' || *p == '_' ) ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   618
+				value = get_val ( a1s, p - a1s, udata, &vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   619
+				if ( operation == value_length ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   620
+					if ( *p == '}' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   621
+						g_string_append_printf ( result, "%lu", vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   622
+						state = in_varend;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   623
+					} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   624
+						g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EWRONGVAREXP, "Wrong variable expansion expression" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   625
+				} else {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   626
+					if ( operation == expand_var && value != NULL && vlen > 0 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   627
+						value = get_val ( value, vlen, udata, &vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   628
+					if ( *p == '}' ) { // end of variable
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   629
+						g_string_append_len ( result, value, vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   630
+						state = in_varend;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   631
+					} else if ( *p == '#' ) { // strip expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   632
+						state = in_varstrip;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   633
+						p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   634
+					} else if ( *p == '%' ) { // chop expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   635
+						state = in_varchop;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   636
+						p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   637
+					} else if ( *p == '/' ) { // replace expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   638
+						state = in_varslash;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   639
+						p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   640
+					} else if ( *p == ':' ) { // substring expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   641
+						state = in_varcolon;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   642
+						p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   643
+					} else // wrong symbols
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   644
+						g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EWRONGVAREXP, "Wrong variable expansion expression" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   645
+				}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   646
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   647
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   648
+		} else if ( state == in_varstrip ) { // one of strip expressions
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   649
+			if ( *p == '#' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   650
+				greedy = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   651
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   652
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   653
+			rtl   = FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   654
+			state = in_varstripchop;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   655
+		} else if ( state == in_varchop ) { // one of chop expressions
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   656
+			if ( *p == '%' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   657
+				greedy = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   658
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   659
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   660
+			rtl   = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   661
+			state = in_varstripchop;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   662
+		} else if ( state == in_varstripchop ) { // pattern expressions
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   663
+			gsize  elen      = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   664
+			gsize  processed = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   665
+			gchar *expansion = tmpl_expand_internal ( p, e - p, get_val, udata, &elen, error, brace_eol, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   666
+			if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   667
+				gsize       mlen  = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   668
+				const char *match = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   669
+				if ( greedy )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   670
+					match = tmpl_greedy_glob ( value, vlen, expansion, elen, rtl, &mlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   671
+				else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   672
+					match = tmpl_glob ( value, vlen, expansion, elen, rtl, &mlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   673
+				if ( mlen > 0 ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   674
+					if ( rtl ) { // % and %%
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   675
+						if ( match + mlen == value + vlen )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   676
+							vlen -= mlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   677
+					} else if ( match == value ) { // # and ##
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   678
+						value  = match + mlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   679
+						vlen  -= mlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   680
+					}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   681
+				}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   682
+				g_string_append_len ( result, value, vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   683
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   684
+			g_free ( expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   685
+			p     += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   686
+			state  = in_varend;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   687
+		} else if ( state == in_varslash ) { // replace expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   688
+			multiglob = FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   689
+			rtl       = FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   690
+			if ( *p == '#' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   691
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   692
+			else if ( *p == '%' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   693
+				rtl = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   694
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   695
+			} else if ( *p == '/' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   696
+				multiglob = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   697
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   698
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   699
+			state = in_varmatch;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   700
+		} else if ( state == in_varmatch ) { // match part of replace expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   701
+			gsize processed  = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   702
+			pattern          = tmpl_expand_internal ( p, e - p, get_val, udata, &plen, error, brace_eol | slash_eol, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   703
+			p               += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   704
+			state            = in_varpresubst;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   705
+		} else if ( state == in_varpresubst ) { // skip slash
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   706
+			if ( *p == '/' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   707
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   708
+			state = in_varsubst;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   709
+		} else if ( state == in_varsubst ) { // replace expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   710
+			gsize  processed = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   711
+			gsize  slen      = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   712
+			gchar *subst     = tmpl_expand_internal ( p, e - p, get_val, udata, &slen, error, brace_eol, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   713
+			if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   714
+				const char       * start = value;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   715
+				const char * const ve    = value + vlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   716
+				while ( start < ve ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   717
+					gsize       mlen  = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   718
+					const char *match = tmpl_glob ( start, ve - start, pattern, plen, rtl, &mlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   719
+					if ( mlen > 0 ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   720
+						g_string_append_len ( result, start, match - start );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   721
+						g_string_append_len ( result, subst, slen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   722
+						start = match + mlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   723
+					} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   724
+						break;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   725
+					if ( ! multiglob )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   726
+						break;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   727
+				}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   728
+				g_string_append_len ( result, start, ve - start );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   729
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   730
+			g_free ( subst );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   731
+			g_free ( pattern );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   732
+			pattern  = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   733
+			p       += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   734
+			state    = in_varend;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   735
+		} else if ( state == in_varcolon ) { // substring or substitution expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   736
+			if ( *p == '-' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   737
+				state = in_varminus;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   738
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   739
+			} else if ( *p == '+' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   740
+				state = in_varplus;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   741
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   742
+			} else {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   743
+				subsoffset = -1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   744
+				subslength = -1;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   745
+				state      = in_varpos;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   746
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   747
+		} else if ( state == in_varminus || state == in_varplus ) { // zero and non-zero substitution
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   748
+			gsize        elen      = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   749
+			gsize        processed = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   750
+			gchar       *expansion = tmpl_expand_internal ( p, e - p, get_val, udata, &elen, error, brace_eol, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   751
+			if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   752
+				if ( ( vlen == 0 && state == in_varminus ) || ( vlen > 0 && state == in_varplus ) )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   753
+					g_string_append_len ( result, expansion, elen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   754
+				else if ( vlen > 0 && state == in_varminus )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   755
+					g_string_append_len ( result, value, vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   756
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   757
+			g_free ( expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   758
+			p     += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   759
+			state  = in_varend;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   760
+		} else if ( state == in_varpos ) { // substring expression
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   761
+			gsize  elen      = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   762
+			gsize  processed = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   763
+			gchar *expansion = tmpl_expand_internal ( p, e - p, get_val, udata, &elen, error, colon_eol | brace_eol | balance_parens, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   764
+			if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   765
+				subsoffset = tmpl_math_expand_internal ( expansion, elen, get_val, udata, error, no_op, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   766
+				if ( subsoffset < 0 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   767
+					subsoffset = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   768
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   769
+			g_free ( expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   770
+			p     += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   771
+			state  = in_postvarpos;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   772
+		} else if ( state == in_postvarpos ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   773
+			if ( *p == ':' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   774
+				state = in_varlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   775
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   776
+			} else if ( *p == '}' )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   777
+				state = in_varsubstring;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   778
+			else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   779
+				g_assert_not_reached ();
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   780
+		} else if ( state == in_varlen ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   781
+			gsize  elen      = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   782
+			gsize  processed = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   783
+			gchar *expansion = tmpl_expand_internal ( p, e - p, get_val, udata, &elen, error, brace_eol | balance_parens, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   784
+			if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   785
+				subslength = tmpl_math_expand_internal ( expansion, elen, get_val, udata, error, no_op, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   786
+				if ( subslength < 0 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   787
+					subslength = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   788
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   789
+			g_free ( expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   790
+			p     += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   791
+			state  = in_varsubstring;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   792
+		} else if ( state == in_varsubstring ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   793
+			g_assert ( subsoffset >= 0 );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   794
+			if ( subslength == -1 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   795
+				subslength = vlen;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   796
+			if ( subsoffset < vlen ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   797
+				if ( subsoffset + subslength > vlen )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   798
+					g_string_append_len ( result, value + subsoffset, vlen - subsoffset );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   799
+				else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   800
+					g_string_append_len ( result, value + subsoffset, subslength );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   801
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   802
+			state = in_varend;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   803
+		} else if ( state == in_varend ) { // end of enclosed variable
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   804
+			if ( *p == '}' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   805
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   806
+				state = in_string;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   807
+				a1s   = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   808
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   809
+				g_assert_not_reached (); // this state must be used only on '}' or EOL
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   810
+		} else if ( state == in_evalstart ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   811
+			if ( *p == '(' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   812
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   813
+				state = in_mathexpand;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   814
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   815
+				g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EUNBALPAREN, "Command evaluation is not supported" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   816
+		} else if ( state == in_mathexpand ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   817
+			gsize  elen      = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   818
+			gsize  processed = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   819
+			gchar *expansion = tmpl_expand_internal ( p, e - p, get_val, udata, &elen, error, dblparen_eol | balance_parens, &processed );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   820
+			if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   821
+				gssize value = tmpl_math_expand_internal ( expansion, elen, get_val, udata, error, no_op, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   822
+				if ( *error == NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   823
+					g_string_append_printf ( result, "%li", value );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   824
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   825
+			g_free ( expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   826
+			p     += processed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   827
+			state  = in_string;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   828
+			a1s    = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   829
+		} else if ( state == in_dblparen_eol ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   830
+			if ( *p == ')' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   831
+				p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   832
+				break;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   833
+			} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   834
+				g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EUNBALPAREN, "Unbalanced parentheses" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   835
+		} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   836
+			g_assert_not_reached ();
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   837
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   838
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   839
+	if ( *error == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   840
+		if ( state == in_plainvar ) { // plain variable at the end of template
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   841
+			gsize        vlen  = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   842
+			const gchar *value = get_val ( a1s, p - a1s, udata, &vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   843
+			g_string_append_len ( result, value, vlen );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   844
+		} else if ( state == in_string ) // end of string
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   845
+			g_string_append_len ( result, a1s, p - a1s );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   846
+		else if ( state != in_dblparen_eol )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   847
+			g_set_error ( error, TMPL_GERROR_QUARK, TMPL_EWRONGENDSTATE, "Parser stopped in incorrect state '%s'", state < nostate ? tmpl_statenames [ state ] : "wrong state" );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   848
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   849
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   850
+	if ( pattern != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   851
+		g_free ( pattern );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   852
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   853
+	if ( proc_len != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   854
+		*proc_len = p - template;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   855
+	if ( ret_len != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   856
+		*ret_len = result -> len;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   857
+	return g_string_free ( result, FALSE );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   858
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   859
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   860
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   861
+//  public wrappers
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   862
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   863
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   864
+gchar *tmpl_expand ( const char *template, gsize len, tmpl_variable_callback_t get_val, gpointer udata, gsize *ret_len, GError **ret_err )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   865
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   866
+	g_return_val_if_fail ( ret_err == NULL || *ret_err == NULL, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   867
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   868
+	GError * error  = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   869
+	gchar *  result = tmpl_expand_internal ( template, len, get_val, udata, ret_len, &error, no_eol, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   870
+	if ( error != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   871
+		g_propagate_error ( ret_err, error );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   872
+	return result;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   873
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   874
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   875
+/* vim: se ts=4 sw=4: */
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   876
diff -r 456d83274014 mcabber/mcabber/parser.h
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   877
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   878
+++ b/mcabber/mcabber/parser.h	Fri Jul 20 17:30:20 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   879
@@ -0,0 +1,77 @@
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   880
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   881
+#ifndef MCABBER_PARSER_H
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   882
+#define MCABBER_PARSER_H
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   883
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   884
+/* Copyright 2012 Myhailo Danylenko
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   885
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   886
+ * This file is part of mcabber
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   887
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   888
+ * mcabber free software: you can redistribute it and/or
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   889
+ * modify it under the terms of the GNU General Public License as published
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   890
+ * by the Free Software Foundation, either version 2 of the License, or
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   891
+ * (at your option) any later version.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   892
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   893
+ * This program is distributed in the hope that it will be useful,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   894
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   895
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   896
+ * GNU General Public License for more details.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   897
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   898
+ * You should have received a copy of the GNU General Public License
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   899
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>. */
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   900
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   901
+#include <glib.h>
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   902
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   903
+#define TMPL_GERROR_QUARK tmpl_gerror_quark ()
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   904
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   905
+#define TMPL_EWRONGVAREXP   ( 0x01 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   906
+#define TMPL_EWRONGVARNAME  ( 0x03 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   907
+#define TMPL_EUNBALPAREN    ( 0x04 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   908
+#define TMPL_EWRONGENDSTATE ( 0x02 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   909
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   910
+#define TMPL_EMATHWRONGARG    ( 0x05 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   911
+#define TMPL_EMATHWRONGNUMBER ( 0x06 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   912
+#define TMPL_EMATHUNBALPAREN  ( 0x07 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   913
+#define TMPL_EMATHWRONGOP     ( 0x08 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   914
+#define TMPL_EMATHWRONGSTATE  ( 0x09 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   915
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   916
+typedef const char *(*tmpl_variable_callback_t)   ( const gchar *name, gsize len, gpointer udata, gsize *ret_len );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   917
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   918
+GQuark tmpl_gerror_quark ( void );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   919
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   920
+//  match tmpl_glob ( string, pattern, right-to-left )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   921
+// Performs matching of given pattern against given string,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   922
+// returns substring, that matched. In pattern, there are currently
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   923
+// two tokens recognized: '*' and '?'. Two flags determine, if
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   924
+// '*' should be greedy and which end of string must match the
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   925
+// pattern (i.e. have anchor).
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   926
+const char *tmpl_glob ( const char *str, gsize strlen, const char *pat, gsize patlen, gboolean rtl, gsize *ret_len );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   927
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   928
+//  match tmpl_greedy_glob ( string, pattern, rigt-to-left )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   929
+// The same, as above, but greedy.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   930
+const char *tmpl_greedy_glob ( const char *str, gsize strlen, const char *pat, gsize patlen, gboolean rtl, gsize *ret_len );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   931
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   932
+//  result tmpl_math_expand ( string, callback )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   933
+// Performs mathematical expansion of given string.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   934
+// Note, that $var expressions are not recognized, you have to
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   935
+// supply already expanded string here.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   936
+// Supported operators:
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   937
+// ( ) + - * / %
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   938
+gssize tmpl_math_expand ( const char *str, gsize len, tmpl_variable_callback_t get_val, gpointer udata, GError **error );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   939
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   940
+//  expansion tmpl_expand ( template, callback )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   941
+// Parse template, substitute shell-like expressions:
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   942
+// * $var ${var}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   943
+// * ${var##pat} ${var#pat} ${var%%pat} ${var%pat}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   944
+// * ${var/pat} ${var/pat/repl} ${var//pat/repl} ${var/%pat/repl} ${var/#pat/repl}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   945
+// * ${var:+tmpl} ${var:-tmpl}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   946
+// * ${var:mathexp} ${var:mathexp:mathexp}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   947
+// * ${#var} ${!var} ${!var[operation]}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   948
+// * $(( mathexp ))
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   949
+// * \n \t \e \$ \\ \X
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   950
+// Callback will be called to obtain variable values.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   951
+// Variable name should be: /^[[:alnum:]][[:alnum:]_-]*$/
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   952
+// For pattern rules see mms_glob ().
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   953
+gchar *tmpl_expand ( const char *template, gsize len, tmpl_variable_callback_t get_val, gpointer udata, gsize *ret_len, GError **error );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   954
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   955
+# endif
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   956
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   957
diff -r 456d83274014 mcabber/mcabber/templates.c
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   958
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   959
+++ b/mcabber/mcabber/templates.c	Fri Jul 20 17:30:20 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   960
@@ -0,0 +1,277 @@
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   961
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   962
+/* Copyright 2012 Myhailo Danylenko
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   963
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   964
+ * This file is part of mcabber
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   965
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   966
+ * mcabber is free software: you can redistribute it and/or
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   967
+ * modify it under the terms of the GNU General Public License as published
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   968
+ * by the Free Software Foundation, either version 2 of the License, or
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   969
+ * (at your option) any later version.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   970
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   971
+ * This program is distributed in the hope that it will be useful,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   972
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   973
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   974
+ * GNU General Public License for more details.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   975
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   976
+ * You should have received a copy of the GNU General Public License
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   977
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>. */
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   978
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   979
+#include <glib.h>
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   980
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   981
+#include <string.h>    // strlen
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   982
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   983
+#include "logprint.h"
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   984
+#include "settings.h"
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   985
+#include "main.h"      // main_context
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   986
+#include "templates.h"
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   987
+#include "parser.h"
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   988
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   989
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   990
+//  globals
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   991
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   992
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   993
+typedef void (*tmpl_callback_t) ( const gchar * expansion, gpointer udata );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   994
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   995
+typedef struct {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   996
+	gchar           * name;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   997
+	tmpl_callback_t   callback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   998
+	gpointer          userdata;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
   999
+	gboolean          in_use;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1000
+	GSList          * guards;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1001
+	gboolean          changed;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1002
+	gchar           * prev_expansion;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1003
+} template_t;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1004
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1005
+typedef struct {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1006
+	gchar  * name;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1007
+	GSList * templates;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1008
+} tmpl_guard_t;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1009
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1010
+static GHashTable * tmpl_templates   = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1011
+static GHashTable * tmpl_guards      = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1012
+static guint        tmpl_attached_id = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1013
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1014
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1015
+//  predeclarations
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1016
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1017
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1018
+static gchar *tmpl_guard ( const gchar *key, const gchar *new_value );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1019
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1020
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1021
+//  code
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1022
+//
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1023
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1024
+// [cb] drops template from guard's 'templates' list
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1025
+static void tmpl_unguard ( gpointer data, gpointer udata )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1026
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1027
+	tmpl_guard_t *guard    = data;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1028
+	template_t   *template = udata;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1029
+	guard -> templates = g_slist_remove ( guard -> templates, template );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1030
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1031
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1032
+// [destructor cb] releases guard hash table entry
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1033
+static void tmpl_free_guard ( gpointer data )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1034
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1035
+	tmpl_guard_t *guard = data;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1036
+	settings_del_guard ( guard -> name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1037
+	g_slist_free ( guard -> templates );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1038
+	g_free ( guard -> name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1039
+	g_slice_free ( tmpl_guard_t, guard );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1040
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1041
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1042
+// [destructor cb] releases taken guards and frees command
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1043
+static void tmpl_free_template ( gpointer data )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1044
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1045
+	template_t *template = data;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1046
+	g_slist_foreach ( template -> guards, tmpl_unguard, template );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1047
+	g_slist_free ( template -> guards );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1048
+	g_free ( template -> name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1049
+	g_free ( template -> prev_expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1050
+	g_slice_free ( template_t, template );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1051
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1052
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1053
+// install guard (name must be glib-allocated string)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1054
+static void tmpl_install_guard ( gchar *name, template_t *template, settings_guard_t callback )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1055
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1056
+	tmpl_guard_t *guard = g_hash_table_lookup ( tmpl_guards, name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1057
+	if ( guard == NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1058
+		if ( ! settings_set_guard ( name, callback ) ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1059
+			scr_log_print ( LPRINT_LOGNORM, "Error: Unable to install guard for variable '%s' for template '%s'.", name, template -> name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1060
+			g_free ( name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1061
+		} else {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1062
+			guard = g_slice_new ( tmpl_guard_t );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1063
+			guard -> name      = name;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1064
+			guard -> templates = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1065
+			g_hash_table_replace ( tmpl_guards, guard -> name, guard ); // to be sure
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1066
+		}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1067
+	} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1068
+		g_free ( name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1069
+	if ( ! g_slist_find ( template -> guards, guard ) ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1070
+		template -> guards = g_slist_prepend ( template -> guards, guard );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1071
+		guard -> templates = g_slist_prepend ( guard -> templates, template );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1072
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1073
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1074
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1075
+// [parser cb] provides mcabber option values & reinstalls guards
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1076
+static const char *tmpl_get_var ( const gchar *name, gsize len, gpointer udata, gsize *ret_len )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1077
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1078
+	const char *result = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1079
+	if ( name != NULL && len > 0 ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1080
+		template_t * template = udata;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1081
+		gchar      * var      = g_strndup ( name, len );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1082
+		result = settings_opt_get ( var );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1083
+		// consumes var
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1084
+		tmpl_install_guard ( var, template, tmpl_guard );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1085
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1086
+	if ( ret_len != NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1087
+		if ( result != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1088
+			*ret_len = strlen ( result );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1089
+		else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1090
+			*ret_len = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1091
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1092
+	return result;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1093
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1094
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1095
+// [cb] mark unused guards for removal
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1096
+static gboolean tmpl_drop_unused_guards ( gpointer key, gpointer value, gpointer udata )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1097
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1098
+	tmpl_guard_t * guard = value;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1099
+	if ( guard -> templates == NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1100
+		return TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1101
+	return FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1102
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1103
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1104
+// [cb] mark deleted templates for removal, reevaluate changed
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1105
+static gboolean reevaluate_template ( gpointer key, gpointer value, gpointer udata )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1106
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1107
+	template_t * template = value;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1108
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1109
+	if ( ! template -> in_use )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1110
+		return TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1111
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1112
+	if ( template -> changed ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1113
+		const gchar * expression = settings_opt_get ( template -> name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1114
+		gchar       * expansion  = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1115
+		// release guards (but do not free them)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1116
+		g_slist_foreach ( template -> guards, tmpl_unguard, template );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1117
+		g_slist_free ( template -> guards );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1118
+		template -> guards = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1119
+		// re-install guards & get updated expansion
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1120
+		if ( expression != NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1121
+			GError *error = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1122
+			expansion = tmpl_expand ( expression, strlen ( expression ), tmpl_get_var, template, NULL, &error );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1123
+			if ( error != NULL ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1124
+				scr_log_print ( LPRINT_LOGNORM, "Error: Expansion error on template '%s': %s.\nExpansion stopped at: '%s'", template -> name, error -> message, expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1125
+				g_error_free ( error );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1126
+				g_free ( expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1127
+				expansion = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1128
+			}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1129
+		}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1130
+		// re-install guard on template itself
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1131
+		tmpl_install_guard ( g_strdup ( template -> name ), template, tmpl_guard );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1132
+		template -> changed = FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1133
+		// pass result to callback
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1134
+		if ( g_strcmp0 ( expansion, template -> prev_expansion ) ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1135
+			g_free ( template -> prev_expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1136
+			template -> prev_expansion = expansion;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1137
+			template -> callback ( expansion, template -> userdata );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1138
+		} else
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1139
+			g_free ( expansion );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1140
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1141
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1142
+	return FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1143
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1144
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1145
+// [idle cb] update commands/guards & call cbs when necessary
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1146
+static gboolean reevaluate_templates ( gpointer data )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1147
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1148
+	// allow reschedule in a process of reevaluation
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1149
+	tmpl_attached_id = 0;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1150
+	// drop removed & reevaluate changed templates
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1151
+	g_hash_table_foreach_remove ( tmpl_templates, reevaluate_template, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1152
+	// free unused guards TODO do only when needed
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1153
+	g_hash_table_foreach_remove ( tmpl_guards, tmpl_drop_unused_guards, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1154
+	// always return false, this is oneshot idle call
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1155
+	return FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1156
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1157
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1158
+// schedule templates reevaluation
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1159
+static void tmpl_schedule_rerun ( void )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1160
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1161
+	if ( tmpl_attached_id == 0 ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1162
+		GSource * source = g_idle_source_new ();
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1163
+		g_source_set_callback ( source, reevaluate_templates, NULL, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1164
+		tmpl_attached_id = g_source_attach ( source, main_context );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1165
+		g_source_unref ( source );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1166
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1167
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1168
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1169
+// [cb] sets changed flag on template
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1170
+static void template_set_changed ( gpointer data, gpointer udata )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1171
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1172
+	template_t * template = data;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1173
+	template -> changed   = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1174
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1175
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1176
+// [guard] generic guard for variable
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1177
+static gchar *tmpl_guard ( const gchar *key, const gchar *new_value )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1178
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1179
+	if ( g_strcmp0 ( new_value, settings_opt_get ( key ) ) ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1180
+		// mark dependent commands as modified
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1181
+		tmpl_guard_t *guard = g_hash_table_lookup ( tmpl_guards, key );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1182
+		g_slist_foreach ( guard -> templates, template_set_changed, NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1183
+		// schedule execution of modified commands
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1184
+		tmpl_schedule_rerun ();
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1185
+	}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1186
+	return g_strdup ( new_value );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1187
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1188
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1189
+// public
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1190
+gboolean template_add ( const gchar * name, tmpl_callback_t callback, gpointer udata )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1191
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1192
+	g_assert ( name != NULL && callback != NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1193
+	// check for existing template
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1194
+	template_t * template = g_hash_table_lookup ( tmpl_templates, name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1195
+	if ( template != NULL )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1196
+		return FALSE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1197
+	// create new
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1198
+	template = g_slice_new ( template_t );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1199
+	template -> name           = g_strdup ( name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1200
+	template -> callback       = callback;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1201
+	template -> userdata       = udata;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1202
+	template -> in_use         = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1203
+	template -> guards         = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1204
+	template -> changed        = TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1205
+	template -> prev_expansion = NULL;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1206
+	// schedule reevaluation
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1207
+	tmpl_schedule_rerun ();
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1208
+	return TRUE;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1209
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1210
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1211
+// public
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1212
+void template_set_in_use ( const gchar * name, gboolean in_use )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1213
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1214
+	g_assert ( name != NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1215
+	template_t * template = g_hash_table_lookup ( tmpl_templates, name );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1216
+	g_assert ( template != NULL );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1217
+	template -> in_use = in_use;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1218
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1219
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1220
+// private
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1221
+void templates_init ( void )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1222
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1223
+	// the key will be freed by destruction cb
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1224
+	tmpl_guards    = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, tmpl_free_guard );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1225
+	tmpl_templates = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, tmpl_free_template );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1226
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1227
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1228
+// private
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1229
+void templates_uninit ( void )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1230
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1231
+	if ( tmpl_attached_id != 0 )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1232
+		g_source_remove ( tmpl_attached_id );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1233
+	g_hash_table_destroy ( tmpl_templates );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1234
+	g_hash_table_destroy ( tmpl_guards );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1235
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1236
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1237
+/* vim: se ts=4 sw=4: */
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1238
diff -r 456d83274014 mcabber/mcabber/templates.h
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1239
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1240
+++ b/mcabber/mcabber/templates.h	Fri Jul 20 17:30:20 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1241
@@ -0,0 +1,44 @@
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1242
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1243
+/* Copyright 2012 Myhailo Danylenko
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1244
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1245
+ * This file is part of mcabber
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1246
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1247
+ * mcabber is free software: you can redistribute it and/or
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1248
+ * modify it under the terms of the GNU General Public License as published
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1249
+ * by the Free Software Foundation, either version 2 of the License, or
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1250
+ * (at your option) any later version.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1251
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1252
+ * This program is distributed in the hope that it will be useful,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1253
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1254
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1255
+ * GNU General Public License for more details.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1256
+ *
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1257
+ * You should have received a copy of the GNU General Public License
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1258
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>. */
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1259
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1260
+#include <glib.h>
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1261
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1262
+// Type for template callback
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1263
+typedef void (*tmpl_callback_t) ( const gchar * expansion, gpointer udata );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1264
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1265
+//  success template_add ( option name, cb, cb udata )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1266
+// Adds given mcabber option to list of watched templates.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1267
+// If any option, used in that template (or template itself) will change,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1268
+// callback will be called with new expansion of template.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1269
+gboolean template_add ( const gchar * name, tmpl_callback_t callback, gpointer udata );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1270
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1271
+//  template_set_in_use ( option name, used flag )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1272
+// Marks template as (un)used.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1273
+// Note: Template will be actually removed only on next evaluation run,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1274
+// though call to this function schedules such run. This way, you can
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1275
+// mark a bunch of templates as unused and then mark some of them as used.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1276
+void template_set_in_use ( const gchar * name, gboolean in_use );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1277
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1278
+// XXX do we need this?
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1279
+// void tmpl_schedule_rerun ( void );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1280
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1281
+// private
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1282
+void templates_init ( void );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1283
+void templates_uninit ( void );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1284
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1285
+/* vim: se ts=4 sw=4: */
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1286
diff -r 456d83274014 mcabber/mcabber/utils.c
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1287
--- a/mcabber/mcabber/utils.c	Fri Jul 20 17:29:53 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1288
+++ b/mcabber/mcabber/utils.c	Fri Jul 20 17:30:20 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1289
@@ -650,6 +650,42 @@
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1290
   g_free(arglst);
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1291
 }
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1292
 
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1293
+//  parse_list(arg, cb, udata)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1294
+// Calls cb for every element in space/semicolon/comma-separated list.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1295
+// Designed to work in-place, so, no escapes, quoting etc.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1296
+// Terminates parsing if callback returns false.
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1297
+void parse_list(const char *arg, parse_list_cb_t cb, void *udata)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1298
+{
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1299
+  const char *p, *start;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1300
+  enum {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1301
+    in_space,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1302
+    in_string,
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1303
+  } state;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1304
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1305
+  if (!arg) 
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1306
+    return;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1307
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1308
+  state = in_space;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1309
+  while ( *p ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1310
+    if ( *p == ' ' || *p == ';' || *p == ',' ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1311
+      if ( state == in_string ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1312
+        if ( ! cb ( start, p, udata ) )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1313
+          return;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1314
+        state = in_space;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1315
+      }
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1316
+    } else {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1317
+      if ( state == in_space ) {
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1318
+        start = p;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1319
+        state = in_string;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1320
+      }
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1321
+    }
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1322
+    p ++;
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1323
+  }
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1324
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1325
+  if ( state == in_string )
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1326
+    cb ( start, p, udata );
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1327
+}
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1328
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1329
 //  replace_nl_with_dots(bufstr)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1330
 // Replace '\n' with "(...)" (or with a NUL if the string is too short)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1331
 void replace_nl_with_dots(char *bufstr)
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1332
diff -r 456d83274014 mcabber/mcabber/utils.h
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1333
--- a/mcabber/mcabber/utils.h	Fri Jul 20 17:29:53 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1334
+++ b/mcabber/mcabber/utils.h	Fri Jul 20 17:30:20 2012 +0300
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1335
@@ -43,6 +43,11 @@
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1336
 char **split_arg(const char *arg, unsigned int n, int dontstriplast);
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1337
 void free_arg_lst(char **arglst);
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1338
 
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1339
+/* fast in-place string split on space/semicolon/comma
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1340
+ * stops processing if callback returns false value */
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1341
+typedef int (*parse_list_cb_t)(const char *start, const char *end, void *udata);
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1342
+void parse_list(const char *arg, parse_list_cb_t cb, void *udata);
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1343
+
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1344
 void replace_nl_with_dots(char *bufstr);
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1345
 char *ut_expand_tabs(const char *text);
ce47dc7fc6c0 Add use-gslice and templates
Myhailo Danylenko <isbear@ukrpost.net>
parents:
diff changeset
  1346