Tcl Source Code

Changes On Branch ferrieux-nacl
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch ferrieux-nacl Excluding Merge-Ins

This is equivalent to a diff from 91a0a93dad to 29517d12f7

2011-10-25
04:21
Add a local copy of reference JS demo at same fps. Add an interactive tclsh page for easy timings, i... Leaf check-in: 29517d12f7 user: ferrieux tags: ferrieux-nacl
2011-10-18
22:03
Streamline demo setup; update README to reflect API changes. check-in: 91aea72dbd user: ferrieux tags: ferrieux-nacl
2011-10-07
21:21
Fix env.test, when running under wine 1.3 check-in: 78d77f044f user: jan.nijtmans tags: trunk
14:49
merge trunk check-in: 3dcfeb9b27 user: dkf tags: dkf-utf16-branch
14:48
merge trunk check-in: efd220a1ac user: dkf tags: dkf-notifier-poll
12:16
Merge updates from trunk check-in: 59daece720 user: ferrieux tags: ferrieux-nacl
12:01
Fix gcc warnings (discovered with latest mingw, based on gcc 4.6.1) check-in: 91a0a93dad user: jan.nijtmans tags: trunk
12:00
Fix gcc warning (discovered with latest mingw, based on gcc 4.6.1) check-in: 7c93b4fe12 user: jan.nijtmans tags: core-8-5-branch
2011-10-06
21:19
Reintegrate the compilation of [dict with], which is now usually much faster (but only inside contex... check-in: 81996420e6 user: dkf tags: trunk

Changes to ChangeLog.

1011
1012
1013
1014
1015
1016
1017





1018
1019
1020
1021
1022
1023
1024
	* generic/tclDictObj.c: a warning: "Why make your own error
	* generic/tclScan.c:   message? Why?"
	* generic/tclTest.c:
	* test/error.test:
	* test/info.test:
	* test/scan.test:
	* unix/tclUnixThrd.h:  Remove this unused header file.






2011-04-03  Donal K. Fellows  <[email protected]>

	* generic/tclNamesp.c, generic/tclObj.c, generic/tclPathObj.c:
	* generic/tclPipe.c, generic/tclPkg.c, generic/tclProc.c:
	* generic/tclScan.c: More generation of error codes (namespace
	creation, path normalization, pipeline creation, package handling,







>
>
>
>
>







1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
	* generic/tclDictObj.c: a warning: "Why make your own error
	* generic/tclScan.c:   message? Why?"
	* generic/tclTest.c:
	* test/error.test:
	* test/info.test:
	* test/scan.test:
	* unix/tclUnixThrd.h:  Remove this unused header file.

2011-04-04 Alexandre Ferrieux  <[email protected]>

	* nacl/...: New branch ferrieux-nacl : a port of Tcl to
	Google's Nacl (Native Client)

2011-04-03  Donal K. Fellows  <[email protected]>

	* generic/tclNamesp.c, generic/tclObj.c, generic/tclPathObj.c:
	* generic/tclPipe.c, generic/tclPkg.c, generic/tclProc.c:
	* generic/tclScan.c: More generation of error codes (namespace
	creation, path normalization, pipeline creation, package handling,

Added nacl/Makefile.patch.





































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
--- Makefile	2011-04-10 13:21:12.773175132 +0200
+++ tweaked.Makefile	2011-04-10 12:34:27.256426620 +0200
@@ -102,12 +102,17 @@
 #CFLAGS			= $(CFLAGS_DEBUG)
 #CFLAGS			= $(CFLAGS_OPTIMIZE)
 #CFLAGS			= $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
-CFLAGS			= $(CFLAGS_OPTIMIZE) -Wno-long-long -pthread -DNACL -pipe
+CFLAGS			= $(CFLAGS_OPTIMIZE) -pipe -fvisibility=hidden 
+
+
+CFLAGS += -Wno-long-long -pthread -DNACL 
 
 # Flags to pass to the linker
 LDFLAGS_DEBUG		= 
 LDFLAGS_OPTIMIZE	= 
-LDFLAGS			= $(LDFLAGS_OPTIMIZE)  -Wl,--export-dynamic 
+LDFLAGS			= $(LDFLAGS_OPTIMIZE)  -Wl,--export-dynamic -lm \
+	       -lppapi \
+          -lpthread
 
 # To disable ANSI-C procedure prototypes reverse the comment characters on the
 # following lines:
@@ -176,7 +184,7 @@
 
 STLIB_LD		= ${AR} cr
 SHLIB_LD		= ${CC} -shared ${CFLAGS} ${LDFLAGS}
-SHLIB_CFLAGS		= -fPIC -DBUILD_tcl
+SHLIB_CFLAGS		= -DBUILD_tcl
 SHLIB_LD_LIBS		= ${LIBS}
 TCL_SHLIB_LD_EXTRAS	= 
 
@@ -216,7 +224,8 @@
 # by hand.
 #--------------------------------------------------------------------------
 
-COMPAT_OBJS		=  waitpid.o fake-rfc2553.o memcmp.o strstr.o strtoul.o strtod.o fixstrtod.o
+#COMPAT_OBJS		=  waitpid.o fake-rfc2553.o memcmp.o strstr.o strtoul.o strtod.o fixstrtod.o
+IGNORE_COMPAT_OBJS		=  waitpid.o fake-rfc2553.o memcmp.o strstr.o strtoul.o strtod.o fixstrtod.o
 
 AC_FLAGS		= -DPACKAGE_NAME=\"tcl\" -DPACKAGE_TARNAME=\"tcl\" -DPACKAGE_VERSION=\"8.6\" -DPACKAGE_STRING=\"tcl\ 8.6\" -DPACKAGE_BUGREPORT=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DNO_VALUES_H=1 -DHAVE_LIMITS_H=1 -DNO_DLFCN_H=1 -DHAVE_SYS_PARAM_H=1 -DTCL_CFGVAL_ENCODING=\"iso8859-1\" -DSTATIC_BUILD=1 -DHAVE_ZLIB=1 -DMODULE_SCOPE=extern -DTCL_SHLIB_EXT=\".so\" -DTCL_CFG_OPTIMIZED=1 -DTCL_CFG_DEBUG=1 -DTCL_TOMMATH=1 -DMP_PREC=4 -DTCL_WIDE_INT_TYPE=long\ long -DUSEGETWD=1 -DHAVE_MKSTEMP=1 -DHAVE_OPENDIR=1 -DHAVE_STRTOL=1 -DNO_GETWD=1 -DNO_WAIT3=1 -DNO_UNAME=1 -DNO_REALPATH=1 -DNEED_FAKE_RFC2553=1 -DHAVE_SYS_TIME_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_GMTIME_R=1 -DHAVE_LOCALTIME_R=1 -DHAVE_MKTIME=1 -DHAVE_TIMEZONE_VAR=1 -DHAVE_STRUCT_STAT_ST_BLOCKS=1 -DHAVE_STRUCT_STAT_ST_BLKSIZE=1 -DHAVE_BLKCNT_T=1 -DNO_FSTATFS=1 -Dstrtod=fixstrtod -Dsocklen_t=int -DHAVE_INTPTR_T=1 -DHAVE_UINTPTR_T=1 -DNO_UNION_WAIT=1 -DHAVE_SIGNED_CHAR=1 -DHAVE_LANGINFO=1 -DHAVE_MKSTEMPS=1 -DTCL_UNLOAD_DLLS=1 
 AR			= nacl-ar
@@ -335,12 +346,13 @@
 
 STUB_LIB_OBJS = tclStubLib.o tclTomMathStubLib.o tclOOStubLib.o ${COMPAT_OBJS}
 
-UNIX_OBJS = tclUnixChan.o tclUnixEvent.o tclUnixFCmd.o \
+UNIX_OBJS = naclMissing.o  tclUnixChan.o tclUnixEvent.o tclUnixFCmd.o \
 	tclUnixFile.o tclUnixPipe.o tclUnixSock.o \
 	tclUnixTime.o tclUnixInit.o tclUnixThrd.o \
 	tclUnixCompat.o
 
 NOTIFY_OBJS = tclUnixNotfy.o
+IGN =  
 
 MAC_OSX_OBJS = tclMacOSXBundle.o tclMacOSXFCmd.o tclMacOSXNotify.o
 
@@ -600,7 +612,7 @@
 
 all: binaries libraries doc packages
 
-binaries: ${LIB_FILE} $(STUB_LIB_FILE) ${TCL_EXE}
+binaries: ${LIB_FILE} $(STUB_LIB_FILE) tcl$(arch).nexe
 
 libraries:
 
@@ -634,14 +646,36 @@
 # Must be empty so it doesn't conflict with rule for ${TCL_EXE} above
 ${NATIVE_TCLSH}:
 
-Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
-	$(SHELL) config.status
+init.tcl.c: ../library/init.tcl init.natcl
+	cat $^ | tools/tocstr > $@
+
+tclUnixPort.h: ../unix/tclUnixPort.h tclUnixPort.h.patch
+	cat ../unix/tclUnixPort.h > tclUnixPort.h
+	patch -p0 < tclUnixPort.h.patch
+
+naclMain.o:	naclMain.c init.tcl.c
+	$(CC) -c $(CC_SWITCHES) naclMain.c
+
+tcl$(arch).nexe: naclMain.o libtcl8.6.a
+	$(CCPLUS)  $^ $(LDFLAGS) -o $@
+
+$(TCL_OBJS) $(STUB_LIB_OBJS) $(TCLSH_OBJS) $(TCLTEST_OBJS): tclUnixPort.h
+
+server:
+	tclsh trivhttpd.tcl 5103 &
+
+balls:
+	google-chrome http://localhost:5103/demo/balls.html
+
+#Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
+#	$(SHELL) config.status
 #tclConfig.h: $(UNIX_DIR)/tclConfig.h.in
 #	$(SHELL) config.status
 
 clean: clean-packages
 	rm -f *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \
-		errors ${TCL_EXE} ${TCLTEST_EXE} lib.exp Tcl 
+		errors ${TCL_EXE} ${TCLTEST_EXE} lib.exp Tcl \
+		init.tcl.c tclUnixPort.h
 	cd dltest ; $(MAKE) clean
 
 distclean: distclean-packages clean
@@ -794,7 +826,6 @@
 	    echo "Installing $(STUB_LIB_FILE) to $(LIB_INSTALL_DIR)/"; \
 	    $(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)"/$(STUB_LIB_FILE) ; (cd "$(LIB_INSTALL_DIR)" ; $(RANLIB) $(STUB_LIB_FILE)) ; \
 	fi
-	
 	@echo "Installing pkg-config file to $(LIB_INSTALL_DIR)/pkgconfig/"
 	@$(INSTALL_DATA_DIR) $(LIB_INSTALL_DIR)/pkgconfig
 	@$(INSTALL_DATA) tcl.pc $(LIB_INSTALL_DIR)/pkgconfig/tcl.pc
@@ -2031,13 +2062,13 @@
 
 html: ${NATIVE_TCLSH}
 	$(BUILD_HTML)
-	
+
 html-tcl: ${NATIVE_TCLSH}
 	$(BUILD_HTML) --tcl
-	
+
 html-tk: ${NATIVE_TCLSH}
 	$(BUILD_HTML) --tk
-	
+
 
 BUILD_HTML = \
 	@${NATIVE_TCLSH} $(TOOL_DIR)/tcltk-man2html.tcl \

Added nacl/README.















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

		NaTcl : Tcl in Nacl


Overview
--------

NaCl == Native Client is Google's neat sandboxing technology, allowing
to  run  untrusted  code  compiled  natively,  in  the  context  of  a
browser. See http://code.google.com/p/nativeclient/.

The idea  is that with Tcl  running in this context,  and a supporting
browser (currently,  Chrome only; in the future,  other browsers too),
one could  develop client-side  code mainly in  Tcl, with a  very thin
layer of JS in the page; so, basically, Tcl to control the HTML5 DOM !

Building Tcl for Nacl
---------------------

 - install the NaCl SDK at http://code.google.com/chrome/nativeclient/docs/download.html

 - for now, only use the pepper_14 bundle

 - add (Nacl-SDK-top-dir)/pepper_14/native_client_sdk_0_5_1052/toolchain/linux_x86/bin to your PATH

 - cd (Tcl-source-tree)/nacl 

 - run './configure' (which calls ../unix/configure with proper flags,
   and patches the generated Makefile)

 - run  'make  binaries'.  This  creates  tcl.nmf  and  tcl32.nexe  or
   tcl64.nexe, depending on  the kind of x86 you're  currently on. You
   can also  simply type  'make' but the  libraries are not  usable by
   NaCl yet (no dynamic linking).

 - (optional) to also build the  other kind, do 'make distclean', then
   './configure -m32  (or -m64)',  then 'make binaries'.  The provided
   manifest file (tcl.nmf) points to  both, to be compatible with both
   builds of Chrome.

 - run 'make sever'. This starts  (on port 5103) a tiny, trivial httpd
   written  in Tcl,  whose  sole purpose  is  to server  the few  demo
   files. Note that NaCl is explicitly disabled on file:// urls.

 - (once) open  about:flags in Chrome  and enable Native  Client (note
   this will  be saved  in your per-user  Chrome preferences  and will
   even survive a Chrome upgrade)

 - run 'make balls'

Overview of the porting method
------------------------------

Nacl  comes with  a  very incomplete  libc  and set  of headers.   The
strategy,  then,  is to  simply  "plug"  missing  syscalls or  library
functions with either explicitly  failing stubs (returning -1 or NULL,
and  setting errno)  or emulators,  and to  build a  big  include file
(naclcompat.h) with  all the necessary  type and macro  definitions to
compile.
 
Of course,  when one  of the  failing stubs is  called at  runtime, an
error is raised.  But one cannot hope much more, it's  a sandbox for a
reason.

This approach allows to compile Tcl for Nacl without changing a single
line of the original source distribution; all new things are in the
nacl subdir. Also, much is reused from ../unix.

Nacl context specifics
----------------------

 NaCl lets  us run in  our sandbox, in  a dedicated process;  the only
possible interactions with the browser process are:

   - at init time, one of our functions is called

   - then, each side can post a string message to the other one

   - on  reception,   a  callback  is   called  with  the   string  as
     argument. This happens on each side's single thread.

This  asynchronous communication  method ensures  that the  JS context
will never be blocked, whatever the sandboxed child does. 

For maximal genericity, the way NaTcl "retroacts" on the JS context is
by posting  back a JS string to  eval(). Then you can  do whatever you
want, including of course arranging  for future JS events to call back
into NaTcl. See [domset] and [after] (in init.natcl, which is compiled
into the binray .nexe) as two very simple examples.

In   an  universe   without   syscalls,  loading   other  scripts   is
problematic. To circumvent this (and bootstrap the loading of the main
script), [source $url] is  reimplemented over a JS XmlHttpRequest. And
to preserve  the blocking semantics of traditional  [source] while XHR
is  purely async,  this  implementation is  coroutine-based and  calls
[yield] after  starting the request.  When the download  completes, JS
calls back  into Tcl to resume  the coro, and  continue the sequential
execution of the  Tcl script where it left.  This allows for arbitrary
series and nesting of [source].

For this reason, the main script is bootstrapped by evaluating:

     coroutine main_coro source $url

This means that all  the init code in the script will  run in the coro
context (for [source]'s  benefit, but that could be  extended to other
things).  But once  the  execution has  fallen  back out  of the  main
script, hopefully after setting up  many (JS) event handlers, it is up
to the app to establish other coro contexts if needed.

A few things about GUI and blocking:

   - a simple,  ol'good-Tk-style event-driven script will work as usual

   - lengthy computations  on the Tcl  side will *not* block  the JS's
     side autonomous GUI elements, thanks to the new async interaction
     described above

   - however, to be able ot interrupt the computation from the GUI, or
     to have Tcl code implement part of the GUI reactions, one must of
     course let the Tcl code return quickly.

   - in all cases, [source] works  as usual to fetch scripts over HTTP
     (in   the   same  domain   as   the   page   serving  the   NaTcl
     plugin). Relative URLs work: [source foo.natcl].

   - in all cases, falling back  out of the main scripts is equivalent
     to going  back to the Tk eventloop  in wish (except it  is the JS
     eventloop).


The "Google Balls" demo
-----------------------

If you point your chrome  to "demo/balls.html" (eg with 'make balls'),
you'll get a full NaTcl emulation of the nice Javascript demo at:

 http://www.html5canvastutorials.com/labs/html5-canvas-google-bouncing-balls

This uses a canvas emulation script "canv.natcl", which demonstrates a
possible  (among  many)  way  of  organizing  Tcl-JS  interaction  for
graphics.  In the balls demo,  items are never destroyed nor shuffled,
which is  a favourable case for  lazy recompilation of  the JS repaint
function (basically the func is written just once, and only the coords
stored in a global array get updated, hence allowing for JIT compiling
of this function).

Perf measurements: the NaTcl version currently costs 3x the CPU of the
JS version,  so at  40fps it consumes  a full  core of my  2GHz laptop
(against 33% for the JS one). 

One should note that the  pure string API used currently precludes any
use  of  the   internal  reps  of  coordinates,  so   there  are  many
string/integer conversions. To be continued.

Comparison with native Tcl/Tk
-----------------------------

With the  command 'tools/natcl2tk balls.natcl',  you can run  the same
code  in pure  Tcl/Tk,  in a  true wish  canvas.  You can  use it  for
performance and rendering comparisons.

Future work
-----------

 Coming soon: [domget], more [canvas] features, and optimizations ;-)

Added nacl/configure.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#! /bin/sh

tmp=/tmp/nacl-configure.$$

findarch()
{
    echo -n "Finding default arch ..." >&2
    echo "int foo(x) {return x*x;}" > $tmp.c
    nacl-gcc -c $tmp.c -o $tmp.o
    kind=`file $tmp.o`
    /bin/rm $tmp.[co]
    case "$kind" in
	*32-bit*) arch=32;;
	*64-bit*) arch=64;;
	*) echo "### Cannot compute default arch. Please specify -m32 or -m64.">&2;exit 1;;
    esac
    echo " -m$arch" >&2
}

case "$1" in
    -m32) arch=32;;
    -m64) arch=64;;
    "") findarch;;
    *) echo "Usage: ./configure [-m32|-m64]">&2;exit 1;;
esac
export arch
set -ex
CC="nacl-gcc -m$arch" CPP="nacl-cpp -m$arch" CFLAGS="-Wno-long-long -pthread -DNACL" ../unix/configure --host nacl --disable-threads --disable-shared
rm -f a.out core.* || true
cat Makefile > $tmp.mk
sed -e '/^CC[ 	]*=/ a\
CCPLUS			= nacl-g++ -m'$arch'\
arch='$arch'
' < $tmp.mk > Makefile
patch -l -p0 < Makefile.patch
set +x
echo "
   Makefile generated and patched for NaCl. Ready for 'make' :)
">&2
exit 0

Added nacl/demo/NaTk/NaTk.html.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="../loader.js"></script>
    <script type="text/javascript" src="NaTk.js"></script>
  </head>
  <body>

   <embed
      name='nacl_module'
      id='tcl'
      width=0 height=0
      nacl='tcl.nmf'
      type='application/x-nacl'
      onload='moduleDidLoad();'
      verbose=0
      source='NaTk.tcl'
      toplevel='toplevel'/>

   <div id="toplevel">Loading ...</div>

   <script id='script' type="text/tcl">
     # this script will be evaluated by NaTk
     button .b -text "Hello, Tk!" -command {alert HELLO} -grid {0 0}
     frame .f -text "Frame" -grid {1 0}
     entry .f.e -grid {0 1}
     label .f.l -text label -textvariable e -grid {0 2}
   </script>

  </body>
</html>

Added nacl/demo/NaTk/NaTk.js.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function variableTk () {
   tcl("::oo::" + $(this).attr("id"), 'changed', $(this).val());
}

function buttonTk () {
   tcl("::oo::" + $(this).attr("id"), 'changed');
}

function rbuttonTk () {
   tcl("::oo::" + $(this).attr("id"), 'changed', $(this).val());
}

function cbuttonTk () {
   var val = this.value;
   if(!$(this).is(":checked")) {
      val = 0;
   }
   tcl("::oo::" + $(this).attr("id"), 'changed', val);
}

function sliderTk (e, id, ui) {
   if(e.originalEvent!=undefined) {
      tcl("::oo::" + id, 'changed', ui.value);
   }
}

function autocompleteTk (event,entry) {
   if(event.originalEvent!=undefined) {
        tcl("::oo::" + $(entry).attr("id"), 'changed', $(entry).val());
   }
}

Added nacl/demo/NaTk/NaTk.tcl.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
# NaTk - Tk emulation under NaTcl
#
# Colin McCormack
proc ::puts {args} {
    if {[llength $args] == 1} {
        printf "STDOUT: [lindex $args 0]"
    } else {
        printf "[string toupper [lindex $args 0]]: [lindex $args 1]"
    }
}

set _packages {mime base64}
proc package {cmd args} {
    printf "PKG: package $cmd $args"
    switch -- $cmd {
        require {
            lassign $args what
            if {$what in {Tcl Tk TclOO}} return
            if {$what in $::_packages} return
            source lib/Utilities/[lindex $args 0].tcl
        }
        provide {
            lassign $args what
            lappend ::_packages $what
        }
        vsatisfies {
            return 1
        }
    }
}
source tcllib/textutil/string.tcl
source tcllib/textutil/repeat.tcl
source tcllib/textutil/adjust.tcl
source tcllib/textutil/split.tcl
source tcllib/textutil/tabify.tcl
source tcllib/textutil/trim.tcl
source tcllib/textutil/textutil.tcl
source lib/extensions/extend-1.0.tm
source lib/extensions/file-1.0.tm
source lib/extensions/memoize-1.0.tm
source lib/extensions/know-1.0.tm

package require Form

namespace import oo::*
package provide NaTk 1.0

# radiobutton - textvariable command variable value
# entry - textvariable validatecommand
# scale - command variable
# checkbutton - textvariable command variable
# button - textvariable command

# TextVariable: radiobutton entry checkbutton button
# Command: radiobutton scale checkbutton button +validate:entry
# Variable: radiobutton scale checkbutton

# NaTk - class connecting an interp to an NaTcl window
class create ::NaTk {
    superclass FormClass

    method toplevel {args} {
        variable widgets
        if {[llength $args]} {
            {*}[dict get $widgets .] {*}$args
        } else {
            return [dict get $widgets .]
        }
    }

    method widget {widget} {
        variable widgets; return [dict get $widgets $widget]
    }

    method widgets {} {
        variable widgets; return $widgets
    }

    method mkwidget {type widget args} {
        variable ns
        variable interp
        variable widgets

        Debug.widget {mkwidget $widget of type $type ($args)}

        if {$widget ne "."} {
            set parent [join [lrange [split $widget .] 0 end-1] .]
            if {$parent eq ""} {
                set parent .
            }
            if {![dict exists $widgets $parent]} {
                error "Invalid Widget Name - no parent widget '$parent' exists for '$widget'"
            }
            set p [list -parent [dict get $widgets $parent]]	;# parent object
        } elseif {[dict exists $widgets .]} {
            error "Invalid Widget - Toplevel . already exists"
        } else {
            set p {-parent ""}
        }

        # construct a widget of given type
        Debug.widget {::NaTk::$type new -widget $widget $args -interp $interp $p -connection [self]}
        set cmd [::NaTk::$type new -widget $widget {*}$args -interp $interp {*}$p -connection [self]]
        return $widget

        if {[catch {
            ::NaTk::$type new -widget $widget {*}$args -interp $interp {*}$p -connection [self]
        } cmd eo]} {
            Debug.widget {FAILED $widget of type '$type' as obj: $cmd ($eo)}
            return -options $eo $cmd
        } else {
            Debug.widget {created $widget of type '$type' as obj:$cmd}
        }

        return $widget
    }

    # addwidget - to both Interp and mapping
    method addwidget {widget cmd} {
        Interp alias $widget $cmd ;# install widget alias in Interp

        # remember name<->command mapping
        variable widgets
        dict set widgets $widget $cmd
        dict set widgets $cmd $widget
    }

    # delwidget - from both Interp and mapping
    method delwidget {obj} {
        Interp alias $widget {}

        # forget name<->command mapping
        variable widgets
        set widget [dict get $widgets $obj]
        dict unset widgets $widget
        dict unset widgets $obj
    }

    method grid {args} {
        Debug.grid {NATK GRID: $args}
        if {[string index [lindex $args 0]] in {x . ^}} {
            set args [linsert $args 0 configure]
        }
        set args [lassign $args command]
        switch -- $command {
            anchor -
            bbox -
            columnconfigure -
            info -
            location -
            propagate -
            rowconfigure -
            size -
            slaves {
                set anchor {}
                set args [lassign $args widget]
                tailcall [dict get $widgets $widget] grid $command $widget {*}$args
            }

            configure -
            forget -
            remove -
            {
                set slaves {}
                while {[string index [lindex $args 0] 0] in {x . ^}} {
                    set args [lassign $args slave]
                    lappend slaves $slave
                }
                variable widgets
                set result {}
                foreach slave $slaves {
                    lappend result $slave
                    lappend result [[dict get $widgets $slave] grid $command $slave {*}$args]
                }
                return $result
            }
        }
    }

    method interp {script} {
        Debug.interp "INTERP: $script"
        return [Interp eval $script]
    }

    method start {script} {
        variable verbose
        set ::nacl::verbose $verbose

        Debug.interp "INTERP: $script"
        Interp eval $script
        my toplevel render
    }

    method bgerror {args} {
        Debug.interp "INTERP BGERROR: $args"
        ::nacl bgerror {*}$args [Interp info errorstack]
    }

    constructor {args} {
        Debug.widgets {[self] Creating ::NaTk $args}
        variable safe 0
        variable verbose 1
        variable {*}$args
        variable widgets {}
        variable ns [info object namespace [self]]

        # create an interpreter for NaTk program
        variable interp [::interp create {*}[expr {$safe?"-safe":""}] ${ns}::Interp]
        Interp alias ::bgerror [self] bgerror
        Interp alias ::alert ::nacl alert

        my mkwidget toplevel .

        # install each widget creator as alias in the interp
        foreach n {button entry label frame
            checkbutton radiobutton scale
            select combobox
        } {
            Interp alias $n [self] mkwidget $n
        }
        Interp alias $n grid [self] grid

        #::dom get [dict get $::argv script] [self] start
    }
}

class create ::NaTk::Widget {
    variable id props widget interp parent connection rendered

    method js {} {return ""}

    method element {} {
        return $id;
        #return "document.getElementById('$id')"
        return "\$('#$id')"	;# if jQuery
    }

    # catch unknown methods and palm them off to the parent
    method unknown {cmd args} {
        Debug.widgets {unknown $cmd $args}
        if {[string match <*> $cmd]} {
            return [{*}$parent $cmd {*}$args]
        } elseif {[string match .* $cmd]} {
            return [$cmd {*}$args]
        }
        error "Unknown method '$cmd' in [self] of class [info object class [self]]"
    }

    method connection {args} {
        return [{*}$parent {*}$args]
    }

    # grid - percolates up to the parent containing a grid
    method grid {args} {
        Debug.grid {percolating grid to $parent: grid $args}
        tailcall $parent grid {*}$args
    }

    # gridded - record grid's values
    method gridded {args} {
        variable grid
        if {[llength $args]} {
            set grid [dict merge $grid $args]
        }
        return $grid
    }

    # Grid - interpret -grid options to configure as grid commands
    method Grid {args} {
        # this widget needs to be gridded
        set rs 1; set cs 1; set r 0; set c 0
        Debug.widgets {config gridding: '$args'}
        set pargs [lsearch -glob $args -*]
        if {$pargs > -1} {
            # we've got extra args
            set gargs [lrange $args $pargs end]
            set args [lrange $args 0 $pargs-1]
        } else {
            set gargs {}
        }
        lassign $args r c rs cs

        set ga {}
        foreach {v1 v2} {r row c column rs rowspan cs columnspan} {
            if {[info exists $v1] && [set $v1] ne ""} {
                if {$v1 in {rs cs}} {
                    if {[set $v1] <= 0} {
                        set $v1 1
                    }
                } else {
                    if {[set $v1] < 0} {
                        set $v1 0
                    }
                }
                lappend ga -$v2 [set $v1]
            }
        }

        Debug.widgets {option -grid: 'grid configure $widget $ga $gargs'}
        return [my grid configure $widget {*}$ga {*}$gargs]
    }

    # style - make an HTML style form
    method style {gridding} {
        set attrs {}
        foreach {css tk} {
            background-color background
            color foreground
            text-align justify
            vertical-align valign
            border borderwidth
            border-color bordercolor
            width width
        } {
            set tkval [dict get? $props $tk]
            if {$tkval eq ""} continue

            if {$tk eq "background"} {
                lappend attrs background "none $tkval !important"
                if {![dict exists $props bordercolor]} {
                    dict set attrs border-color $tkval
                }
                # TODO: background images, URLs
            } else {
                dict set attrs $css $tkval
            }
        }

        if {0} {
            # process -sticky gridding
            set sticky [dict gridding.sticky?]
            if {$sticky ne ""} {
                # we have to use float and width CSS to emulate sticky
                set sticky [string trim [string tolower $sticky]]
                set sticky [string map {n "" s ""} $sticky];# forget NS
                if {[string first e $sticky] > -1} {
                    dict set attrs float "left"
                } elseif {[string first w $sticky] > -1} {
                    dict set attrs float "right"
                }

                if {$sticky in {"ew" "we"}} {
                    # this is the usual case 'stretch me'
                    dict set attrs width "100%"
                }
            }
        }

        # todo - padding
        set result ""
        dict for {n v} $attrs {
            append result "$n: $v;"
        }
        append result [dict gridding.style?]

        if {$result ne ""} {
            set result [list style $result]
        }

        Debug.widgets {style attrs:($attrs), style:($result)}

        if {[dict exists $props class]} {
            lappend result class [dict get $props class]
        }

        if {[dict exists $props state]
            && [dict get $props state] ne "normal"
        } {
            lappend result disabled 1
        }

        return $result
    }

    # getvalue - return a widget's textvariable or text, where applicable
    method getvalue {} {
        if {[dict exists $props textvariable]} {
            set result [my iget? [dict get $props textvariable]]
            Debug.widgets {[self] getvalue from textvariable:'[dict get $props textvariable]' value:'$result'}
        } elseif {[dict exists $props text]} {
            set result [dict get $props text]
            Debug.widgets {[self] getvalue from text '$result'}
        } else {
            Debug.widgets {[self] getvalue default to ""}
            set result ""
        }
        return $result
    }

    # compound - return a widget's image/value compound
    method compound {args} {
        if {[llength $args] == 1} {
            set text [lindex $args 0]
            Debug.widget {[self] compound explicit '$text'}
        } else {
            set text [my getvalue]
            Debug.widget {[self] compound implicit '$text'}
        }
        set text [armour $text]

        set image [dict get? $props image]
        if {$image ne ""} {
            set image [$image render]
        }
        set result ""
        switch -- [dict get? $props compound] {
            left {
                set result $image$text
            }
            right {
                set result $text$image
            }
            center -
            top {
                set result "$image[my <br>]$text"
            }
            bottom {
                set result "$text[my <br>]$image"
            }
            none -
            default {
                # image instead of text
                if {$image ne ""} {
                    set result "$image"
                } else {
                    set result "$text"
                }
            }
        }
        Debug.widget {[self] compound ($args) -> $result}
        return $result
    }

    # access interp variables
    method iset {n v} {
        Debug.interp {iset '$n' <- '$v' traces:([{*}$interp eval [list trace info variable $n]]) ([lrange [info level -1] 0 1])}
        return [{*}$interp eval [list ::set $n $v]]
    }

    method iget? {n} {
        try {
            Debug.widgets {iget $n: {*}$interp eval ::if \{\[info exists $n\]\} \{set $n\}}
            set result [{*}$interp eval ::if \{\[info exists $n\]\} \{set $n\}]
        } on error {e eo} {
            set result ""
        }

        Debug.interp {iget '$n' -> '$result' ([lrange [info level -1] 0 1])}
        return $result
    }

    method iget {n} {
        try {
            set result [{*}$interp eval [list ::set $n]]
        } on error {e eo} {
            set result ""
        }

        Debug.interp {iget '$n' -> '$result' ([lrange [info level -1] 0 1])}
        return $result
    }

    method iexists {n} {
        set result [{*}$interp eval [list ::info exists $n]]
        Debug.interp {iexists '$n' -> $result}
        return $result
    }

    # itrace - trace an Interp variable
    method itrace {what args} {
        variable trace	;# set of active traces for this widget
        if {[llength $args]} {
            # add a trace
            dict set trace $what $args
            {*}$interp eval [list trace add variable $what write $args]
            Debug.interp {itrace add $what $args: ([{*}$interp eval [list trace info variable $what]])}
        } elseif {[dict exists $trace $what]} {
            {*}$interp eval [list trace remove variable $what write [dict get $trace $what]]
            Debug.interp {itrace removed $what $args ([dict get $trace $what]) leaving ([{*}$interp eval [list trace info variable $what]])}
            dict unset trace $what
        }
    }

    # Configure - reflect configuration in $props dict
    # give trace-effect to -textvariable and -variable opts
    method Configure {args} {
        # set configuration opts
        Debug.widgets {[info coroutine] Configure [self] ($args)/[llength $args]}
        if {[llength $args]%2} {
            error "Configure requires even number of args"
        }

        # clean the '-' prefix from property names
        dict for {n v} $args {
            if {[string match -* $n]} {
                dict unset args $n
                dict set args [string trim $n -] $v
            }
        }

        dict for {n v} $args {
            switch -- $n {
                variable -
                textvariable {
                    # remove any old traces first
                    if {[dict get? $props $n] ne ""} {
                        my itrace [dict get $props $n]
                    }

                    dict set props $n $v

                    if {$v ne ""} {
                        # (re-)establish variable trace
                        Debug.widgets {tracking -$n '$v' changes}
                        if {![my iexists $v]} {
                            # create variable if necessary
                            {*}$interp eval [list ::variable ::$v]
                        }

                        if {[dict exists $args text]} {
                            my iset $v [dict get $args text]
                        }

                        # track changes to textvariable
                        my itrace [dict get $props $n] $widget $n
                    } else {
                        catch {dict unset props $n}
                    }
                }

                grid {
                    my Grid {*}$v
                }

                default {
                    # normal old configuration variable
                    dict set props $n $v
                }
            }
        }
    }

    method configure {args} {
        switch -- [llength $args] {
            0 {
                # get the names of all configuration opts
                set _result {};
                foreach v $props {
                    lappend result -$v [dict get $props $v]
                }
                return $result
            }

            1 {
                # get the value of a single configuration opt
                set v [string trimleft [llength $args 0] -]
                return [dict get $props $v]
            }

            default {
                # handle configure with sensitivity to -command, -variable, etc
                tailcall my Configure {*}$args
            }
        }
    }

    destructor {
        $connection delwidget [self]	;# remove full widget name
    }

    method id {} {
        return $id
    }

    method nacl {args} {
        if {!$rendered} return
        set script [join $args \;\n]
        ::nacl js $script
    }

    method render {args} {
        incr rendered
    }

    constructor {args} {
        variable grid {}
        set id [namespace tail [self]]
        set rendered 0	;# not yet rendered

        # get structural vars from NaTk mkwidget
        foreach v {widget interp parent connection} {
            set $v [dict get $args -$v]
            dict unset args -$v
        }
        Debug.widgets "create $widget ([self])  parent: $parent"

        # add widget to Interp and mapping
        $connection addwidget $widget [self]

        set props {}		;# no properties yet
        variable trace {}	;# no traces yet
        my Configure {*}$args	;# fill up props
    }
}

class create ::NaTk::button {
    superclass ::NaTk::Widget
    variable id props widget interp parent connection rendered

    # button - textvariable command

    # textvariable - interp's textvariable has changed
    method textvariable {} {
        variable ignore; if {$ignore} return
        set val [my iget [dict get $props textvariable]]
        my nacl [my element].innerHTML='[my compound]'
    }

    method changed {} {
        set cmd [dict get? $props command]
        if {$cmd ne ""} {
            {*}$interp eval $cmd
        }
    }

    method render {args} {
        next
        set event [list onclick "tcl(\"[self]\",\"changed\");"]
        return [my <button> $id id $id type button class button {*}$event {*}[my style $args] [my compound]]
    }

    constructor {args} {
        next justify left {*}$args
    }
}

class create ::NaTk::entry {
    superclass ::NaTk::Widget
    variable id props widget interp parent connection rendered

    # entry - textvariable validatecommand

    # textvariable - interp's textvariable has changed
    # reflect change onto browser widget
    method textvariable {args} {
        variable ignore; if {$ignore} return
        set val [my iget [dict get $props textvariable]]
        my nacl [my element].value='$val'
    }

    method changed {value} {
        # the entry value has changed
        # TODO call validation cmd
        variable ignore; incr ignore
        my iset [dict get $props textvariable] $value
        incr ignore -1
    }

    method render {args} {
        next
        Debug.widgets {[info coroutine] rendering Entry [self]}

        switch -- [dict get? $props type] {
            password {
                set tag <password>
            }
            date {
                set tag <text>
                #append js [my element].datepicker();
            }
            default {
                set tag <text>
            }
        }
        set event [list onchange "tcl(\"[self]\",\"changed\",tclEsc([my element].value));return false;"]
        set result [my $tag $id id $id class var {*}$event {*}[my style $args] size [dict get $props width] [tclarmour [my getvalue]]]
        return $result
    }

    constructor {args} {
        variable ignore 1
        next {*}[dict merge {
            justify left
            state normal width 16
        } $args]
        if {![dict exists $props textvariable]} {
            my Configure textvariable [lindex [split $widget .] end]
        }
        if {[dict exists $props show] && ![dict exists $props type]} {
            my configure -type password
        }
        incr ignore -1
    }
}

class create ::NaTk::label {
    superclass ::NaTk::Widget
    variable id props widget interp parent connection rendered

    # label - textvariable text

    method textvariable {args} {
        variable ignore; if {$ignore} return
        Debug.widget {label $id: getvalue: '[my getvalue]'}
        my nacl [my element].innerHTML='[my compound]'
    }

    method render {args} {
        next
        return [my <div> id $id class label {*}[my style $args] [my compound]]
    }

    constructor {args} {
        variable ignore; incr ignore
        next justify left {*}$args
        if {![dict exists $props textvariable]} {
            my Configure textvariable [lindex [split $widget .] end]
        }
        incr ignore -1
    }
}

class create ::NaTk::checkbutton {
    superclass ::NaTk::Widget
    variable id props widget interp parent connection rendered

    # checkbutton - textvariable command variable

    method textvariable {} {
        variable ignore; if {$ignore} return
        set val [my iget [dict get $props textvariable]]
        my nacl [my element].whatever
    }

    # changed - button state in browser - reflect to var/command
    method changed {value} {
        variable ignore; incr ignore
        my iset [dict get $props variable] $value
        incr ignore -1
        if {[dict exists $props command]} {
            {*}$interp eval [dict get $props command]
        }
    }

    method js {} {
        return "\$('#$id'>:checkbox').change(cbuttonTk);"
    }

    method render {args} {
        next
        Debug.widgets {checkbutton render: getting '[dict get $props variable]' == [my iget [dict get $props variable]]}

        set val [my iget [dict get $props variable]]
        if {$val ne "" && $val} {
            set checked 1
        } else {
            set checked 0
        }

        Debug.widgets {[self] checkbox render: checked:$checked}
        return [my <checkbox> $id id $id {*}[my style $args] checked $checked [tclarmour [my compound]]]
    }

    constructor {args} {
        variable ignore 0
        next justify left {*}$args
        if {![dict exists $props variable]} {
            my Configure variable [lindex [split $widget .] end]
        }
    }
}

# rbC - pseudo-widget which handles change events for a set of
# radiobuttons sharing the same variable.
class create ::NaTk::rb {
    superclass ::NaTk::Widget
    variable id props widget interp parent connection rendered

    method render {args} {
        next
        error "Can't render an rbC"
    }

    constructor {args} {
        next {*}$args	;# set up traces etc
    }
}

class create ::NaTk::radiobutton {
    superclass ::NaTk::Widget
    variable id props widget interp parent connection rendered

    # radiobutton - textvariable command variable value

    method textvariable {} {
        variable ignore; if {$ignore} return
        set val [my iget [dict get $props textvariable]]
        my nacl [my element].whatever
    }

    method variable {} {
        set val [my iget [dict get $props textvariable]]
        my nacl [my element].whatever
    }

    # changed - button state in browser - reflect to var/command
    method changed {value} {
        variable ignore; incr ignore
        my iset [dict get $props variable] $value
        incr ignore -1
        if {[dict exists $props command]} {
            {*}$interp eval [dict get $props command]
        }
    }

    method js {} {
        return "[my element].click(rbuttonTk);"
    }

    method update {args} {
        Debug.widgets {radiobutton render: getting '[dict get $props variable]' == [my iget [dict get $props variable]]}

        set checked 0
        set var [dict get $props variable]
        if {[my iexists $var]} {
            set val [my iget $var]
            if {$val eq [dict get $props value]} {
                set checked 1
            }
        }

        Debug.widgets {[self] radiobox render: checked:$checked}
        set result [my <radio> [[my connection rbvar $var] widget] id $id class rbutton {*}[my style $args] checked $checked value [dict get $props value] [dict args.label?]]
        Debug.widgets {RADIO html: $result}
        return $result
    }

    method render {args} {
        next
        set label [tclarmour [my compound]]
        return [my update {*}$args label $label]
    }

    constructor {args} {
        variable ignore 0
        next justify left {*}$args

        if {![dict exists $props variable]} {
            my Configure variable selectedButton
        }
    }
}

class create ::NaTk::scale {
    superclass ::NaTk::Widget
    variable id props widget interp parent connection rendered

    # scale - command variable

    # scale value has changed in browser
    method changed {value} {
        variable ignore; incr ignore
        my iset [dict get $props variable] $value
        incr ignore -1
        if {[dict exists $props command]} {
            {*}$interp eval [dict get $props command]
        }
    }

    # variable - interp var has changed - reflect to browser widget
    method variable {} {
        variable ignore; if {$ignore} return
        set val [my iget [dict get $props variable]]
        my nacl [my element].whatever
    }

    # js - javascript to track changes to the browser widget
    method js {} {
        # need to generate the slider interaction
        lappend opts orientation '[dict get $props orient]'
        lappend opts min [dict get $props from]
        lappend opts max [dict get $props to]
        lappend opts value [my iget [dict get $props variable]]
        lappend opts change [string map [list %ID% $id] {
            function (event,ui) {
                sliderTk(event, '%ID%', ui);
            }
        }]

        return "[my element].slider([::nacl opts {*}$opts]); [my element].change(sliderTk);"
    }

    method render {args} {
        next
        Debug.widgets {scale $id render $args}
        set result ""
        if {[dict get? $props label] ne ""} {
            set result [my <label> [dict get $props label]]
        }

        append result [my <div> id $id class slider {*}[my style $args] {}]
        Debug.widgets {scale $id rendered '$result'}

        return $result
    }

    constructor {args} {
        variable ignore 0
        set var [lindex [split [dict get $args -name] .] end]
        next {*}[dict merge [list -variable $var] {
            justify left state active
            label "" command "" -length 100 -width 10 -showvalue 0
            -from 0 -to 100 -tickinterval 0
            -orient horizontal
        } $args]
    }
}

class create ::NaTk::select {
    superclass ::NaTk::Widget
    variable id props widget interp parent connection rendered

    method textvariable {} {
        variable ignore; if {$ignore} return
        set val [my iget [dict get $props textvariable]]
        my nacl [my element].value='$val'
    }

    # variable - interp var has changed - reflect to browser widget
    method variable {} {
        variable ignore; if {$ignore} return
        set val [my iget [dict get $props variable]]
        my nacl [my element].value='$val'
    }

    # select value has changed in browser
    method changed {value} {
        variable ignore; incr ignore
        my iset [dict get $props variable] $value
        incr ignore -1
        if {[dict exists $props command]} {
            {*}$interp eval [dict get $props command]
        }
    }

    method render {args} {
        next
        set var [dict get $props textvariable]
        if {[my iexists $var]} {
            set val [my iget $var]
        }

        set values [dict get $props values]
        Debug.widgets {select: val=$val values=$values}
        foreach opt $values {
            lappend opts [my <option> value [tclarmour $opt]]
        }
        set opts [join $opts \n]

        set class {variable ui-widget ui-state-default ui-corner-all}
        if {[dict exists $props combobox]
            && [dict get $props combobox]
        } {
            lappend class combobox
        }

        set event [list onclick "tcl(\"[self]\",\"changed\",[my element].value);return false;"]

        return [my <select> $id id $id {*}$event class [join $class] {*}[my style $args] $opts]
    }

    constructor {args} {
        variable ignore 0
        next justify left {*}$args
        if {![dict exists $props variable]} {
            my Configure variable [lindex [split $widget .] end]
        }
    }
}

class create ::NaTk::combobox {
    superclass ::NaTk::select
    variable id props widget interp parent connection rendered

    method render {} {
        next
        Debug.widgets {combobox}
        set result [next]
        my nacl [my element].combobox()
        return $result
    }

    constructor {args} {
        next {*}$args -combobox 1
    }
}

# grid store grid info in an x/y array gridLayout(column.row)
class create ::NaTk::grid {
    variable id props widget interp parent connection rendered

    # traverse grid looking for changes.
    method changes {r} {
        if {[dict exists $r -repaint]} {
            # repaint short-circuits change search
            #Debug.grid {Grid '[namespace tail [self]]' repainting}
            return [list $r {}]
        }

        variable grid;variable oldgrid
        #Debug.grid {Grid detecting changes: '[namespace tail [self]]'}

        # look for modified grid entries, these will cause a repaint
        dict for {row rval} $grid {
            dict for {col val} $rval {
                if {$val ne [dict oldgrid.$row.$col?]} {
                    # grid has changed ... force reload
                    Debug.grid {[namespace tail [self]] repainting}
                    dict set r -repaint 1
                    return [list $r {}]	;# return the dict of changes by id
                }
            }
        }

        if {[dict size [dict ni $oldgrid [dict keys $grid]]]} {
            # a grid element has been deleted
            Debug.grid {Grid repainting: '[namespace tail [self]]'}
            dict set r -repaint 1
            return [list $r {}]	;# return the dict of changes by id
        }

        set changes {}
        dict for {row rval} $grid {
            dict for {col val} $rval {
                dict with val {
                    set type [uplevel 1 [list $widget type]]
                    set changed {}
                    switch -- $type {
                        accordion -
                        notebook -
                        frame {
                            # propagate change request to geometry managing widgets
                            #Debug.grid {Grid changing $type '$widget' at ($row,$col)}
                            set changed [lassign [uplevel 1 [list $widget changes $r]] r]
                            if {[dict exists $r -repaint]} {
                                Debug.grid {Grid '[namespace tail [self]]' subgrid repaint $type '$widget'}
                                return [list $r {}]	;# repaint
                            } else {
                                #Debug.grid {Grid '[namespace tail [self]]' subgrid [string totitle $type] '$widget' at ($row,$col) ($val) -> ($changed)}
                            }
                        }

                        default {
                            if {[uplevel 1 [list $widget changed?]]} {
                                Debug.grid {[namespace tail [self]] changing: ($row,$col) $widget [uplevel 1 [list $widget type]] reports it's changed}
                                uplevel 1 [list $widget reset]
                                set changed $widget
                                lappend changed [uplevel 1 [list $widget wid]]
                                lappend changed [uplevel 1 [list $widget update]]
                                lappend changed [uplevel 1 [list $widget type]]

                                Debug.grid {Grid '[namespace tail [self]]' accumulate changes to [string totitle $type] '$widget' at ($row,$col) ($val) -> ($changed)}
                            }
                        }
                    }

                    lappend changes {*}$changed
                    set r [uplevel 1 [list $widget js $r]]
                }
            }
        }

        return [list $r {*}$changes]	;# return the dict of changes by id
    }

    method changed? {} {return 1}

    # render - construct a grid's <table>
    method grid_render {args} {
        variable maxrows; variable maxcols; variable grid
        Debug.grid {grid render [dict keys grid] over $maxrows/$maxcols}

        set rows {}	;# accumulate rows
        for {set row 0} {$row < $maxrows} {incr row} {
            set cols {}	;# accumulate cols

            for {set col 0} {$col < $maxcols} {} {
                set columnspan 1
                if {[dict exists $grid $row $col]} {
                    set el [dict get $grid $row $col]
                    dict with el {
                        Debug.grid {'[namespace tail [self]]' grid rendering $widget/$object}
                        for {set rt $row} {$rt < $rowspan} {incr rt} {
                            set rspan($widget,[expr {$row + $rt}].$col) 1
                            for {set ct $col} {$ct < $columnspan} {incr ct} {
                                set rspan($widget,$rt.[expr {$col + $ct}]) 1
                            }
                        }

                        if {$rowspan != 1} {
                            set rowspan [list rowspan $rowspan]
                        } else {
                            set rowspan {}
                        }

                        lappend cols [my <td> id [my id]_${row}_$col colspan $columnspan {*}$rowspan [$object render style $style sticky $sticky]]
                    }
                    incr col $columnspan
                } else {
                    # empty cell
                    if {[info exists widget]
                        && ![info exists rspan($widget,$row.$col)]
                    } {
                        lappend cols [my <td> id [my id]_${row}_$col "&nbsp;"]
                    }
                    incr col $columnspan
                }
            }

            # now we have a complete row - accumulate it
            # align and valign not allowed here
            lappend rows [my <tr> id [my id]_$row style width:100% [join $cols \n]]
        }

        variable oldgrid $grid	;# record the old grid
        set content [my <tbody> [join $rows \n]]
        dict set args width 100%

        set border [dict get? $props border]
        if {$border eq ""} {
            set b {}
        } elseif {[string is integer -strict $border]} {
            set b [list border ${border}px]
        } else {
            set b [list border $border]
        }

        set content [my <table> class grid {*}$b {*}[my style $args] $content]
        Debug.grid {Grid '[namespace tail [self]]' rendered ($content)}
        return $content
    }

    method grid_js {} {
        set result ""
        variable grid
        dict for {rc row} $grid {
            dict for {cc col} $row {
                append result [[dict get $col object] js]
            }
        }
        return $result
    }

    method grid_anchor {master {anchor ""}} {
        if {$master ne $widget} {
            return [$parent grid anchor $master {*}$args]
        }
    }

    method grid_bbox {master args} {
        if {$master ne $widget} {
            return [$parent grid bbox $master {*}$args]
        }
    }
    method grid_columnconfigure {master index args} {
        if {$master ne $widget} {
            return [$parent grid columnconfigure $master $index {*}$args]
        }
    }
    method grid_location {master x y} {
        if {$master ne $widget} {
            return [$parent grid location $master $x $y]
        }
    }
    method grid_propagate {master boolean} {
        if {$master ne $widget} {
            return [$parent grid propagate $master $boolean]
        }
    }
    method grid_rowconfigure {master index args} {
        if {$master ne $widget} {
            return [$parent grid rowconfigure $master $index {*}$args]
        }
    }

    method grid_size {master} {
        if {$master ne $widget} {
            return [$parent grid size $master]
        }
        variable maxcols; variable maxrows
        return [list $maxcols $maxrows]
    }

    method grid_slaves {master {option all} {value 0}} {
        if {$master ne $widget} {
            return [$parent grid slaves $master $option $value]
        }
        variable grid
        switch -- $option {
            -row {
                dict for {col v} [dict get $grid $value] {
                    lappend result [dict get $v widget]
                }
            }
            -column {
                dict for {row v} $grid {
                    if {[dict exists $v $value]} {
                        lappend result [dict get $v $value widget]
                    }
                }
            }
            default {
                dict for {row c} $grid {
                    dict for {col v} $c {
                        lappend result [dict get $v widget]
                    }
                }
            }
        }
        return $result
    }

    method grid_forget {slave} {
        if {$slave eq $widget} {
            return [$parent grid forget $widget {*}$args]
        }
    }

    method grid_info {slave} {
        if {$slave eq $widget} {
            return [$parent grid info $widget {*}$args]
        }
    }

    method grid_remove {slave} {
        if {$slave eq $widget} {
            return [$parent grid remove $widget {*}$args]
        }
        [$connection widget $slave] hide
    }

    method grid_configure {slave args} {
        if {$slave eq $widget} {
            return [$parent grid configure $widget {*}$args]
        }

        # set defaults
        set column 0
        set row 0
        set columnspan 1
        set rowspan 1
        set sticky ""
        set in ""
        set style ""

        foreach {var val} $args {
            set [string trim $var -] $val
        }

        variable maxcols
        set width [expr {$column + $columnspan}]
        if {$width > $maxcols} {
            set maxcols $width
        }

        variable maxrows
        set height [expr {$row + $rowspan}]
        if {$height > $maxrows} {
            set maxrows $height
        }

        set object [$connection widget $slave]

        variable grid
        dict set grid $row $column [list widget $slave columnspan $columnspan rowspan $rowspan sticky $sticky in $in style $style object $object]
        $object gridded columnspan $columnspan rowspan $rowspan sticky $sticky in $in style $style

        Debug.grid {[namespace tail [self]] configure gridding $slave/$object}
        return $slave
    }

    method grid {cmd args} {
        Debug.grid {[self] Calling grid_$cmd $args}
        tailcall my grid_$cmd {*}$args
    }

    constructor {args} {
        Debug.grid {[self] GRID constructing ($args)}
        variable maxcols 1
        variable maxrows 1
        variable border 0
        variable grid {}
        variable connection [dict get $args -connection]

        next {*}$args
        Debug.grid {[self] GRID constructed ($args)}
    }
}

# frame widget
class create ::NaTk::frame {
    superclass ::NaTk::Widget
    mixin ::NaTk::grid
    variable id props widget interp parent connection rendered

    # render widget
    method render {args} {
        next
        Debug.widgets {Frame [namespace tail [self]] render}
        if {[dict exists $props div]
            || [dict get? $props text] eq ""
        } {
            append content \n [my grid_render {*}$args]
            return [my <div> id $id class frame {*}[my style $args] $content]
        } else {
            set label [dict get? $props text]
            if {$label ne ""} {
                set content [my <legend> [tclarmour $label]]
            }
            append content \n [my grid_render {*}$args]
            return [my <fieldset> $id class frame {*}[my style $args] -raw 1 $content]
        }
    }

    destructor {
        # TODO destroy all child widgets
        next
    }

    constructor {args} {
        Debug.widgets {creating Frame [self]}
        next -border 0 {*}$args
        Debug.widgets {created Frame [self]}
    }
}

# toplevel widget
class create ::NaTk::toplevel {
    superclass ::NaTk::Widget
    mixin ::NaTk::grid
    variable id props widget interp parent connection rendered

    # render widget
    method render {args} {
        next
        Debug.widgets {[namespace tail [self]] toplevel render}

        my nacl toplevel.innerHTML=[::nacl jsquote [my <form> form_$id onsubmit "return false;" [my grid_render {*}$args]]]
        my nacl [::nacl jsquote [my grid_js]]
    }

    constructor {args} {
        next -titlebar 1 -menubar 1 -border 0 -toolbar 1 -location 1 -scrollbars 1 -status 1 -resizable 1 {*}$args
        set id toplevel
    }
}

Debug on form
Debug on widgets
Debug on widget
Debug on interp
Debug on grid

set ::nacl::verbose 1

# fetch all the <script> elements which are type text/tcl
# pass them as one big string to the NaTk object for evaluation.
::nacl js "runTclScripts('[::NaTk new] start')"

Added nacl/demo/NaTk/tcl.nmf.













>
>
>
>
>
>
1
2
3
4
5
6
{
  "nexes": {
    "x86-32": "../tcl32.nexe",
    "x86-64": "../tcl64.nexe",
  }
}

Added nacl/demo/a.natcl.







>
>
>
1
2
3
printf "I'm a.natcl"
source c.natcl

Added nacl/demo/b.natcl.





>
>
1
2
printf "I'm b.natcl"

Added nacl/demo/balls.html.













































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="loader.js"></script>
  </head>
  <body>
	 <div id="listener">
    	<script type="text/javascript">
      		document.getElementById('listener')
        	  .addEventListener('load', moduleDidLoad, true);
    	</script>

    <embed
      name='nacl_module'
      id='tcl'
      width=0 height=0
      src='../tcl.nmf'
      type='application/x-nacl'
      verbose=0
      source='balls.natcl'>

         <canvas id="canvas" width="578" height="200"></canvas>
         <h2>Status</h2>
         <div id="modstatus">NO-STATUS</div>
   </embed>
</div>

   <p style="font-size : smaller;">
      To run this demo, you need
      <ul style="font-size : smaller;">
        <li> An x86-family processor</li>
        <li> Chrome 15 or higher</li>
        <li> Enabled "Native Client" item in about:flags</li>
       <li> if everything else fails, try the Nacl demos at <a href="http://code.google.com/chrome/nativeclient/docs/examples.html">http://code.google.com/chrome/nativeclient/docs/examples.html</a></li>
      </ul>
   </p>

    <script type="text/javascript">
      var statusField = document.getElementById('modstatus');
      var canvas = document.getElementById('canvas');
      var context=canvas.getContext("2d");
      var repaint = function () {};
      var canvcoords = [];
      function updateCoords(ar) {
          var i,n;
          n=ar.length;
          for(i=0;i<n;i+=2)
             canvcoords[ar[i]]=ar[i+1];
      }

    </script>

  </body>
</html>

Added nacl/demo/balls.natcl.









































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
source canv.natcl
#set ::canv_verbose 1
domset statusField "Running..."

# will be retrieved by [domget]
set width 578
set height 200

# animation globals
set t 0
set frameInterval 25

# ball globals
set ballRadius 10

# physics global
set collisionDamper 0.3
set floorFriction [expr {0.0005*$frameInterval}]
set mouseForceMultiplier [expr {1.0*$frameInterval}]
set restoreForce  [expr {0.002*$frameInterval}]

set mouseX 99999
set mouseY 99999

set balls {}

set blue   "#3A5BCD"
set red    "#EF2B36"
set yellow "#FFC636"
set green  "#02A817"

proc newball {x y vx vy col} {
    set id [canv_create circle $x $y $::ballRadius -fill $col -outline ""]
    set ::b($id) [list $x $y $vx $vy $x $y]
    lappend ::balls $id
}

# G
newball 173 63 0 0 $blue
newball 158 53 0 0 $blue
newball 143 52 0 0 $blue
newball 130 53 0 0 $blue
newball 117 58 0 0 $blue
newball 110 70 0 0 $blue
newball 102 82 0 0 $blue
newball 104 96 0 0 $blue
newball 105 107 0 0 $blue
newball 110 120 0 0 $blue
newball 124 130 0 0 $blue
newball 139 136 0 0 $blue
newball 152 136 0 0 $blue
newball 166 136 0 0 $blue
newball 174 127 0 0 $blue
newball 179 110 0 0 $blue
newball 166 109 0 0 $blue
newball 156 110 0 0 $blue

# O
newball 210 81 0 0 $red
newball 197 91 0 0 $red
newball 196 103 0 0 $red
newball 200 116 0 0 $red
newball 209 127 0 0 $red
newball 223 130 0 0 $red
newball 237 127 0 0 $red
newball 244 114 0 0 $red
newball 242 98 0 0 $red
newball 237 86 0 0 $red
newball 225 81 0 0 $red

# O
set oOffset 67
newball [expr {$oOffset + 210}] 81 0 0 $yellow
newball [expr {$oOffset + 197}] 91 0 0 $yellow
newball [expr {$oOffset + 196}] 103 0 0 $yellow
newball [expr {$oOffset + 200}] 116 0 0 $yellow
newball [expr {$oOffset + 209}] 127 0 0 $yellow
newball [expr {$oOffset + 223}] 130 0 0 $yellow
newball [expr {$oOffset + 237}] 127 0 0 $yellow
newball [expr {$oOffset + 244}] 114 0 0 $yellow
newball [expr {$oOffset + 242}] 98 0 0 $yellow
newball [expr {$oOffset + 237}] 86 0 0 $yellow
newball [expr {$oOffset + 225}] 81 0 0 $yellow

# G
newball 370 80 0 0 $blue
newball 358 79 0 0 $blue
newball 346 79 0 0 $blue
newball 335 84 0 0 $blue
newball 330 98 0 0 $blue
newball 334 111 0 0 $blue
newball 348 116 0 0 $blue
newball 362 109 0 0 $blue
newball 362 94 0 0 $blue
newball 355 128 0 0 $blue
newball 340 135 0 0 $blue
newball 327 142 0 0 $blue
newball 325 155 0 0 $blue
newball 339 165 0 0 $blue
newball 352 166 0 0 $blue
newball 367 161 0 0 $blue
newball 371 149 0 0 $blue
newball 366 137 0 0 $blue

# L
newball 394 49 0 0 $green
newball 381 50 0 0 $green
newball 391 61 0 0 $green
newball 390 73 0 0 $green
newball 392 89 0 0 $green
newball 390 105 0 0 $green
newball 390 118 0 0 $green
newball 388 128 0 0 $green
newball 400 128 0 0 $green

# E
newball 426 101 0 0 $red
newball 436 98 0 0 $red
newball 451 95 0 0 $red
newball 449 83 0 0 $red
newball 443 78 0 0 $red
newball 430 77 0 0 $red
newball 418 82 0 0 $red
newball 414 93 0 0 $red
newball 412 108 0 0 $red
newball 420 120 0 0 $red
newball 430 127 0 0 $red
newball 442 130 0 0 $red
newball 450 125 0 0 $red

set oldcnt 0
proc computeFps {} {
     set fps [expr $::cnt-$::oldcnt]
     set ::oldcnt $::cnt
     domset statusField "Running - $fps fps"
}

set cnt 0
proc updateStage {} {
    incr ::cnt
    foreach id $::balls {
	foreach {x y vx vy rx ry} $::b($id) break
	# set ball position based on velocity
	set x [expr {$x+$vx}]
	set y [expr {$y+$vy}]
	# restore forces
	if {$x>$rx} {
	    set vx [expr {$vx-$::restoreForce}]
	} else {
	    set vx [expr {$vx+$::restoreForce}]
	}
	if {$y>$ry} {
	    set vy [expr {$vy-$::restoreForce}]
	} else {
	    set vy [expr {$vy+$::restoreForce}]
	}
	# mouse forces
	set distX [expr {$x-$::mouseX}]
	set distY [expr {$y-$::mouseY}]
	set radius [expr {hypot($distX,$distY)}]
	set totalDist [expr {abs($distX)+abs($distY)}]
	set forceX [expr {(abs($distX)/double($totalDist))*(1.0/$radius)*$::mouseForceMultiplier}]
	set forceY [expr {(abs($distY)/double($totalDist))*(1.0/$radius)*$::mouseForceMultiplier}]
	if {$distX>0} { # mouse is left of ball
	    set vx [expr {$vx+$forceX}]
	} else {
	    set vx [expr {$vx-$forceX}]
	}
	if {$distY>0} { # mouse is on top of ball
	    set vy [expr {$vy+$forceY}]
	} else {
	    set vy [expr {$vy-$forceY}]
	}
	# floor friction
	if {$vx>0} {
	    set vx [expr {$vx-$::floorFriction}]
	} elseif {$vx<0} {
	    set vx [expr {$vx+$::floorFriction}]
	}
	if {$vy>0} {
	    set vy [expr {$vy-$::floorFriction}]
	} elseif {$vy<0} {
	    set vy [expr {$vy+$::floorFriction}]
	}
	# floor condition
	if {$y>($::height-$::ballRadius)} {
	    set y [expr {$::height-$::ballRadius-2}]
	    set vy [expr {-$vy*(1.0-$::collisionDamper)}]
	}
	# ceiling condition
	if {$y<$::ballRadius} {
	    set y [expr {$::ballRadius+2}]
	    set vy [expr {-$vy*(1.0-$::collisionDamper)}]
	}
	# right wall condition
	if {$x>($::width-$::ballRadius)} {
	    set x [expr {$::width-$::ballRadius-2}]
	    set vx [expr {-$vx*(1.0-$::collisionDamper)}]
	}
	# left wall condition
	if {$x<$::ballRadius} {
	    set x [expr {$::ballRadius+2}]
	    set vx [expr {-$vx*(1.0-$::collisionDamper)}]
	}
	set ::b($id) [list $x $y $vx $vy $rx $ry]
	canv_moveto $id [expr {int($x+0.5)}] [expr {int($y+0.5)}]
    }
}

proc motioncb {x y} {
    set ::mouseX $x
    set ::mouseY $y
}
proc entercb {} {
    printf "Enter Canvas !!!"
}
proc leavecb {} {
    printf "Leave Canvas !!!"
    set ::mouseX 99999
    set ::mouseY 99999
}

canv_bind <Motion> motioncb
canv_bind <Enter> entercb
canv_bind <Leave> leavecb

every $frameInterval updateStage
every 1000 computeFps

Added nacl/demo/ballsjs.html.





































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
<!DOCTYPE HTML>
<html>
    <head>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            
            #myCanvas {
                border: 1px solid #9C9898;
            }
        </style>
        <script src="kinetic2d-v1.0.3.js">
        </script>
        <script>
            function initBalls(){
                balls = [];
                
                var blue = "#3A5BCD";
                var red = "#EF2B36";
                var yellow = "#FFC636";
                var green = "#02A817";
                
                // G
                balls.push(new Ball(173, 63, 0, 0, blue));
                balls.push(new Ball(158, 53, 0, 0, blue));
                balls.push(new Ball(143, 52, 0, 0, blue));
                balls.push(new Ball(130, 53, 0, 0, blue));
                balls.push(new Ball(117, 58, 0, 0, blue));
                balls.push(new Ball(110, 70, 0, 0, blue));
                balls.push(new Ball(102, 82, 0, 0, blue));
                balls.push(new Ball(104, 96, 0, 0, blue));
                balls.push(new Ball(105, 107, 0, 0, blue));
                balls.push(new Ball(110, 120, 0, 0, blue));
                balls.push(new Ball(124, 130, 0, 0, blue));
                balls.push(new Ball(139, 136, 0, 0, blue));
                balls.push(new Ball(152, 136, 0, 0, blue));
                balls.push(new Ball(166, 136, 0, 0, blue));
                balls.push(new Ball(174, 127, 0, 0, blue));
                balls.push(new Ball(179, 110, 0, 0, blue));
                balls.push(new Ball(166, 109, 0, 0, blue));
                balls.push(new Ball(156, 110, 0, 0, blue));
                
                // O
                balls.push(new Ball(210, 81, 0, 0, red));
                balls.push(new Ball(197, 91, 0, 0, red));
                balls.push(new Ball(196, 103, 0, 0, red));
                balls.push(new Ball(200, 116, 0, 0, red));
                balls.push(new Ball(209, 127, 0, 0, red));
                balls.push(new Ball(223, 130, 0, 0, red));
                balls.push(new Ball(237, 127, 0, 0, red));
                balls.push(new Ball(244, 114, 0, 0, red));
                balls.push(new Ball(242, 98, 0, 0, red));
                balls.push(new Ball(237, 86, 0, 0, red));
                balls.push(new Ball(225, 81, 0, 0, red));
                
                // O
                var oOffset = 67;
                balls.push(new Ball(oOffset + 210, 81, 0, 0, yellow));
                balls.push(new Ball(oOffset + 197, 91, 0, 0, yellow));
                balls.push(new Ball(oOffset + 196, 103, 0, 0, yellow));
                balls.push(new Ball(oOffset + 200, 116, 0, 0, yellow));
                balls.push(new Ball(oOffset + 209, 127, 0, 0, yellow));
                balls.push(new Ball(oOffset + 223, 130, 0, 0, yellow));
                balls.push(new Ball(oOffset + 237, 127, 0, 0, yellow));
                balls.push(new Ball(oOffset + 244, 114, 0, 0, yellow));
                balls.push(new Ball(oOffset + 242, 98, 0, 0, yellow));
                balls.push(new Ball(oOffset + 237, 86, 0, 0, yellow));
                balls.push(new Ball(oOffset + 225, 81, 0, 0, yellow));
                
                // G
                balls.push(new Ball(370, 80, 0, 0, blue));
                balls.push(new Ball(358, 79, 0, 0, blue));
                balls.push(new Ball(346, 79, 0, 0, blue));
                balls.push(new Ball(335, 84, 0, 0, blue));
                balls.push(new Ball(330, 98, 0, 0, blue));
                balls.push(new Ball(334, 111, 0, 0, blue));
                balls.push(new Ball(348, 116, 0, 0, blue));
                balls.push(new Ball(362, 109, 0, 0, blue));
                balls.push(new Ball(362, 94, 0, 0, blue));
                balls.push(new Ball(355, 128, 0, 0, blue));
                balls.push(new Ball(340, 135, 0, 0, blue));
                balls.push(new Ball(327, 142, 0, 0, blue));
                balls.push(new Ball(325, 155, 0, 0, blue));
                balls.push(new Ball(339, 165, 0, 0, blue));
                balls.push(new Ball(352, 166, 0, 0, blue));
                balls.push(new Ball(367, 161, 0, 0, blue));
                balls.push(new Ball(371, 149, 0, 0, blue));
                balls.push(new Ball(366, 137, 0, 0, blue));
                
                // L
                balls.push(new Ball(394, 49, 0, 0, green));
                balls.push(new Ball(381, 50, 0, 0, green));
                balls.push(new Ball(391, 61, 0, 0, green));
                balls.push(new Ball(390, 73, 0, 0, green));
                balls.push(new Ball(392, 89, 0, 0, green));
                balls.push(new Ball(390, 105, 0, 0, green));
                balls.push(new Ball(390, 118, 0, 0, green));
                balls.push(new Ball(388, 128, 0, 0, green));
                balls.push(new Ball(400, 128, 0, 0, green));
                
                // E
                balls.push(new Ball(426, 101, 0, 0, red));
                balls.push(new Ball(436, 98, 0, 0, red));
                balls.push(new Ball(451, 95, 0, 0, red));
                balls.push(new Ball(449, 83, 0, 0, red));
                balls.push(new Ball(443, 78, 0, 0, red));
                balls.push(new Ball(430, 77, 0, 0, red));
                balls.push(new Ball(418, 82, 0, 0, red));
                balls.push(new Ball(414, 93, 0, 0, red));
                balls.push(new Ball(412, 108, 0, 0, red));
                balls.push(new Ball(420, 120, 0, 0, red));
                balls.push(new Ball(430, 127, 0, 0, red));
                balls.push(new Ball(442, 130, 0, 0, red));
                balls.push(new Ball(450, 125, 0, 0, red));
                
                return balls;
            }
            
            function updateBalls(kin, balls){
                var canvas = kin.getCanvas();
                var context = kin.getContext();
                var collisionDamper = 0.3;
                var floorFriction = 0.0005 * kin.getTimeInterval();
                var mouseForceMultiplier = 1 * kin.getTimeInterval();
                var restoreForce = 0.002 * kin.getTimeInterval();
                
                for (var n = 0; n < balls.length; n++) {
                    var ball = balls[n];
                    // set ball position based on velocity
                    ball.y += ball.vy;
                    ball.x += ball.vx;
                    
                    // restore forces
                    if (ball.x > ball.origX) {
                        ball.vx -= restoreForce;
                    }
                    else {
                        ball.vx += restoreForce;
                    }
                    if (ball.y > ball.origY) {
                        ball.vy -= restoreForce;
                    }
                    else {
                        ball.vy += restoreForce;
                    }
                    
                    // mouse forces
                    var mousePos = kin.getMousePos();
                    mouseX = mousePos === null ? 99999 : mousePos.x;
                    mouseY = mousePos === null ? 99999 : mousePos.y;
                    var distX = ball.x - mouseX;
                    var distY = ball.y - mouseY;
                    
                    var radius = Math.sqrt(Math.pow(distX, 2) +
                    Math.pow(distY, 2));
                    
                    var totalDist = Math.abs(distX) + Math.abs(distY);
                    
                    var forceX = (Math.abs(distX) / totalDist) *
                    (1 / radius) *
                    mouseForceMultiplier;
                    var forceY = (Math.abs(distY) / totalDist) *
                    (1 / radius) *
                    mouseForceMultiplier;
                    
                    if (distX > 0) { // mouse is left of ball
                        ball.vx += forceX;
                    }
                    else {
                        ball.vx -= forceX;
                    }
                    if (distY > 0) { // mouse is on top of ball
                        ball.vy += forceY;
                    }
                    else {
                        ball.vy -= forceY;
                    }
                    
                    // floor friction
                    if (ball.vx > 0) {
                        ball.vx -= floorFriction;
                    }
                    else if (ball.vx < 0) {
                        ball.vx += floorFriction;
                    }
                    if (ball.vy > 0) {
                        ball.vy -= floorFriction;
                    }
                    else if (ball.vy < 0) {
                        ball.vy += floorFriction;
                    }
                    
                    // floor condition
                    if (ball.y > (canvas.height - ball.radius)) {
                        ball.y = canvas.height - ball.radius - 2;
                        ball.vy *= -1;
                        ball.vy *= (1 - collisionDamper);
                    }
                    
                    // ceiling condition
                    if (ball.y < (ball.radius)) {
                        ball.y = ball.radius + 2;
                        ball.vy *= -1;
                        ball.vy *= (1 - collisionDamper);
                    }
                    
                    // right wall condition
                    if (ball.x > (canvas.width - ball.radius)) {
                        ball.x = canvas.width - ball.radius - 2;
                        ball.vx *= -1;
                        ball.vx *= (1 - collisionDamper);
                    }
                    
                    // left wall condition
                    if (ball.x < (ball.radius)) {
                        ball.x = ball.radius + 2;
                        ball.vx *= -1;
                        ball.vx *= (1 - collisionDamper);
                    }
                }
            }
            
            function Ball(x, y, vx, vy, color){
                this.x = x;
                this.y = y;
                this.vx = vx;
                this.vy = vy;
                this.color = color;
                this.origX = x;
                this.origY = y;
                this.radius = 10;
            }
            
            window.onload = function(){
                kin = new Kinetic_2d("myCanvas");
                var canvas = kin.getCanvas();
                var context = kin.getContext();
                var mouseX = 99999;
                var mouseY = 99999;
                
                canvas.onmouseout = function(){
                    mouseX = 99999;
                    mouseY = 99999;
                };
                
                var balls = initBalls();
                
                kin.setDrawStage(function(){
                    updateBalls(this, balls);
                    this.clear();
                    var mousePos = kin.getMousePos();
                    mouseX = mousePos === null ? 99999 : mousePos.x;
                    mouseY = mousePos === null ? 99999 : mousePos.y;
                    
                    for (var n = 0; n < balls.length; n++) {
                        var ball = balls[n];
                        context.beginPath();
                        context.arc(ball.x, ball.y, ball.radius, 0, 2 * Math.PI, false);
                        context.fillStyle = ball.color;
                        context.fill();
                    }
                });
                
                kin.startAnimation();
            };
        </script>
    </head>
    <body onmousedown="return false;">
        <canvas id="myCanvas" width="578" height="200">
        </canvas>
    </body>
</html>

Added nacl/demo/c.natcl.





>
>
1
2
printf "I'm c.natcl"

Added nacl/demo/canv.natcl.

































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#
#  crude canvas emulation for NaTcl -- mapping to HTML5 canvas
#
set ::canv_verbose 0

set ::canv_uniq 1
set ::canv_hooked 0
set ::canv_tlist {}
set ::canv_jcnt 0
set ::canv_status_func 0
set ::canv_status_coords 0

# canv_status_coords : 1: some old items moved
# canv_status_func: 0:unchanged 1:new-items-on-top 2:changed

proc canv_addhook {} {
    if {$::canv_hooked} return
    set ::canv_hooked 1
    ::nacl hook canv_hook
}

proc canv_new_items {} {
    return [lrange $::canv_tlist $::canv_jcnt end]
}

proc canv_compile_repaint l {
    set j ""
    set oldprep ""
    foreach i $l {
	set prep $::canv_jprep($i)
	if {[string compare $prep $oldprep]} {
	    set oldprep $prep
	    append j $prep
	}
	append j $::canv_jdraw($i)
    }
    return $j
}

proc canv_hook {} {
    set ::canv_hooked 0
    set repaint 0
    if {$::canv_status_coords} {
	set repaint 1
    }
    if {![info exists ::canv_jcode]} {
	set ::canv_status_func 2
    }
    switch $::canv_status_func {
	0 {
	    # valid, do nothing
	}
	1 {
	    # incremental, append
	    set jnew [canv_compile_repaint [canv_new_items]]
	    append ::canv_jcode $jnew
	    append js "repaint = function(){\n$::canv_jcode\n}\n"
	    if {!$repaint} {
		# old ones didn't move: just draw the new ones
		append js $jnew
	    }
	    set ::canv_jcnt [llength $::canv_tlist]
	}
	2 {
	    # invalid, recompute
	    set ::canv_jcode "context.clearRect(0,0,canvas.width,canvas.height);
\n"
	    append ::canv_jcode [canv_compile_repaint $::canv_tlist]
	    append js "repaint=function(){\n$::canv_jcode\n}\n"
	    set ::canv_jcnt [llength $::canv_tlist]
	    set repaint 1
	}
    }
    set l {}
    foreach i [array names ::canv_moved] {
	#append js "canvcoords\[$i\]=\[[join $::canv_coords($i) ,]\];\n"
	lappend l "$i,\[[join $::canv_coords($i) ,]\]"
    }
    append js "updateCoords(\[[join $l ,]\]);\n"
    if {$repaint} {
	append js "repaint();\n"
    }
    set ::canv_status_func 0
    set ::canv_status_coords 0
    array unset ::canv_moved

    if {[info exists js]} {
	if {$::canv_verbose} {
	    printf "CANV_HOOK emits:\n$js\n"
	}
	nacl js $js
    }
}

proc lremove {l e} {
     set out {}
    foreach x $l {
	if {$x==$e} continue
	lappend out $x
    }
    return $out
}

proc canv_delete id { 
    if {$id=="all"} {
	array unset ::canv_moved
	array unset ::canv_coords
	array unset ::canv_jprep
	array unset ::canv_jdraw
	set ::canv_tlist {}
	set ::canv_status_func 2
    } else {
	catch {unset ::canv_moved($id)}
	unset ::canv_coords($id)
	unset ::canv_jprep($id)
	unset ::canv_jdraw($id)
	set ::canv_tlist [lremove $::canv_tlist $id]
	set ::canv_status_func 2
    }
    canv_addhook
}

proc canv_find tag {
    if {$tag!="all"} {
	error "Unsupported tag '$tag'"
    }
    return $::canv_tlist
}

proc canv_create {ty args} {
    set id $::canv_uniq
    incr ::canv_uniq
    lappend ::canv_tlist $id
    set att(-fill) "#FFFFFF"
    set att(-outline) "#000000"
    switch -exact -- $ty {
	rect {
	    foreach {x1 y1 x2 y2} $args break
	    set ::canv_coords($id) [list $x1 $y1 [expr {$x2-$x1}] [expr {$y2-$y1}]]
	    array set att [lrange $args 4 end]
	    set prep ""
	    set draw ""
	    if {$att(-outline)!=""} {append prep "context.strokeStyle='$att(-outline)';";append draw "context.stroke();"}
	    if {$att(-fill)!=""} {append prep "context.fillStyle='$att(-fill)';";append draw "context.fill();"}
	    set ::canv_jprep($id) $prep
	    set ::canv_jdraw($id) "context.beginPath();context.rect(canvcoords\[$id\]\[0\],canvcoords\[$id\]\[1\],canvcoords\[$id\]\[2\],canvcoords\[$id\]\[3\]);$draw\n"
	}
	circle {
	    set ::canv_coords($id) [lrange $args 0 2]
	    array set att [lrange $args 3 end]
	    set prep ""
	    set draw ""
	    if {$att(-outline)!=""} {append prep "context.strokeStyle='$att(-outline)';";append draw "context.stroke();"}
	    if {$att(-fill)!=""} {append prep "context.fillStyle='$att(-fill)';";append draw "context.fill();"}
	    set ::canv_jprep($id) $prep
	    set ::canv_jdraw($id) "context.beginPath();context.arc(canvcoords\[$id\]\[0\],canvcoords\[$id\]\[1\],canvcoords\[$id\]\[2\],0,2*Math.PI,0);$draw\n"
	}
	default {error "Unknown canv item type '$ty'"}
    }
    set ::canv_type($id) $ty
    if {!$::canv_status_func} {
	# incremental
	set ::canv_status_func 1
    }
    set ::canv_moved($id) 1
    canv_addhook
    return $id
}

proc canv_move {id dx dy} {
    foreach {x y} $::canv_coords($id) break
    incr x $dx
    incr y $dy
    set ::canv_coords($id) [concat [list $x $y] [lrange $::canv_coords($id) 2 end]]
    if {![info exists ::canv_moved($id)]} {
	set ::canv_moved($id) 1
	set ::canv_status_coords 1
    }
}

proc canv_moveto {id x y} {
    set ::canv_coords($id) [concat [list $x $y] [lrange $::canv_coords($id) 2 end]]
    if {![info exists ::canv_moved($id)]} {
	set ::canv_moved($id) 1
	set ::canv_status_coords 1
    }
}

proc canv_bind {evt cb} {
    switch -exact -- $evt {
	<Motion> {
	    nacl js "canvas.onmousemove = function (evt) {
			tclDo([::nacl jsquote "$cb "]+(evt.clientX-canvas.offsetLeft)+' '+(evt.clientY-canvas.offsetTop));
		}"
	}
	<Leave> {
	    nacl js "canvas.onmouseout = function (evt) {
			tclDo([::nacl jsquote "$cb "]);
		}"
	}
	<Enter> {
	    nacl js "canvas.onmouseover = function (evt) {
			tclDo([::nacl jsquote "$cb "]);
		}"
	}
	default {error "Unsupported event '$evt'"}
    }
}

Added nacl/demo/index.html.

































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!DOCTYPE html>
<html>
  <!--
  Copyright (c) 2010 The Native Client Authors. All rights reserved.
  Use of this source code is governed by a BSD-style license that can be
  found in the LICENSE file.
  -->
<head>
  <title>Tcl in Nacl</title>

  <script type="text/javascript">
    tclModule = null;  // Global application object.
    statusText = 'NO-STATUS';

	function nil() {};

    // Handle a message coming from the NaCl module.
    function handleMessage(message_event) {
      alert("Result: "+message_event.data);
    }



    function moduleDidLoad() {
      tclModule = document.getElementById('tcl');
	  tclModule.addEventListener('message', handleMessage, false);
      updateStatus('SUCCESS');
    }



    // If the page loads before the Native Client module loads, then set the
    // status message indicating that the module is still loading.  Otherwise,
    // do not change the status message.
    function pageDidLoad() {
      if (tclModule == null) {
        updateStatus('LOADING...');
      } else {
        // It's possible that the Native Client module onload event fired
        // before the page's onload event.  In this case, the status message
        // will reflect 'SUCCESS', but won't be displayed.  This call will
        // display the current message.
        updateStatus();
      }
    }

    function doeval() {
      try {
        tclModule.postMessage("eval:"+this.the_form.input_id.value);
      } catch(e) {
        alert(e.message);
      }
    }

    // Set the global status message.  If the element with id 'statusField'
    // exists, then set its HTML to the status message as well.
    // opt_message The message test.  If this is null or undefined, then
    //     attempt to set the element with id 'statusField' to the value of
    //     |statusText|.
    function updateStatus(opt_message) {
      if (opt_message)
        statusText = opt_message;
      var statusField = document.getElementById('status_field');
      if (statusField) {
        statusField.innerHTML = statusText;
      }
    }
  </script>
</head>
<body onload="pageDidLoad()">

<h1>Native Client Tcl Module</h1>
<p>
  <form name="the_form" action="javascript:doeval()">
  <input type="text" id="input_id" name="inputbox" value="list a b c"><p>
  <input type="button" value="Call eval()" onclick="doeval()">
  </form>

  <!-- Load the published .nexe.  This includes the 'src' attribute which
  shows how to load multi-architecture modules.  Each entry in the "nexes"
  object in the  .nmf manifest file is a key-value pair: the key is the runtime
  ('x86-32', 'x86-64', etc.); the value is a URL for the desired NaCl module.
  To load the debug versions of your .nexes, set the 'src' attribute to the
  _dbg.nmf version of the manifest file.

  Note that the <EMBED> element is wrapped inside a <DIV>, which has a 'load'
  event listener attached.  This method is used instead of attaching the 'load'
  event listener directly to the <EMBED> element to ensure that the listener
  is active before the NaCl module 'load' event fires.
  -->
  <div id="listener">
    <script type="text/javascript">
      document.getElementById('listener')
          .addEventListener('load', moduleDidLoad, true);
    </script>

    <embed name="nacl_module"
           id="tcl"
           width=0 height=0
           src="tcl.nmf"
           type="application/x-nacl"/>
  </div>

</p>

<p>If the module is working correctly, a click on the "Call eval()" button
  should open a popup dialog containing the Tcl result as its value.</p>

<h2>Status</h2>
<div id="status_field">NO-STATUS</div>
</body>
</html>

Added nacl/demo/inter.html.















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="loader.js"></script>
  </head>
  <body>
    <div id="listener">
      <script type="text/javascript">
      	document.getElementById('listener')
        .addEventListener('load', moduleDidLoad, true);
      </script>

      <textarea id="txt" cols="160" rows="40"></textarea>
      
      <embed
	 name='nacl_module'
	 id='tcl'
	 width=0 height=0
	 src='../tcl.nmf'
	 type='application/x-nacl'
	 verbose=0
	 source='inter.natcl'>

        <h2>Status</h2>
        <div id="modstatus">NO-STATUS</div>
      </embed>
    </div>

    <p style="font-size : smaller;">
      To run this demo, you need
      <ul style="font-size : smaller;">
        <li> An x86-family processor</li>
        <li> Chrome 15 or higher</li>
        <li> Enabled "Native Client" item in about:flags</li>
	<li> if everything else fails, try the Nacl demos at <a href="http://code.google.com/chrome/nativeclient/docs/examples.html">http://code.google.com/chrome/nativeclient/docs/examples.html</a></li>
      </ul>
    </p>
  </body>
</html>

Added nacl/demo/inter.natcl.









































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# sourced by inter.html demo

::nacl::js {
    t0=document.getElementById('txt');
    function bot(w) {
        len=w.value.length+1;
	w.setSelectionRange(len,len);
   	w.focus();     
    }
    t0.value = "# Type Tcl code in there\n";
    t0.onkeydown=function(event) {
	if (event.which==13) {
	    bot(t0);
	    tclDoCoro("swallow \""+tclEsc(t0.value.replace(/.*\n/g,''))+"\"");
	    bot(t0);
	}
	return true;
    }
    bot(t0);
}

proc swallow s {
    append ::accu $s \n
    if {[info complete $::accu]} {
	set x $::accu
	unset ::accu
	set res [uplevel #0 $x]
	::nacl::js "t0.value+=[::nacl::jsquote $res\n];bot(t0);"
    }
}

proc ::nacl::bgerror s {
    ::nacl::js "t0.value+=[::nacl::jsquote ###$s\n];bot(t0);"
}

source rowland.natcl

Added nacl/demo/kinetic2d-v1.0.3.js.











































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/**
 * KineticJS 2d JavaScript Library v1.0.3
 * http://www.kineticjs.com/
 * Copyright 2011, Eric Rowell
 * Licensed under the MIT or GPL Version 2 licenses.
 * Date: September 2 2011
 *
 * Copyright (C) 2011 by Eric Rowell
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
var Kinetic_2d = function(canvasId) {
    this.canvas = document.getElementById(canvasId);
    this.context = this.canvas.getContext("2d");
    this.drawStage = undefined;
    this.listening = false;

    // desktop flags
    this.mousePos = null;
    this._mouseDown = false;
    this._mouseUp = false;
    this._mouseOver = false;
    this._mouseMove = false;

    // mobile flags
    this.touchPos = null;
    this._touchStart = false;
    this._touchMove = false;
    this._touchEnd = false;

    // Region Events
    this._currentRegion = null;
    this._regionIndex = 0;
    this._lastRegionIndex = -1;
    this._mouseOverRegionIndex = -1;

    // Animation
    this.t = 0;
    this.timeInterval = 0;
    this.startTime = 0;
    this.lastTime = 0;
    this.frame = 0;
    this.animating = false;
    
    this.mouseDown = false;

    // provided by Paul Irish
    window.requestAnimFrame = (function(callback) {
        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function(callback) {
            window.setTimeout(callback, 1000 / 40);
        };

    })();
};

// ======================================= GENERAL
// =======================================

Kinetic_2d.prototype.getContext = function() {
    return this.context;
};

Kinetic_2d.prototype.getCanvas = function() {
    return this.canvas;
};

Kinetic_2d.prototype.clear = function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};

Kinetic_2d.prototype.getCanvasPos = function() {
    var obj = this.getCanvas();
    var top = 0;
    var left = 0;
    while(obj.tagName != "BODY") {
        top += obj.offsetTop;
        left += obj.offsetLeft;
        obj = obj.offsetParent;
    }
    return {
        top : top,
        left : left
    };
};

Kinetic_2d.prototype._drawStage = function() {
    if(this.drawStage !== undefined) {
        this.drawStage();

        // desktop flags
        this._mouseOver = false;
        this._mouseMove = false;
        this._mouseDown = false;
        this._mouseUp = false;

        // mobile touch flags
        this._touchStart = false;
        this._touchMove = false;
        this._touchEnd = false;
    }
};

Kinetic_2d.prototype.setDrawStage = function(func) {
    this.drawStage = func;
    this.listen();
};

// ======================================= CANVAS EVENTS

Kinetic_2d.prototype.handleEvent = function(evt) {
    if(!evt) {
        evt = window.event;
    }

    this.setMousePosition(evt);
    this.setTouchPosition(evt);
    this._regionIndex = 0;

    if(!this.animating) {
        this._drawStage();
    }
};

Kinetic_2d.prototype.listen = function() {
    var that = this;
    this._drawStage();

    // desktop events
    this.canvas.addEventListener("mousedown", function(evt) {
        that._mouseDown = true;
        that.mouseDown = true;
        that.handleEvent(evt);
    }, false);

    this.canvas.addEventListener("mousemove", function(evt) {
        that.handleEvent(evt);
    }, false);

    this.canvas.addEventListener("mouseup", function(evt) {
        that._mouseUp = true;
        that.mouseDown = false;
        that.handleEvent(evt);
    }, false);

    this.canvas.addEventListener("mouseover", function(evt) {
        that.handleEvent(evt);
    }, false);

    this.canvas.addEventListener("mouseout", function(evt) {
        that.mousePos = null;
    }, false);

    // mobile events
    this.canvas.addEventListener("touchstart", function(evt) {
        evt.preventDefault();
        that._touchStart = true;
        that.handleEvent(evt);
    }, false);

    this.canvas.addEventListener("touchmove", function(evt) {
        evt.preventDefault();
        that.handleEvent(evt);
    }, false);

    this.canvas.addEventListener("touchend", function(evt) {
        evt.preventDefault();
        that._touchEnd = true;
        that.handleEvent(evt);
    }, false);

};

Kinetic_2d.prototype.getMousePos = function(evt) {
    return this.mousePos;
};

Kinetic_2d.prototype.getTouchPos = function(evt) {
    return this.touchPos;
};

Kinetic_2d.prototype.setMousePosition = function(evt) {
    var mouseX = evt.clientX - this.getCanvasPos().left + window.pageXOffset;
    var mouseY = evt.clientY - this.getCanvasPos().top + window.pageYOffset;
    this.mousePos = {
        x : mouseX,
        y : mouseY
    };
};

Kinetic_2d.prototype.setTouchPosition = function(evt) {
    if(evt.touches !== undefined && evt.touches.length == 1) { // Only deal with
        // one finger
        var touch = evt.touches[0];
        // Get the information for finger #1
        var touchX = touch.pageX - this.getCanvasPos().left + window.pageXOffset;
        var touchY = touch.pageY - this.getCanvasPos().top + window.pageYOffset;

        this.touchPos = {
            x : touchX,
            y : touchY
        };
    }
};

Kinetic_2d.prototype.isMouseDown = function() {
    return this.mouseDown;  
};

// ======================================= REGION EVENTS

Kinetic_2d.prototype.beginRegion = function() {
    this._currentRegion = {};
    this._regionIndex++;
};

Kinetic_2d.prototype.addRegionEventListener = function(type, func) {
    var event = (type.indexOf('touch') == -1) ? 'on' + type : type;
    this._currentRegion[event] = func;
};

Kinetic_2d.prototype.closeRegion = function() {
    var pos = this.touchPos || this.mousePos;

    if(pos !== null && this.context.isPointInPath(pos.x, pos.y)) {
        if(this._lastRegionIndex != this._regionIndex) {
            this._lastRegionIndex = this._regionIndex;
        }

        // handle onmousedown
        if(this._mouseDown && this._currentRegion.onmousedown !== undefined) {
            this._currentRegion.onmousedown();
            this._mouseDown = false;
        }

        // handle onmouseup
        else if(this._mouseUp && this._currentRegion.onmouseup !== undefined) {
            this._currentRegion.onmouseup();
            this._mouseUp = false;
        }

        // handle onmouseover
        else if(!this._mouseOver && this._regionIndex != this._mouseOverRegionIndex && this._currentRegion.onmouseover !== undefined) {
            this._currentRegion.onmouseover();
            this._mouseOver = true;
            this._mouseOverRegionIndex = this._regionIndex;
        }

        // handle onmousemove
        else if(!this._mouseMove && this._currentRegion.onmousemove !== undefined) {
            this._currentRegion.onmousemove();
            this._mouseMove = true;
        }

        // handle touchstart
        if(this._touchStart && this._currentRegion._touchStart !== undefined) {
            this._currentRegion._touchStart();
            this._touchStart = false;
        }

        // handle touchend
        if(this._touchEnd && this._currentRegion._touchEnd !== undefined) {
            this._currentRegion._touchEnd();
            this._touchEnd = false;
        }

        // handle touchmove
        if(!this._touchMove && this._currentRegion._touchMove !== undefined) {
            this._currentRegion._touchMove();
            this._touchMove = true;
        }

    }
    else if(this._regionIndex == this._lastRegionIndex) {
        this._lastRegionIndex = -1;
        this._mouseOverRegionIndex = -1;

        // handle mouseout condition
        if(this._currentRegion.onmouseout !== undefined) {
            this._currentRegion.onmouseout();
        }
    }
};

// ======================================= ANIMATION
// =======================================

Kinetic_2d.prototype.isAnimating = function() {
    return this.animating;
};

Kinetic_2d.prototype.getFrame = function() {
    return this.frame;
};

Kinetic_2d.prototype.startAnimation = function() {
    this.animating = true;
    var date = new Date();
    this.startTime = date.getTime();
    this.lastTime = this.startTime;

    this._drawStage();

    this.animationLoop();
};

Kinetic_2d.prototype.stopAnimation = function() {
    this.animating = false;
};

Kinetic_2d.prototype.getTimeInterval = function() {
    return this.timeInterval;
};

Kinetic_2d.prototype.getTime = function() {
    return this.t;
};

Kinetic_2d.prototype.getFps = function() {
    return this.timeInterval > 0 ? 1000 / this.timeInterval : 0;
};

Kinetic_2d.prototype.animationLoop = function() {
    var that = this;

    this.frame++;
    var date = new Date();
    var thisTime = date.getTime();
    this.timeInterval = thisTime - this.lastTime;
    this.t += this.timeInterval;
    this.lastTime = thisTime;

    this._drawStage();

    if(this.animating) {
        requestAnimFrame(function() {
            that.animationLoop();
        });

    }
};

Added nacl/demo/loader.js.

















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// NaTcl -- JS glue
var tclModule = null;  // our singleton Tcl interp

function printf()
{
    // I like debugging to stderr instead of console.log,
    // because when things go wrong, the JS console is not
    // alays reachable.
    tclModule.postMessage('eval:printf '+Array.prototype.slice.call(arguments).join(' '));
}

// --- tclDo is the main JS-Tcl trampoline.
//
//  Its job is to pass a Tcl string to [eval] (through naclwrap, see
//  init.nacl), and then take back the result as JS and eval() it.
//  It also detects errors in the latter eval() and pipes them back
//  to [bgerror].

function tclEsc(text) {
    return text.replace(/([\[\]\\$""{}])/g,'\\$1');
}

function tclDo(s) {
    //console.log("TclDo: "+s);
    tclModule.postMessage("eval:::nacl::wrap {" + s + "}");
}
function tclDoCoro(s) {
    tclModule.postMessage("eval:coroutine ::main_coro ::nacl::wrap \"" + tclEsc(s) + "\"");
}
function tcl()
{
	tclDo(Array.prototype.slice.call(arguments).join(" "));
}

// Handle a message coming from the NaCl module.
function handleMessage(message_event) {
    try {
		
		t = message_event.data;
		//console.log("JSdo:"+t);
		window.eval(t);
    } catch(err) {
		//printf("JS-err:"+err);
		alert("ERROR:"+err);
    }
}

function serialT (thing) {
    alert("serialT " + thing.type + " " + thing.toString());
    var result = '{';
    switch (thing.type) {

    case 'string':
        return tclEsc(thing);
        break;

    case 'array':
        for (var i=0; i < thing.length(); i++) {
            result = result + " " + serialT(thing[i]);
        }
        result = result + '}';
        break;

    case 'object':
        for (var prop in thing) {
            result = result + " " + serialT(prop) + " " + serialT(thing[prop]);
        }
        result = result + '}';
        break;

    case 'function':
        result = thing.toString();
        break;

    default:
        return undefined;
        break;
    }
    return result;
}

function callback(to,js) {
    alert("callback " + to + " " + js);
    try {
	tclDo(to + " " + serialT(eval(js)));
    } catch (err) {
        alert("JS-error " + err);
	//printf("JS-err:", err);
	setTimeout('tcl("::nacl::bgerror,"'+ err + ',' + js + ')',0);
    }
}

// --- tclsource starts an XHR, and calls the given 'tcb' (Tcl
// --- Callback) on completion. A catchable Tcl-level error is raised
// --- in case of not-200. Used by [source].
function tclsource(url,tcb) {
    //printf('tclsource:'+url);
    xs = new XMLHttpRequest();
    xs.open("GET",url,true);
    xs.send(null);
    xs.onreadystatechange = function() {
	//printf("XHR-source:"+xs.readyState);
	if (xs.readyState==4)
        {
            if (xs.status==200) {
                tclDo(tcb+" {"+xs.responseText+"}");
            } else {
                tclDo(tcb+" {error \"Can't source -- "+xs.statusText+"\"}");
            }
        }
    };
}

// traverse - apply function to subtree of dom returning object
function traverse(fn)
{
    var result;
    var target;
    if (arguments.length() > 1) {
        target = arguments[1];
    } else {
        target = document;
    }

    result[target]=fn.apply(target);

    for (var i=0; i<target.childNodes.length; i++) {
        var child = target.childNodes[i];
        var traversal = traverse(fn, child);
        for (var prop in traversal) {
            result[prop] = traversal[prop];
        }
    }

    return result;
}

// ---------- GUI and standard NaCl-loading machinery --------

function moduleDidLoad() {
    tclModule = document.getElementById('tcl');
	tclModule.addEventListener('message', handleMessage, false);
    // tcl('lappend', '::JS', "alert('ARGV:[join $::argv]')");
    tcl('eval', 'coroutine', '::main_coro', 'source', '[dict get $::argv source]');
}

// runTclScripts - collect all <script> elements with type text/tcl
// Pass them to the Tcl header given in 'where' (or uplevel)
function runTclScripts(where) {
    if (where == undefined) {
        where = "uplevel #0";
    }

    var scripts = document.getElementsByTagName('script');
    var script = "";
    for (var i = 0; i < scripts.length; i++) {
        if (scripts[i].getAttribute('type') == 'text/tcl') {
            if (scripts[i].hasAttribute('src')) {
                script = script + '\nsource ' + scripts[i].getAttribute('src');
            }
            var s = scripts[i].innerHTML;
            if (s != "") {
                script = script + '\n' + s;
            }
        }
    }
    tclDo(where + " {" + tclEsc(script)+ "}");
}

Added nacl/demo/rowland.natcl.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
proc tcl::mathfunc::gcd {a b} { 
     while {$b} {set b [expr {$a % [set a $b]}]} 
     return $a 
}
# Rowland's: compute a(n)-a(n-1) where a(1)=7 and 
#   a(n) = a(n – 1) + gcd(n, a(n – 1)) 

proc rowland m {
    set a 7   
    set n 1 
    set out {}
    while {$n<=$m} { 
	incr n 
	set b $a 
	set a [expr {$b+gcd($n,$b)}] 
	set p [expr {$a-$b}] 
	if {$p>1} {lappend out $p} 
    }
    return $out
}

Added nacl/init.natcl.













































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#------ Standard NaTcl preamble

namespace eval ::nacl {
    variable verbose 0

    # core JS/Tcl interaction
    proc jsquote s {
        regsub -all {[''\\]} $s {\\&} s
        regsub -all \n $s {'+"\\n"+'} s
        return '${s}'
    }

    # hook - append Tcl hooks to be evaluated per ???
    variable hooks {}
    proc hook {args} {
        variable hooks
        lappend hooks {*}$args
    }

    # js - append javascript to be evaluated in nacl
    # as a result of currently evaluating Tcl script
    variable JS {}	;# accumulation of javascript to evaluate
    proc js {args} {
        variable JS
        append JS [join $args \;\n] \n
    }

    variable defaults {}
    proc opts {args} {
	set type ""
	if {[llength $args]%2} {
	    set args [lassign $args type]
	}

	set opts {}
	variable defaults
	if {$type ne "" && [dict exists $defaults $type]} {
	    set args [list {*}[dict get $defaults $type] {*}$args]
	}
	dict for {n v} $args {
	    if {$v eq ""} {
		set v "''"	;# ensure we don't send naked names
	    }
	    lappend opts "$n:$v"
	}

	if {$opts eq ""} {
	    return ""
	} else {
	    return "\{[join $opts ,]\}"
	}
    }

    proc alert {args} {
        js "alert([::nacl::jsquote [join $args]])"
    }

    proc bgerror {args} {
        printf "### BGERROR: [join $args]\n# [info errorstack]"
        js "alert([::nacl::jsquote [join $args]])"
    }

    proc wrap {s} {
        variable hooks
        if {[catch {
            uplevel #0 $s
            foreach x $hooks {uplevel #0 $x}
        } err eo]} {
            bgerror "$err ($eo)"
        }

        variable JS; set toJS $JS; set JS ""
        return $toJS
    }

    # evall - evaluate a list as a command
    # returns javascript to evaluate in nacl
    proc evall {args} {
        variable hooks
        if {[catch {
            uplevel #0 $args
            foreach x $hooks {uplevel #0 $x}
        } err eo]} {
            bgerror "$err ($eo)"
        }

        variable JS; set toJS $JS; set JS ""
        return $toJS
    }

    # start - natcl module has been loaded with the following args
    proc start {args} {
        set defaults {
            verbose 0
            script script
            toplevel toplevel
        }
        set ::argv [dict merge $defaults $args]
        if {[dict exists $args verbose]} {
            variable verbose [dict get $args verbose]
        }
    }

    namespace export -clear *
    namespace ensemble create -subcommands {}
}

namespace eval ::dom {
    # Delayed DOM-setting through the tclDo() trampoline
    proc put {element inner} {
        nacl js "$element.innerHTML=[nacl jsquote $inner]"
    }

    # get - get element's innerHTML and pass it to callback
    proc get {element args} {
        if {![llength $args]} {
            set args [info coroutine]
        }
        nacl js "tcl('[join $args "', '"]', '{'+$element.innerHTML+'}')"
    }

    namespace export -clear *
    namespace ensemble create -subcommands {}
}

# Coro-based [source] necessary for bootstrapping
proc ::source {url} {
    nacl js "tclsource([::nacl::jsquote $url],[::nacl::jsquote [info coroutine]])"
    set x [yield]
    uplevel #0 $x
}

# Async [after] using JS's setTimeout()
proc ::after {ms script} {
    nacl js "setTimeout(function(){tclDo([::nacl::jsquote $script]);},$ms)"
}

# Async [every] using JS's setInterval()
proc ::every {ms script} {
    nacl js "setInterval(function(){tclDo([::nacl::jsquote $script]);},$ms)"
}

# Delayed DOM-setting through the tclDo() trampoline
proc ::domset {element inner} {
    nacl js "$element.innerHTML=[::nacl::jsquote $inner]"
}

proc tclInit {} {
        printf "### tclInit called"
}

Added nacl/naclMain.c.













































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
#include <stdlib.h>
#include <string.h>
//#include <ppapi/c/dev/ppb_var_deprecated.h>
//#include <ppapi/c/dev/ppp_class_deprecated.h>

#include <ppapi/c/pp_errors.h>
#include <ppapi/c/pp_module.h>
#include <ppapi/c/pp_var.h>

#include <ppapi/c/ppb.h>
#include <ppapi/c/ppb_instance.h>
#include <ppapi/c/ppb_messaging.h>
#include <ppapi/c/ppb_var.h>

#include <ppapi/c/ppp.h>
#include <ppapi/c/ppp_instance.h>
#include <ppapi/c/ppp_messaging.h>

struct MessageInfo {
  PP_Instance instance;
  struct PP_Var message;
};

static struct PPB_Messaging* messaging_interface = NULL;
static struct PPB_Var* var_interface = NULL;
static PP_Module module_id = 0;

#include <errno.h>
#include "tcl.h"
#include "tclInt.h"

static Tcl_Interp *interp = NULL;
static int pid = 0;
static int verbose = 0;

const char *init_tcl_contents =
"set ::tcl_library {/}\n"
# include "init.tcl.c"
  ;

static int PrintfObjCmd(
			ClientData clientData,
			Tcl_Interp *interp,
			int objc,
			Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "string");
	return TCL_ERROR;
    }
    printf("NaTcl(%d): %s\n", pid, Tcl_GetString(objv[1]));
    return TCL_OK;
}


static Tcl_Interp *NewTcl(void)
{
  Tcl_Interp *ii;

  printf("DBUG:TclInitSubsystems\n");
  TclInitSubsystems();
  printf("DBUG:TclpSetInitialEncodings\n");
  TclpSetInitialEncodings();

  {
    volatile int x;

    x=0;
    if (x) printf("NaTcl(%d): BUSYLOOP : break out by resetting the var (set $eax=0)\n",pid);
    while(x) {}
  }
  printf("DBUG:CreateInterp\n");
  ii=Tcl_CreateInterp();
  if (!ii) {
    printf("NaTcl(%d): Tcl CreateInterp Failed !!!\n",pid);
    return NULL;
  }
  printf("DBUG:Tcl_Init2\n");
  if (Tcl_Eval(ii,init_tcl_contents)!=TCL_OK) {
    printf("NaTcl(%d): Tcl Init Failed: %s !!!\n",pid,Tcl_GetStringResult(ii));
    return NULL;
  }
  Tcl_CreateObjCommand(ii,"printf",PrintfObjCmd,NULL,NULL);
  Tcl_LinkVar(ii, "::nacl::verbose", (char *)&verbose, TCL_LINK_INT);
  TclSetPreInitScript("proc ::tclInit {} {}");
  return ii;
}

static const char *EvalTcl(const char *s)
{
  if (!interp) return "No Tcl Interp!!!";
  Tcl_Eval(interp,s);
  return Tcl_GetStringResult(interp);
}


/**
 * Returns a mutable C string contained in the @a var or NULL if @a var is not
 * string.  This makes a copy of the string in the @ var and adds a NULL
 * terminator.  Note that VarToUtf8() does not guarantee the NULL terminator on
 * the returned string.  See the comments for VatToUtf8() in ppapi/c/ppb_var.h
 * for more info.  The caller is responsible for freeing the returned memory.
 * @param[in] var PP_Var containing string.
 * @return a C string representation of @a var.
 * @note The caller is responsible for freeing the returned string.
 */
static char* VarToCStr(struct PP_Var var) {
  uint32_t len = 0;
  if (var_interface != NULL) {
    const char* var_c_str = var_interface->VarToUtf8(var, &len);
    if (len > 0) {
      char* c_str = (char*)malloc(len + 1);
      memcpy(c_str, var_c_str, len);
      c_str[len] = 0;
      return c_str;
    }
  }
  return NULL;
}

/**
 * Creates new string PP_Var from C string. The resulting object will be a
 * refcounted string object. It will be AddRef()ed for the caller. When the
 * caller is done with it, it should be Release()d.
 * @param[in] str C string to be converted to PP_Var
 * @return PP_Var containing string.
 */
static struct PP_Var StrToVar(const char* str) {
  if (NULL != var_interface)
    return var_interface->VarFromUtf8(module_id, str, strlen(str));
  return PP_MakeUndefined();
}

/**
 * A simple function that always returns 42.
 * @return always returns the integer 42
static struct PP_Var FortyTwo() {
  return PP_MakeInt32(42);
}
 */

/**
 * Called when the NaCl module is instantiated on the web page. The identifier
 * of the new instance will be passed in as the first argument (this value is
 * generated by the browser and is an opaque handle).  This is called for each
 * instantiation of the NaCl module, which is each time the <embed> tag for
 * this module is encountered.
 *
 * If this function reports a failure (by returning @a PP_FALSE), the NaCl
 * module will be deleted and DidDestroy will be called.
 * @param[in] instance The identifier of the new instance representing this
 *     NaCl module.
 * @param[in] argc The number of arguments contained in @a argn and @a argv.
 * @param[in] argn An array of argument names.  These argument names are
 *     supplied in the <embed> tag, for example:
 *       <embed id="nacl_module" dimensions="2">
 *     will produce two arguments, one named "id" and one named "dimensions".
 * @param[in] argv An array of argument values.  These are the values of the
 *     arguments listed in the <embed> tag.  In the above example, there will
 *     be two elements in this array, "nacl_module" and "2".  The indices of
 *     these values match the indices of the corresponding names in @a argn.
 * @return @a PP_TRUE on success.
 */
static PP_Bool Instance_DidCreate(PP_Instance instance,
                                  uint32_t argc,
                                  const char* argn[],
                                  const char* argv[]) {
    printf("NaTcl(%d): DBUG: Instance_DidCreate %x\n", getpid(), (unsigned int)instance);
  int i;
  Tcl_Obj *args[1+argc+argc];

  args[0] = Tcl_NewStringObj("::nacl::start",-1);
  Tcl_IncrRefCount(args[0]);

  for (i = 0; i < argc; i++) {
      printf("NaTcl(%d): DBUG: Instance_DidCreate arg %s=%s\n", getpid(), argn[i], argv[i]);

      args[(2*i)+1] = Tcl_NewStringObj(argn[i], -1);
      Tcl_IncrRefCount(args[(2*i)+1]);

      args[(2*i)+2] = Tcl_NewStringObj(argv[i], -1);
      Tcl_IncrRefCount(args[(2*i)+2]);
  }

  Tcl_EvalObjv(interp, argc*2+1, args, 0);
  for (i = 0; i < (2*argc)+1; i++) {
      Tcl_DecrRefCount(args[i]);
  }
  printf("NaTcl(%d): Instance_DidCreate result: %s\n", pid, Tcl_GetStringResult(interp));

  return PP_TRUE;
}

/**
 * Called when the NaCl module is destroyed. This will always be called,
 * even if DidCreate returned failure. This routine should deallocate any data
 * associated with the instance.
 * @param[in] instance The identifier of the instance representing this NaCl
 *     module.
 */
static void Instance_DidDestroy(PP_Instance instance) {
}

/**
 * Called when the position, the size, or the clip rect of the element in the
 * browser that corresponds to this NaCl module has changed.
 * @param[in] instance The identifier of the instance representing this NaCl
 *     module.
 * @param[in] position The location on the page of this NaCl module. This is
 *     relative to the top left corner of the viewport, which changes as the
 *     page is scrolled.
 * @param[in] clip The visible region of the NaCl module. This is relative to
 *     the top left of the plugin's coordinate system (not the page).  If the
 *     plugin is invisible, @a clip will be (0, 0, 0, 0).
 */
static void Instance_DidChangeView(PP_Instance instance,
                                   const struct PP_Rect* position,
                                   const struct PP_Rect* clip) {
}

/**
 * Notification that the given NaCl module has gained or lost focus.
 * Having focus means that keyboard events will be sent to the NaCl module
 * represented by @a instance. A NaCl module's default condition is that it
 * will not have focus.
 *
 * Note: clicks on NaCl modules will give focus only if you handle the
 * click event. You signal if you handled it by returning @a true from
 * HandleInputEvent. Otherwise the browser will bubble the event and give
 * focus to the element on the page that actually did end up consuming it.
 * If you're not getting focus, check to make sure you're returning true from
 * the mouse click in HandleInputEvent.
 * @param[in] instance The identifier of the instance representing this NaCl
 *     module.
 * @param[in] has_focus Indicates whether this NaCl module gained or lost
 *     event focus.
 */
static void Instance_DidChangeFocus(PP_Instance instance,
                                    PP_Bool has_focus) {
}

/**
 * Handler that gets called after a full-frame module is instantiated based on
 * registered MIME types.  This function is not called on NaCl modules.  This
 * function is essentially a place-holder for the required function pointer in
 * the PPP_Instance structure.
 * @param[in] instance The identifier of the instance representing this NaCl
 *     module.
 * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance.
 * @return PP_FALSE.
 */
static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
                                           PP_Resource url_loader) {
  /* NaCl modules do not need to handle the document load function. */
  return PP_FALSE;
}

/**
 * Handler for messages coming in from the browser via postMessage.  Extracts
 * the method call from @a message, parses it for method name and value, then
 * calls the appropriate function.
 * @param[in] instance The instance ID.
 * @param[in] message The contents, copied by value, of the message sent from
 *     browser via postMessage.
 */
void Messaging_HandleMessage(PP_Instance instance, struct PP_Var var_message) {

  struct PP_Var v = PP_MakeUndefined();
  const char *message = NULL;

  if (var_message.type != PP_VARTYPE_STRING) {
    /* Only handle string messages */
	v = StrToVar("ERROR:Method+Arg from Javascript is not a string!");
    goto post;
  }
  message = VarToCStr(var_message);
  if (message == NULL) {
	v = StrToVar("ERROR:Method+Arg from Javascript is empty!");
    goto post;
  }
  if (strncmp(message, "eval:", 5) == 0) {
	const char* str = message+5;
	if (verbose) {
	  printf("NaTcl(%d): EVAL of: %s\n",pid, str);
	}
	const char* res = EvalTcl(str);
	if (verbose) {
	  printf("NaTcl(%d): EVAL result: %s\n",pid, res);
	}
	v = StrToVar(res);
	goto post;
  } else {
	v = StrToVar("Unknown method");
	goto post;
  }
 post:
  if (message) free((void *)message);
  messaging_interface->PostMessage(instance, v);
  if (v.type == PP_VARTYPE_STRING) {
    var_interface->Release(v);
  }
}

/**
 * Entrypoints for the module.
 * Initialize instance interface and scriptable object class.
 * @param[in] a_module_id module ID
 * @param[in] get_browser pointer to PPB_GetInterface
 * @return PP_OK on success, any other value on failure.
 */
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
                                       PPB_GetInterface get_browser) {
  pid = getpid();
  module_id = a_module_id;
  messaging_interface =
      (struct PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
  var_interface =
      (struct PPB_Var*)(get_browser(PPB_VAR_INTERFACE));

  printf("NaTcl(%d): DBUG: PPP_InitializeModule\n",pid);
  interp = NewTcl();
  if (!interp) return PP_ERROR_FAILED;

  return PP_OK;
}

/**
 * Returns an interface pointer for the interface of the given name, or NULL
 * if the interface is not supported.
 * @param[in] interface_name name of the interface
 * @return pointer to the interface
 */
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
  printf("NaTcl(%d): DBUG: PPP_GetInterface '%s'\n", getpid(), (char *)interface_name);
  if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
    static struct PPP_Instance itf = {
      &Instance_DidCreate,
      &Instance_DidDestroy,
      &Instance_DidChangeView,
      &Instance_DidChangeFocus,
      &Instance_HandleDocumentLoad,
    };
    return &itf;
  } else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
    static struct PPP_Messaging itf = {
      &Messaging_HandleMessage
    };
    return &itf;
  }
  return NULL;
}

/**
 * Called before the plugin module is unloaded.
 */
PP_EXPORT void PPP_ShutdownModule() {
  //  if (interp) EndTcl(interp);
}

Added nacl/naclMissing.c.





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
 *
 *   naclMissing: "implement" all missing syscalls, library funcs and vars.
 *
 */


#include <stdio.h>
#include <errno.h>
#include <string.h>

int timezone;

/* emulated */

char * getwd (char *buf)
{
  printf("*BADSYSCALL:getwd\n");
  strcpy(buf,"/");
  return "/";
}

/* traced */

int access(const char *name, int mode)
{
  printf("*BADSYSCALL:access(\"%s\",%d)\n",name,mode);
  // return 0;
  errno=ENOENT;return -1;
}

/* plugged */

int _execve (){printf("BADSYSCALL:_execve\n");errno=EINVAL;return -1;}
int accept (){printf("BADSYSCALL:accept\n");errno=EINVAL;return -1;}
//int access (){printf("BADSYSCALL:access\n");errno=EINVAL;return -1;}
int bind (){printf("BADSYSCALL:bind\n");errno=EINVAL;return -1;}
int chdir (){printf("BADSYSCALL:chdir\n");errno=EINVAL;return -1;}
int chmod (){printf("BADSYSCALL:chmod\n");errno=EINVAL;return -1;}
int chown (){printf("BADSYSCALL:chown\n");errno=EINVAL;return -1;}
int connect (){printf("BADSYSCALL:connect\n");errno=EINVAL;return -1;}
int dlclose (){printf("BADSYSCALL:dlclose\n");errno=EINVAL;return -1;}
int dlerror (){printf("BADSYSCALL:dlerror\n");errno=EINVAL;return -1;}
int dlopen (){printf("BADSYSCALL:dlopen\n");errno=EINVAL;return -1;}
int dlsym (){printf("BADSYSCALL:dlsym\n");errno=EINVAL;return -1;}
int dup2 (){printf("BADSYSCALL:\n");errno=EINVAL;return -1;}
int fcntl (){printf("BADSYSCALL:fcntl\n");errno=EINVAL;return -1;}
int fork (){printf("BADSYSCALL:fork\n");errno=EINVAL;return -1;}
int freeaddrinfo (){printf("BADSYSCALL:freeaddrinfo\n");errno=EINVAL;return -1;}
int ftruncate (){printf("BADSYSCALL:ftruncate\n");errno=EINVAL;return -1;}
char * gai_strerror (){printf("BADSYSCALL:gai_strerror\n");errno=EINVAL;return NULL;}
int getaddrinfo (){printf("BADSYSCALL:getaddrinfo\n");errno=EINVAL;return -1;}
int geteuid (){printf("BADSYSCALL:geteuid\n");errno=EINVAL;return -1;}
int getgrgid (){printf("BADSYSCALL:getgrgid\n");errno=EINVAL;return -1;}
void * getgrnam (){printf("BADSYSCALL:getgrnam\n");errno=EINVAL;return NULL;}
void * gethostbyaddr (){printf("BADSYSCALL:gethostbyaddr\n");errno=EINVAL;return NULL;}
void * gethostbyname (){printf("BADSYSCALL:gethostbyname\n");errno=EINVAL;return NULL;}
int gethostname (){printf("BADSYSCALL:gethostname\n");errno=EINVAL;return -1;}
int getnameinfo (){printf("BADSYSCALL:getnameinfo\n");errno=EINVAL;return -1;}
int getpeername (){printf("BADSYSCALL:getpeername\n");errno=EINVAL;return -1;}
void * getpwnam (){printf("BADSYSCALL:getpwnam\n");errno=EINVAL;return NULL;}
void * getpwuid (){printf("BADSYSCALL:getpwuid\n");errno=EINVAL;return NULL;}
void * getservbyname (){printf("BADSYSCALL:getservbyname\n");errno=EINVAL;return NULL;}
int getsockname (){printf("BADSYSCALL:getsockname\n");errno=EINVAL;return -1;}
int getsockopt (){printf("BADSYSCALL:getsockopt\n");errno=EINVAL;return -1;}
int getuid (){printf("BADSYSCALL:getuid\n");errno=EINVAL;return -1;}
//void * getwd (){printf("BADSYSCALL:getwd\n");errno=EINVAL;return NULL;}
void * inet_ntoa (){printf("BADSYSCALL:inet_ntoa\n");errno=EINVAL;return NULL;}
int kill (){printf("BADSYSCALL:kill\n");errno=EINVAL;return -1;}
int link (){printf("BADSYSCALL:link\n");errno=EINVAL;return -1;}
int listen (){printf("BADSYSCALL:listen\n");errno=EINVAL;return -1;}
int lstat (){printf("BADSYSCALL:lstat\n");errno=EINVAL;return -1;}
int mkdir (){printf("BADSYSCALL:mkdir\n");errno=EINVAL;return -1;}
int mkfifo (){printf("BADSYSCALL:mkfifo\n");errno=EINVAL;return -1;}
int mknod (){printf("BADSYSCALL:mknod\n");errno=EINVAL;return -1;}
int pipe (){printf("BADSYSCALL:pipe\n");errno=EINVAL;return -1;}
int readlink (){printf("BADSYSCALL:readlink\n");errno=EINVAL;return -1;}
int recv (){printf("BADSYSCALL:recv\n");errno=EINVAL;return -1;}
int rmdir (){printf("BADSYSCALL:rmdir\n");errno=EINVAL;return -1;}
int select (){printf("BADSYSCALL:select\n");errno=EINVAL;return -1;}
int send (){printf("BADSYSCALL:send\n");errno=EINVAL;return -1;}
int setsockopt (){printf("BADSYSCALL:setsockopt\n");errno=EINVAL;return -1;}
int shutdown (){printf("BADSYSCALL:shutdown\n");errno=EINVAL;return -1;}
int socket (){printf("BADSYSCALL:socket\n");errno=EINVAL;return -1;}
int symlink (){printf("BADSYSCALL:symlink\n");errno=EINVAL;return -1;}
int umask (){printf("BADSYSCALL:umask\n");errno=EINVAL;return -1;}
int unlink (){printf("BADSYSCALL:unlink\n");errno=EINVAL;return -1;}
int utime (){printf("BADSYSCALL:utime\n");errno=EINVAL;return -1;}
int waitpid (){printf("BADSYSCALL:waitpid\n");errno=EINVAL;return -1;}

Added nacl/naclcompat.h.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
typedef __signed__ char __s8;
typedef unsigned char __u8;

typedef __signed__ short __s16;
typedef unsigned short __u16;

typedef __signed__ int __s32;
typedef unsigned int __u32;

typedef __signed__ long __s64;
typedef unsigned long __u64;

#define __bitwise 

typedef __u16 __bitwise __le16;
typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __le32;
typedef __u32 __bitwise __be32;
typedef __u64 __bitwise __le64;
typedef __u64 __bitwise __be64;

typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __wsum;

/* Description of data base entry for a single service.  */
struct servent
{
  char *s_name;			/* Official service name.  */
  char **s_aliases;		/* Alias list.  */
  int s_port;			/* Port number.  */
  char *s_proto;		/* Protocol to use.  */
};
/* For setsockopt(2) */
#define SOL_SOCKET	1

#define SO_DEBUG	1
#define SO_REUSEADDR	2
#define SO_TYPE		3
#define SO_ERROR	4
#define SO_DONTROUTE	5
#define SO_BROADCAST	6
#define SO_SNDBUF	7
#define SO_RCVBUF	8
#define SO_SNDBUFFORCE	32
#define SO_RCVBUFFORCE	33
#define SO_KEEPALIVE	9
#define SO_OOBINLINE	10
#define SO_NO_CHECK	11
#define SO_PRIORITY	12
#define SO_LINGER	13
#define SO_BSDCOMPAT	14
/* To add :#define SO_REUSEPORT 15 */

#ifndef SO_PASSCRED /* powerpc only differs in these */
#define SO_PASSCRED	16
#define SO_PEERCRED	17
#define SO_RCVLOWAT	18
#define SO_SNDLOWAT	19
#define SO_RCVTIMEO	20
#define SO_SNDTIMEO	21
#endif

/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION		22
#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
#define SO_SECURITY_ENCRYPTION_NETWORK		24

#define SO_BINDTODEVICE	25

/* Socket filtering */
#define SO_ATTACH_FILTER	26
#define SO_DETACH_FILTER	27

#define SO_PEERNAME		28
#define SO_TIMESTAMP		29
#define SCM_TIMESTAMP		SO_TIMESTAMP

#define SO_ACCEPTCONN		30

#define SO_PEERSEC		31
#define SO_PASSSEC		34
#define SO_TIMESTAMPNS		35
#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS

#define SO_MARK			36

#define SO_TIMESTAMPING		37
#define SCM_TIMESTAMPING	SO_TIMESTAMPING

#define SO_PROTOCOL		38
#define SO_DOMAIN		39

typedef socklen_t __socklen_t;

struct addrinfo
{
  int ai_flags;			/* Input flags.  */
  int ai_family;		/* Protocol family for socket.  */
  int ai_socktype;		/* Socket type.  */
  int ai_protocol;		/* Protocol for socket.  */
  socklen_t ai_addrlen;		/* Length of socket address.  */
  struct sockaddr *ai_addr;	/* Socket address for socket.  */
  char *ai_canonname;		/* Canonical name for service location.  */
  struct addrinfo *ai_next;	/* Pointer to next in list.  */
};

/* Types of sockets.  */
enum __socket_type
{
  SOCK_STREAM = 1,		/* Sequenced, reliable, connection-based
				   byte streams.  */
#define SOCK_STREAM SOCK_STREAM
  SOCK_DGRAM = 2,		/* Connectionless, unreliable datagrams
				   of fixed maximum length.  */
#define SOCK_DGRAM SOCK_DGRAM
  SOCK_RAW = 3,			/* Raw protocol interface.  */
#define SOCK_RAW SOCK_RAW
  SOCK_RDM = 4,			/* Reliably-delivered messages.  */
#define SOCK_RDM SOCK_RDM
  SOCK_SEQPACKET = 5,		/* Sequenced, reliable, connection-based,
				   datagrams of fixed maximum length.  */
#define SOCK_SEQPACKET SOCK_SEQPACKET
  SOCK_DCCP = 6,		/* Datagram Congestion Control Protocol.  */
#define SOCK_DCCP SOCK_DCCP
  SOCK_PACKET = 10,		/* Linux specific way of getting packets
				   at the dev level.  For writing rarp and
				   other similar things on the user level. */
#define SOCK_PACKET SOCK_PACKET

  /* Flags to be ORed into the type parameter of socket and socketpair and
     used for the flags parameter of paccept.  */

  SOCK_CLOEXEC = 02000000,	/* Atomically set close-on-exec flag for the
				   new descriptor(s).  */
#define SOCK_CLOEXEC SOCK_CLOEXEC
  SOCK_NONBLOCK = 04000		/* Atomically mark descriptor(s) as
				   non-blocking.  */
#define SOCK_NONBLOCK SOCK_NONBLOCK
};

/* Protocol families.  */
#define	PF_UNSPEC	0	/* Unspecified.  */
#define	PF_LOCAL	1	/* Local to host (pipes and file-domain).  */
#define	PF_UNIX		PF_LOCAL /* POSIX name for PF_LOCAL.  */
#define	PF_FILE		PF_LOCAL /* Another non-standard name for PF_LOCAL.  */
#define	PF_INET		2	/* IP protocol family.  */
#define	PF_AX25		3	/* Amateur Radio AX.25.  */
#define	PF_IPX		4	/* Novell Internet Protocol.  */
#define	PF_APPLETALK	5	/* Appletalk DDP.  */
#define	PF_NETROM	6	/* Amateur radio NetROM.  */
#define	PF_BRIDGE	7	/* Multiprotocol bridge.  */
#define	PF_ATMPVC	8	/* ATM PVCs.  */
#define	PF_X25		9	/* Reserved for X.25 project.  */
#define	PF_INET6	10	/* IP version 6.  */
#define	PF_ROSE		11	/* Amateur Radio X.25 PLP.  */
#define	PF_DECnet	12	/* Reserved for DECnet project.  */
#define	PF_NETBEUI	13	/* Reserved for 802.2LLC project.  */
#define	PF_SECURITY	14	/* Security callback pseudo AF.  */
#define	PF_KEY		15	/* PF_KEY key management API.  */
#define	PF_NETLINK	16
#define	PF_ROUTE	PF_NETLINK /* Alias to emulate 4.4BSD.  */
#define	PF_PACKET	17	/* Packet family.  */
#define	PF_ASH		18	/* Ash.  */
#define	PF_ECONET	19	/* Acorn Econet.  */
#define	PF_ATMSVC	20	/* ATM SVCs.  */
#define PF_RDS		21	/* RDS sockets.  */
#define	PF_SNA		22	/* Linux SNA Project */
#define	PF_IRDA		23	/* IRDA sockets.  */
#define	PF_PPPOX	24	/* PPPoX sockets.  */
#define	PF_WANPIPE	25	/* Wanpipe API sockets.  */
#define PF_LLC		26	/* Linux LLC.  */
#define PF_CAN		29	/* Controller Area Network.  */
#define PF_TIPC		30	/* TIPC sockets.  */
#define	PF_BLUETOOTH	31	/* Bluetooth sockets.  */
#define	PF_IUCV		32	/* IUCV sockets.  */
#define PF_RXRPC	33	/* RxRPC sockets.  */
#define PF_ISDN		34	/* mISDN sockets.  */
#define PF_PHONET	35	/* Phonet sockets.  */
#define PF_IEEE802154	36	/* IEEE 802.15.4 sockets.  */
#define	PF_MAX		37	/* For now..  */

/* Address families.  */
#define	AF_UNSPEC	PF_UNSPEC
#define	AF_LOCAL	PF_LOCAL
#define	AF_UNIX		PF_UNIX
#define	AF_FILE		PF_FILE
#define	AF_INET		PF_INET
#define	AF_AX25		PF_AX25
#define	AF_IPX		PF_IPX
#define	AF_APPLETALK	PF_APPLETALK
#define	AF_NETROM	PF_NETROM
#define	AF_BRIDGE	PF_BRIDGE
#define	AF_ATMPVC	PF_ATMPVC
#define	AF_X25		PF_X25
#define	AF_INET6	PF_INET6
#define	AF_ROSE		PF_ROSE
#define	AF_DECnet	PF_DECnet
#define	AF_NETBEUI	PF_NETBEUI
#define	AF_SECURITY	PF_SECURITY
#define	AF_KEY		PF_KEY
#define	AF_NETLINK	PF_NETLINK
#define	AF_ROUTE	PF_ROUTE
#define	AF_PACKET	PF_PACKET
#define	AF_ASH		PF_ASH
#define	AF_ECONET	PF_ECONET
#define	AF_ATMSVC	PF_ATMSVC
#define AF_RDS		PF_RDS
#define	AF_SNA		PF_SNA
#define	AF_IRDA		PF_IRDA
#define	AF_PPPOX	PF_PPPOX
#define	AF_WANPIPE	PF_WANPIPE
#define AF_LLC		PF_LLC
#define AF_CAN		PF_CAN
#define AF_TIPC		PF_TIPC
#define	AF_BLUETOOTH	PF_BLUETOOTH
#define	AF_IUCV		PF_IUCV
#define AF_RXRPC	PF_RXRPC
#define AF_ISDN		PF_ISDN
#define AF_PHONET	PF_PHONET
#define AF_IEEE802154	PF_IEEE802154
#define	AF_MAX		PF_MAX

/* Socket level values.  Others are defined in the appropriate headers.

   XXX These definitions also should go into the appropriate headers as
   far as they are available.  */
#define SOL_RAW		255
#define SOL_DECNET      261
#define SOL_X25         262
#define SOL_PACKET	263
#define SOL_ATM		264	/* ATM layer (cell level).  */
#define SOL_AAL		265	/* ATM Adaption Layer (packet level).  */
#define SOL_IRDA	266

/* Maximum queue length specifiable by listen.  */
#define SOMAXCONN	128


/* POSIX.1g specifies this type name for the `sa_family' member.  */
typedef unsigned short int sa_family_t;

/* This macro is used to declare the initial common members
   of the data types used for socket addresses, `struct sockaddr',
   `struct sockaddr_in', `struct sockaddr_un', etc.  */

#define	__SOCKADDR_COMMON(sa_prefix) \
  sa_family_t sa_prefix##family

#define __SOCKADDR_COMMON_SIZE	(sizeof (unsigned short int))

/* Structure describing a generic socket address.  */
struct sockaddr
  {
    __SOCKADDR_COMMON (sa_);	/* Common data: address family and length.  */
    char sa_data[14];		/* Address data.  */
  };


/* Structure large enough to hold any socket address (with the historical
   exception of AF_UNIX).  We reserve 128 bytes.  */
#define __ss_aligntype	unsigned long int
#define _SS_SIZE	128
#define _SS_PADSIZE	(_SS_SIZE - (2 * sizeof (__ss_aligntype)))

struct sockaddr_storage
  {
    __SOCKADDR_COMMON (ss_);	/* Address family, etc.  */
    __ss_aligntype __ss_align;	/* Force desired alignment.  */
    char __ss_padding[_SS_PADSIZE];
  };


/* Bits in the FLAGS argument to `send', `recv', et al.  */
enum
  {
    MSG_OOB		= 0x01,	/* Process out-of-band data.  */
#define MSG_OOB		MSG_OOB
    MSG_PEEK		= 0x02,	/* Peek at incoming messages.  */
#define MSG_PEEK	MSG_PEEK
    MSG_DONTROUTE	= 0x04,	/* Don't use local routing.  */
#define MSG_DONTROUTE	MSG_DONTROUTE
#ifdef __USE_GNU
    /* DECnet uses a different name.  */
    MSG_TRYHARD		= MSG_DONTROUTE,
# define MSG_TRYHARD	MSG_DONTROUTE
#endif
    MSG_CTRUNC		= 0x08,	/* Control data lost before delivery.  */
#define MSG_CTRUNC	MSG_CTRUNC
    MSG_PROXY		= 0x10,	/* Supply or ask second address.  */
#define MSG_PROXY	MSG_PROXY
    MSG_TRUNC		= 0x20,
#define	MSG_TRUNC	MSG_TRUNC
    MSG_DONTWAIT	= 0x40, /* Nonblocking IO.  */
#define	MSG_DONTWAIT	MSG_DONTWAIT
    MSG_EOR		= 0x80, /* End of record.  */
#define	MSG_EOR		MSG_EOR
    MSG_WAITALL		= 0x100, /* Wait for a full request.  */
#define	MSG_WAITALL	MSG_WAITALL
    MSG_FIN		= 0x200,
#define	MSG_FIN		MSG_FIN
    MSG_SYN		= 0x400,
#define	MSG_SYN		MSG_SYN
    MSG_CONFIRM		= 0x800, /* Confirm path validity.  */
#define	MSG_CONFIRM	MSG_CONFIRM
    MSG_RST		= 0x1000,
#define	MSG_RST		MSG_RST
    MSG_ERRQUEUE	= 0x2000, /* Fetch message from error queue.  */
#define	MSG_ERRQUEUE	MSG_ERRQUEUE
    MSG_NOSIGNAL	= 0x4000, /* Do not generate SIGPIPE.  */
#define	MSG_NOSIGNAL	MSG_NOSIGNAL
    MSG_MORE		= 0x8000,  /* Sender will send more.  */
#define	MSG_MORE	MSG_MORE

    MSG_CMSG_CLOEXEC	= 0x40000000	/* Set close_on_exit for file
                                           descriptor received through
                                           SCM_RIGHTS.  */
#define MSG_CMSG_CLOEXEC MSG_CMSG_CLOEXEC
  };


/* Structure describing messages sent by
   `sendmsg' and received by `recvmsg'.  */
struct msghdr
  {
    void *msg_name;		/* Address to send to/receive from.  */
    socklen_t msg_namelen;	/* Length of address data.  */

    struct iovec *msg_iov;	/* Vector of data to send/receive into.  */
    size_t msg_iovlen;		/* Number of elements in the vector.  */

    void *msg_control;		/* Ancillary data (eg BSD filedesc passing). */
    size_t msg_controllen;	/* Ancillary data buffer length.
				   !! The type should be socklen_t but the
				   definition of the kernel is incompatible
				   with this.  */

    int msg_flags;		/* Flags on received message.  */
  };


# define __flexarr	[]



/* Structure used for storage of ancillary data object information.  */
struct cmsghdr
  {
    size_t cmsg_len;		/* Length of data in cmsg_data plus length
				   of cmsghdr structure.
				   !! The type should be socklen_t but the
				   definition of the kernel is incompatible
				   with this.  */
    int cmsg_level;		/* Originating protocol.  */
    int cmsg_type;		/* Protocol specific type.  */
#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L
    __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data.  */
#endif
  };

/* Ancillary data object manipulation macros.  */
#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L
# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data)
#else
# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1))
#endif
#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg)
#define CMSG_FIRSTHDR(mhdr) \
  ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr)		      \
   ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) 0)
#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \
			 & (size_t) ~(sizeof (size_t) - 1))
#define CMSG_SPACE(len) (CMSG_ALIGN (len) \
			 + CMSG_ALIGN (sizeof (struct cmsghdr)))
#define CMSG_LEN(len)   (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
# define __THROW

extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
				      struct cmsghdr *__cmsg) __THROW;
#ifdef __USE_EXTERN_INLINES
# ifndef _EXTERN_INLINE
#  define _EXTERN_INLINE __extern_inline
# endif
_EXTERN_INLINE struct cmsghdr *
__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg))
{
  if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
    /* The kernel header does this so there may be a reason.  */
    return 0;

  __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
			       + CMSG_ALIGN (__cmsg->cmsg_len));
  if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control
					+ __mhdr->msg_controllen)
      || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
	  > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
    /* No more entries.  */
    return 0;
  return __cmsg;
}
#endif	/* Use `extern inline'.  */

/* Socket level message types.  This must match the definitions in
   <linux/socket.h>.  */
enum
  {
    SCM_RIGHTS = 0x01		/* Transfer file descriptors.  */
#define SCM_RIGHTS SCM_RIGHTS
#ifdef __USE_GNU
    , SCM_CREDENTIALS = 0x02	/* Credentials passing.  */
# define SCM_CREDENTIALS SCM_CREDENTIALS
#endif
  };

#ifdef __USE_GNU
/* User visible structure for SCM_CREDENTIALS message */
struct ucred
{
  pid_t pid;			/* PID of sending process.  */
  uid_t uid;			/* UID of sending process.  */
  gid_t gid;			/* GID of sending process.  */
};
#endif

/* Ugly workaround for unclean kernel headers.  */
#if !defined __USE_MISC && !defined __USE_GNU
# ifndef FIOGETOWN
#  define __SYS_SOCKET_H_undef_FIOGETOWN
# endif
# ifndef FIOSETOWN
#  define __SYS_SOCKET_H_undef_FIOSETOWN
# endif
# ifndef SIOCATMARK
#  define __SYS_SOCKET_H_undef_SIOCATMARK
# endif
# ifndef SIOCGPGRP
#  define __SYS_SOCKET_H_undef_SIOCGPGRP
# endif
# ifndef SIOCGSTAMP
#  define __SYS_SOCKET_H_undef_SIOCGSTAMP
# endif
# ifndef SIOCGSTAMPNS
#  define __SYS_SOCKET_H_undef_SIOCGSTAMPNS
# endif
# ifndef SIOCSPGRP
#  define __SYS_SOCKET_H_undef_SIOCSPGRP
# endif
#endif

/* Get socket manipulation related informations from kernel headers.  */


#if !defined __USE_MISC && !defined __USE_GNU
# ifdef __SYS_SOCKET_H_undef_FIOGETOWN
#  undef __SYS_SOCKET_H_undef_FIOGETOWN
#  undef FIOGETOWN
# endif
# ifdef __SYS_SOCKET_H_undef_FIOSETOWN
#  undef __SYS_SOCKET_H_undef_FIOSETOWN
#  undef FIOSETOWN
# endif
# ifdef __SYS_SOCKET_H_undef_SIOCATMARK
#  undef __SYS_SOCKET_H_undef_SIOCATMARK
#  undef SIOCATMARK
# endif
# ifdef __SYS_SOCKET_H_undef_SIOCGPGRP
#  undef __SYS_SOCKET_H_undef_SIOCGPGRP
#  undef SIOCGPGRP
# endif
# ifdef __SYS_SOCKET_H_undef_SIOCGSTAMP
#  undef __SYS_SOCKET_H_undef_SIOCGSTAMP
#  undef SIOCGSTAMP
# endif
# ifdef __SYS_SOCKET_H_undef_SIOCGSTAMPNS
#  undef __SYS_SOCKET_H_undef_SIOCGSTAMPNS
#  undef SIOCGSTAMPNS
# endif
# ifdef __SYS_SOCKET_H_undef_SIOCSPGRP
#  undef __SYS_SOCKET_H_undef_SIOCSPGRP
#  undef SIOCSPGRP
# endif
#endif

/* Structure used to manipulate the SO_LINGER option.  */
struct linger
  {
    int l_onoff;		/* Nonzero to linger on close.  */
    int l_linger;		/* Time to linger.  */
  };
/* Standard well-defined IP protocols.  */
enum {
  IPPROTO_IP = 0,		/* Dummy protocol for TCP		*/
  IPPROTO_ICMP = 1,		/* Internet Control Message Protocol	*/
  IPPROTO_IGMP = 2,		/* Internet Group Management Protocol	*/
  IPPROTO_IPIP = 4,		/* IPIP tunnels (older KA9Q tunnels use 94) */
  IPPROTO_TCP = 6,		/* Transmission Control Protocol	*/
  IPPROTO_EGP = 8,		/* Exterior Gateway Protocol		*/
  IPPROTO_PUP = 12,		/* PUP protocol				*/
  IPPROTO_UDP = 17,		/* User Datagram Protocol		*/
  IPPROTO_IDP = 22,		/* XNS IDP protocol			*/
  IPPROTO_DCCP = 33,		/* Datagram Congestion Control Protocol */
  IPPROTO_RSVP = 46,		/* RSVP protocol			*/
  IPPROTO_GRE = 47,		/* Cisco GRE tunnels (rfc 1701,1702)	*/

  IPPROTO_IPV6	 = 41,		/* IPv6-in-IPv4 tunnelling		*/

  IPPROTO_ESP = 50,            /* Encapsulation Security Payload protocol */
  IPPROTO_AH = 51,             /* Authentication Header protocol       */
  IPPROTO_BEETPH = 94,	       /* IP option pseudo header for BEET */
  IPPROTO_PIM    = 103,		/* Protocol Independent Multicast	*/

  IPPROTO_COMP   = 108,                /* Compression Header protocol */
  IPPROTO_SCTP   = 132,		/* Stream Control Transport Protocol	*/
  IPPROTO_UDPLITE = 136,	/* UDP-Lite (RFC 3828)			*/

  IPPROTO_RAW	 = 255,		/* Raw IP packets			*/
  IPPROTO_MAX
};


/* Internet address. */
struct in_addr {
	__be32	s_addr;
};

#define IP_TOS		1
#define IP_TTL		2
#define IP_HDRINCL	3
#define IP_OPTIONS	4
#define IP_ROUTER_ALERT	5
#define IP_RECVOPTS	6
#define IP_RETOPTS	7
#define IP_PKTINFO	8
#define IP_PKTOPTIONS	9
#define IP_MTU_DISCOVER	10
#define IP_RECVERR	11
#define IP_RECVTTL	12
#define	IP_RECVTOS	13
#define IP_MTU		14
#define IP_FREEBIND	15
#define IP_IPSEC_POLICY	16
#define IP_XFRM_POLICY	17
#define IP_PASSSEC	18
#define IP_TRANSPARENT	19

/* BSD compatibility */
#define IP_RECVRETOPTS	IP_RETOPTS

/* TProxy original addresses */
#define IP_ORIGDSTADDR       20
#define IP_RECVORIGDSTADDR   IP_ORIGDSTADDR

/* IP_MTU_DISCOVER values */
#define IP_PMTUDISC_DONT		0	/* Never send DF frames */
#define IP_PMTUDISC_WANT		1	/* Use per route hints	*/
#define IP_PMTUDISC_DO			2	/* Always DF		*/
#define IP_PMTUDISC_PROBE		3       /* Ignore dst pmtu      */

#define IP_MULTICAST_IF			32
#define IP_MULTICAST_TTL 		33
#define IP_MULTICAST_LOOP 		34
#define IP_ADD_MEMBERSHIP		35
#define IP_DROP_MEMBERSHIP		36
#define IP_UNBLOCK_SOURCE		37
#define IP_BLOCK_SOURCE			38
#define IP_ADD_SOURCE_MEMBERSHIP	39
#define IP_DROP_SOURCE_MEMBERSHIP	40
#define IP_MSFILTER			41
#define MCAST_JOIN_GROUP		42
#define MCAST_BLOCK_SOURCE		43
#define MCAST_UNBLOCK_SOURCE		44
#define MCAST_LEAVE_GROUP		45
#define MCAST_JOIN_SOURCE_GROUP		46
#define MCAST_LEAVE_SOURCE_GROUP	47
#define MCAST_MSFILTER			48
#define IP_MULTICAST_ALL		49

#define MCAST_EXCLUDE	0
#define MCAST_INCLUDE	1

/* These need to appear somewhere around here */
#define IP_DEFAULT_MULTICAST_TTL        1
#define IP_DEFAULT_MULTICAST_LOOP       1



/*
 * Desired design of maximum size and alignment (see RFC2553)
 */
#define _K_SS_MAXSIZE	128	/* Implementation specific max size */
#define _K_SS_ALIGNSIZE	(__alignof__ (struct sockaddr *))
				/* Implementation specific desired alignment */

struct __kernel_sockaddr_storage {
	unsigned short	ss_family;		/* address family */
	/* Following field(s) are implementation specific */
	char		__data[_K_SS_MAXSIZE - sizeof(unsigned short)];
				/* space to achieve desired size, */
				/* _SS_MAXSIZE value minus size of ss_family */
} __attribute__ ((aligned(_K_SS_ALIGNSIZE)));	/* force desired alignment */

/* Request struct for multicast socket ops */

struct ip_mreq 
{
	struct in_addr imr_multiaddr;	/* IP multicast address of group */
	struct in_addr imr_interface;	/* local IP address of interface */
};

struct ip_mreqn
{
	struct in_addr	imr_multiaddr;		/* IP multicast address of group */
	struct in_addr	imr_address;		/* local IP address of interface */
	int		imr_ifindex;		/* Interface index */
};

struct ip_mreq_source {
	__be32		imr_multiaddr;
	__be32		imr_interface;
	__be32		imr_sourceaddr;
};

struct ip_msfilter {
	__be32		imsf_multiaddr;
	__be32		imsf_interface;
	__u32		imsf_fmode;
	__u32		imsf_numsrc;
	__be32		imsf_slist[1];
};

#define IP_MSFILTER_SIZE(numsrc) \
	(sizeof(struct ip_msfilter) - sizeof(__u32) \
	+ (numsrc) * sizeof(__u32))

struct group_req
{
	__u32				 gr_interface;	/* interface index */
	struct __kernel_sockaddr_storage gr_group;	/* group address */
};

struct group_source_req
{
	__u32				 gsr_interface;	/* interface index */
	struct __kernel_sockaddr_storage gsr_group;	/* group address */
	struct __kernel_sockaddr_storage gsr_source;	/* source address */
};

struct group_filter
{
	__u32				 gf_interface;	/* interface index */
	struct __kernel_sockaddr_storage gf_group;	/* multicast address */
	__u32				 gf_fmode;	/* filter mode */
	__u32				 gf_numsrc;	/* number of sources */
	struct __kernel_sockaddr_storage gf_slist[1];	/* interface index */
};

#define GROUP_FILTER_SIZE(numsrc) \
	(sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) \
	+ (numsrc) * sizeof(struct __kernel_sockaddr_storage))

struct in_pktinfo
{
	int		ipi_ifindex;
	struct in_addr	ipi_spec_dst;
	struct in_addr	ipi_addr;
};

/* Structure describing an Internet (IP) socket address. */
#define __SOCK_SIZE__	16		/* sizeof(struct sockaddr)	*/
struct sockaddr_in {
  sa_family_t		sin_family;	/* Address family		*/
  __be16		sin_port;	/* Port number			*/
  struct in_addr	sin_addr;	/* Internet address		*/

  /* Pad to size of `struct sockaddr'. */
  unsigned char		__pad[__SOCK_SIZE__ - sizeof(short int) -
			sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero	__pad		/* for BSD UNIX comp. -FvK	*/


/*
 * Definitions of the bits in an Internet address integer.
 * On subnets, host and network parts are found according
 * to the subnet mask, not these masks.
 */
#define	IN_CLASSA(a)		((((long int) (a)) & 0x80000000) == 0)
#define	IN_CLASSA_NET		0xff000000
#define	IN_CLASSA_NSHIFT	24
#define	IN_CLASSA_HOST		(0xffffffff & ~IN_CLASSA_NET)
#define	IN_CLASSA_MAX		128

#define	IN_CLASSB(a)		((((long int) (a)) & 0xc0000000) == 0x80000000)
#define	IN_CLASSB_NET		0xffff0000
#define	IN_CLASSB_NSHIFT	16
#define	IN_CLASSB_HOST		(0xffffffff & ~IN_CLASSB_NET)
#define	IN_CLASSB_MAX		65536

#define	IN_CLASSC(a)		((((long int) (a)) & 0xe0000000) == 0xc0000000)
#define	IN_CLASSC_NET		0xffffff00
#define	IN_CLASSC_NSHIFT	8
#define	IN_CLASSC_HOST		(0xffffffff & ~IN_CLASSC_NET)

#define	IN_CLASSD(a)		((((long int) (a)) & 0xf0000000) == 0xe0000000)
#define	IN_MULTICAST(a)		IN_CLASSD(a)
#define IN_MULTICAST_NET	0xF0000000

#define	IN_EXPERIMENTAL(a)	((((long int) (a)) & 0xf0000000) == 0xf0000000)
#define	IN_BADCLASS(a)		IN_EXPERIMENTAL((a))

/* Address to accept any incoming messages. */
#define	INADDR_ANY		((unsigned long int) 0x00000000)

/* Address to send to all hosts. */
#define	INADDR_BROADCAST	((unsigned long int) 0xffffffff)

/* Address indicating an error return. */
#define	INADDR_NONE		((unsigned long int) 0xffffffff)

/* Network number for local host loopback. */
#define	IN_LOOPBACKNET		127

/* Address to loopback in software to local host.  */
#define	INADDR_LOOPBACK		0x7f000001	/* 127.0.0.1   */
#define	IN_LOOPBACK(a)		((((long int) (a)) & 0xff000000) == 0x7f000000)

/* Defines for Multicast INADDR */
#define INADDR_UNSPEC_GROUP   	0xe0000000U	/* 224.0.0.0   */
#define INADDR_ALLHOSTS_GROUP 	0xe0000001U	/* 224.0.0.1   */
#define INADDR_ALLRTRS_GROUP    0xe0000002U	/* 224.0.0.2 */
#define INADDR_MAX_LOCAL_GROUP  0xe00000ffU	/* 224.0.0.255 */

/*
 *	IPv6 address structure
 */

struct in6_addr
{
	union 
	{
		__u8		u6_addr8[16];
		__be16		u6_addr16[8];
		__be32		u6_addr32[4];
	} in6_u;
#define s6_addr			in6_u.u6_addr8
#define s6_addr16		in6_u.u6_addr16
#define s6_addr32		in6_u.u6_addr32
};

/* IPv6 Wildcard Address (::) and Loopback Address (::1) defined in RFC2553
 * NOTE: Be aware the IN6ADDR_* constants and in6addr_* externals are defined
 * in network byte order, not in host byte order as are the IPv4 equivalents
 */

struct sockaddr_in6 {
	unsigned short int	sin6_family;    /* AF_INET6 */
	__be16			sin6_port;      /* Transport layer port # */
	__be32			sin6_flowinfo;  /* IPv6 flow information */
	struct in6_addr		sin6_addr;      /* IPv6 address */
	__u32			sin6_scope_id;  /* scope id (new in RFC2553) */
};

struct ipv6_mreq {
	/* IPv6 multicast address of group */
	struct in6_addr ipv6mr_multiaddr;

	/* local IPv6 address of interface */
	int		ipv6mr_ifindex;
};

#define ipv6mr_acaddr	ipv6mr_multiaddr

struct in6_flowlabel_req
{
	struct in6_addr	flr_dst;
	__be32	flr_label;
	__u8	flr_action;
	__u8	flr_share;
	__u16	flr_flags;
	__u16 	flr_expires;
	__u16	flr_linger;
	__u32	__flr_pad;
	/* Options in format of IPV6_PKTOPTIONS */
};

#define IPV6_FL_A_GET	0
#define IPV6_FL_A_PUT	1
#define IPV6_FL_A_RENEW	2

#define IPV6_FL_F_CREATE	1
#define IPV6_FL_F_EXCL		2

#define IPV6_FL_S_NONE		0
#define IPV6_FL_S_EXCL		1
#define IPV6_FL_S_PROCESS	2
#define IPV6_FL_S_USER		3
#define IPV6_FL_S_ANY		255


/*
 *	Bitmask constant declarations to help applications select out the 
 *	flow label and priority fields.
 *
 *	Note that this are in host byte order while the flowinfo field of
 *	sockaddr_in6 is in network byte order.
 */

#define IPV6_FLOWINFO_FLOWLABEL		0x000fffff
#define IPV6_FLOWINFO_PRIORITY		0x0ff00000

/* These defintions are obsolete */
#define IPV6_PRIORITY_UNCHARACTERIZED	0x0000
#define IPV6_PRIORITY_FILLER		0x0100
#define IPV6_PRIORITY_UNATTENDED	0x0200
#define IPV6_PRIORITY_RESERVED1		0x0300
#define IPV6_PRIORITY_BULK		0x0400
#define IPV6_PRIORITY_RESERVED2		0x0500
#define IPV6_PRIORITY_INTERACTIVE	0x0600
#define IPV6_PRIORITY_CONTROL		0x0700
#define IPV6_PRIORITY_8			0x0800
#define IPV6_PRIORITY_9			0x0900
#define IPV6_PRIORITY_10		0x0a00
#define IPV6_PRIORITY_11		0x0b00
#define IPV6_PRIORITY_12		0x0c00
#define IPV6_PRIORITY_13		0x0d00
#define IPV6_PRIORITY_14		0x0e00
#define IPV6_PRIORITY_15		0x0f00

/*
 *	IPV6 extension headers
 */
#define IPPROTO_HOPOPTS		0	/* IPv6 hop-by-hop options	*/
#define IPPROTO_ROUTING		43	/* IPv6 routing header		*/
#define IPPROTO_FRAGMENT	44	/* IPv6 fragmentation header	*/
#define IPPROTO_ICMPV6		58	/* ICMPv6			*/
#define IPPROTO_NONE		59	/* IPv6 no next header		*/
#define IPPROTO_DSTOPTS		60	/* IPv6 destination options	*/
#define IPPROTO_MH		135	/* IPv6 mobility header		*/

/*
 *	IPv6 TLV options.
 */
#define IPV6_TLV_PAD0		0
#define IPV6_TLV_PADN		1
#define IPV6_TLV_ROUTERALERT	5
#define IPV6_TLV_JUMBO		194
#define IPV6_TLV_HAO		201	/* home address option */

/*
 *	IPV6 socket options
 */

#define IPV6_ADDRFORM		1
#define IPV6_2292PKTINFO	2
#define IPV6_2292HOPOPTS	3
#define IPV6_2292DSTOPTS	4
#define IPV6_2292RTHDR		5
#define IPV6_2292PKTOPTIONS	6
#define IPV6_CHECKSUM		7
#define IPV6_2292HOPLIMIT	8
#define IPV6_NEXTHOP		9
#define IPV6_AUTHHDR		10	/* obsolete */
#define IPV6_FLOWINFO		11

#define IPV6_UNICAST_HOPS	16
#define IPV6_MULTICAST_IF	17
#define IPV6_MULTICAST_HOPS	18
#define IPV6_MULTICAST_LOOP	19
#define IPV6_ADD_MEMBERSHIP	20
#define IPV6_DROP_MEMBERSHIP	21
#define IPV6_ROUTER_ALERT	22
#define IPV6_MTU_DISCOVER	23
#define IPV6_MTU		24
#define IPV6_RECVERR		25
#define IPV6_V6ONLY		26
#define IPV6_JOIN_ANYCAST	27
#define IPV6_LEAVE_ANYCAST	28

/* IPV6_MTU_DISCOVER values */
#define IPV6_PMTUDISC_DONT		0
#define IPV6_PMTUDISC_WANT		1
#define IPV6_PMTUDISC_DO		2
#define IPV6_PMTUDISC_PROBE		3

/* Flowlabel */
#define IPV6_FLOWLABEL_MGR	32
#define IPV6_FLOWINFO_SEND	33

#define IPV6_IPSEC_POLICY	34
#define IPV6_XFRM_POLICY	35

/*
 * Multicast:
 * Following socket options are shared between IPv4 and IPv6.
 *
 * MCAST_JOIN_GROUP		42
 * MCAST_BLOCK_SOURCE		43
 * MCAST_UNBLOCK_SOURCE		44
 * MCAST_LEAVE_GROUP		45
 * MCAST_JOIN_SOURCE_GROUP	46
 * MCAST_LEAVE_SOURCE_GROUP	47
 * MCAST_MSFILTER		48
 */

/*
 * Advanced API (RFC3542) (1)
 *
 * Note: IPV6_RECVRTHDRDSTOPTS does not exist. see net/ipv6/datagram.c.
 */

#define IPV6_RECVPKTINFO	49
#define IPV6_PKTINFO		50
#define IPV6_RECVHOPLIMIT	51
#define IPV6_HOPLIMIT		52
#define IPV6_RECVHOPOPTS	53
#define IPV6_HOPOPTS		54
#define IPV6_RTHDRDSTOPTS	55
#define IPV6_RECVRTHDR		56
#define IPV6_RTHDR		57
#define IPV6_RECVDSTOPTS	58
#define IPV6_DSTOPTS		59
#if 0	/* not yet */
#define IPV6_RECVPATHMTU	60
#define IPV6_PATHMTU		61
#define IPV6_DONTFRAG		62
#define IPV6_USE_MIN_MTU	63
#endif

/*
 * Netfilter (1)
 *
 * Following socket options are used in ip6_tables;
 * see include/linux/netfilter_ipv6/ip6_tables.h.
 *
 * IP6T_SO_SET_REPLACE / IP6T_SO_GET_INFO		64
 * IP6T_SO_SET_ADD_COUNTERS / IP6T_SO_GET_ENTRIES	65
 */

/*
 * Advanced API (RFC3542) (2)
 */
#define IPV6_RECVTCLASS		66
#define IPV6_TCLASS		67

/*
 * Netfilter (2)
 *
 * Following socket options are used in ip6_tables;
 * see include/linux/netfilter_ipv6/ip6_tables.h.
 *
 * IP6T_SO_GET_REVISION_MATCH	68
 * IP6T_SO_GET_REVISION_TARGET	69
 */

/* RFC5014: Source address selection */
#define IPV6_ADDR_PREFERENCES	72

#define IPV6_PREFER_SRC_TMP		0x0001
#define IPV6_PREFER_SRC_PUBLIC		0x0002
#define IPV6_PREFER_SRC_PUBTMP_DEFAULT	0x0100
#define IPV6_PREFER_SRC_COA		0x0004
#define IPV6_PREFER_SRC_HOME		0x0400
#define IPV6_PREFER_SRC_CGA		0x0008
#define IPV6_PREFER_SRC_NONCGA		0x0800

/*
 * Multicast Routing:
 * see include/linux/mroute6.h.
 *
 * MRT6_INIT			200
 * MRT6_DONE			201
 * MRT6_ADD_MIF			202
 * MRT6_DEL_MIF			203
 * MRT6_ADD_MFC			204
 * MRT6_DEL_MFC			205
 * MRT6_VERSION			206
 * MRT6_ASSERT			207
 * MRT6_PIM			208
 * (reserved)			209
 */



/* The following constants should be used for the second parameter of
   `shutdown'.  */
enum
{
  SHUT_RD = 0,		/* No more receptions.  */
#define SHUT_RD		SHUT_RD
  SHUT_WR,		/* No more transmissions.  */
#define SHUT_WR		SHUT_WR
  SHUT_RDWR		/* No more receptions or transmissions.  */
#define SHUT_RDWR	SHUT_RDWR
};

/* Add more `struct sockaddr_AF' types here as necessary.
   These are all the ones I found on NetBSD and Linux.  */
# define __SOCKADDR_ALLTYPES \
  __SOCKADDR_ONETYPE (sockaddr) \
  __SOCKADDR_ONETYPE (sockaddr_at) \
  __SOCKADDR_ONETYPE (sockaddr_ax25) \
  __SOCKADDR_ONETYPE (sockaddr_dl) \
  __SOCKADDR_ONETYPE (sockaddr_eon) \
  __SOCKADDR_ONETYPE (sockaddr_in) \
  __SOCKADDR_ONETYPE (sockaddr_in6) \
  __SOCKADDR_ONETYPE (sockaddr_inarp) \
  __SOCKADDR_ONETYPE (sockaddr_ipx) \
  __SOCKADDR_ONETYPE (sockaddr_iso) \
  __SOCKADDR_ONETYPE (sockaddr_ns) \
  __SOCKADDR_ONETYPE (sockaddr_un) \
  __SOCKADDR_ONETYPE (sockaddr_x25)

# define __SOCKADDR_ONETYPE(type) struct type *__restrict __##type##__;
typedef union { __SOCKADDR_ALLTYPES
	      } __SOCKADDR_ARG __attribute__ ((__transparent_union__));
# undef __SOCKADDR_ONETYPE
# define __SOCKADDR_ONETYPE(type) __const struct type *__restrict __##type##__;
typedef union { __SOCKADDR_ALLTYPES
	      } __CONST_SOCKADDR_ARG __attribute__ ((__transparent_union__));
# undef __SOCKADDR_ONETYPE


/* Create a new socket of type TYPE in domain DOMAIN, using
   protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
   Returns a file descriptor for the new socket, or -1 for errors.  */
extern int socket (int __domain, int __type, int __protocol) __THROW;

/* Create two new sockets, of type TYPE in domain DOMAIN and using
   protocol PROTOCOL, which are connected to each other, and put file
   descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
   one will be chosen automatically.  Returns 0 on success, -1 for errors.  */
extern int socketpair (int __domain, int __type, int __protocol,
		       int __fds[2]) __THROW;

/* Give the socket FD the local address ADDR (which is LEN bytes long).  */
extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
     __THROW;

/* Put the local address of FD into *ADDR and its length in *LEN.  */
extern int getsockname (int __fd, __SOCKADDR_ARG __addr,
			socklen_t *__restrict __len) __THROW;

/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
   For connectionless socket types, just set the default address to send to
   and the only address from which to accept transmissions.
   Return 0 on success, -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);

/* Put the address of the peer connected to socket FD into *ADDR
   (which is *LEN bytes long), and its actual length into *LEN.  */
extern int getpeername (int __fd, __SOCKADDR_ARG __addr,
			socklen_t *__restrict __len) __THROW;


/* Return entry from network data base for network with NAME and
   protocol PROTO.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern struct servent *getservbyname (__const char *__name,
				      __const char *__proto);

/* Check the first NFDS descriptors each in READFDS (if not NULL) for read
   readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
   (if not NULL) for exceptional conditions.  If TIMEOUT is not NULL, time out
   after waiting the interval specified therein.  Returns the number of ready
   descriptors, or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int select (int __nfds, fd_set *__restrict __readfds,
		   fd_set *__restrict __writefds,
		   fd_set *__restrict __exceptfds,
		   struct timeval *__restrict __timeout);


/* Send N bytes of BUF to socket FD.  Returns the number sent or -1.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern ssize_t send (int __fd, __const void *__buf, size_t __n, int __flags);

/* Read N bytes into BUF from socket FD.
   Returns the number read or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags);

/* Send N bytes of BUF on socket FD to peer at address ADDR (which is
   ADDR_LEN bytes long).  Returns the number sent, or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern ssize_t sendto (int __fd, __const void *__buf, size_t __n,
		       int __flags, __CONST_SOCKADDR_ARG __addr,
		       socklen_t __addr_len);

/* Read N bytes into BUF through socket FD.
   If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of
   the sender, and store the actual size of the address in *ADDR_LEN.
   Returns the number of bytes read or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n,
			 int __flags, __SOCKADDR_ARG __addr,
			 socklen_t *__restrict __addr_len);


/* Send a message described MESSAGE on socket FD.
   Returns the number of bytes sent, or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern ssize_t sendmsg (int __fd, __const struct msghdr *__message,
			int __flags);

/* Receive a message as described by MESSAGE from socket FD.
   Returns the number of bytes read or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags);


/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL
   into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's
   actual length.  Returns 0 on success, -1 for errors.  */
extern int getsockopt (int __fd, int __level, int __optname,
		       void *__restrict __optval,
		       socklen_t *__restrict __optlen) __THROW;

/* Set socket FD's option OPTNAME at protocol level LEVEL
   to *OPTVAL (which is OPTLEN bytes long).
   Returns 0 on success, -1 for errors.  */
extern int setsockopt (int __fd, int __level, int __optname,
		       __const void *__optval, socklen_t __optlen) __THROW;


/* Prepare to accept connections on socket FD.
   N connection requests will be queued before further requests are refused.
   Returns 0 on success, -1 for errors.  */
extern int listen (int __fd, int __n) __THROW;

/* Await a connection on socket FD.
   When a connection arrives, open a new socket to communicate with it,
   set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
   peer and *ADDR_LEN to the address's actual length, and return the
   new socket's descriptor, or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int accept (int __fd, __SOCKADDR_ARG __addr,
		   socklen_t *__restrict __addr_len);

#define __nonnull(x) 
#define __USE_BSD 1
#define __wur 

#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K

/* Truncate the file FD is open on to LENGTH bytes.  */
# ifndef __USE_FILE_OFFSET64
extern int ftruncate (int __fd, __off_t __length) __THROW __wur;
# else
#  ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (ftruncate, (int __fd, __off64_t __length),
			   ftruncate64) __wur;
#  else
#   define ftruncate ftruncate64
#  endif
# endif
# ifdef __USE_LARGEFILE64
extern int ftruncate64 (int __fd, __off64_t __length) __THROW __wur;
# endif

#endif /* Use BSD || X/Open Unix || POSIX 2003.  */

#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
# ifndef __USE_FILE_OFFSET64
/* Get file attributes about FILE and put them in BUF.
   If FILE is a symbolic link, do not follow it.  */
extern int lstat (__const char *__restrict __file,
		  struct stat *__restrict __buf) __THROW __nonnull ((1, 2));
# else
#  ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (lstat,
			   (__const char *__restrict __file,
			    struct stat *__restrict __buf), lstat64)
     __nonnull ((1, 2));
#  else
#   define lstat lstat64
#  endif
# endif
# ifdef __USE_LARGEFILE64
extern int lstat64 (__const char *__restrict __file,
		    struct stat64 *__restrict __buf)
     __THROW __nonnull ((1, 2));
# endif
#endif


/* Create a device file named PATH, with permission and special bits MODE
   and device number DEV (which can be constructed from major and minor
   device numbers with the `makedev' macro above).  */
#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
extern int mknod (__const char *__path, __mode_t __mode, __dev_t __dev)
     __THROW __nonnull ((1));
#endif

/* Create a new FIFO named PATH, with permission bits MODE.  */
extern int mkfifo (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

/* Set the file creation mask of the current process to MASK,
   and return the old creation mask.  */
extern __mode_t umask (__mode_t __mask) __THROW;

/* Set the access and modification times of FILE to those given in
   *FILE_TIMES.  If FILE_TIMES is NULL, set them to the current time.  */
extern int utime (__const char *__file,
		  __const struct utimbuf *__file_times)
     __THROW __nonnull ((1));

/* Rewind DIRP to the beginning of the directory.  */
extern void rewinddir (DIR *__dirp) __THROW __nonnull ((1));


#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
/* Put the absolute pathname of the current working directory in BUF.
   If successful, return BUF.  If not, put an error message in
   BUF and return NULL.  BUF should be at least PATH_MAX bytes long.  */
extern char *getwd (char *__buf)
     __THROW __nonnull ((1)) __wur;
#endif


#if defined __USE_BSD || defined __USE_UNIX98
/* Put the name of the current host in no more than LEN bytes of NAME.
   The result is null-terminated if LEN is large enough for the full
   name and the terminator.  */
extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1));
#endif


/* Return entry from host data base which address match ADDR with
   length LEN and type TYPE.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern struct hostent *gethostbyaddr (__const void *__addr, __socklen_t __len,
				      int __type);

/* Return entry from host data base for host with NAME.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern struct hostent *gethostbyname (__const char *__name);

#ifdef __USE_GNU
/* Similar to 'accept' but takes an additional parameter to specify flags.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int accept4 (int __fd, __SOCKADDR_ARG __addr,
		    socklen_t *__restrict __addr_len, int __flags);
#endif

/* Shut down all or part of the connection open on socket FD.
   HOW determines what to shut down:
     SHUT_RD   = No more receptions;
     SHUT_WR   = No more transmissions;
     SHUT_RDWR = No more receptions or transmissions.
   Returns 0 on success, -1 for errors.  */
extern int shutdown (int __fd, int __how) __THROW;


#ifdef __USE_XOPEN2K
/* Determine wheter socket is at a out-of-band mark.  */
extern int sockatmark (int __fd) __THROW;
#endif


#ifdef __USE_MISC
/* FDTYPE is S_IFSOCK or another S_IF* macro defined in <sys/stat.h>;
   returns 1 if FD is open on an object of the indicated type, 0 if not,
   or -1 for errors (setting errno).  */
extern int isfdtype (int __fd, int __fdtype) __THROW;
#endif


/* Define some macros helping to catch buffer overflows.  */
#if __USE_FORTIFY_LEVEL > 0 && defined __extern_always_inline
# include <bits/socket2.h>
#endif


#define __USE_POSIX
#define __USE_GNU 

/* Extension from POSIX.1g.  */
#ifdef	__USE_POSIX


# ifdef __USE_GNU


/* Lookup mode.  */
#  define GAI_WAIT	0
#  define GAI_NOWAIT	1
# endif

/* Possible values for `ai_flags' field in `addrinfo' structure.  */
# define AI_PASSIVE	0x0001	/* Socket address is intended for `bind'.  */
# define AI_CANONNAME	0x0002	/* Request for canonical name.  */
# define AI_NUMERICHOST	0x0004	/* Don't use name resolution.  */
# define AI_V4MAPPED	0x0008	/* IPv4 mapped addresses are acceptable.  */
# define AI_ALL		0x0010	/* Return IPv4 mapped and IPv6 addresses.  */
# define AI_ADDRCONFIG	0x0020	/* Use configuration of this host to choose
				   returned address type..  */
# ifdef __USE_GNU
#  define AI_IDN	0x0040	/* IDN encode input (assuming it is encoded
				   in the current locale's character set)
				   before looking it up. */
#  define AI_CANONIDN	0x0080	/* Translate canonical name from IDN format. */
#  define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode
					    code points.  */
#  define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings according to
						STD3 rules.  */
# endif
# define AI_NUMERICSERV	0x0400	/* Don't use name resolution.  */

/* Error values for `getaddrinfo' function.  */
# define EAI_BADFLAGS	  -1	/* Invalid value for `ai_flags' field.  */
# define EAI_NONAME	  -2	/* NAME or SERVICE is unknown.  */
# define EAI_AGAIN	  -3	/* Temporary failure in name resolution.  */
# define EAI_FAIL	  -4	/* Non-recoverable failure in name res.  */
# define EAI_FAMILY	  -6	/* `ai_family' not supported.  */
# define EAI_SOCKTYPE	  -7	/* `ai_socktype' not supported.  */
# define EAI_SERVICE	  -8	/* SERVICE not supported for `ai_socktype'.  */
# define EAI_MEMORY	  -10	/* Memory allocation failure.  */
# define EAI_SYSTEM	  -11	/* System error returned in `errno'.  */
# define EAI_OVERFLOW	  -12	/* Argument buffer overflow.  */
# ifdef __USE_GNU
#  define EAI_NODATA	  -5	/* No address associated with NAME.  */
#  define EAI_ADDRFAMILY  -9	/* Address family for NAME not supported.  */
#  define EAI_INPROGRESS  -100	/* Processing request in progress.  */
#  define EAI_CANCELED	  -101	/* Request canceled.  */
#  define EAI_NOTCANCELED -102	/* Request not canceled.  */
#  define EAI_ALLDONE	  -103	/* All requests done.  */
#  define EAI_INTR	  -104	/* Interrupted by a signal.  */
#  define EAI_IDN_ENCODE  -105	/* IDN encoding failed.  */
# endif

#define __USE_MISC
# ifdef __USE_MISC
#  define NI_MAXHOST      1025
#  define NI_MAXSERV      32
# endif

# define NI_NUMERICHOST	1	/* Don't try to look up hostname.  */
# define NI_NUMERICSERV 2	/* Don't convert port number to name.  */
# define NI_NOFQDN	4	/* Only return nodename portion.  */
# define NI_NAMEREQD	8	/* Don't return numeric addresses.  */
# define NI_DGRAM	16	/* Look up UDP service rather than TCP.  */
# ifdef __USE_GNU
#  define NI_IDN	32	/* Convert name from IDN format.  */
#  define NI_IDN_ALLOW_UNASSIGNED 64 /* Don't reject unassigned Unicode
					code points.  */
#  define NI_IDN_USE_STD3_ASCII_RULES 128 /* Validate strings according to
					     STD3 rules.  */
/* Translate name of a service location and/or a service name to set of
   socket addresses.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int getaddrinfo (__const char *__restrict __name,
			__const char *__restrict __service,
			__const struct addrinfo *__restrict __req,
			struct addrinfo **__restrict __pai);

/* Free `addrinfo' structure AI including associated storage.  */
extern void freeaddrinfo (struct addrinfo *__ai) __THROW;

/* Convert error return from getaddrinfo() to a string.  */
extern __const char *gai_strerror (int __ecode) __THROW;

/* Translate a socket address to a location and service name.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int getnameinfo (__const struct sockaddr *__restrict __sa,
			socklen_t __salen, char *__restrict __host,
			socklen_t __hostlen, char *__restrict __serv,
			socklen_t __servlen, unsigned int __flags);

# endif	 /* POSIX */


#endif
/* We can optimize calls to the conversion functions.  Either nothing has
   to be done or we are using directly the byte-swapping functions which
   often can be inlined.  */
# if __BYTE_ORDER == __BIG_ENDIAN
/* The host byte order is the same as network byte order,
   so these functions are all just identity.  */
# define ntohl(x)	(x)
# define ntohs(x)	(x)
# define htonl(x)	(x)
# define htons(x)	(x)
# else
#  if __BYTE_ORDER == __LITTLE_ENDIAN
#   define ntohl(x)	__bswap_32 (x)
#   define ntohs(x)	__bswap_16 (x)
#   define htonl(x)	__bswap_32 (x)
#   define htons(x)	__bswap_16 (x)
#  endif
# endif
extern int timezone;

/* Convert Internet number in IN to ASCII representation.  The return value
   is a pointer to an internal array containing the string.  */
extern char *inet_ntoa (struct in_addr __in) __THROW;

Added nacl/tcl.nmf.













>
>
>
>
>
>
1
2
3
4
5
6
{
  "program": {
    "x86-32": {"url":"tcl32.nexe"},
    "x86-64": {"url":"tcl64.nexe"}
  }
}

Added nacl/tclUnixPort.h.patch.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--- tclUnixPort.h	2011-04-04 20:36:08.686478500 +0200
+++ tclUnixPort.h	2011-04-06 23:10:38.296769763 +0200
@@ -138,6 +138,7 @@
  *---------------------------------------------------------------------------
  */
 
+#ifndef NACL
 #include <sys/socket.h>		/* struct sockaddr, SOCK_STREAM, ... */
 #ifndef NO_UNAME
 #   include <sys/utsname.h>	/* uname system call. */
@@ -148,6 +149,11 @@
 #ifdef NEED_FAKE_RFC2553
 # include "../compat/fake-rfc2553.h"
 #endif
+#else /* NACL */
+
+#include "naclcompat.h"
+
+#endif /* NACL */
 
 /*
  *---------------------------------------------------------------------------

Added nacl/tools/natcl2tk.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#! /bin/sh
#\
exec wish $0 "$@"

if {!$argc} {
    puts stderr "Usage: [file tail $::argv0] <file.natcl> \[<file.natcl> ...\]"
    exit 1
}
foreach fn $argv {
    set direct($fn) 1
}
set mydir [info script].dir
rename source _source
proc source fn {
    if {![info exists ::direct($fn)]} {
	set fn $::mydir/[file tail $fn]
    }
    uplevel 1 [list _source $fn]
}

proc domset {x y} {wm title . $y}

set ::uniqEv 1
proc every {ms scr} {
    set fn every#$::uniqEv
    incr ::uniqEv
    proc $fn {} "after $ms $fn;uplevel #0 {$scr}"
    after 0 $fn
}

proc printf s {puts stderr $s}
    
source [lindex $argv 0]

Added nacl/tools/natcl2tk.dir/canv.natcl.





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#
# emu/canv.tcl: reimplement NaTcl's canv verbs in Tk
#

set width 578
set height 200

canvas .c -width $width -height $height -bg white
pack .c
update

proc canv_create {ty a b c args} {
    switch -exact -- $ty {
	circle {
	    set cc [list [expr {$a-$c}] [expr {$b-$c}] \
			[expr {$a+$c}] [expr {$b+$c}]]
	    set ty oval
	}
	default {
	    error "Unknown canv item type '$ty'"
	}
    }
    set it [eval .c create $ty $cc $args]
    set ::canvx($it) $a
    set ::canvy($it) $b
    return $it
}

proc canv_moveto {it x y} {
    set dx [expr {$x-$::canvx($it)}]
    set ::canvx($it) $x
    set dy [expr {$y-$::canvy($it)}]
    set ::canvy($it) $y
    .c move $it $dx $dy
}

proc canv_bind {evt cb} {
    switch -exact -- $evt {
	<Motion> {
	    bind .c <Motion> "$cb %x %y"
	}
	<Enter> - <Leave> {
	    bind .c $evt $cb
	}
	default {
	    error "Unknown canv event type '$evt'"
	}
    }
}
	

Added nacl/tools/tocstr.





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
#! /bin/sh
#\
exec tclsh $0 "$@"

while {[gets stdin line]>=0} {
    regsub -all {[""\\]} $line {\\&} line
    puts " \"$line\\n\""
}
flush stdout
exit 0

Added nacl/trivhttpd.tcl.

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#! /bin/sh
#\
exec tclsh $0 "$@"

if {$argc!=1} {puts stderr "Usage: [file tail $::argv0] <port>";exit 1}
set port [lindex $argv 0]

proc serve {sok h p} {
    fconfigure $sok -translation binary -buffering full
    if {[catch {
	if {[gets $sok line]<0} {error "400 Empty request"}
	if {![regexp {^GET[ 	]+([^ 	]+)} $line -> path]} {error "403 Method Not Supported"}
	puts stderr "$h:$p - GET $path"
	if {[regexp {[.][.]} $path]} {error "403 Forbidden"}
	set ty text/plain
	switch -glob  [file extension $path] {
	    .html {set ty text/html}
	    .nexe - .nmf {set ty application/octet-stream}
	}
	if {[catch {set ff [open .$path r]}]} {error "404 File Not Found"}
	fconfigure $ff -translation binary
	set data [read $ff]
	close $ff
    } err]} {
	puts $sok "HTTP/1.0 $err\r\n\r"
    } else {
	puts -nonewline $sok "HTTP/1.0 200 OK\r\nContent-Type: $ty\r\nContent-Length: [string length $data]\r\n\r\n$data"
    }
    close $sok
}
socket -server serve $port
vwait forever