Commit 98646186 authored by stolpmann's avatar stolpmann

Extension of bracket expressions: many new functions.

Functions in bracket expressions may now lazily evaluate their arguments.
ui:if and ui:ifvar may refer to any functions defined for bracket
expressions.
New: ui:ifexpr
Parsing of bracket expressions is now done with ulex. Private interfaces
of PXP are no longer used for this purpose.
Serialization has been rewritten, and it is now safe.
Fix: In ui:context there may now be macro references at any location.
Also documented all these changes.


git-svn-id: https://godirepo.camlcity.org/svn/wdialog/trunk@210 f54c9a64-0731-4a92-b797-30fd5898f27c
parent 4b4d5adf
#! /bin/sh
# $Id: configure,v 3.15 2005-06-02 21:14:35 stolpmann Exp $
# $Id: configure,v 3.16 2005-06-11 14:24:13 stolpmann Exp $
#--- Options ---
# value -1: off by command line ("forced")
......@@ -21,7 +21,7 @@ set_defaults () {
}
set_defaults
version="2.0.2"
version="2.1"
exec_suffix=""
ehelp_findlib="Enable/disable installation as findlib package"
......@@ -469,6 +469,18 @@ if true; then
fi
fi
######################################################################
# Check for ulex (now needed for core Wdialog!)
printf "%s" "Checking for ulex... "
if check_library ulex ulexing.cmi; then
echo "found"
else
echo "not found"
echo "Sorry, you need ulex to build wdialog!"
exit 1
fi
######################################################################
# Check for wd-session-daemon and rpc, inifiles
......
......@@ -54,11 +54,8 @@ if you want to make the Perl bindings, too.
library. The library parts "netstring" and "cgi" are required.
</p>
</li>
<li><p>Optionally, you may now install the runtime library for
Alain Frisch's <a href="&link-frisch;">wlex</a> lexer generator patch
(this reduces the size of the WDialog executables significantly, and is
recommended, but no strict requirement). See below for special
instructions.</p>
<li><p>Next, you need
Alain Frisch's <a href="&link-frisch;">ulex</a> lexer generator.</p>
</li>
<li><p>Next, you need PXP, the XML parser for Caml. It is available
on <a href="&link-gerd;">Gerd Stolpmann's site about Caml</a>, too. Version
......@@ -217,7 +214,7 @@ ocamlfind remove pcre
<!-- ************************************************************ -->
<!--
<sect1>
<title>Special instructions for wlex</title>
<p>
......@@ -239,6 +236,7 @@ runtime part of wlex. <em>You do not need to build wlex.</em></p>
<p>
Install the library with <code>make install_runtime</code></p>
</sect1>
-->
<!-- ************************************************************ -->
......
......@@ -77,6 +77,19 @@ Copyright holders are Joachim Schrod NPC GmbH and Gerd Stolpmann.</p>
<sect1>
<title>Version History</title>
<ul>
<li><p><em>Version 2.1:</em> Inclusion of several new session managers
(in-memory session manager, daemon session manager).</p>
<p>Extension of the
"bracket expressions": There are many new functions.</p>
<p>New element ui:ifexpr
which takes a boolean bracket expression as argument. The element ui:if
can process any number of value arguments. The elements ui:if and ui:ifvar
can call all functions, not only comparison functions. </p>
<p>A bug in ui:context has been fixed.</p>
<p>The serialization format has been changed. It is now secure against attacks
based on malformed strings.</p>
</li>
<li><p><em>Version 2.0.2:</em> Updates for findlib-1.0</p>
</li>
......
......@@ -24,8 +24,18 @@ let rec make_unique_session_id tbl =
let copy_dialog universe env dlg =
let new_dlg = universe#create env (dlg#name) in
new_dlg#unserialize (dlg#serialize);
new_dlg
let b = Buffer.create 1000 in
dlg # serialize (Hashtbl.create 10) b;
let ds_buf =
{ ds_str = Buffer.contents b;
ds_pos = 0;
ds_end = Buffer.length b;
ds_universe = universe;
ds_environment = env;
ds_dialogs = Hashtbl.create 10;
} in
new_dlg # unserialize ds_buf;
new_dlg
exception Session_not_found
......
# $Id: Makefile.code,v 1.8 2004-12-04 03:50:50 gremlin43820 Exp $
# $Id: Makefile.code,v 1.9 2005-06-11 14:24:13 stolpmann Exp $
TOP_DIR=../..
OBJECTS = wd_ocamlversion.cmo \
wd_dictionary.cmo wd_types.cmo wd_interactor.cmo \
OBJECTS = wd_ocamlversion.cmo \
wd_dictionary.cmo wd_serialize_types.cmo \
wd_types.cmo wd_serialize.cmo wd_interactor.cmo \
wd_encoding.cmo wd_stdlib.cmo wd_var_functions.cmo \
wd_brexpr_lex.cmo \
wd_upload.cmo wd_templrep.cmo wd_application_dtd.cmo \
wd_dialog_decl.cmo wd_application.cmo wd_transform.cmo \
wd_template.cmo wd_dialog.cmo \
wd_universe.cmo wd_cycle.cmo wd_run_fcgi.cmo \
wd_run_cgi.cmo wd_run_jserv.cmo
wd_run_cgi.cmo wd_run_jserv.cmo
# interfaces to include in the ocamldoc output:
INTERFACES = $(shell echo *.mli)
......@@ -20,9 +22,18 @@ INSTALL_EXTRA = stdlib.xml wd_application_1.dtd wd_application_2.dtd
include $(TOP_DIR)/Makefile.rules
wd_brexpr_lex.cmo: wd_brexpr_lex.mlu
cp wd_brexpr_lex.mlu wd_brexpr_lex.ml
$(OCAMLC) -package ulex -syntax camlp4o -c wd_brexpr_lex.ml
wd_brexpr_lex.cmx: wd_brexpr_lex.mlu
cp wd_brexpr_lex.mlu wd_brexpr_lex.ml
$(OCAMLOPT) -package ulex -syntax camlp4o -c wd_brexpr_lex.ml
clean::
rm -f *.bin wd-ocamldoc.xml wd_application_dtd.ml wd_stdlib.ml
rm -f wd_ocamlversion.ml
rm -f wd_ocamlversion.ml wd_brexpr_lex.ml
rm -rf tmp
wd-ocamldoc.xml: *.mli
......@@ -36,6 +47,10 @@ wd-ocamldoc.xml: *.mli
.PHONY: mk-depend
mk-depend: *.ml *.mli
rm -f wd_brexpr_lex.ml
$(OCAMLDEP) *.ml *.mli >depend
wd_templrep.cmo: wd_brexpr_lex.cmo
wd_templrep.cmx: wd_brexpr_lex.cmx
-include depend
......@@ -21,7 +21,7 @@
* </>
*)
(* $Id: wd_application.ml,v 3.8 2004-12-12 17:57:32 stolpmann Exp $
(* $Id: wd_application.ml,v 3.9 2005-06-11 14:24:14 stolpmann Exp $
* ----------------------------------------------------------------------
*
*)
......@@ -47,7 +47,7 @@ class application init_dtd : application_type =
(Hashtbl.create 10 : (string, string->string) Hashtbl.t)
val mutable var_functions =
(Hashtbl.create 10 :
(string, dialog_type -> var_value list -> var_value) Hashtbl.t)
(string, dialog_type -> var_value Lazy.t list -> var_value) Hashtbl.t)
val mutable dtd =
init_dtd
val mutable debug_mode =
......@@ -69,31 +69,84 @@ class application init_dtd : application_type =
self # add_output_encoding "jslong"
(Wd_encoding.encode_as_js_longstring ~enc);
(* Add the standard functions: *)
self # add_var_function "size" Wd_var_functions.size;
self # add_var_function "add" Wd_var_functions.add;
self # add_var_function "sub" Wd_var_functions.sub;
self # add_var_function "mul" Wd_var_functions.mul;
self # add_var_function "div" Wd_var_functions.div;
self # add_var_function "assoc" Wd_var_functions.assoc;
self # add_var_function "nth" Wd_var_functions.nth;
self # add_var_function "id" Wd_var_functions.id;
self # add_var_function "length" Wd_var_functions.length;
self # add_var_function "card" Wd_var_functions.card;
self # add_var_function "size" Wd_var_functions.size;
self # add_var_function "add" Wd_var_functions.add;
self # add_var_function "sub" Wd_var_functions.sub;
self # add_var_function "mul" Wd_var_functions.mul;
self # add_var_function "div" Wd_var_functions.div;
self # add_var_function "modulo" Wd_var_functions.modulo;
self # add_var_function "assoc" Wd_var_functions.assoc;
self # add_var_function "nth" Wd_var_functions.nth;
self # add_var_function "contains" Wd_var_functions.contains;
self # add_var_function "mentions" Wd_var_functions.mentions;
self # add_var_function "translate" Wd_var_functions.translate;
self # add_var_function "rev_translate" Wd_var_functions.rev_translate;
self # add_var_function "rev_translate" Wd_var_functions.rev_translate; (* legacy *)
self # add_var_function "rev-translate" Wd_var_functions.rev_translate;
self # add_var_function "eq" Wd_var_functions.eq;
self # add_var_function "ne" Wd_var_functions.ne;
self # add_var_function "match" Wd_var_functions.match_;
self # add_var_function "nomatch" Wd_var_functions.nomatch;
self # add_var_function "substring" Wd_var_functions.substring;
self # add_var_function "concat" Wd_var_functions.concat;
self # add_var_function "concat" Wd_var_functions.concat;
self # add_var_function "int-eq" Wd_var_functions.int_eq;
self # add_var_function "int-ne" Wd_var_functions.int_ne;
self # add_var_function "int-lt" Wd_var_functions.int_lt;
self # add_var_function "int-le" Wd_var_functions.int_le;
self # add_var_function "int-gt" Wd_var_functions.int_gt;
self # add_var_function "int-ge" Wd_var_functions.int_ge;
self # add_var_function "int-min" Wd_var_functions.int_min;
self # add_var_function "int-max" Wd_var_functions.int_max;
self # add_var_function "int-abs" Wd_var_functions.int_abs;
self # add_var_function "int-sign" Wd_var_functions.int_sign;
self # add_var_function "card-eq" Wd_var_functions.card_eq;
self # add_var_function "card-ne" Wd_var_functions.card_ne;
self # add_var_function "card-lt" Wd_var_functions.card_lt;
self # add_var_function "card-le" Wd_var_functions.card_le;
self # add_var_function "card-gt" Wd_var_functions.card_gt;
self # add_var_function "card-ge" Wd_var_functions.card_ge;
self # add_var_function "size-eq" Wd_var_functions.card_eq; (* legacy name *)
self # add_var_function "size-ne" Wd_var_functions.card_ne; (* legacy name *)
self # add_var_function "size-lt" Wd_var_functions.card_lt; (* legacy name *)
self # add_var_function "size-le" Wd_var_functions.card_le; (* legacy name *)
self # add_var_function "size-gt" Wd_var_functions.card_gt; (* legacy name *)
self # add_var_function "size-ge" Wd_var_functions.card_ge; (* legacy name *)
self # add_var_function "height" Wd_var_functions.height;
self # add_var_function "width" Wd_var_functions.width;
self # add_var_function "dialog-exists" Wd_var_functions.dialog_exists;
self # add_lazy_var_function "and" Wd_var_functions.and_;
self # add_lazy_var_function "or" Wd_var_functions.or_;
self # add_var_function "not" Wd_var_functions.not_;
self # add_var_function "true" Wd_var_functions.true_;
self # add_var_function "false" Wd_var_functions.false_;
self # add_lazy_var_function "if" Wd_var_functions.if_;
self # add_var_function "var" Wd_var_functions.var;
self # add_var_function "dialog" Wd_var_functions.dialog;
self # add_var_function "self" Wd_var_functions.self;
self # add_var_function "page" Wd_var_functions.page;
self # add_var_function "language" Wd_var_functions.language;
self # add_var_function "self_base_url" Wd_var_functions.self_base_url;
self # add_var_function "session_id" Wd_var_functions.session_id;
self # add_var_function "create_anchor_event" Wd_var_functions.create_anchor_event;
self # add_var_function "self_base_url" Wd_var_functions.self_base_url; (* legacy *)
self # add_var_function "self-base-url" Wd_var_functions.self_base_url;
self # add_var_function "session_id" Wd_var_functions.session_id; (* legacy *)
self # add_var_function "session-id" Wd_var_functions.session_id;
self # add_var_function "create_anchor_event" Wd_var_functions.create_anchor_event; (* legacy *)
self # add_var_function "create-anchor-event" Wd_var_functions.create_anchor_event;
self # add_var_function "create_xanchor_event" Wd_var_functions.create_xanchor_event;
self # add_var_function "create-xanchor-event" Wd_var_functions.create_xanchor_event; (* legacy *)
(* There are also the following, magically defined functions:
* - type
* - is_associative
* - is_associative/is-associative
* - default
* - enum
* - words
*)
......@@ -124,9 +177,13 @@ class application init_dtd : application_type =
method output_encoding name =
Hashtbl.find output_encodings name
method var_function name =
method lazy_var_function name =
Hashtbl.find var_functions name
method var_function name =
let f = self # lazy_var_function name in
(fun dlg args -> f dlg (List.map (fun arg -> lazy arg) args))
method dtd = dtd
method charset = dtd # encoding
......@@ -184,7 +241,16 @@ class application init_dtd : application_type =
(* fails if 'fn_name' already used *)
if Hashtbl.mem var_functions fn_name then
failwith ("This variable function already exists: " ^ fn_name );
Hashtbl.add var_functions fn_name fn;
Hashtbl.add var_functions fn_name
(fun dlg lazy_args ->
let args = List.map Lazy.force lazy_args in
fn dlg args)
method add_lazy_var_function fn_name fn =
(* fails if 'fn_name' already used *)
if Hashtbl.mem var_functions fn_name then
failwith ("This variable function already exists: " ^ fn_name );
Hashtbl.add var_functions fn_name fn
method set_debug_mode b style =
debug_mode <- b;
......@@ -201,7 +267,19 @@ class application init_dtd : application_type =
* History:
*
* $Log: wd_application.ml,v $
* Revision 3.8 2004-12-12 17:57:32 stolpmann
* Revision 3.9 2005-06-11 14:24:14 stolpmann
* Extension of bracket expressions: many new functions.
* Functions in bracket expressions may now lazily evaluate their arguments.
* ui:if and ui:ifvar may refer to any functions defined for bracket
* expressions.
* New: ui:ifexpr
* Parsing of bracket expressions is now done with ulex. Private interfaces
* of PXP are no longer used for this purpose.
* Serialization has been rewritten, and it is now safe.
* Fix: In ui:context there may now be macro references at any location.
* Also documented all these changes.
*
* Revision 3.8 2004/12/12 17:57:32 stolpmann
* Added <q:wd-link> and <q:wd-xlink> to generate links for
* applications that cannot use Javascript. Limited functionality, however.
* See stdlib.xml for details.
......
<?xml version="1.0" encoding="ISO8859-1"?>
<!-- $Id: wd_application_2.dtd,v 3.5 2003-02-16 21:33:58 stolpmann Exp $ -->
<!-- $Id: wd_application_2.dtd,v 3.6 2005-06-11 14:24:14 stolpmann Exp $ -->
<!-- This DTD should be referred to by the PUBLIC identifier:
PUBLIC "-//NPC//DTD WDIALOG 2.2//EN"
PUBLIC "-//NPC//DTD WDIALOG 2.3//EN"
Version numbers: have the form major.minor; a change in a major
number means that the versions are incompatible, while a
......@@ -20,6 +20,7 @@
>= 1.11 "-//NPC//DTD WDIALOG 1.1//EN"
>= 2.1 "-//NPC//DTD WDIALOG 2.1//EN"
>= 3.2 "-//NPC//DTD WDIALOG 2.2//EN"
>= 3.6 "-//NPC//DTD WDIALOG 2.3//EN"
-->
<!-- TODO:
......@@ -94,8 +95,13 @@
- New: ui:richbutton that maps to the BUTTON html element
- New: "dot notation" can be used to access variables of subdialogs.
-->
<!-- Changes between 2.2 and 2.3:
- IDEA: support for SELECT + OPTGROUP
- ui:if: accepts now any number of values, and op can be any function name
- ui:ifvar: op can be any function name
- New: ui:ifexpr
-->
......@@ -576,91 +582,14 @@
expand anything.
-->
<!ENTITY % string-operators
'eq|ne|match|nomatch'>
<!-- eq: two strings are equal
ne: two strings are not equal
match: a string matches the regular expression
contained in the other string
nomatch: a string does not match the reg exp
contained in the other string
match,nomatch raise Runtime_error if the reg exp
cannot be compiled
-->
<!ENTITY % int-operators
'int-eq|int-ne|int-lt|int-le|int-gt|int-ge'>
<!-- int-eq: two ints are equal
int-ne: two ints are not equal
int-lt: first int is less than second int
int-le: first int is less or equal than second int
int-gt: first int is greater than second int
int-ge: first int is greater or equal than second int
These operators raise Runtime_error if the values are
not valid integers
-->
<!ENTITY % list-operators
'contains|mentions|size-eq|size-ne|size-lt|size-le|size-gt|size-ge'>
<!-- contains: The variable contains the value. This means:
- for enumerators: the value is enumerated as
internal value
- for alists: the value is an index of the alist
mentions: The variable contains the value on the right side:
- for enums: currently not implemented!
- for dyn enums: the value occurs as external value
- for alists: the value occurs as value of the alist.
More precise:
for alists of strings: clear
for alists of enums:
the value occurs as internal enum value
for alists of dyn enums:
the value occurs as internal enum value
other: not implemented!
size-*: The number of elements of the variable is
compared with the int value.
-->
<!ENTITY % dlg-operators
'dialog-exists'>
<!-- dialog-exists: The variable is of type 'dialog', the
value is either "yes" or "no", and the following
condition holds:
- The variable actually contains a dialog
<=>
The value is "yes"
-->
<!ENTITY % operators
'%string-operators;|%int-operators;'>
<!-- The possible operators for <ui:if> -->
<!ENTITY % var-operators
'%operators;|%list-operators;|%dlg-operators;'>
<!-- The possible operators for <ui:ifvar> -->
<!ELEMENT ui:if ANY>
<!ATTLIST ui:if
value1 CDATA #REQUIRED
value2 CDATA #REQUIRED
op (%operators;) "eq"
op CDATA "eq"
>
<!-- condition: value1 and value2 are equal (op="eq") or not
equal (op="ne"). Note that you can use ${param} and
$[variable] inside value1 and value2.
<!-- There must also be attributes value1, value2, ... which are the arguments
of the operation selected by op.
-->
......@@ -670,7 +599,7 @@
variable %nametoken; #REQUIRED
index %nametoken; #IMPLIED
value CDATA #REQUIRED
op (%var-operators;) "eq"
op CDATA "eq"
>
<!-- condition: the variable, optionally the item at the selected
......@@ -689,6 +618,13 @@
<!-- condition: the selected language is xml:lang -->
<!ELEMENT ui:ifexpr ANY>
<!ATTLIST ui:ifexpr
expr CDATA #REQUIRED>
<!-- This conditional is evaluated when expr is a non-zero integer -->
<!ELEMENT ui:true ANY>
......@@ -701,7 +637,7 @@
<!ELEMENT ui:cond ( (ui:if | ui:ifvar | ui:iflang | ui:true | ui:false)+ )>
<!ELEMENT ui:cond ( (ui:if | ui:ifexpr | ui:ifvar | ui:iflang | ui:true | ui:false)+ )>
<!-- ui:cond tries the conditions in turn, and expands the first
matching condition.
......@@ -940,5 +876,5 @@
<?pxp:dtd optional-attribute-declarations
elements="ui:form ui:button ui:imagebutton ui:checkbox ui:radio
ui:file ui:password ui:text ui:select ui:textarea ui:a
ui:richbutton"?>
ui:richbutton ui:if"?>
(*
* <COPYRIGHT>
* Copyright 2002 Joachim Schrod Network and Publication Consultance GmbH, Gerd Stolpmann
*
* <GPL>
* This file is part of WDialog.
*
* WDialog is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* WDialog is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WDialog; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* </>
*)
(* $Id: wd_brexpr_lex.mlu,v 3.1 2005-06-11 14:24:14 stolpmann Exp $
* ----------------------------------------------------------------------
*
*)
open Netulex
(* Scanner for bracket expressions *)
type tok =
| Token of string
| Number of int
| Slash
| Dollar
| LParen
| RParen
| LBrace
| RBrace
| Comma
| Equal
| Eof
| Other of string
(* Delimiters reserved for the future *)
let scan =
lexer
| "/" -> Slash
| "$" -> Dollar
| "(" -> LParen
| ")" -> RParen
| "{" -> LBrace
| "}" -> RBrace
| "," -> Comma
| "=" -> Equal
| '-'? [ '0'-'9'] + -> Number (int_of_string (Ulexing.utf8_lexeme lexbuf))
| [ 'A'-'Z' 'a'-'z' '_' 160-0x10ffff ]
[ 'A'-'Z' 'a'-'z' '_' '0'-'9' '-' ':' '.' 160-0x10ffff ]* ->
Token (Ulexing.utf8_lexeme lexbuf)
| _ -> Other (Ulexing.utf8_lexeme lexbuf)
| eof -> Eof
;;
......@@ -21,7 +21,7 @@
* </>
*)
(* $Id: wd_cycle.ml,v 3.14 2004-12-12 17:57:32 stolpmann Exp $
(* $Id: wd_cycle.ml,v 3.15 2005-06-11 14:24:14 stolpmann Exp $
* ----------------------------------------------------------------------
*
*)
......@@ -979,6 +979,7 @@ let process_request
(* If working with uidebuggger, output the new dialog state now to the
* communication pipe.
*)
(*
begin match ui_pipe_ch with
Some ch ->
output_string ch dlg_name;
......@@ -989,6 +990,7 @@ let process_request
| None ->
()
end;
*)
);
()
;;
......@@ -997,7 +999,19 @@ let process_request
* History:
*
* $Log: wd_cycle.ml,v $
* Revision 3.14 2004-12-12 17:57:32 stolpmann
* Revision 3.15 2005-06-11 14:24:14 stolpmann
* Extension of bracket expressions: many new functions.
* Functions in bracket expressions may now lazily evaluate their arguments.
* ui:if and ui:ifvar may refer to any functions defined for bracket
* expressions.
* New: ui:ifexpr
* Parsing of bracket expressions is now done with ulex. Private interfaces
* of PXP are no longer used for this purpose.
* Serialization has been rewritten, and it is now safe.
* Fix: In ui:context there may now be macro references at any location.
* Also documented all these changes.
*
* Revision 3.14 2004/12/12 17:57:32 stolpmann
* Added <q:wd-link> and <q:wd-xlink> to generate links for
* applications that cannot use Javascript. Limited functionality, however.
* See stdlib.xml for details.
......
This diff is collapsed.
......@@ -21,12 +21,13 @@
* </>
*)
(* $Id: wd_interactor.ml,v 3.4 2002-04-10 21:27:52 stolpmann Exp $
(* $Id: wd_interactor.ml,v 3.5 2005-06-11 14:24:14 stolpmann Exp $
* ----------------------------------------------------------------------
*
*)
open Wd_types
open Wd_serialize
type id = string;;
exception Element_exists of id;;
......@@ -230,14 +231,100 @@ let lookup ia id =
;;
let revision_interactor = "$Revision: 3.4 $" ;;
let serialize f b ia =
(* Format:
* T(<base_id>,<next_id>,<n_entries>,<n_names>)
* <all names as strings>
* <all entries as tuples>
*
* Strings:
* S(<length>)<string value>
*
* Tuples:
* 0 if None
* or
* <name_pos as string><index as string><value encoded by f><id as string>
*)
Buffer.add_string b "T(";
Buffer.add_string b (string_of_int ia.base_id);
Buffer.add_string b ",";
Buffer.add_string b (string_of_int ia.next_id);
Buffer.add_string b ",";
Buffer.add_string b (string_of_int ia.n_entries);
Buffer.add_string b ",";
Buffer.add_string b (string_of_int ia.n_names);
Buffer.add_string b ")";
for k = 0 to ia.n_names - 1 do
serialize_string b ia.names.(k)
done;
for k = 0 to ia.n_entries - 1 do
match ia.entries.(k) with
| Some (name_pos, index, value, id) ->
serialize_string b (string_of_int name_pos);
serialize_string b index;
Buffer.add_string b (f value);
serialize_string b id
| None ->
assert false
done
;;
let unserialize f buf =
let tok = ds_scan_token buf in
match tok with
| T_tok(base_id,next_id,n_entries,n_names) ->
let l = buf.ds_end - buf.ds_pos in
if n_entries > l || n_names > l then failwith "Wd_interactor.unserialize";
let entries = Array.make n_entries None in
let names = Array.make n_names "" in
for k = 0 to n_names - 1 do
names.(k) <- unserialize_string buf
done;
for k = 0 to n_entries - 1 do
let name_pos_str = unserialize_string buf in
let index = unserialize_string buf in
let value = f buf in
let id = unserialize_string buf in
let name_pos =
try int_of_string name_pos_str
with _ -> failwith "Wd_interactor.unserialize" in
if name_pos < 0 || name_pos >= n_names then
failwith "Wd_interactor.unserialize";
entries.(k) <- Some(name_pos, index, value, id);
done;
{ base_id = base_id;
next_id = next_id;
entries = entries;
n_entries = n_entries;
names = names;
n_names = n_names
}
| _ ->
failwith "Wd_interactor.unserialize"
;;
let revision_interactor = "$Revision: 3.5 $" ;;
(* Intentionally the CVS revision string *)
(* ======================================================================
* History:
*
* $Log: wd_interactor.ml,v $
* Revision 3.4 2002-04-10 21:27:52 stolpmann
* Revision 3.5 2005-06-11 14:24:14 stolpmann
* Extension of bracket expressions: many new functions.
* Functions in bracket expressions may now lazily evaluate their arguments.
* ui:if and ui:ifvar may refer to any functions defined for bracket
* expressions.
* New: ui:ifexpr
* Parsing of bracket expressions is now done with ulex. Private interfaces
* of PXP are no longer used for this purpose.
* Serialization has been rewritten, and it is now safe.
* Fix: In ui:context there may now be macro references at any location.
* Also documented all these changes.
*
* Revision 3.4 2002/04/10 21:27:52 stolpmann
* New scheme for automatically generated interactor IDs. There
* are now two parts: <base>_<seq> where <base> is the base number
* (currently derived from the system clock), and where <seq> is the
......