00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <clipsmm/environment.h>
00020
00021 #include <stdexcept>
00022
00023 extern "C" {
00024 #include <clips/clips.h>
00025 };
00026
00027 #include <clipsmm/utility.h>
00028
00029 namespace DACLIPS {
00030
00031 std::map<void*, Environment*> Environment::m_environment_map;
00032
00033 Environment::Environment():
00034 m_run_thread(NULL)
00035 {
00036 m_cobj = CreateEnvironment();
00037
00038 m_environment_map[m_cobj] = this;
00039
00040 if ( EnvAddClearFunction( m_cobj, "clipsmm_clear_callback", Environment::clear_callback, 2001 ) == 0 )
00041 throw std::logic_error("clipsmm: Error adding clear callback to clips environment");
00042 if ( EnvAddPeriodicFunction( m_cobj, "clipsmm_periodic_callback", Environment::periodic_callback, 2001 ) == 0 )
00043 throw std::logic_error("clipsmm: Error adding periodic callback to clips environment");
00044 if ( EnvAddResetFunction( m_cobj, "clipsmm_reset_callback", Environment::reset_callback, 2001 ) == 0 )
00045 throw std::logic_error("clipsmm: Error adding reset callback to clips environment");
00046 if ( EnvAddRunFunction( m_cobj, "clipsmm_rule_firing_callback", Environment::rule_firing_callback, 2001 ) == 0 )
00047 throw std::logic_error("clipsmm: Error adding rule firing callback to clips environment");
00048 }
00049
00050 Environment::~Environment()
00051 {
00052 EnvRemoveClearFunction( m_cobj, "clipsmm_clear_callback" );
00053 EnvRemovePeriodicFunction( m_cobj, "clipsmm_periodic_callback" );
00054 EnvRemoveResetFunction( m_cobj, "clipsmm_reset_callback" );
00055 EnvRemoveRunFunction( m_cobj, "clipsmm_rule_firing_callback" );
00056
00057 m_environment_map.erase(m_cobj);
00058
00059 DestroyEnvironment( m_cobj );
00060 }
00061
00062 bool Environment::batch_evaluate( const std::string& filename ) {
00063 return EnvBatchStar( m_cobj, const_cast<char*>( filename.c_str() ) );
00064 }
00065
00066 bool Environment::binary_load( const std::string& filename ) {
00067 return EnvBload( m_cobj, const_cast<char*>( filename.c_str() ) );
00068 }
00069
00070 bool Environment::binary_save( const std::string& filename ) {
00071 return EnvBsave( m_cobj, const_cast<char*>( filename.c_str() ) );
00072 }
00073
00074 bool Environment::build( const std::string& construct ) {
00075 return EnvBuild( m_cobj, const_cast<char*>( construct.c_str() ) );
00076 }
00077
00078 void Environment::clear( ) {
00079 EnvClear( m_cobj );
00080 }
00081
00082 int Environment::load( const std::string& filename )
00083 {
00084 return EnvLoad( m_cobj, const_cast<char*>( filename.c_str() ) );
00085 }
00086
00087 void Environment::reset( )
00088 {
00089 EnvReset( m_cobj );
00090 }
00091
00092 bool Environment::save( const std::string& filename )
00093 {
00094 return EnvSave( m_cobj, const_cast<char*>( filename.c_str() ) );
00095 }
00096
00097 bool Environment::is_dribble_active( ) {
00098 return EnvDribbleActive( m_cobj );
00099 }
00100
00101 bool Environment::dribble_off( ) {
00102 return EnvDribbleOff( m_cobj );
00103 }
00104
00105 bool Environment::dribble_on( const std::string& filename )
00106 {
00107 return EnvDribbleOn( m_cobj, const_cast<char*>( filename.c_str() ) );
00108 }
00109
00110 int Environment::is_watched( const std::string& item ) {
00111 return EnvGetWatchItem( m_cobj, const_cast<char*>( item.c_str() ) );
00112 }
00113
00114 bool Environment::watch( const std::string& item )
00115 {
00116 return EnvWatch( m_cobj, const_cast<char*>( item.c_str() ) );
00117 }
00118
00119 bool Environment::unwatch( const std::string& item )
00120 {
00121 return EnvUnwatch( m_cobj, const_cast<char*>( item.c_str() ) );
00122 }
00123
00124 long int Environment::run( long int runlimit )
00125 {
00126 long int executed;
00127 m_mutex_run.lock();
00128 executed = EnvRun( m_cobj, runlimit );
00129 m_mutex_run_signal.lock();
00130 m_mutex_run.unlock();
00131 m_signal_run.emit(executed);
00132 m_mutex_run_signal.unlock();
00133 return executed;
00134 }
00135
00136 void Environment::run_threaded( long int runlimit, int priority ) {
00137
00138
00139
00140 m_mutex_run_queue.lock();
00141 if ( m_mutex_threaded_run.trylock() ) {
00142 m_run_queue.push( Job( priority, runlimit ) );
00143 m_mutex_run.lock();
00144
00145 m_run_thread = Glib::Thread::create( sigc::mem_fun(*this, &Environment::threaded_run), true );
00146
00147 return;
00148 } else {
00149
00150
00151 m_run_queue.push( Job( priority, runlimit ) );
00152 m_mutex_run_queue.unlock();
00153 return;
00154 }
00155 }
00156
00157 void Environment::join_run_thread() {
00158 m_mutex_run_queue.lock();
00159 if ( m_mutex_threaded_run.trylock() ) {
00160
00161
00162
00163 m_mutex_threaded_run.unlock();
00164 m_mutex_run_queue.unlock();
00165 return;
00166 }
00167 else {
00168
00169
00170
00171 m_mutex_run_queue.unlock();
00172 m_run_thread->join();
00173 return;
00174 }
00175 }
00176
00177 sigc::signal<void,long int> Environment::signal_run() {
00178 return m_signal_run;
00179 }
00180
00181 void Environment::threaded_run() {
00182 long int executed;
00183 long int current_runlimit;
00184
00185
00186 while ( m_run_queue.size() > 0 ) {
00187 current_runlimit = m_run_queue.top().runlimit;
00188 m_run_queue.pop();
00189
00190
00191 m_mutex_run_queue.unlock();
00192
00193 executed = EnvRun( m_cobj, current_runlimit );
00194
00195 m_mutex_run_signal.lock();
00196 m_signal_run.emit(executed);
00197 m_mutex_run_signal.unlock();
00198
00199
00200 m_mutex_run_queue.lock();
00201 }
00202
00203
00204 m_mutex_threaded_run.unlock();
00205 m_mutex_run.unlock();
00206 m_mutex_run_queue.unlock();
00207 }
00208
00209 void Environment::set_as_current( )
00210 {
00211 SetCurrentEnvironment( m_cobj );
00212 }
00213
00214 void Environment::clear_focus_stack( )
00215 {
00216 EnvClearFocusStack( m_cobj );
00217 }
00218
00219 bool Environment::auto_float_dividend_enabled() {
00220 return EnvGetAutoFloatDividend( m_cobj );
00221 }
00222
00223 bool Environment::use_auto_float_dividend(bool use) {
00224 return EnvSetAutoFloatDividend( m_cobj, use );
00225 }
00226
00227 bool Environment::dynamic_constraint_checking_enabled() {
00228 return EnvGetDynamicConstraintChecking( m_cobj );
00229 }
00230
00231 bool Environment::use_dynamic_constraint_checking(bool use) {
00232 return EnvSetDynamicConstraintChecking( m_cobj, use );
00233 }
00234
00235 bool Environment::sequence_operator_recognition_enabled() {
00236 return EnvGetSequenceOperatorRecognition( m_cobj );
00237 }
00238
00239 bool Environment::use_sequence_operator_recognition(bool use) {
00240 return EnvSetSequenceOperatorRecognition( m_cobj, use );
00241 }
00242
00243 bool Environment::static_constraint_checking_enabled() {
00244 return EnvGetStaticConstraintChecking( m_cobj );
00245 }
00246
00247 bool Environment::use_static_constraint_checking(bool use) {
00248 return EnvSetStaticConstraintChecking( m_cobj, use );
00249 }
00250
00251 bool Environment::fact_duplication_enabled() {
00252 return EnvGetFactDuplication( m_cobj );
00253 }
00254
00255 bool Environment::use_fact_duplication(bool use) {
00256 return EnvSetFactDuplication( m_cobj, use );
00257 }
00258
00259 bool Environment::global_reset_enable() {
00260 return EnvGetResetGlobals( m_cobj );
00261 }
00262
00263 bool Environment::use_global_reset( bool use ) {
00264 return EnvSetResetGlobals( m_cobj, use );
00265 }
00266
00267 DefaultFacts::pointer Environment::get_default_facts( const std::string & default_facts_name )
00268 {
00269 void* deffacts;
00270 deffacts = EnvFindDeffacts( m_cobj, const_cast<char*>(default_facts_name.c_str()) );
00271 if ( deffacts )
00272 return DefaultFacts::create( *this, deffacts );
00273 else
00274 return DefaultFacts::pointer();
00275 }
00276
00277 std::vector< std::string > Environment::get_default_facts_names( )
00278 {
00279 DATA_OBJECT clipsdo;
00280 EnvGetDeffactsList( m_cobj, &clipsdo, NULL );
00281 return data_object_to_strings( clipsdo );
00282 }
00283
00284 std::vector<std::string> Environment::get_default_facts_names(const Module& module) {
00285 DATA_OBJECT clipsdo;
00286 if ( module.cobj() ) {
00287 EnvGetDeffactsList( m_cobj, &clipsdo, module.cobj() );
00288 return data_object_to_strings( clipsdo );
00289 }
00290 else
00291 return std::vector<std::string>();
00292 }
00293
00294 std::vector<std::string> Environment::get_default_facts_names(Module::pointer module) {
00295 DATA_OBJECT clipsdo;
00296 if ( module && module->cobj() ) {
00297 EnvGetDeffactsList( m_cobj, &clipsdo, module->cobj() );
00298 return data_object_to_strings( clipsdo );
00299 }
00300 else
00301 return std::vector<std::string>();
00302 }
00303
00304 DefaultFacts::pointer Environment::get_default_facts_list_head( )
00305 {
00306 void* df;
00307 df = EnvGetNextDeffacts( m_cobj, NULL );
00308 if (df)
00309 return DefaultFacts::create( *this, df );
00310 else
00311 return DefaultFacts::pointer();
00312 }
00313
00314 Template::pointer Environment::get_template( const std::string & template_name )
00315 {
00316 if ( ! m_cobj )
00317 return Template::pointer();
00318
00319 void* tem = EnvFindDeftemplate( m_cobj, const_cast<char*>( template_name.c_str() ) );
00320
00321 if ( !tem )
00322 return Template::pointer();
00323
00324 return Template::create( *this, tem );
00325 }
00326
00327 std::vector< std::string > Environment::get_template_names( )
00328 {
00329 DATA_OBJECT clipsdo;
00330 EnvGetDeftemplateList( m_cobj, &clipsdo, NULL );
00331 return data_object_to_strings( clipsdo );
00332 }
00333
00334 std::vector<std::string> Environment::get_template_names(const Module& module) {
00335 DATA_OBJECT clipsdo;
00336 if ( module.cobj() ) {
00337 EnvGetDeftemplateList( m_cobj, &clipsdo, module.cobj() );
00338 return data_object_to_strings( clipsdo );
00339 }
00340 else
00341 return std::vector<std::string>();
00342 }
00343
00344 std::vector<std::string> Environment::get_template_names(Module::pointer module) {
00345 DATA_OBJECT clipsdo;
00346 if ( module && module->cobj() ) {
00347 EnvGetDeftemplateList( m_cobj, &clipsdo, module->cobj() );
00348 return data_object_to_strings( clipsdo );
00349 }
00350 else
00351 return std::vector<std::string>();
00352 }
00353
00354 Template::pointer Environment::get_template_list_head( )
00355 {
00356 void* tem;
00357 tem = EnvGetNextDeftemplate( m_cobj, NULL );
00358 if (tem)
00359 return Template::create( *this, tem );
00360 else
00361 return Template::pointer();
00362 }
00363
00364 Rule::pointer Environment::get_rule( const std::string & rule_name )
00365 {
00366 void* rule;
00367 rule = EnvFindDefrule( m_cobj, const_cast<char*>(rule_name.c_str()) );
00368 if ( rule )
00369 return Rule::create( *this, rule );
00370 else
00371 return Rule::pointer();
00372 }
00373
00374 std::vector< std::string > Environment::get_rule_names( )
00375 {
00376 DATA_OBJECT clipsdo;
00377 EnvGetDefruleList( m_cobj, &clipsdo, NULL );
00378 return data_object_to_strings( clipsdo );
00379 }
00380
00381 std::vector<std::string> Environment::get_rule_names(const Module& module) {
00382 DATA_OBJECT clipsdo;
00383 if ( module.cobj() ) {
00384 EnvGetDefruleList( m_cobj, &clipsdo, module.cobj() );
00385 return data_object_to_strings( clipsdo );
00386 }
00387 else
00388 return std::vector<std::string>();
00389 }
00390
00391 std::vector<std::string> Environment::get_rule_names(Module::pointer module) {
00392 DATA_OBJECT clipsdo;
00393 if ( module && module->cobj() ) {
00394 EnvGetDefruleList( m_cobj, &clipsdo, module->cobj() );
00395 return data_object_to_strings( clipsdo );
00396 }
00397 else
00398 return std::vector<std::string>();
00399 }
00400
00401 Rule::pointer Environment::get_rule_list_head( )
00402 {
00403 void* r;
00404 r = EnvGetNextDefrule( m_cobj, NULL );
00405 if (r)
00406 return Rule::create( *this, r );
00407 else
00408 return Rule::pointer();
00409 }
00410
00411 void Environment::remove_rules( )
00412 {
00413 EnvUndefrule( m_cobj, NULL );
00414 }
00415
00416 Fact::pointer Environment::assert_fact( const std::string& factstring )
00417 {
00418 void* clips_fact = EnvAssertString( m_cobj, const_cast<char*>(factstring.c_str()) );
00419 if ( clips_fact )
00420 return Fact::create( *this, clips_fact );
00421 else
00422 return Fact::pointer();
00423 }
00424
00425 bool Environment::incremental_reset_enabled( )
00426 {
00427 return EnvGetIncrementalReset( m_cobj );
00428 }
00429
00430 bool Environment::use_incremental_reset( bool use )
00431 {
00432 return EnvSetIncrementalReset( m_cobj, use );
00433 }
00434
00435 Module::pointer Environment::get_module( const std::string & module_name )
00436 {
00437 void* module;
00438 module = EnvFindDefmodule( m_cobj, const_cast<char*>(module_name.c_str()) );
00439 if (module)
00440 return Module::create( *this, module );
00441 else
00442 return Module::pointer();
00443 }
00444
00445 Module::pointer Environment::get_current_module( )
00446 {
00447 void* module;
00448 module = EnvGetCurrentModule( m_cobj );
00449 if ( module )
00450 return Module::create( *this, module );
00451 else
00452 return Module::pointer();
00453 }
00454
00455 Module::pointer Environment::get_focused_module( )
00456 {
00457 void* module;
00458 module = EnvGetFocus( m_cobj );
00459 if ( module )
00460 return Module::create( *this, module );
00461 else
00462 return Module::pointer();
00463 }
00464
00465 std::vector<std::string> Environment::get_focus_stack() {
00466 DATA_OBJECT clipsdo;
00467 EnvGetFocusStack( m_cobj, &clipsdo );
00468 return data_object_to_strings( clipsdo );
00469 }
00470
00471 Activation::pointer Environment::get_activation_list_head( )
00472 {
00473 void* head;
00474 head = EnvGetNextActivation( m_cobj, NULL );
00475 if (head)
00476 return Activation::create( *this, head );
00477 else
00478 return Activation::pointer();
00479 }
00480
00481 void Environment::refresh_agenda() {
00482 EnvRefreshAgenda( m_cobj, NULL );
00483 }
00484
00485 void Environment::refresh_agenda(const Module& module) {
00486 if ( module.cobj() )
00487 EnvRefreshAgenda( m_cobj, module.cobj() );
00488 }
00489
00490 void Environment::refresh_agenda(Module::pointer module) {
00491 if ( module && module->cobj() )
00492 EnvRefreshAgenda( m_cobj, module->cobj() );
00493 }
00494
00495 void Environment::reorder_agenda() {
00496 EnvReorderAgenda( m_cobj, NULL );
00497 }
00498
00499 void Environment::reorder_agenda(const Module& module) {
00500 if ( module.cobj() )
00501 EnvReorderAgenda( m_cobj, module.cobj() );
00502 }
00503
00504 void Environment::reorder_agenda(Module::pointer module) {
00505 if ( module && module->cobj() )
00506 EnvReorderAgenda( m_cobj, module->cobj() );
00507 }
00508
00509 SalienceEvaluation Environment::get_salience_evaluation( )
00510 {
00511 return (SalienceEvaluation) EnvGetSalienceEvaluation( m_cobj );
00512 }
00513
00514 SalienceEvaluation Environment::set_salience_evaluation( SalienceEvaluation se )
00515 {
00516 return (SalienceEvaluation) EnvSetSalienceEvaluation( m_cobj, se );
00517 }
00518
00519 ConflictResolution Environment::get_conflict_resolution_strategy( )
00520 {
00521 return (ConflictResolution) EnvGetStrategy( m_cobj );
00522 }
00523
00524 ConflictResolution Environment::set_conflict_resolution_strategy( ConflictResolution cr )
00525 {
00526 return (ConflictResolution) EnvSetStrategy( m_cobj, cr );
00527 }
00528
00529 std::vector< std::string > Environment::get_module_names( )
00530 {
00531 DATA_OBJECT clipsdo;
00532 EnvGetDefmoduleList( m_cobj, &clipsdo );
00533 return data_object_to_strings( clipsdo );
00534 }
00535
00536 Module::pointer Environment::get_module_list_head( )
00537 {
00538 void* module;
00539 module = EnvGetNextDefmodule( m_cobj, NULL );
00540 if (module)
00541 return Module::create( *this, module );
00542 else
00543 return Module::pointer();
00544 }
00545
00546 Values Environment::evaluate( const std::string& expression )
00547 {
00548 DATA_OBJECT clipsdo;
00549 int result;
00550 result = EnvEval( m_cobj, const_cast<char*>(expression.c_str()), &clipsdo );
00551 if ( result )
00552 return data_object_to_values( clipsdo );
00553 else
00554 return Values();
00555 }
00556
00557 Values Environment::function( const std::string & function_name,
00558 const std::string & arguments )
00559 {
00560 DATA_OBJECT clipsdo;
00561 int result;
00562 result = EnvFunctionCall( m_cobj,
00563 const_cast<char*>(function_name.c_str()),
00564 const_cast<char*>(arguments.c_str()),
00565 &clipsdo);
00566 if ( !result )
00567 return data_object_to_values( clipsdo );
00568 else
00569 return Values();
00570 }
00571
00572 bool Environment::remove_function( std::string name )
00573 {
00574 bool result = UndefineFunction( m_cobj, const_cast<char*>(name.c_str()) );
00575 m_slots.erase(name);
00576 return result;
00577 }
00578
00579 Global::pointer Environment::get_global( const std::string& global_name ) {
00580 void* clips_global = EnvFindDefglobal( m_cobj, const_cast<char*>(global_name.c_str()));
00581 if ( clips_global )
00582 return Global::create( *this, clips_global );
00583 else
00584 return Global::pointer();
00585 }
00586
00587 Global::pointer Environment::get_global_list_head( )
00588 {
00589 void* global;
00590 global = EnvGetNextDefglobal( m_cobj, NULL );
00591 if (global)
00592 return Global::create( *this, global );
00593 else
00594 return Global::pointer();
00595 }
00596
00597 std::vector<std::string> Environment::get_globals_names()
00598 {
00599 DATA_OBJECT clipsdo;
00600 EnvGetDefglobalList( m_cobj, &clipsdo, NULL );
00601 return data_object_to_strings( clipsdo );
00602 }
00603
00604 std::vector<std::string> Environment::get_globals_names( const Module& module )
00605 {
00606 DATA_OBJECT clipsdo;
00607 if ( module.cobj() ) {
00608 EnvGetDefglobalList( m_cobj, &clipsdo, module.cobj() );
00609 return data_object_to_strings( clipsdo );
00610 }
00611 else
00612 return std::vector<std::string>();
00613 }
00614
00615 std::vector<std::string> Environment::get_globals_names( Module::pointer module )
00616 {
00617 DATA_OBJECT clipsdo;
00618 if ( module && module->cobj() ) {
00619 EnvGetDefglobalList( m_cobj, &clipsdo, module->cobj() );
00620 return data_object_to_strings( clipsdo );
00621 }
00622 else
00623 return std::vector<std::string>();
00624 }
00625
00626 Function::pointer Environment::get_function( const std::string& function_name ) {
00627 void* clips_function = EnvFindDeffunction( m_cobj, const_cast<char*>(function_name.c_str()));
00628 if ( clips_function )
00629 return Function::create( *this, clips_function );
00630 else
00631 return Function::pointer();
00632 }
00633
00634 Function::pointer Environment::get_function_list_head( )
00635 {
00636 void* function;
00637 function = EnvGetNextDeffunction( m_cobj, NULL );
00638 if (function)
00639 return Function::create( *this, function );
00640 else
00641 return Function::pointer();
00642 }
00643
00644 std::vector<std::string> Environment::get_function_names()
00645 {
00646 DATA_OBJECT clipsdo;
00647 EnvGetDeffunctionList( m_cobj, &clipsdo, NULL );
00648 return data_object_to_strings( clipsdo );
00649 }
00650
00651 std::vector<std::string> Environment::get_function_names( const Module& module )
00652 {
00653 DATA_OBJECT clipsdo;
00654 if ( module.cobj() ) {
00655 EnvGetDeffunctionList( m_cobj, &clipsdo, (defmodule*)(module.cobj()) );
00656 return data_object_to_strings( clipsdo );
00657 }
00658 else
00659 return std::vector<std::string>();
00660 }
00661
00662 std::vector<std::string> Environment::get_function_names( Module::pointer module )
00663 {
00664 DATA_OBJECT clipsdo;
00665 if ( module && module->cobj() ) {
00666 EnvGetDeffunctionList( m_cobj, &clipsdo, (defmodule*)(module->cobj()) );
00667 return data_object_to_strings( clipsdo );
00668 }
00669 else
00670 return std::vector<std::string>();
00671 }
00672
00673 sigc::signal< void > Environment::signal_clear( )
00674 {
00675 return m_signal_clear;
00676 }
00677
00678 sigc::signal< void > Environment::signal_periodic( )
00679 {
00680 return m_signal_periodic;
00681 }
00682
00683 sigc::signal< void > Environment::signal_reset( )
00684 {
00685 return m_signal_reset;
00686 }
00687
00688 sigc::signal< void > Environment::signal_rule_firing( )
00689 {
00690 return m_signal_rule_firing;
00691 }
00692
00693 bool Environment::check_agenda_changed() {
00694 if ( EnvGetAgendaChanged( m_cobj ) ) {
00695 EnvSetAgendaChanged( m_cobj, 0 );
00696 m_signal_agenda_changed.emit();
00697 return true;
00698 }
00699 else
00700 return false;
00701 }
00702
00703 sigc::signal< void > Environment::signal_agenda_changed()
00704 {
00705 return m_signal_agenda_changed;
00706 }
00707
00708 bool Environment::check_globals_changed() {
00709 if ( EnvGetGlobalsChanged( m_cobj ) ) {
00710 EnvSetGlobalsChanged( m_cobj, 0 );
00711 m_signal_globals_changed.emit();
00712 return true;
00713 }
00714 else
00715 return false;
00716 }
00717
00718 sigc::signal< void > Environment::signal_globals_changed()
00719 {
00720 return m_signal_globals_changed;
00721 }
00722
00723 void Environment::clear_callback( void * env )
00724 {
00725 m_environment_map[env]->m_signal_clear.emit();
00726 }
00727
00728 void Environment::periodic_callback( void * env )
00729 {
00730 m_environment_map[env]->m_signal_periodic.emit();
00731 }
00732
00733 void Environment::reset_callback( void * env )
00734 {
00735 m_environment_map[env]->m_signal_reset.emit();
00736 }
00737
00738 void Environment::rule_firing_callback( void * env )
00739 {
00740 m_environment_map[env]->m_signal_rule_firing.emit();
00741 }
00742
00743 int Environment::get_arg_count( void* env ) {
00744 return EnvRtnArgCount( env );
00745 }
00746
00747 void* Environment::get_function_context( void* env ) {
00748
00749 return NULL;
00750 }
00751
00752 void* Environment::add_symbol( const char* s ) {
00753 return AddSymbol( const_cast<char*>(s) );
00754 }
00755
00756 }
00757