⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sequencer.cc

📁 This Source-Navigator, an IDE for C/C++/Fortran/Java/Tcl/PHP/Python and a host of other languages.
💻 CC
📖 第 1 页 / 共 3 页
字号:
// $Header: /cvsroot/sourcenav/src/snavigator/demo/c++_demo/glish/Sequencer.cc,v 1.1.1.1 2002/04/18 23:35:25 mdejong Exp $#include "system.h"#include <stdlib.h>#include <string.h>#include <stream.h>#include <osfcn.h>#include <sys/param.h>#include <sys/types.h>#ifdef HAVE_SIGPROCMASK#include <signal.h>#endif#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endif#ifndef MAXHOSTNAMELEN#define MAXHOSTNAMELEN 64#endifextern "C" {char* getenv( const char* );int isatty( int fd );int system( const char* string );}#include "Reporter.h"#include "Sequencer.h"#include "Frame.h"#include "BuiltIn.h"#include "Task.h"#include "input.h"#include "Channel.h"#include "Select.h"#include "Socket.h"#include "ports.h"#include "version.h"#define GLISH_RC_FILE ".glishrc"// Time to wait until probing a remote daemon, in seconds.#define PROBE_DELAY 5// Interval between subsequent probes, in seconds.#define PROBE_INTERVAL 5// A Selectee corresponding to input for a Glish client.class ClientSelectee : public Selectee {    public:	ClientSelectee( Sequencer* s, Task* t );	int NotifyOfSelection();    protected:	Sequencer* sequencer;	Task* task;	};// A Selectee used only to intercept the initial "established" event// generated by a local Glish client.  Because we communicate with these// clients using pipes instead of sockets, we can't use the AcceptSelectee// (see below) to recognize when they're connecting.class LocalClientSelectee : public Selectee {    public:	LocalClientSelectee( Sequencer* s, Channel* c );	int NotifyOfSelection();    protected:	Sequencer* sequencer;	Channel* chan;	};// A Selectee corresponding to a new request of a client to connect// to the sequencer.class AcceptSelectee : public Selectee {    public:	AcceptSelectee( Sequencer* s, Socket* conn_socket );	int NotifyOfSelection();    protected:	Sequencer* sequencer;	Socket* connection_socket;	};// A Selectee corresponding to a Glish script's own client.class ScriptSelectee : public Selectee {public:	ScriptSelectee( Client* client, Agent* agent, int conn_socket );	int NotifyOfSelection();protected:	Client* script_client;	Agent* script_agent;	int connection_socket;	};// A Selectee for detecting user input.class UserInputSelectee : public Selectee {public:	UserInputSelectee( int user_fd ) : Selectee( user_fd )	{ }	// Indicate user input available by signalling to end the	// select.	int NotifyOfSelection()	{ return 1; }	};// A Selectee for detecting Glish daemon activity.class DaemonSelectee : public Selectee {public:	DaemonSelectee( RemoteDaemon* daemon, Selector* sel, Sequencer* s );	int NotifyOfSelection();protected:	RemoteDaemon* daemon;	Selector* selector;	Sequencer* sequencer;	};// A SelectTimer for handling glishd probes.class ProbeTimer : public SelectTimer {public:	ProbeTimer( PDict(RemoteDaemon)* daemons, Sequencer* s );protected:	int DoExpiration();	PDict(RemoteDaemon)* daemons;	Sequencer* sequencer;	};// A special type of Client used for script clients.  It overrides// FD_Change() to create or delete ScriptSelectee's as needed.class ScriptClient : public Client {public:	ScriptClient( int& argc, char** argv );	// Inform the ScriptClient as to which selector and agent	// it should use for getting and propagating events.	void SetInterface( Selector* selector, Agent* agent );protected:	void FD_Change( int fd, int add_flag );	Selector* selector;	Agent* agent;	};// A special type of Agent used for script clients; when it receives// an event, it propagates it via the ScriptClient object.class ScriptAgent : public Agent {public:	ScriptAgent( Sequencer* s, Client* c ) : Agent(s)	{ client = c; }	Value* SendEvent( const char* event_name, parameter_list* args,			int /* is_request */, int /* log */ )		{		Value* event_val = BuildEventValue( args, 1 );		client->PostEvent( event_name, event_val );		Unref( event_val );		return 0;		}protected:	Client* client;	};// A RemoteDaemon keeps track of a glishd running on a remote host.// This includes the Channel used to communicate with the daemon and// modifiable state indicating whether we're currently waiting for// a probe response from the daemon.// Possible states a daemon can be in.typedef enum	{	DAEMON_OK,	// all is okay	DAEMON_REPLY_PENDING,	// we're waiting for reply to last probe	DAEMON_LOST	// we've lost connectivity	} daemon_states;class RemoteDaemon {public:	RemoteDaemon( const char* daemon_host, Channel* channel )		{		host = daemon_host;		chan = channel;		SetState( DAEMON_OK );		}	const char* Host()		{ return host; }	Channel* DaemonChannel()	{ return chan; }	daemon_states State()		{ return state; }	void SetState( daemon_states s )	{ state = s; }protected:	const char* host;	Channel* chan;	daemon_states state;	};Notification::Notification( Agent* arg_notifier, const char* arg_field,			    Value* arg_value, Notifiee* arg_notifiee )	{	notifier = arg_notifier;	field = strdup( arg_field );	value = arg_value;	notifiee = arg_notifiee;	Ref( value );	}Notification::~Notification()	{	delete field;	Unref( value );	}void Notification::Describe( ostream& s ) const	{	s << "notification of ";	notifier->DescribeSelf( s );	s << "." << field << " (";	value->DescribeSelf( s );	s << ") for ";	notifiee->stmt->DescribeSelf( s );	}Sequencer::Sequencer( int& argc, char**& argv )	{	init_reporters();	init_values();	// Create the global scope.	scopes.append( new expr_dict );	create_built_ins( this );	null_stmt = new NullStmt;	stmts = null_stmt;	last_task_id = my_id = 1;	await_stmt = except_stmt = 0;	await_only_flag = 0;	pending_task = 0;	maximize_num_fds();	// avoid SIGPIPE's - they can occur if a client's termination	// is not detected prior to sending an event to the client#ifdef HAVE_SIGPROCMASK	sigset_t sig_mask;	sigemptyset( &sig_mask );	sigaddset( &sig_mask, SIGPIPE );	sigprocmask( SIG_BLOCK, &sig_mask, 0 );#else	sigblock( sigmask( SIGPIPE ) );#endif	connection_socket = new AcceptSocket( 0, INTERPRETER_DEFAULT_PORT );	mark_close_on_exec( connection_socket->FD() );	selector = new Selector;	selector->AddSelectee( new AcceptSelectee( this, connection_socket ) );	selector->AddTimer( new ProbeTimer( &daemons, this ) );	connection_host = local_host_name();	connection_port = new char[32];	sprintf( connection_port, "%d", connection_socket->Port() );	static const char tag_fmt[] = "*tag-%s.%d*";	int n = strlen( tag_fmt ) + strlen( connection_host ) + /* slop */ 32;	interpreter_tag = new char[n];	sprintf( interpreter_tag, tag_fmt, connection_host, int( getpid() ) );	monitor_task = 0;	last_notification = 0;	last_whenever_executed = 0;	num_active_processes = 0;	verbose = 0;	// Create the "system" global variable.	system_agent = new UserAgent( this );	Value* system_val = system_agent->AgentRecord();	Expr* system_expr = InstallID( strdup( "system" ), GLOBAL_SCOPE );	system_expr->Assign( system_val );	system_val->SetField( "version", new Value( GLISH_VERSION ) );	// Create "script" global.	script_client = new ScriptClient( argc, argv );	Expr* script_expr = InstallID( strdup( "script" ), GLOBAL_SCOPE );	if ( script_client->HasSequencerConnection() )		{		// Set up script agent to deal with incoming and outgoing		// events.		ScriptAgent* script_agent =			new ScriptAgent( this, script_client );		script_client->SetInterface( selector, script_agent );		script_expr->Assign( script_agent->AgentRecord() );		system_val->SetField( "is_script_client",					new Value( glish_true ) );		// Include ourselves as an active process; otherwise		// we'll exit once our child processes are gone.		++num_active_processes;		}	else		{		script_expr->Assign( new Value( glish_false ) );		system_val->SetField( "is_script_client",					new Value( glish_false ) );		}	name = argv[0];	for ( ++argv, --argc; argc > 0; ++argv, --argc )		{		if ( ! strcmp( argv[0], "-v" ) )			++verbose;		else if ( strchr( argv[0], '=' ) )			putenv( argv[0] );		else			break;		}	MakeEnvGlobal();	BuildSuspendList();	char* monitor_client_name = getenv( "glish_monitor" );	if ( monitor_client_name )		ActivateMonitor( monitor_client_name );	Parse( glish_init );	const char* glish_rc;	if ( (glish_rc = getenv( "GLISHRC" )) )		Parse( glish_rc );	else		{		FILE* glish_rc_file = fopen( GLISH_RC_FILE, "r" );		const char* home;		if ( glish_rc_file )			{			fclose( glish_rc_file );			Parse( GLISH_RC_FILE );			}		else if ( (home = getenv( "HOME" )) )			{			char glish_rc_filename[256];			sprintf( glish_rc_filename, "%s/%s",					home, GLISH_RC_FILE );			if ( (glish_rc_file = fopen( glish_rc_filename, "r")) )				{				fclose( glish_rc_file );				Parse( glish_rc_filename );				}			}		}	int do_interactive = 1;	if ( argc > 0 && strcmp( argv[0], "--" ) )		{ // We have a file to parse.		Parse( argv[0] );		do_interactive = 0;		++argv, --argc;		}	MakeArgvGlobal( argv, argc );	if ( do_interactive )		Parse( stdin );	}Sequencer::~Sequencer()	{	delete script_client;	delete selector;	delete connection_socket;	delete connection_port;	delete interpreter_tag;	}void Sequencer::AddBuiltIn( BuiltIn* built_in )	{	Expr* id = InstallID( strdup( built_in->Name() ), GLOBAL_SCOPE );	id->Assign( new Value( built_in ) );	}void Sequencer::QueueNotification( Notification* n )	{	if ( verbose > 1 )		message->Report( "queueing", n );	notification_queue.EnQueue( n );	}void Sequencer::PushScope()	{	scopes.append( new expr_dict );	}int Sequencer::PopScope()	{	int top_scope_pos = scopes.length() - 1;	if ( top_scope_pos < 0 )		fatal->Report( "scope underflow in Sequencer::PopScope" );	expr_dict* top_scope = scopes[top_scope_pos];	int frame_size = top_scope->Length();	scopes.remove( top_scope );	delete top_scope;	return frame_size;	}Expr* Sequencer::InstallID( char* id, scope_type scope )	{	int scope_index;	if ( scope == LOCAL_SCOPE )		scope_index = scopes.length() - 1;	else		scope_index = 0;	int frame_offset = scopes[scope_index]->Length();	Expr* result = new VarExpr( id, scope, frame_offset, this );	scopes[scope_index]->Insert( id, result );	if ( scope == GLOBAL_SCOPE )		global_frame.append( 0 );	return result;	}Expr* Sequencer::LookupID( char* id, scope_type scope, int do_install )	{	int scope_index;	if ( scope == LOCAL_SCOPE )		scope_index = scopes.length() - 1;	else		scope_index = 0;	Expr* result = (*scopes[scope_index])[id];	if ( ! result && do_install )		{		if ( scope == LOCAL_SCOPE )			return LookupID( id, GLOBAL_SCOPE );		else			return InstallID( id, GLOBAL_SCOPE );		}	delete id;	return result;	}void Sequencer::PushFrame( Frame* new_frame )	{	local_frames.append( new_frame );	}Frame* Sequencer::PopFrame()	{	int top_frame = local_frames.length() - 1;	if ( top_frame < 0 )		fatal->Report(			"local frame stack underflow in Sequencer::PopFrame" );	return local_frames.remove_nth( top_frame );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -