1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
32 //-----------------------------------------------------------------------------
37 #include "util_buffers.h"
38 #include "util_console.h"
39 #include "util_math.h"
40 #include "util_string.h"
41 #include "util_thread.h"
42 #include "chuck_type.h"
43 #include "chuck_instr.h"
44 #include "chuck_globals.h"
46 #if defined(__PLATFORM_WIN32__)
50 int setenv( const char *n
, const char *v
, int i
)
52 return !SetEnvironmentVariable(n
, v
);
61 // for ConsoleInput and StringTokenizer
64 #include "util_thread.h"
69 CK_DLL_CTOR( KBHit_ctor
);
70 CK_DLL_DTOR( KBHit_dtor
);
71 CK_DLL_MFUN( KBHit_on
);
72 CK_DLL_MFUN( KBHit_off
);
73 CK_DLL_MFUN( KBHit_state
);
74 CK_DLL_MFUN( KBHit_hit
);
75 CK_DLL_MFUN( KBHit_more
);
76 CK_DLL_MFUN( KBHit_getchar
);
77 CK_DLL_MFUN( KBHit_can_wait
);
79 static t_CKUINT KBHit_offset_data
= 0;
82 CK_DLL_CTOR( Skot_ctor
);
83 CK_DLL_DTOR( Skot_dtor
);
84 CK_DLL_MFUN( Skot_prompt
);
85 CK_DLL_MFUN( Skot_prompt2
);
86 CK_DLL_MFUN( Skot_more
);
87 CK_DLL_MFUN( Skot_getLine
);
88 CK_DLL_MFUN( Skot_can_wait
);
90 static t_CKUINT Skot_offset_data
= 0;
93 CK_DLL_CTOR( StrTok_ctor
);
94 CK_DLL_DTOR( StrTok_dtor
);
95 CK_DLL_MFUN( StrTok_set
);
96 CK_DLL_MFUN( StrTok_reset
);
97 CK_DLL_MFUN( StrTok_more
);
98 CK_DLL_MFUN( StrTok_next
);
99 CK_DLL_MFUN( StrTok_next2
);
100 CK_DLL_MFUN( StrTok_get
);
101 CK_DLL_MFUN( StrTok_get2
);
102 CK_DLL_MFUN( StrTok_size
);
104 static t_CKUINT StrTok_offset_data
= 0;
111 CK_DLL_CTOR( VCR_ctor
);
112 CK_DLL_MFUN( VCR_load
);
113 CK_DLL_MFUN( VCR_reset
);
114 CK_DLL_MFUN( VCR_seek
);
115 CK_DLL_MFUN( VCR_more
);
116 CK_DLL_MFUN( VCR_curr
);
117 CK_DLL_MFUN( VCR_next
);
118 CK_DLL_MFUN( VCR_pos
);
119 CK_DLL_MFUN( VCR_size
);
120 CK_DLL_MFUN( VCR_name
);
122 static t_CKUINT VCR_offset_data
= 0;
125 CK_DLL_CTOR( Cereal_ctor
);
126 CK_DLL_MFUN( Cereal_open
);
127 CK_DLL_MFUN( Cereal_close
);
128 CK_DLL_MFUN( Cereal_send
);
129 CK_DLL_MFUN( Cereal_recv
);
130 CK_DLL_MFUN( Cereal_more
);
132 static t_CKUINT Cereal_offset_data
= 0;
139 //-----------------------------------------------------------------------------
140 // name: libstd_query()
141 // desc: query entry point
142 //-----------------------------------------------------------------------------
143 DLL_QUERY
libstd_query( Chuck_DL_Query
* QUERY
)
146 Chuck_Env
* env
= Chuck_Env::instance();
148 QUERY
->setname( QUERY
, "Std" );
151 std.rand2f( 100.0, 1000.0 ) => stdout;
154 // register deprecate
155 type_engine_register_deprecate( env
, "std", "Std" );
158 QUERY
->begin_class( QUERY
, "Std", "Object" );
161 QUERY
->add_sfun( QUERY
, abs_impl
, "int", "abs" );
162 QUERY
->add_arg( QUERY
, "int", "value" );
165 QUERY
->add_sfun( QUERY
, fabs_impl
, "float", "fabs" );
166 QUERY
->add_arg( QUERY
, "float", "value" );
169 QUERY
->add_sfun( QUERY
, rand_impl
, "int", "rand"); //! return int between 0 and RAND_MAX
172 QUERY
->add_sfun( QUERY
, rand2_impl
, "int", "rand2" ); //! integer between [min,max]
173 QUERY
->add_arg( QUERY
, "int", "min" );
174 QUERY
->add_arg( QUERY
, "int", "max" );
177 QUERY
->add_sfun( QUERY
, randf_impl
, "float", "randf" ); //! rand between -1.0,1.0
180 QUERY
->add_sfun( QUERY
, rand2f_impl
, "float", "rand2f" ); //! rand between min and max
181 QUERY
->add_arg( QUERY
, "float", "min" );
182 QUERY
->add_arg( QUERY
, "float", "max" );
185 QUERY
->add_sfun( QUERY
, srand_impl
, "void", "srand" );
186 QUERY
->add_arg( QUERY
, "int", "seed" );
189 QUERY
->add_sfun( QUERY
, sgn_impl
, "float", "sgn" ); //! return sign of value (-1, 0, 1)
190 QUERY
->add_arg( QUERY
, "float", "value" );
193 //! see \example std.ck
194 QUERY
->add_sfun( QUERY
, system_impl
, "int", "system" ); //! issue system command
195 QUERY
->add_arg( QUERY
, "string", "cmd" );
198 QUERY
->add_sfun( QUERY
, atoi_impl
, "int", "atoi" ); //! string to integer
199 QUERY
->add_arg( QUERY
, "string", "value" );
202 QUERY
->add_sfun( QUERY
, atof_impl
, "float", "atof" ); //! string to float
203 QUERY
->add_arg( QUERY
, "string", "value" );
206 QUERY
->add_sfun( QUERY
, itoa_impl
, "string", "itoa" ); //! int to string
207 QUERY
->add_arg( QUERY
, "int", "i" );
210 QUERY
->add_sfun( QUERY
, ftoa_impl
, "string", "ftoa" ); //! float to string
211 QUERY
->add_arg( QUERY
, "float", "f" );
212 QUERY
->add_arg( QUERY
, "int", "precision" );
215 QUERY
->add_sfun( QUERY
, getenv_impl
, "string", "getenv" ); //! fetch environment variable
216 QUERY
->add_arg( QUERY
, "string", "value" );
219 QUERY
->add_sfun( QUERY
, setenv_impl
, "int", "setenv" ); //! set environment variable
220 QUERY
->add_arg( QUERY
, "string", "key" );
221 QUERY
->add_arg( QUERY
, "string", "value" );
224 //! see \example mand-o-matic.ck
225 QUERY
->add_sfun( QUERY
, mtof_impl
, "float", "mtof" ); //! midi note to frequency
226 QUERY
->add_arg( QUERY
, "float", "value" );
229 QUERY
->add_sfun( QUERY
, ftom_impl
, "float", "ftom" ); //! frequency to midi note
230 QUERY
->add_arg( QUERY
, "float", "value" );
233 QUERY
->add_sfun( QUERY
, powtodb_impl
, "float", "powtodb" ); //! linear power to decibel
234 QUERY
->add_arg( QUERY
, "float", "value" );
237 QUERY
->add_sfun( QUERY
, rmstodb_impl
, "float", "rmstodb" ); //! rms to decibel
238 QUERY
->add_arg( QUERY
, "float", "value" );
241 QUERY
->add_sfun( QUERY
, dbtopow_impl
, "float", "dbtopow" ); //! decibel to linear
242 QUERY
->add_arg( QUERY
, "float", "value" );
245 QUERY
->add_sfun( QUERY
, dbtorms_impl
, "float", "dbtorms" ); //! decibel to rms
246 QUERY
->add_arg( QUERY
, "float", "value" );
249 QUERY
->end_class( QUERY
);
252 srand( time( NULL
) );
254 Chuck_DL_Func
* func
= NULL
;
257 // begin class (KBHit)
258 if( !type_engine_import_class_begin( env
, "KBHit", "Event",
259 env
->global(), KBHit_ctor
,
263 // add member variable
264 KBHit_offset_data
= type_engine_import_mvar( env
, "int", "@KBHit_data", FALSE
);
265 if( KBHit_offset_data
== CK_INVALID_OFFSET
) goto error
;
268 func
= make_new_mfun( "void", "on", KBHit_on
);
269 if( !type_engine_import_mfun( env
, func
) ) goto error
;
272 func
= make_new_mfun( "void", "off", KBHit_off
);
273 if( !type_engine_import_mfun( env
, func
) ) goto error
;
276 func
= make_new_mfun( "void", "state", KBHit_state
);
277 if( !type_engine_import_mfun( env
, func
) ) goto error
;
280 func
= make_new_mfun( "Event", "hit", KBHit_hit
);
281 if( !type_engine_import_mfun( env
, func
) ) goto error
;
284 func
= make_new_mfun( "int", "more", KBHit_more
);
285 if( !type_engine_import_mfun( env
, func
) ) goto error
;
288 func
= make_new_mfun( "int", "getchar", KBHit_getchar
);
289 if( !type_engine_import_mfun( env
, func
) ) goto error
;
292 func
= make_new_mfun( "int", "can_wait", KBHit_can_wait
);
293 if( !type_engine_import_mfun( env
, func
) ) goto error
;
296 type_engine_import_class_end( env
);
299 KBHitManager::init();
302 // register deprecate
303 type_engine_register_deprecate( env
, "Skot", "ConsoleInput" );
305 // begin class (Skot)
306 if( !type_engine_import_class_begin( env
, "ConsoleInput", "Event",
307 env
->global(), Skot_ctor
,
311 // add member variable
312 Skot_offset_data
= type_engine_import_mvar( env
, "int", "@Skot_data", FALSE
);
313 if( Skot_offset_data
== CK_INVALID_OFFSET
) goto error
;
316 func
= make_new_mfun( "Event", "prompt", Skot_prompt
);
317 if( !type_engine_import_mfun( env
, func
) ) goto error
;
320 func
= make_new_mfun( "Event", "prompt", Skot_prompt2
);
321 func
->add_arg( "string", "what" );
322 if( !type_engine_import_mfun( env
, func
) ) goto error
;
325 func
= make_new_mfun( "int", "more", Skot_more
);
326 if( !type_engine_import_mfun( env
, func
) ) goto error
;
329 func
= make_new_mfun( "string", "getLine", Skot_getLine
);
330 if( !type_engine_import_mfun( env
, func
) ) goto error
;
333 func
= make_new_mfun( "int", "can_wait", Skot_can_wait
);
334 if( !type_engine_import_mfun( env
, func
) ) goto error
;
337 type_engine_import_class_end( env
);
340 // register deprecate
341 type_engine_register_deprecate( env
, "PRC", "StringTokenizer" );
343 // begin class (StrTok)
344 if( !type_engine_import_class_begin( env
, "StringTokenizer", "Object",
345 env
->global(), StrTok_ctor
,
349 // add member variable
350 StrTok_offset_data
= type_engine_import_mvar( env
, "int", "@StrTok_data", FALSE
);
351 if( StrTok_offset_data
== CK_INVALID_OFFSET
) goto error
;
354 func
= make_new_mfun( "void", "set", StrTok_set
);
355 func
->add_arg( "string", "line" );
356 if( !type_engine_import_mfun( env
, func
) ) goto error
;
359 func
= make_new_mfun( "void", "reset", StrTok_reset
);
360 if( !type_engine_import_mfun( env
, func
) ) goto error
;
363 func
= make_new_mfun( "int", "more", StrTok_more
);
364 if( !type_engine_import_mfun( env
, func
) ) goto error
;
367 func
= make_new_mfun( "string", "next", StrTok_next
);
368 if( !type_engine_import_mfun( env
, func
) ) goto error
;
371 func
= make_new_mfun( "string", "next", StrTok_next2
);
372 func
->add_arg( "string", "out" );
373 if( !type_engine_import_mfun( env
, func
) ) goto error
;
376 func
= make_new_mfun( "string", "get", StrTok_get
);
377 func
->add_arg( "int", "index" );
378 if( !type_engine_import_mfun( env
, func
) ) goto error
;
381 func
= make_new_mfun( "string", "get", StrTok_get2
);
382 func
->add_arg( "int", "index" );
383 func
->add_arg( "string", "out" );
384 if( !type_engine_import_mfun( env
, func
) ) goto error
;
387 func
= make_new_mfun( "int", "size", StrTok_size
);
388 if( !type_engine_import_mfun( env
, func
) ) goto error
;
391 type_engine_import_class_end( env
);
398 if( !type_engine_import_class_begin( env
, "VCR", "Object",
399 env
->global(), VCR_ctor
) )
402 // add member variable
403 VCR_offset_data
= type_engine_import_mvar( env
, "int", "@me", FALSE
);
404 if( VCR_offset_data
== CK_INVALID_OFFSET
) goto error
;
407 func
= make_new_mfun( "int", "load", VCR_load
);
408 func
->add_arg( "string", "filename" );
409 func
->add_arg( "int", "column" );
410 if( !type_engine_import_mfun( env
, func
) ) goto error
;
413 func
= make_new_mfun( "int", "reset", VCR_reset
);
414 if( !type_engine_import_mfun( env
, func
) ) goto error
;
417 func
= make_new_mfun( "int", "seek", VCR_seek
);
418 func
->add_arg( "int", "where" );
419 if( !type_engine_import_mfun( env
, func
) ) goto error
;
422 func
= make_new_mfun( "int", "more", VCR_more
);
423 if( !type_engine_import_mfun( env
, func
) ) goto error
;
426 func
= make_new_mfun( "float", "curr", VCR_curr
);
427 if( !type_engine_import_mfun( env
, func
) ) goto error
;
430 func
= make_new_mfun( "int", "next", VCR_next
);
431 if( !type_engine_import_mfun( env
, func
) ) goto error
;
434 func
= make_new_mfun( "int", "pos", VCR_pos
);
435 if( !type_engine_import_mfun( env
, func
) ) goto error
;
438 func
= make_new_mfun( "int", "size", VCR_size
);
439 if( !type_engine_import_mfun( env
, func
) ) goto error
;
442 func
= make_new_mfun( "string", "name", VCR_name
);
443 if( !type_engine_import_mfun( env
, func
) ) goto error
;
445 // end the class import
446 type_engine_import_class_end( env
);
449 #if defined(__PLATFORM_WIN32__)
450 // begin class (Cereal)
451 if( !type_engine_import_class_begin( env
, "Cereal", "Object",
452 env
->global(), Cereal_ctor
) )
456 Cereal_offset_data
= type_engine_import_mvar( env
, "int", "@Cereal_data", FALSE
);
457 if( Cereal_offset_data
== CK_INVALID_OFFSET
) goto error
;
460 func
= make_new_mfun( "int", "open", Cereal_open
);
461 func
->add_arg( "string", "name" );
462 func
->add_arg( "int", "baudrate" );
463 if( !type_engine_import_mfun( env
, func
) ) goto error
;
466 func
= make_new_mfun( "void", "close", Cereal_close
);
467 if( !type_engine_import_mfun( env
, func
) ) goto error
;
470 func
= make_new_mfun( "int", "more", Cereal_more
);
471 if( !type_engine_import_mfun( env
, func
) ) goto error
;
474 func
= make_new_mfun( "int", "send", Cereal_send
);
475 func
->add_arg( "int", "bite" );
476 if( !type_engine_import_mfun( env
, func
) ) goto error
;
479 func
= make_new_mfun( "int", "recv", Cereal_recv
);
480 if( !type_engine_import_mfun( env
, func
) ) goto error
;
483 type_engine_import_class_end( env
);
496 // end the class import
497 type_engine_import_class_end( env
);
503 #define RAND_INV_RANGE(r) (RAND_MAX / (r))
505 int irand_exclusive ( int max
) {
508 while (x
>= max
* RAND_INV_RANGE (max
))
511 x
/= RAND_INV_RANGE (max
);
517 CK_DLL_SFUN( abs_impl
)
519 t_CKINT v
= GET_CK_INT(ARGS
);
520 RETURN
->v_int
= v
>= 0 ? v
: -v
;
524 CK_DLL_SFUN( fabs_impl
)
526 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
527 RETURN
->v_float
= v
>= 0.0 ? v
: -v
;
528 //RETURN->v_float = ::fabs( GET_CK_FLOAT(ARGS) );
532 CK_DLL_SFUN( rand_impl
)
534 RETURN
->v_int
= ::rand();
538 CK_DLL_SFUN( randf_impl
)
540 RETURN
->v_float
= ( 2.0 * ::rand() / (t_CKFLOAT
)RAND_MAX
- 1.0 );
544 CK_DLL_SFUN( rand2f_impl
)
546 t_CKFLOAT min
= GET_CK_FLOAT(ARGS
), max
= *((t_CKFLOAT
*)ARGS
+ 1);
547 RETURN
->v_float
= min
+ (max
-min
)*(::rand()/(t_CKFLOAT
)RAND_MAX
);
551 CK_DLL_SFUN( rand2_impl
) // inclusive.
553 int min
= *(int *)ARGS
, max
= *((int *)ARGS
+ 1);
554 int range
= max
- min
;
559 //else if ( range < RAND_MAX / 2 ) {
560 // RETURN->v_int = ( range > 0 ) ? min + irand_exclusive(1 + range) : max + irand_exclusive ( -range + 1 ) ;
566 RETURN
->v_int
= min
+ (int) ( (1.0 + range
) * ( ::rand()/(RAND_MAX
+1.0) ) );
570 RETURN
->v_int
= min
- (int) ( (-range
+ 1.0) * ( ::rand()/(RAND_MAX
+1.0) ) );
576 CK_DLL_SFUN( srand_impl
)
578 t_CKINT seed
= GET_CK_INT(ARGS
);
583 CK_DLL_SFUN( sgn_impl
)
585 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
586 RETURN
->v_float
= v
== 0.0f
? 0.0f
: ( v
> 0.0f
? 1.0f
: -1.0f
);
590 CK_DLL_SFUN( system_impl
)
592 const char * cmd
= GET_CK_STRING(ARGS
)->str
.c_str();
594 // check globals for permission
595 if( !g_enable_system_cmd
)
597 fprintf( stderr
, "[chuck]:error: VM not authorized to call Std.system( string )...\n" );
598 fprintf( stderr
, "[chuck]: (command string was: \"%s\")\n", cmd
);
599 fprintf( stderr
, "[chuck]: (note: enable via --caution-to-the-wind flag or other means)\n" );
605 EM_log( CK_LOG_SEVERE
, "invoking system( CMD )..." );
607 EM_log( CK_LOG_SEVERE
, "CMD: \"%s\"", cmd
);
609 RETURN
->v_int
= system( cmd
);
614 CK_DLL_SFUN( atoi_impl
)
616 Chuck_String
* str
= GET_CK_STRING(ARGS
);
619 const char * v
= str
->str
.c_str();
620 RETURN
->v_int
= atoi( v
);
629 CK_DLL_SFUN( atof_impl
)
631 Chuck_String
* str
= GET_CK_STRING(ARGS
);
634 const char * v
= GET_CK_STRING(ARGS
)->str
.c_str();
635 RETURN
->v_float
= atof( v
);
639 RETURN
->v_float
= 0.0;
644 CK_DLL_SFUN( itoa_impl
)
646 t_CKINT i
= GET_CK_INT(ARGS
);
647 // TODO: memory leak, please fix. Thanks.
648 Chuck_String
* a
= (Chuck_String
*)instantiate_and_initialize_object( &t_string
, NULL
);
650 RETURN
->v_string
= a
;
654 CK_DLL_SFUN( ftoa_impl
)
656 t_CKFLOAT f
= GET_NEXT_FLOAT(ARGS
);
657 t_CKINT p
= GET_NEXT_INT(ARGS
);
658 Chuck_String
* a
= (Chuck_String
*)instantiate_and_initialize_object( &t_string
, NULL
);
659 a
->str
= ftoa( f
, (t_CKUINT
)p
);
660 RETURN
->v_string
= a
;
664 static Chuck_String g_str
; // PROBLEM: not thread friendly
665 CK_DLL_SFUN( getenv_impl
)
667 const char * v
= GET_CK_STRING(ARGS
)->str
.c_str();
668 const char * s
= getenv( v
);
669 Chuck_String
* a
= (Chuck_String
*)instantiate_and_initialize_object( &t_string
, NULL
);
671 RETURN
->v_string
= a
;
675 CK_DLL_SFUN( setenv_impl
)
677 const char * v1
= GET_NEXT_STRING(ARGS
)->str
.c_str();
678 const char * v2
= GET_NEXT_STRING(ARGS
)->str
.c_str();
679 RETURN
->v_int
= setenv( v1
, v2
, 1 );
684 CK_DLL_SFUN( mtof_impl
)
686 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
687 RETURN
->v_float
= mtof(v
);
691 CK_DLL_SFUN( ftom_impl
)
693 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
694 RETURN
->v_float
= ftom(v
);
698 CK_DLL_SFUN( powtodb_impl
)
700 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
701 RETURN
->v_float
= powtodb(v
);
705 CK_DLL_SFUN( rmstodb_impl
)
707 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
708 RETURN
->v_float
= rmstodb(v
);
712 CK_DLL_SFUN( dbtopow_impl
)
714 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
715 RETURN
->v_float
= dbtopow(v
);
719 CK_DLL_SFUN( dbtorms_impl
)
721 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
722 RETURN
->v_float
= dbtorms(v
);
729 CBufferAdvance
* KBHitManager::the_buf
= NULL
;
730 t_CKINT
KBHitManager::the_onoff
= 0;
731 t_CKBOOL
KBHitManager::the_init
= FALSE
;
732 XThread
* KBHitManager::the_thread
;
733 #define BUFFER_SIZE 1024
736 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
737 static void * kb_loop( void * )
739 static unsigned int __stdcall
kb_loop( void * )
743 EM_log( CK_LOG_INFO
, "starting kb loop..." );
746 while( KBHitManager::the_init
)
749 if( KBHitManager::the_onoff
)
751 // see if we have kb hit
757 KBHitManager::the_buf
->put( &c
, 1 );
770 t_CKBOOL
KBHitManager::init()
773 if( the_buf
) return FALSE
;
775 EM_log( CK_LOG_INFO
, "initializing KBHitManager..." );
776 the_buf
= new CBufferAdvance
;
777 if( !the_buf
->initialize( BUFFER_SIZE
, sizeof(t_CKINT
) ) )
779 EM_log( CK_LOG_SEVERE
, "KBHitManager: couldn't allocate central KB buffer..." );
780 SAFE_DELETE( the_buf
);
786 the_thread
= new XThread
;
787 the_thread
->start( kb_loop
, NULL
);
794 void KBHitManager::shutdown()
796 EM_log( CK_LOG_INFO
, "shutting down KBHitManager..." );
797 SAFE_DELETE( the_buf
);
806 void KBHitManager::on()
815 void KBHitManager::off()
818 if( kb_ready() && the_onoff
== 0 )
824 t_CKBOOL
KBHitManager::open( KBHit
* kb
)
826 if( the_buf
== NULL
) return FALSE
;
827 if( kb
->m_buffer
!= NULL
) return FALSE
;
829 EM_log( CK_LOG_INFO
, "adding KBHit..." );
831 kb
->m_buffer
= the_buf
;
833 kb
->m_read_index
= kb
->m_buffer
->join( (Chuck_Event
*)kb
->SELF
);
840 t_CKBOOL
KBHitManager::close( KBHit
* kb
)
842 if( the_buf
== NULL
) return FALSE
;
843 if( kb
->m_buffer
== NULL
) return FALSE
;
845 EM_log( CK_LOG_INFO
, "removing KBHit..." );
847 kb
->m_buffer
->resign( kb
->m_read_index
);
849 kb
->m_read_index
= 0;
875 t_CKBOOL
KBHit::open()
877 return KBHitManager::open( this );
882 t_CKBOOL
KBHit::close()
884 return KBHitManager::close( this );
891 if( m_onoff
== FALSE
)
903 if( m_onoff
== TRUE
)
913 t_CKBOOL
KBHit::empty()
915 if( m_buffer
== NULL
) return TRUE
;
916 if( m_onoff
== FALSE
) return TRUE
;
917 // if( m_read_index == 0 ) return TRUE;
918 return m_buffer
->empty( m_read_index
);
923 t_CKINT
KBHit::getch()
926 if( empty() ) return 0;
927 m_buffer
->get( &c
, 1, m_read_index
);
933 CK_DLL_CTOR( KBHit_ctor
)
935 KBHit
* kb
= new KBHit
;
936 OBJ_MEMBER_INT(SELF
, KBHit_offset_data
) = (t_CKINT
)kb
;
943 CK_DLL_DTOR( KBHit_dtor
)
945 delete (KBHit
*)OBJ_MEMBER_INT(SELF
, KBHit_offset_data
);
946 OBJ_MEMBER_INT(SELF
, KBHit_offset_data
) = 0;
950 CK_DLL_MFUN( KBHit_on
)
952 KBHit
* kb
= (KBHit
*)(OBJ_MEMBER_INT(SELF
, KBHit_offset_data
));
958 CK_DLL_MFUN( KBHit_off
)
960 KBHit
* kb
= (KBHit
*)(OBJ_MEMBER_INT(SELF
, KBHit_offset_data
));
966 CK_DLL_MFUN( KBHit_state
)
968 KBHit
* kb
= (KBHit
*)(OBJ_MEMBER_INT(SELF
, KBHit_offset_data
));
969 RETURN
->v_int
= kb
->state();
974 CK_DLL_MFUN( KBHit_hit
)
976 KBHit
* kb
= (KBHit
*)(OBJ_MEMBER_INT(SELF
, KBHit_offset_data
));
977 RETURN
->v_object
= SELF
;
982 CK_DLL_MFUN( KBHit_more
)
984 KBHit
* kb
= (KBHit
*)(OBJ_MEMBER_INT(SELF
, KBHit_offset_data
));
985 RETURN
->v_int
= (kb
->empty() == FALSE
);
990 CK_DLL_MFUN( KBHit_getchar
)
992 KBHit
* kb
= (KBHit
*)(OBJ_MEMBER_INT(SELF
, KBHit_offset_data
));
993 RETURN
->v_int
= kb
->getch();
998 CK_DLL_MFUN( KBHit_can_wait
)
1000 KBHit
* kb
= (KBHit
*)(OBJ_MEMBER_INT(SELF
, KBHit_offset_data
));
1001 RETURN
->v_int
= kb
->empty();
1007 class LineEvent
: public Chuck_Event
1010 LineEvent( Chuck_Event
* SELF
);
1014 void prompt( const string
& what
= "" );
1017 t_CKBOOL
can_wait();
1018 void enqueue( const string
& line
)
1019 { m_q
.push( line
); }
1028 t_CKBOOL g_le_launched
= FALSE
;
1029 t_CKBOOL g_le_wait
= TRUE
;
1030 // CHUCK_THREAD g_tid_le = 0;
1031 extern CHUCK_THREAD g_tid_whatever
;
1032 map
<LineEvent
*, LineEvent
*> g_le_map
;
1035 extern Chuck_VM
* g_vm
;
1037 void * le_cb( void * p
)
1040 map
<LineEvent
*, LineEvent
*>::iterator iter
;
1041 LineEvent
* le
= NULL
;
1056 if( !cin
.getline( line
, 2048 ) ) break;
1059 g_le_mutex
.acquire();
1061 for( iter
= g_le_map
.begin(); iter
!= g_le_map
.end(); iter
++ )
1063 // get the line event
1066 le
->enqueue( line
);
1068 le
->SELF
->queue_broadcast();
1071 g_le_mutex
.release();
1081 LineEvent::LineEvent( Chuck_Event
* SELF
)
1084 if( !g_le_launched
)
1086 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
1087 pthread_create( &g_tid_whatever
, NULL
, le_cb
, NULL
);
1089 g_tid_whatever
= CreateThread( NULL
, 0, (LPTHREAD_START_ROUTINE
)le_cb
, NULL
, 0, 0 );
1091 g_le_launched
= TRUE
;
1095 g_le_mutex
.acquire();
1097 g_le_map
[this] = this;
1100 g_le_mutex
.release();
1103 LineEvent::~LineEvent()
1108 void LineEvent::prompt( const string
& what
)
1112 if( g_le_what
!= "" ) g_le_what
+= " ";
1117 t_CKBOOL
LineEvent::more()
1120 return m_q
.size() > 0;
1123 string
LineEvent::getLine()
1128 g_le_mutex
.acquire();
1139 ret
= "[ERROR -> getLine() called on empty Skot]";
1142 g_le_mutex
.release();
1147 t_CKBOOL
LineEvent::can_wait()
1154 CK_DLL_CTOR( Skot_ctor
)
1156 LineEvent
* le
= new LineEvent((Chuck_Event
*)SELF
);
1157 OBJ_MEMBER_INT(SELF
, Skot_offset_data
) = (t_CKINT
)le
;
1160 CK_DLL_DTOR( Skot_dtor
)
1162 delete (LineEvent
*)OBJ_MEMBER_INT(SELF
, Skot_offset_data
);
1163 OBJ_MEMBER_INT(SELF
, Skot_offset_data
) = 0;
1166 CK_DLL_MFUN( Skot_prompt
)
1168 LineEvent
* le
= (LineEvent
*)OBJ_MEMBER_INT(SELF
, Skot_offset_data
);
1170 RETURN
->v_int
= (t_CKINT
)(SELF
);
1173 CK_DLL_MFUN( Skot_prompt2
)
1175 LineEvent
* le
= (LineEvent
*)OBJ_MEMBER_INT(SELF
, Skot_offset_data
);
1176 const char * v
= GET_CK_STRING(ARGS
)->str
.c_str();
1178 RETURN
->v_int
= (t_CKINT
)(SELF
);
1181 CK_DLL_MFUN( Skot_more
)
1183 LineEvent
* le
= (LineEvent
*)OBJ_MEMBER_INT(SELF
, Skot_offset_data
);
1184 RETURN
->v_int
= le
->more();
1187 CK_DLL_MFUN( Skot_getLine
)
1189 LineEvent
* le
= (LineEvent
*)OBJ_MEMBER_INT(SELF
, Skot_offset_data
);
1190 // TODO: memory leak
1191 Chuck_String
* a
= (Chuck_String
*)instantiate_and_initialize_object( &t_string
, NULL
);
1192 a
->str
= le
->getLine();
1193 RETURN
->v_string
= a
;
1196 CK_DLL_MFUN( Skot_can_wait
)
1198 LineEvent
* le
= (LineEvent
*)OBJ_MEMBER_INT(SELF
, Skot_offset_data
);
1199 RETURN
->v_int
= le
->can_wait();
1211 void set( const string
& line
);
1215 string
get( t_CKINT index
);
1219 istringstream
* m_ss
;
1221 vector
<string
> m_tokens
;
1222 vector
<string
>::size_type m_index
;
1233 SAFE_DELETE( m_ss
);
1236 void StrTok::set( const string
& line
)
1241 SAFE_DELETE( m_ss
);
1243 m_ss
= new istringstream( line
);
1247 while( (*m_ss
) >> s
)
1248 m_tokens
.push_back( s
);
1251 void StrTok::reset()
1256 t_CKBOOL
StrTok::more()
1258 return m_index
< m_tokens
.size();
1261 string
StrTok::next()
1263 if( !more() ) return "";
1264 return m_tokens
[m_index
++];
1267 string
StrTok::get( t_CKINT index
)
1269 if( index
>= (t_CKINT
)m_tokens
.size() ) return "";
1270 return m_tokens
[index
];
1273 t_CKINT
StrTok::size()
1275 return (t_CKINT
)m_tokens
.size();
1278 CK_DLL_CTOR( StrTok_ctor
)
1280 StrTok
* tokens
= new StrTok
;
1281 OBJ_MEMBER_INT(SELF
, StrTok_offset_data
) = (t_CKINT
)tokens
;
1284 CK_DLL_DTOR( StrTok_dtor
)
1286 delete (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1287 OBJ_MEMBER_INT(SELF
, StrTok_offset_data
) = 0;
1290 CK_DLL_MFUN( StrTok_set
)
1292 StrTok
* tokens
= (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1293 Chuck_String
* s
= GET_CK_STRING(ARGS
);
1294 if( s
) tokens
->set( s
->str
);
1295 else tokens
->set( "" );
1298 CK_DLL_MFUN( StrTok_reset
)
1300 StrTok
* tokens
= (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1304 CK_DLL_MFUN( StrTok_more
)
1306 StrTok
* tokens
= (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1307 RETURN
->v_int
= (t_CKINT
)tokens
->more();
1310 CK_DLL_MFUN( StrTok_next
)
1312 StrTok
* tokens
= (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1313 Chuck_String
* a
= (Chuck_String
*)instantiate_and_initialize_object( &t_string
, NULL
);
1314 a
->str
= tokens
->next();
1315 RETURN
->v_string
= a
;
1318 CK_DLL_MFUN( StrTok_next2
)
1320 StrTok
* tokens
= (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1321 Chuck_String
* a
= GET_CK_STRING(ARGS
);
1322 string s
= tokens
->next();
1324 RETURN
->v_string
= a
;
1327 CK_DLL_MFUN( StrTok_get
)
1329 StrTok
* tokens
= (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1330 t_CKINT index
= GET_NEXT_INT(ARGS
);
1331 Chuck_String
* a
= (Chuck_String
*)instantiate_and_initialize_object( &t_string
, NULL
);
1332 string s
= tokens
->get( index
);
1334 RETURN
->v_string
= a
;
1337 CK_DLL_MFUN( StrTok_get2
)
1339 StrTok
* tokens
= (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1340 t_CKINT index
= GET_NEXT_INT(ARGS
);
1341 Chuck_String
* a
= GET_NEXT_STRING(ARGS
);
1342 string s
= tokens
->get( index
);
1344 RETURN
->v_string
= a
;
1347 CK_DLL_MFUN( StrTok_size
)
1349 StrTok
* tokens
= (StrTok
*)OBJ_MEMBER_INT(SELF
, StrTok_offset_data
);
1350 RETURN
->v_int
= tokens
->size();
1363 virtual ~ColumnReader();
1365 bool init( const string
& filename
, long col
);
1367 bool reset() { if( !fin
.good() ) return false; where
= 0; return true; }
1368 bool seek( long pos
) { if( pos
< 0 || pos
>= values
.size() ) return false; where
= pos
; return true; }
1369 bool more() { return where
< values
.size(); }
1371 bool next() { if( where
< values
.size() ) where
++; return more(); }
1372 long pos() { return where
; }
1373 long size() { return values
.size(); }
1374 string
name() { return n
; }
1379 bool get_str( string
& out
);
1380 bool get_double( double & out
);
1390 vector
<double> values
;
1394 ColumnReader::ColumnReader()
1403 ColumnReader::~ColumnReader()
1410 bool ColumnReader::init( const string
& filename
, long col
)
1415 cerr
<< "column must be greater than 0!!!" << endl
;
1420 fin
.open( filename
.c_str(), ios::in
);
1424 cerr
<< "ColumnReader: cannot open file: '" << filename
<< "'..." << endl
;
1432 if( !fin
.getline( line
, len
) )
1434 cerr
<< "ColumnReader: cannot read first line: '" << filename
<< "'..." << endl
;
1441 cerr
<< "ColumnReader: cannot seek to column " << col
<< ": " << filename
<< "..." << endl
;
1448 while( fin
.getline( line
, len
) )
1452 if( !get_double( v
) )
1454 cerr
<< "ColumnReader: cannot read column " << v
<< " on line i: " << n
<< "..." << endl
;
1458 values
.push_back( v
);
1462 if( values
.size() == 0 )
1464 cerr
<< "ColumnReader: file doesn't not contain data after first line: " << n
<< "..." << endl
;
1476 double ColumnReader::curr()
1478 if( where
>= values
.size() )
1480 cerr
<< "ColumnReader: trying to read beyond end of file: " << n
<< "..." << endl
;
1484 return values
[where
];
1487 bool ColumnReader::get_double( double & out
)
1489 assert( column
> 0 );
1492 char * start
= line
;
1493 char * curr
= start
;
1498 while( *curr
&& *curr
!= ',' ) curr
++;
1500 while( *curr
&& *curr
== ',' ) curr
++;
1504 cerr
<< "ColumnReader: cannot find column " << column
<< ": " << n
<< endl
;
1515 while( *curr
&& *curr
!= ',' ) curr
++;
1519 out
= atof( start
);
1525 bool ColumnReader::get_str( string
& out
)
1527 assert( column
> 0 );
1530 char * start
= line
;
1531 char * curr
= start
;
1536 while( *curr
&& *curr
!= ',' ) curr
++;
1538 while( *curr
&& *curr
== ',' ) curr
++;
1542 cerr
<< "ColumnReader: cannot find column " << column
<< ": " << n
<< endl
;
1553 while( *curr
&& *curr
!= ',' ) curr
++;
1563 CK_DLL_CTOR( VCR_ctor
)
1565 OBJ_MEMBER_INT(SELF
, VCR_offset_data
) = (t_CKUINT
)new ColumnReader
;
1568 CK_DLL_MFUN( VCR_load
)
1570 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1571 const char * filename
= GET_NEXT_STRING(ARGS
)->str
.c_str();
1572 t_CKINT column
= GET_NEXT_INT(ARGS
);
1573 RETURN
->v_int
= vcr
->init( filename
, column
);
1576 CK_DLL_MFUN( VCR_reset
)
1578 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1579 RETURN
->v_int
= vcr
->reset();
1582 CK_DLL_MFUN( VCR_seek
)
1584 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1585 t_CKINT where
= GET_CK_INT(ARGS
);
1586 RETURN
->v_int
= vcr
->seek( where
);
1589 CK_DLL_MFUN( VCR_more
)
1591 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1592 RETURN
->v_int
= vcr
->more();
1595 CK_DLL_MFUN( VCR_curr
)
1597 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1598 RETURN
->v_float
= vcr
->curr();
1601 CK_DLL_MFUN( VCR_next
)
1603 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1604 RETURN
->v_int
= vcr
->next();
1607 CK_DLL_MFUN( VCR_pos
)
1609 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1610 RETURN
->v_int
= vcr
->pos();
1613 CK_DLL_MFUN( VCR_size
)
1615 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1616 RETURN
->v_int
= vcr
->size();
1619 CK_DLL_MFUN( VCR_name
)
1621 ColumnReader
* vcr
= (ColumnReader
*)OBJ_MEMBER_INT(SELF
, VCR_offset_data
);
1622 RETURN
->v_string
= &(vcr
->s
);
1626 #ifdef __PLATFORM_WIN32__
1633 // one stop bit, 8 bits, no parity
1637 unsigned read( char * buffer
, unsigned numberOfBytesToRead
);
1638 unsigned write( char * buffer
, unsigned numberOfBytesToWrite
);
1640 void write( char c
);
1643 unsigned available() const;
1645 t_CKBOOL
open( char * port
, t_CKUINT baudrate
);
1663 t_CKBOOL
Serial::open( char * port
, t_CKUINT baudrate
)
1669 serialFile
= CreateFile( port
,
1670 GENERIC_READ
| GENERIC_WRITE
,
1674 FILE_ATTRIBUTE_NORMAL
,
1676 if( serialFile
== INVALID_HANDLE_VALUE
)
1678 if( GetLastError() == ERROR_FILE_NOT_FOUND
)
1680 EM_log( CK_LOG_SYSTEM
, "error: cannot open serial port '%s'...", port
);
1684 EM_log( CK_LOG_SYSTEM
, "error opening serial port '%s'...", port
);
1691 DCB dcbSerialParams
= {0};
1692 dcbSerialParams
.DCBlength
= sizeof( dcbSerialParams
);
1693 if( !GetCommState( serialFile
, &dcbSerialParams
) )
1695 EM_log( CK_LOG_SYSTEM
, "error getting serial state..." );
1700 dcbSerialParams
.BaudRate
= baudrate
;
1701 dcbSerialParams
.ByteSize
= 8;
1702 dcbSerialParams
.StopBits
= ONESTOPBIT
;
1703 dcbSerialParams
.Parity
= NOPARITY
;
1704 if( !SetCommState( serialFile
, &dcbSerialParams
) )
1706 EM_log( CK_LOG_SYSTEM
, "error setting serial state..." );
1713 COMMTIMEOUTS timeouts = {0};
1714 timeouts.ReadIntervalTimeout = 50;
1715 timeouts.ReadTotalTimeoutConstant = 50;
1716 timeouts.ReadTotalTimeoutMultiplier = 10;
1717 timeouts.WriteTotalTimeoutConstant= 50;
1718 timeouts.WriteTotalTimeoutMultiplier = 10;
1719 if( !SetCommTimeouts( serialFile, &timeouts ) )
1721 //error occureed. Inform user
1728 void Serial::close()
1732 CloseHandle( serialFile
);
1737 void Serial::write( char c
)
1749 unsigned Serial::available() const
1751 struct _COMSTAT status
;
1753 memset( &status
, 0, sizeof(status
) );
1757 ClearCommError( serialFile
, &etat
, &status
);
1758 return status
.cbInQue
;
1764 // try to read numberOfBytesToRead into buffer, return how many bytes read
1765 unsigned Serial::read( char * buffer
, unsigned numberOfBytesToRead
)
1767 DWORD bytesRead
= 0;
1769 ReadFile( serialFile
, buffer
, numberOfBytesToRead
, &bytesRead
, NULL
);
1773 // try to write numberOfBytesToWrite to serial from buffer, return how many bytes written
1774 unsigned Serial::write( char * buffer
, unsigned numberOfBytesToWrite
)
1776 DWORD bytesWritten
= 0;
1778 WriteFile( serialFile
, buffer
, numberOfBytesToWrite
, &bytesWritten
, NULL
);
1779 return bytesWritten
;
1784 CK_DLL_CTOR( Cereal_ctor
)
1786 OBJ_MEMBER_UINT(SELF
, Cereal_offset_data
) = (t_CKUINT
)new Serial
;
1790 CK_DLL_MFUN( Cereal_open
)
1792 Serial
* s
= (Serial
*)OBJ_MEMBER_UINT(SELF
, Cereal_offset_data
);
1793 Chuck_String
* str
= GET_NEXT_STRING(ARGS
);
1794 t_CKINT i
= GET_NEXT_INT(ARGS
);
1800 RETURN
->v_int
= s
->open( (char *)str
->str
.c_str(), i
);
1806 CK_DLL_MFUN( Cereal_close
)
1808 Serial
* s
= (Serial
*)OBJ_MEMBER_UINT(SELF
, Cereal_offset_data
);
1813 CK_DLL_MFUN( Cereal_more
)
1815 Serial
* s
= (Serial
*)OBJ_MEMBER_UINT(SELF
, Cereal_offset_data
);
1816 RETURN
->v_int
= s
->available();
1820 CK_DLL_MFUN( Cereal_send
)
1822 Serial
* s
= (Serial
*)OBJ_MEMBER_UINT(SELF
, Cereal_offset_data
);
1823 t_CKINT i
= GET_NEXT_INT(ARGS
);
1829 CK_DLL_MFUN( Cereal_recv
)
1831 Serial
* s
= (Serial
*)OBJ_MEMBER_UINT(SELF
, Cereal_offset_data
);
1832 if( s
->available() )
1833 RETURN
->v_int
= (t_CKINT
)s
->read();