guint add_outbound_sexp ( xmlnode *resp ) { guint qlen = 0; GString *sexp = NULL; if( !resp ) return g_queue_get_length( &out_queue ); sexp = xnode_to_sexp_gstring( resp ); xnode_free( resp ); if( sexp->len == 0 ) { g_string_free( sexp, TRUE ); return g_queue_get_length( &out_queue ); } g_queue_push_head ( &out_queue, sexp ); // start up the outbound sexp pump if this is the only thing // in the queue (ie it was empty but now it's not): if( (qlen = g_queue_get_length( &out_queue )) == 1 ) g_io_add_watch( out, IO_OUT, (GIOFunc)sexp_xmitter, NULL ); return qlen; }
/** * Traversal callback to free up the structure. */ static void xnode_item_free(void *item) { xnode_t *xn = item; ZERO(&xn->node); /* Make node standalone */ xnode_free(item); }
static gboolean sexp_handler(GIOChannel *io, GIOCondition cond, gpointer data) { int fd = g_io_channel_unix_get_fd( io ); gboolean go = TRUE; char buf[CHUNK]; while( go ) { ssize_t len = read( fd, buf, CHUNK ); if ( len == 0 ) { go = FALSE; } else if( len < 0 ) { switch( errno ) { case EAGAIN: case EINTR : go = FALSE; break; default: perror( "during read from input fd" ); close( fd ); return FALSE; } } else { gboolean parse = TRUE; // any unused data gets cached in the parser data structure, // so buf only needs to be passed in once: xnode_from_sexp_chunk( buf, &parser, len ); // now loop until we can't extract another complete // s-expression from the buffer: while( (parse = (parser.state == SEXP_PARSED)) ) { xmlnode *root = parser.root; xmlnode *meth = xnode_first_child_tag( root ); // fprintf( stderr, "sexp root: %p; %s\n", root, root->name ); // fprintf( stderr, "sexp meth: %p; %s\n", meth, // meth ? meth->name : "nil" ); if( meth ) { sexp_func func = strcmp( "function-call", root->name ) ? _h_elim_response : get_handler( meth->name ); fprintf( stderr , "function: %s; handler: %p; (default: %p)\n", meth->name , func , _h_elim_default ); if( func ) { // handlers are responsible for freeing *args // when they are done with it: const char *id = xnode_get_attrib( meth, "id" ); xmlnode *argl = xnode_get_next_sibling( meth ); SEXP_VALUE *args = argl ? sexp_value( argl ) : NULL; xmlnode *resp = (func)( meth->name, id, args, NULL ); if( resp ) add_outbound_sexp( resp ); } } // free up the parser related state now we're done with it: xnode_free( parser.root ); sexp_rset ( &parser ); // see if there's another complete s-expression in the buffer: xnode_from_sexp_chunk( "", &parser, 0 ); } } } return TRUE; }