Check-in [841f181044]

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

Overview
Comment:added gets command for easier reading of strings from pointers
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:841f1810445f9b3f55845d34de87bbb99ec57a067047958e756a910c30336afe
User & Date: grable 2018-10-31 00:32:53
Context
2018-10-31
00:34
forgot i renamed this :p check-in: c5c81d4195 user: grable tags: trunk
00:32
added gets command for easier reading of strings from pointers check-in: 841f181044 user: grable tags: trunk
00:04
C will promote float to double when uncertain, this includes callbacks. probably best to use float only when known by all parties. check-in: 469c1dd3d6 user: grable tags: trunk
Changes

Changes to jimff-commands.c.

20
21
22
23
24
25
26

27
28
29
30
31
32
33
..
53
54
55
56
57
58
59

60
61
62
63
64
65
66
...
488
489
490
491
492
493
494



















































495
496
497
498
499
500
501
//NOTE: the "info" command is optional, and a special "free" command is handled seperatly
#define __jimff_commands(_)								\
  /*	name		cmdfn						freefn	*/		\
	_( load,			fn_context_load,		NULL )			\
	_( import,		fn_context_import,		NULL )			\
	_( callback,	fn_context_callback,	NULL )			\
	_( pointer,		fn_context_pointer,	NULL )			\

	_( read,			fn_pointer_read,		NULL )			\
	_( write,		fn_pointer_write,		NULL )			\
	_( copy,			fn_pointer_copy,		NULL )			\
	__jimff_the_info_command(_)

// macros for use by __jimff_commands()
#define __jimff_create_command( _name, _cmdfn, _freefn)								\
................................................................................

static int fn_context_new( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_free( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_load( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_import( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_callback( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_pointer( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);

static int fn_pointer_read( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_pointer_write( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_pointer_copy( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
#ifndef JIMFF_DISABLE_INFO_COMMAND
static int fn_context_info( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
#endif
static int fn_symbol_call( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
................................................................................
		void* name ## _start = (ptr) + (offs);												\
		void* name ## _stop = (ptr) + (size);												\
		if(name ## _start < (ptr)) goto err_offset_oob;									\
		if(name ## _stop > (ptr)) {																\
			if(name ## _start >= name ## _stop) goto err_offset_oob;				\
			if(name ## _start + (len) > name ## _stop) goto err_length_oob;	\
		}




















































static int fn_pointer_read( Jim_Interp* interp, int argc, Jim_Obj* const argv[]) {
	struct jimff_context* ctx = Jim_CmdPrivData(interp);
	void* ptr;
	int size;
	long offset = 0;
	long length;







>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
...
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
//NOTE: the "info" command is optional, and a special "free" command is handled seperatly
#define __jimff_commands(_)								\
  /*	name		cmdfn						freefn	*/		\
	_( load,			fn_context_load,		NULL )			\
	_( import,		fn_context_import,		NULL )			\
	_( callback,	fn_context_callback,	NULL )			\
	_( pointer,		fn_context_pointer,	NULL )			\
	_( gets,			fn_pointer_gets,			NULL )			\
	_( read,			fn_pointer_read,		NULL )			\
	_( write,		fn_pointer_write,		NULL )			\
	_( copy,			fn_pointer_copy,		NULL )			\
	__jimff_the_info_command(_)

// macros for use by __jimff_commands()
#define __jimff_create_command( _name, _cmdfn, _freefn)								\
................................................................................

static int fn_context_new( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_free( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_load( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_import( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_callback( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_context_pointer( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_pointer_gets( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_pointer_read( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_pointer_write( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
static int fn_pointer_copy( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
#ifndef JIMFF_DISABLE_INFO_COMMAND
static int fn_context_info( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
#endif
static int fn_symbol_call( Jim_Interp* interp, int argc, Jim_Obj* const argv[]);
................................................................................
		void* name ## _start = (ptr) + (offs);												\
		void* name ## _stop = (ptr) + (size);												\
		if(name ## _start < (ptr)) goto err_offset_oob;									\
		if(name ## _stop > (ptr)) {																\
			if(name ## _start >= name ## _stop) goto err_offset_oob;				\
			if(name ## _start + (len) > name ## _stop) goto err_length_oob;	\
		}

static int fn_pointer_gets( Jim_Interp* interp, int argc, Jim_Obj* const argv[]) {
	struct jimff_context* ctx = Jim_CmdPrivData(interp);
	void* ptr;
	int size;
	long offset = 0;
	Jim_Obj* varName = NULL;
	
	if(argc < 2) goto wrongnumargs;
	if(argc >= 2) {
		ptr = jimff_getpointer( ctx, argv[1], &size, 0);
		if(size == -1) goto err_not_pointer;
	}
	if(argc >= 3) {
		if(Jim_GetLong( interp, argv[2], &offset) != JIM_OK) {
			if(argc >= 4) return JIM_ERR;
			offset = 0;
			varName = argv[2];
		}
	}
	if(argc == 4) {
		varName = argv[3];
	}
	if(argc > 4) {
wrongnumargs:
		Jim_WrongNumArgs( interp, 1, argv, "pointer ?offset? ?varName?");
		return JIM_ERR;
	}

	check_oob( src, ptr, size, offset, 0);
	Jim_Obj* str = Jim_NewStringObj( interp, (const char*)src_start, -1);
	if(varName) {
		Jim_SetVariable( interp, varName, str);
		Jim_SetResultInt( interp, Jim_Length(str));
	} else {
		Jim_SetResult( interp, str);
	}
	return JIM_OK;
	
err_offset_oob:
	Jim_SetResultFormatted( interp, "%#s: offset for pointer \"%#s\" is out of bounds", argv[0], argv[1]);
	return JIM_ERR;
	
err_length_oob:
	Jim_SetResultFormatted( interp, "%#s: length for pointer \"%#s\" is out of bounds", argv[0], argv[1]);
	return JIM_ERR;
	
err_not_pointer:
	Jim_SetResultFormatted( interp, "%#s: argument #1 \"%#s\" is not a valid pointer", argv[0], argv[1]);
	return JIM_ERR;
}

static int fn_pointer_read( Jim_Interp* interp, int argc, Jim_Obj* const argv[]) {
	struct jimff_context* ctx = Jim_CmdPrivData(interp);
	void* ptr;
	int size;
	long offset = 0;
	long length;

Changes to jimff_test.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



lappend auto_path .
package require jimff

#
# testing jimff pointers
#
jimff ff


set lib [ff::load test_lib.dll]
puts "lib = $lib"
ff::import -function $lib {__malloc malloc} {
	#
	# standard malloc
	#
	P	;# returns pointer to newly allocated memory with full ownership
	i	;# size of memory to allocate
}
ff::import -function $lib {__realloc realloc} PPi
ff::import -function $lib {__free free} vP
ff::import -function $lib {__strdup strdup} Pp
ff::import -function $lib {__strdup strdup_z} Pz
ff::import -function $lib {__strdup z_strdup} Zp
ff::import -function $lib {__strlen strlen} ip
ff::import -function $lib {__strcpy strcpy} ppp
ff::import -function $lib {__strcpy strcpy_z} ppz
ff::import -function $lib {__strncpy strncpy} pppi
ff::import -function $lib {__strncpy strncpy_z} ppzi
ff::import -function $lib {__strcat strcat} ppp
ff::import -function $lib {__strcat strcat_z} ppz
ff::import -function $lib {__strcmp strcmp} ipp
ff::import -function $lib {__strcmp strcmp_z} ipz
ff::import -function $lib {__strncmp strncmp} ippi
ff::import -function $lib {__strncmp strncmp_z} ipzi
ff::import -function $lib {__strchr strchr} ppc
ff::import -function $lib {__strrchr strrchr} ppc
ff::import -function $lib {strid ptr2str} zp
ff::import -function $lib {strid str2ptr} Pz





set p [ff::pointer -alloc 64]
puts "p = $p"
ff::pointer -realloc $p 128




puts "p = $p"
ff::pointer -free $p

set n [ff::pointer -null]

puts "n = $n"
puts "size = [ff::pointer -size $n]"
puts "valid = [ff::pointer -valid $n]"
puts "null = [ff::pointer -null $n]"
set n [ff::pointer -realloc $n 256]

puts "n = $n"
puts "size = [ff::pointer -size $n]"
puts "valid = [ff::pointer -valid $n]"
puts "null = [ff::pointer -null $n]"








<
|
|
|
>


<
<
|
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
|
<
|
<
<
<
<
<
<
<

>
>
>

|
<
|
>
>
>
>
|
<

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

lappend auto_path .
package require jimff


jimff ff

puts "jimff commands:"
ff::info -help

set lib [ff::load test_lib.dll]









ff::import -function $lib {__malloc	malloc}	Pi




ff::import -function $lib {__strcpy	strcpy}	ppz



ff::import -function $lib {__strcat	strcat}	ppz

ff::import -function $lib {__free		free}		vP








ff::import -function test_callback vzx
set test_1 [ff::callback test_1 iizd]
puts callback=$test_1

set p [malloc 64]

ff::pointer -size $p 64
strcpy $p "Hello"
strcat $p " World!"
puts p=[ff::gets $p]
puts gets->s=[ff::gets $p 6 s]
puts s=$s



proc test_1 {i z f} {
   puts "\ti=$i"




   puts "\tz=\"$z\""
   puts "\tf=$f"



   expr $i + 1
}
test_callback "message" $test_1

Deleted jimff_test_1.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

lappend auto_path .
package require jimff

proc printlist {m l {n 1}} {
	puts $m:
	foreach [lrange {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} 0 $n-1] $l {
		puts -nonewline \t
		loop i 1 $($n + 1) {
			puts -nonewline [set $i]
			if {$i < $n} { puts -nonewline { } }
		}
		puts {}
	}
}

#
# testing jimff
#
jimff ff
set lib [ff::load test_lib.dll]; puts "loaded $lib"
ff::import print vz
ff::import $lib {print ff::print} vz
ff::import -variable test_var_i i
ff::import -variable test_var_f f
ff::import -variable test_var_z z
ff::import -variable test_var_p p
ff::import -pointer test_array 1024
ff::import -function read_int ipi
ff::import -function write_int vpii
ff::import -function read_str zpii
ff::import -function write_str vpizi
ff::import -function {__malloc malloc} Pi
ff::import -function {__free free} vP
ff::import -function test_callback vzx
set test_1 [ff::callback test_1 iizd]; puts "callback $test_1"
puts {}

#
# testing context info
#
printlist libraries [ff::info -libraries] 2
printlist functions [ff::info -functions -typetags] 2
printlist variables [ff::info -variables -typetags] 2
printlist callbacks [ff::info -callbacks -typetags] 2
puts {}

#
# testing functions
#
print "printed using:\t::print"
ff::print "printed using:\tff::print"
puts {}

#
# testing variables 
#
puts "test_var_i = [test_var_i]"
puts "test_var_f = [test_var_f]"
puts "test_var_z = \"[test_var_z]\""
puts "changing the variables..."
test_var_i 200
test_var_f 3.21
test_var_z "Goodbye World?"
puts "test_var_i = [test_var_i]"
puts "test_var_f = [test_var_f]"
puts "test_var_z = \"[test_var_z]\""
puts {}

#
# testing pointer variables and external pointers
#
puts "test_array size = [ff::pointer -size $test_array]"
puts "test_array = $test_array"
loop offs 0 128 16 {
	puts "read $offs..$($offs + 15)\t\"[string map {\n \\n} [read_str $test_array $offs 16]]\""
}
puts "test_var_p=[test_var_p] -> \"[string map {\n \\n} [read_str [test_var_p] 0 32]]\""
puts "setting test_var_p to test_array"
test_var_p $test_array
puts "test_var_p=[test_var_p] -> \"[string map {\n \\n} [read_str [test_var_p] 0 32]]\""
puts {}

#
# testing callback
#
proc test_1 {i z f} {
	puts "\ti=$i"
	puts "\tz=\"$z\""
	puts "\tf=$f"
#	hello cruel world			;# <-- uncomment this to throw an error that should propogate through the callback and to the calling interpreter
	expr $i + 1
}
test_callback "message" $test_1
puts {}

#
# testing updating callback command
#
proc test_2 {i z f} {
	puts "\ttest_2 ti=$i z=\"$z\" f=$f"
	expr $i + 10
}
ff::callback -update $test_1 test_2
test_callback "message 2" $test_1
puts {}

#
# testing allocated pointers and some pointer commands
#
set p [ff::pointer -alloc 64]
puts "p id = $p"
puts "p size = [ff::pointer -size $p]"
puts "writing to p"
ff::write $p "hello\0"
puts "p read 5 = [ff::read $p 5]"
puts "writing to p"
ff::write $p 5 " world!\0"
puts "p read 12 = [ff::read $p 12]"
puts "copying from test_array to p"
ff::copy $p 12 $test_array 6 39
puts "p read 51 = [ff::read $p 51]"
puts "freeing p"
puts {}


#
# testing using a callback value of an already freed context
# 
ff::free
jimff ff
ff::load test_lib.dll
ff::import test_callback vzx
puts "** next line should fail!"
#set test_1 [ff::callback test_1 iizf]  ;# <-- skipping this step to use the last one defined, next line should should fail
test_callback "message" $test_1
puts {}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<