Tcl Source Code

Check-in [d6b778727b]
Login

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

Overview
Comment:Update to new (incompatible, stabilized) ABI. Now requires Chrome 15 or above.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | ferrieux-nacl
Files: files | file ages | folders
SHA1: d6b778727b6a5879d15fb2bbc0a583b1974496c8
User & Date: ferrieux 2011-10-18 06:33:49
Context
2011-10-18
22:03
Streamline demo setup; update README to reflect API changes. check-in: 91aea72dbd user: ferrieux tags: ferrieux-nacl
06:33
Update to new (incompatible, stabilized) ABI. Now requires Chrome 15 or above. check-in: d6b778727b user: ferrieux tags: ferrieux-nacl
2011-10-07
12:16
Merge updates from trunk check-in: 59daece720 user: ferrieux tags: ferrieux-nacl
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to 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
--- Makefile	2011-04-10 13:21:12.773175132 +0200
+++ tweaked.Makefile	2011-04-10 12:34:27.256426620 +0200
@@ -102,12 +102,20 @@
 #CFLAGS			= $(CFLAGS_DEBUG)
 #CFLAGS			= $(CFLAGS_OPTIMIZE)
 #CFLAGS			= $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
-CFLAGS			= $(CFLAGS_OPTIMIZE) -Wno-long-long -pthread -DNACL -pipe -fvisibility=hidden 
+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 \
+	  -lppruntime \
+          -lpthread \
+          -lgoogle_nacl_platform \
+          -lgio \
+          -lsrpc
 
 # 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}


|



|










<
|
<
|
<







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
--- 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}

Changes to nacl/configure.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
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 -p0 < Makefile.patch
set +x
echo "
   Makefile generated and patched for NaCl. Ready for 'make' :)
">&2
exit 0








|






28
29
30
31
32
33
34
35
36
37
38
39
40
41
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

Changes to 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
<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="loader.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='balls.natcl'>

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


   <p style="font-size : smaller;">
      To run this demo, you need
      <ul style="font-size : smaller;">
        <li> An x86-family processor</li>
        <li> Chrome 10 or higher</li>
        <li> Enabled "Native Client" item in about:flags</li>
        <li> (if on Linux) the --no-sandbox command-line flag to Chrome</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');






>
>
>
>
>

|



|

<


>




>





|

<







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
<!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');

Changes to nacl/demo/balls.natcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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}]










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 33

# ball globals
set ballRadius 10

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

Changes to 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
<!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 moduleDidLoad() {
      tclModule = document.getElementById('tcl');

      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 {
        alert(tclModule.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.













>
>
>
>
>
>
>
>
>



>


>
>


















|







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
<!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.
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
    }
  </script>
</head>
<body onload="pageDidLoad()">

<h1>Native Client Tcl Module</h1>
<p>
  <form name="the_form" action="" method="get">
  <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 'nacl' 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 'nacl' attribute to the
  _dbg.nmf version of the manifest file.





  -->






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

         onload="moduleDidLoad();" />
</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>







|



>
|



|

>
>
>
>
>

>
>
>
>
>
>
|
|
|
|
|
>
|









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
    }
  </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>

Changes to 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
// 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.evall('printf', arguments.join(' '));
}

function ljoin()
{
    // yeah. 'arguments' is 'similar to an array but not quite'
    // that's why I think JS has no soul.

    return Array.prototype.slice.call(arguments).join("\n");
}

// --- 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,'\\$0');
}

function tclDo(s) {
    try {
        //printf("do:"+s);
	t = tclModule.eval("::nacl::wrap {" + s + "}");
	//printf("ret:"+t);
	eval(t);
    } catch(err) {
	//printf("JS-err:"+err);
	setTimeout('tcl("::nacl::bgerror,"'+ err + ',' + t + ')',0);
    }



}


function tcl() {
    var t;
    try {
        //printf.apply(this, arguments);
        t = tclModule.evall.apply(tclModule, arguments);
    } catch (err) {
	//printf("JS-err:", err);
	setTimeout('tcl("::nacl::bgerror,"'+ err + ',' + t + ')',0);
    }

    try {
        //printf("ret:", t);
	eval(t);
    } catch(err) {
	//printf("JS-err:", err);
	setTimeout('tcl("::nacl::bgerror,"'+ err + ',' + t + ')',0);

    }
}

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








<
<
<
<
<
<
<
<
|














<
<
|
<
<
<
<
<
|
>
>
>


>
|
<

<
<
<
<
<
|
|
<
|
|

|
<
>







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
// 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,'\\$0');
}

function tclDo(s) {


	tclModule.postMessage("eval:::nacl::wrap {" + 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;

		//printf("ret:"+t);
		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) {
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
    }
}

// --- 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');
    xs = new XMLHttpRequest();
    xs.open("GET",url,true);
    xs.send(null);
    xs.onreadystatechange = function() {
	//printf("XHR-source:"+xs.readyState);
	if (xs.readyState==4)
        {







|







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    }
}

// --- 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)
        {
149
150
151
152
153
154
155

156
157
158
159
160
161
162
    return result;
}

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

function moduleDidLoad() {
    tclModule = document.getElementById('tcl');

    // 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) {







>







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
    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) {

Changes to nacl/demo/tcl.nmf.

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

|
|
|


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

Changes to nacl/naclMain.c.

1
2
3
4

5
6
7

8
9



10
11

12








13
14
15
16
17
18
19
#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_var.h>
#include <ppapi/c/pp_module.h>

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



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











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

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


|
|
>

|
|
>


>
>
>


>

>
>
>
>
>
>
>
>







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
#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;
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
}


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(char *s)
{
  if (!interp) return "No Tcl Interp!!!";
  Tcl_Eval(interp,s);
  return Tcl_GetStringResult(interp);
}


static PP_Bool Instance_DidCreate(PP_Instance instance,
                                  uint32_t argc,
                                  const char* argn[],
                                  const char* argv[]);
static void Instance_DidDestroy(PP_Instance instance);
static void Instance_DidChangeView(PP_Instance instance,
                                   const struct PP_Rect* position,
                                   const struct PP_Rect* clip);
static void Instance_DidChangeFocus(PP_Instance instance,
                                    PP_Bool has_focus);
static PP_Bool Instance_HandleInputEvent(PP_Instance instance,
                                         const struct PP_InputEvent* event);
static struct PP_Var Instance_GetInstanceObject(PP_Instance instance);

static PP_Module module_id = 0;
static struct PPB_Var_Deprecated* var_interface = NULL;
static struct PPP_Class_Deprecated ppp_class;
static struct PPP_Instance instance_interface = {
  &Instance_DidCreate,
  &Instance_DidDestroy,
  &Instance_DidChangeView,
  &Instance_DidChangeFocus,
  &Instance_HandleInputEvent,
  NULL,  /* HandleDocumentLoad is not supported by NaCl modules. */
  &Instance_GetInstanceObject,
};


/**
 * Returns C string contained in the @a var or NULL if @a var is not string.




 * @param[in] var PP_Var containing string.
 * @return a C string representation of @a var.
 * @note Returned pointer will be invalid after destruction of @a var.
 */
static const char* VarToCStr(struct PP_Var var) {
  uint32_t len = 0;
  if (NULL != var_interface)
    return var_interface->VarToUtf8(var, &len);







  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.







|

|









|





|










|







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
>
>
>
>


|

|

|
|
>
>
>
>
>
>
>







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
}


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.
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
 *     event focus.
 */
static void Instance_DidChangeFocus(PP_Instance instance,
                                    PP_Bool has_focus) {
}

/**
 * General handler for input events. Returns true if the event was handled or
 * false if it was not.
 *
 * If the event was handled, it will not be forwarded to the web page or
 * browser. If it was not handled, it will bubble according to the normal
 * rules. So it is important that the NaCl module respond accurately with
 * whether event propogation should continue.
 *
 * Event propogation also controls focus. If you handle an event like a mouse
 * event, typically your NaCl module will be given focus. Returning false means
 * that the click will be given to a lower part of the page and your NaCl
 * module will not receive focus. This allows a plugin to be partially
 * transparent, where clicks on the transparent areas will behave like clicks

 * to the underlying page.
 * @param[in] instance The identifier of the instance representing this NaCl
 *     module.
 * @param[in] event The event.
 * @return PP_TRUE if @a event was handled, PP_FALSE otherwise.
 */
static PP_Bool Instance_HandleInputEvent(PP_Instance instance,
                                         const struct PP_InputEvent* event) {
  /* We don't handle any events. */
  return PP_FALSE;
}

/**


 * Create scriptable object for the given instance.
 * @param[in] instance The instance ID.
 * @return A scriptable object.


 */
static struct PP_Var Instance_GetInstanceObject(PP_Instance instance) {
    printf("NaTcl(%d): DBUG: NaTcl GetInstanceObject %x\n",getpid(), (unsigned int)instance);
  if (var_interface) {
    return var_interface->CreateObject(instance, &ppp_class, NULL);
  }
  return PP_MakeUndefined();
}

/**
 * Check existence of the function associated with @a name.
 * @param[in] object unused
 * @param[in] name method name
 * @param[out] exception pointer to the exception object, unused
 * @return If the method does exist, return true.
 * If the method does not exist, return false and don't set the exception.
 */
static bool Tcl_HasMethod(void* object,
                                 struct PP_Var name,
                                 struct PP_Var* exception) {
  const char* method_name = VarToCStr(name);
  if (NULL != method_name) {
      if (strcmp(method_name, "eval") == 0)
          return true;
      else if (strcmp(method_name, "evall") == 0)
          return true;
  }

  return false;


}





/**
 * Invoke the function associated with @a name.
 * @param[in] object unused
 * @param[in] name method name
 * @param[in] argc number of arguments
 * @param[in] argv array of arguments
 * @param[out] exception pointer to the exception object, unused
 * @return If the method does exist, return true.
 */
static struct PP_Var Tcl_Call(void* object,
                                     struct PP_Var name,
                                     uint32_t argc,
                                     struct PP_Var* argv,
                                     struct PP_Var* exception) {
  struct PP_Var v = PP_MakeUndefined();
  const char* method_name = VarToCStr(name);
  if (NULL != method_name) {
    if (strcmp(method_name, "eval") == 0) {
      if (argc == 1) {
        if (argv[0].type != PP_VARTYPE_STRING) {
          v = StrToVar("Arg from Javascript is not a string!");
        } else {
          char* str = strdup(VarToCStr(argv[0]));
          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, Tcl_GetStringResult(interp));
          }
          v = StrToVar(res);
          free(str);
        }
      } else {
        v = StrToVar("Unexpected number of args");

      }
    } else if (strcmp(method_name, "evall") == 0) {
        Tcl_Obj *args[argc+1];
        uint32_t len = 0;
        int i;

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

        for (i = 0; i < argc; i++) {
            if (argv[i].type == PP_VARTYPE_STRING) {
                const char *bytes = var_interface->VarToUtf8(argv[i], &len);
                args[i+1] = Tcl_NewStringObj(bytes, len);
                Tcl_IncrRefCount(args[i+1]);
                if (verbose) {
                    printf("NaTcl(%d): EVALL arg: '%s'\n",pid, bytes);
                }
            } else {
                v = StrToVar("Arg from Javascript is not a string!");
            }
        }

        Tcl_EvalObjv(interp, argc+1, args, 0);

        if (verbose) {
            printf("NaTcl(%d): EVALL result: '%s'\n",pid, Tcl_GetStringResult(interp));
        }

        for (i = 0; i < argc+1; i++) {
            Tcl_DecrRefCount(args[i]);
        }
        v = StrToVar(Tcl_GetStringResult(interp));
    } else {
        v = StrToVar("Unknown method");
    }
  }

  return 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;


  var_interface =
      (struct PPB_Var_Deprecated*)(get_browser(PPB_VAR_DEPRECATED_INTERFACE));

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

  memset(&ppp_class, 0, sizeof(ppp_class));
  ppp_class.Call = Tcl_Call;
  ppp_class.HasMethod = Tcl_HasMethod;
  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)







    return &instance_interface;






  return NULL;
}

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







|
<
<
<
<
|
<
<
<
<
<
<
<
>
|


|
|

|
|
|




>
>
|

<
>
>

|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
|
>
|
>
>
|
>
>
>
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
|
|
|
|
|
|
|
|
|
<
|
|
>
|
<
<
<
|
|
<
<
|
<
|
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<













>
>

|





<
<
<










|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>









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
 *     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);
}

Changes to nacl/tcl.nmf.

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

|
|
|


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