PAB3

 view release on metacpan or  search on metacpan

xs/PAB3/PAB3.xs  view on Meta::CPAN

#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

#include <stdlib.h>

#include "my_pab3.h"

MODULE = PAB3		PACKAGE = PAB3

BOOT:
{
	MY_CXT_INIT;
	MY_CXT.first_thread = MY_CXT.last_thread = NULL;
}

#/*****************************************************************************
# * CLONE( ... )
# *****************************************************************************/

#if defined(USE_ITHREADS) && defined(MY_CXT_KEY)

void
CLONE( ... )
CODE:
	MY_CXT_CLONE;

#endif


#/*****************************************************************************
# * _new( class, ... )
# *****************************************************************************/

void
_new( class, ... )
	SV *class;
PREINIT:
	dMY_CXT;
	my_thread_var_t *tv;
	SV *sv;
	HV *hv;
	int itemp;
	STRLEN lkey, lval;
	char *key, *val;
PPCODE:
	sv = sv_2mortal( (SV*) newHV() );
	tv = my_thread_var_add( &MY_CXT, sv );
	for( itemp = 1; itemp < items - 1; itemp += 2 ) {
		if( ! SvPOK( ST(itemp) ) ) continue;
		key = SvPVx( ST(itemp), lkey );
		/*printf( "item %u %s\n", itemp, key );*/
		if( strcmp( key, "path_template" ) == 0 ) {
			val = SvPVx( ST(itemp + 1), lval );
			New( 1, tv->path_template, lval + 2, char );
			Copy( val, tv->path_template, lval, char );
			if( tv->path_template[lval - 1] != '/' )
				tv->path_template[lval ++] = '/';
			tv->path_template[lval] = '\0';
			tv->path_template_length = (WORD) lval;
		}
		else if( strcmp( key, "path_cache" ) == 0 ) {
			val = SvPVx( ST(itemp + 1), lval );
			New( 1, tv->path_cache, lval + 2, char );
			Copy( val, tv->path_cache, lval, char );
			if( tv->path_cache[lval - 1] != '/' )
				tv->path_cache[lval ++] = '/';
			tv->path_cache[lval] = '\0';
			tv->path_cache_length = (WORD) lval;
		}
		else if( strcmp( key, "prg_start" ) == 0 ) {
			val = SvPVx( ST(itemp + 1), lval );
			New( 1, tv->prg_start, lval + 1, char );
			Copy( val, tv->prg_start, lval + 1, char );
			tv->prg_start_length = (BYTE) lval;
		}
		else if( strcmp( key, "prg_end" ) == 0 ) {
			val = SvPVx( ST(itemp + 1), lval );
			New( 1, tv->prg_end, lval + 1, char );
			Copy( val, tv->prg_end, lval + 1, char );
			tv->prg_start_length = (BYTE) lval;
		}
		else if( strcmp( key, "cmd_sep" ) == 0 ) {
			val = SvPVx( ST(itemp + 1), lval );
			New( 1, tv->cmd_sep, lval + 1, char );
			Copy( val, tv->cmd_sep, lval + 1, char );
			tv->cmd_sep_length = (BYTE) lval;
		}
		else if( strcmp( key, "class_name" ) == 0 ) {
			val = SvPVx( ST(itemp + 1), lval );
			New( 1, tv->class_name, lval + 5, char );
			Copy( val, tv->class_name, lval + 1, char );
			set_var_str( tv->class_name, &lval, PAB_TYPE_SCALAR );
			tv->class_name_length = (WORD) lval;
		}
		else if( strcmp( key, "default_record" ) == 0 ) {
			val = SvPVx( ST(itemp + 1), lval );
			switch( *val ) {
			case '$': case '%': case '@': case '&':
				val ++;
				lval --;
				break;
			}
			New( 1, tv->default_record, lval + 5, char );
			Copy( val, tv->default_record, lval + 1, char );
			tv->default_record_length = (WORD) lval;
		}
	}
	hv = gv_stashpv( __PACKAGE__, 0 );
	XPUSHs( sv_bless( sv_2mortal( newRV( sv ) ), hv ) );


#/*****************************************************************************
# * reset( this )
# *****************************************************************************/

void
reset( this )
	SV *this;
PREINIT:
	dMY_CXT;
	my_thread_var_t *tv;
PPCODE:
	if( ( tv = my_thread_var_find( &MY_CXT, this ) ) != NULL ) {
		my_parser_session_cleanup( tv );
		my_loop_def_cleanup( tv );
		my_hashmap_cleanup( tv );
	}


#/*****************************************************************************
# * _parse_template( this, template )
# *****************************************************************************/

void
_parse_template( this, template )
	SV *this;
	SV *template;
PREINIT:
	dMY_CXT;
	my_thread_var_t *tv;
	STRLEN ltmp;
	char *tmp;
CODE:
	if( ( tv = my_thread_var_find( &MY_CXT, this ) ) == NULL ) goto error;
	tv->last_error[0] = '\0';
	tmp = SvPVx( template, ltmp );
	_debug( "parse_template\n" );
	if( ! parse_template( tv, tmp, ltmp, 1 ) ) goto error;
	optimize_script( tv, tv->root_item );
	_debug( "map_parsed\n" );
	if( ! map_parsed( tv, tv->root_item, 0 ) ) goto error;
	_debug( "build_script\n" );
	if( ! build_script( tv ) ) goto error;
	ST(0) = sv_2mortal( newSVpvn( tv->parser.output, tv->parser.curout - tv->parser.output ) );
	my_parser_session_cleanup( tv );
	goto exit;
error:
	ST(0) = &PL_sv_undef;
	my_parser_session_cleanup( tv );
exit:
	{}


#/*****************************************************************************
# * _make_script( this, template, cache )
# *****************************************************************************/

void
_make_script( this, template, cache )
	SV *this;
	SV *template;
	SV *cache;
PREINIT:
	dMY_CXT;
	my_thread_var_t *tv;
	STRLEN ltmp, ltpl;
	char *tmp, *p1;
	char tpl[256], cac[256];
	/*PerlIO *pfile;*/
PPCODE:
	if( (tv = my_thread_var_find( &MY_CXT, this )) == NULL )
		goto ferror;
	tv->last_error[0] = '\0';
	tmp = SvPVx( template, ltpl );
	if( ltpl + tv->path_template_length < 256 ) {
		if( tv->path_template != NULL ) {
			p1 = my_strcpy( tpl, tv->path_template );
			ltpl += tv->path_template_length;
		}
		else
			p1 = tpl;
		p1 = my_strcpy( p1, tmp );
		tmp = SvPVx( cache, ltmp );
		if( ltmp ) {
			if( tv->path_cache != NULL )
				p1 = my_strncpy( cac, tv->path_cache, 256 );
			else
				p1 = cac;
			p1 = my_strncpy( p1, tmp, 256 - ( p1 - cac ) );
		}
		else
			cac[0] = '\0';
	}
parse:	
	if( ! parse_template( tv, tpl, ltpl, 0 ) )
		goto error;
	optimize_script( tv, tv->root_item );
	if( ! map_parsed( tv, tv->root_item, 0 ) )
		goto error;
	if( ! build_script( tv ) )
		goto error;
	if( cac[0] == '\0' ) {
		XPUSHs( sv_2mortal( newSVuv( 2 ) ) );
		XPUSHs( sv_2mortal( newSVpvn(
			tv->parser.output, tv->parser.curout - tv->parser.output ) ) );
	}
	else {
		XPUSHs( sv_2mortal( newSVuv( 3 ) ) );
		XPUSHs( sv_2mortal( newSVpvn(
			tv->parser.output, tv->parser.curout - tv->parser.output ) ) );
		/*
		pfile = PerlIO_open( cac, "w" );
		if( pfile == NULL ) {
			my_set_error( tv, "Unable to open file!" );
			goto error;
		}
		flock( pfile, LOCK_EX );
		PerlIO_write( pfile,
			tv->parser.output, tv->parser.curout - tv->parser.output );
		flock( pfile, LOCK_UN );
		PerlIO_close( pfile );
		XPUSHs( sv_2mortal( newSVuv( 1 ) ) );
		*/
	}
	my_parser_session_cleanup( tv );
	goto exit;
error:
	my_parser_session_cleanup( tv );
ferror:	
	XPUSHs( &PL_sv_undef );

xs/PAB3/PAB3.xs  view on Meta::CPAN

			set_var_str( hd->record, &l1, PAB_TYPE_SCALAR );
			hd->record_length = l1;
		}
	}
	if( hd->record == NULL ) {
		my_set_error( tv, "Parameter record is invalid" );
		goto error;
	}
	if( SvROK( fieldmap ) && SvTYPE( SvRV( fieldmap ) ) == SVt_PVHV ) {
	    hv = (HV*) SvRV( fieldmap );
	    hd->field_count = len = hv_iterinit( hv );
		Newz( 1, hd->fields, len, char* );
		while( ( he = hv_iternext( hv ) ) != NULL ) {
			s1 = hv_iterkey( he, &l2 );
			sv = hv_iterval( hv, he );
			if( ! SvOK( sv ) || ! SvIOK( sv ) ) goto error_fm;
			i = (int) SvIV( sv );
			if( i < 0 || i >= len ) goto error_fm;
			New( 1, hd->fields[i], l2 + 1, char );
			Copy( s1, hd->fields[i], l2 + 1, char );
		}
		for( i = 0; i < len; i ++ ) {
			if( hd->fields[i] == NULL ) goto error_fm;
		}
	}
	else if( SvROK( fieldmap ) && SvTYPE( SvRV( fieldmap ) ) == SVt_PVAV ) {
		av = (AV*) SvRV( fieldmap );
		hd->field_count = len = av_len( av ) + 1;
		Newz( 1, hd->fields, len, char* );
		for( i = 0; i < len; i ++ ) {
			psv = av_fetch( av, i, 0 );
			if( psv == NULL || ! SvPOK( *psv ) ) goto error_fm;
			s1 = SvPVx( *psv, l1 );
			if( l1 == 0 ) goto error_fm;
			New( 1, hd->fields[i], l1 + 1, char );
			Copy( s1, hd->fields[i], l1 + 1, char );
		}
	}
	else goto error_fm;
	ST(0) = sv_2mortal( newSVuv( 1 ) );
	goto exit;
error_fm:
	my_set_error( tv, "Parameter fieldmap is invalid" );
error:
	if( hd != NULL ) my_hashmap_rem( tv, hd );
	ST(0) = &PL_sv_undef;
exit:
	{}


#/*****************************************************************************
# * error( this )
# *****************************************************************************/

void
error( this )
	SV *this;
PREINIT:
	dMY_CXT;
	my_thread_var_t *tv;
PPCODE:
	if( ( tv = my_thread_var_find( &MY_CXT, this ) ) == NULL ) goto error;
	if( tv->last_error[0] != '\0' ) {
		XPUSHs( sv_2mortal( newSVpvn( tv->last_error, strlen( tv->last_error ) ) ) );
	}
	goto exit;
error:
	XPUSHs( &PL_sv_undef );
exit:
	{}


#/******************************************************************************
# * set_error( this, msg )
# ******************************************************************************/

void
set_error( this, msg )
	SV *this;
	char *msg;
PREINIT:
	dMY_CXT;
	my_thread_var_t *tv;
PPCODE:
	if( ( tv = my_thread_var_find( &MY_CXT, this ) ) == NULL ) return;
	my_strncpy( tv->last_error, msg, sizeof( tv->last_error ) );


#/*****************************************************************************
# * DESTROY( this )
# *****************************************************************************/

void
DESTROY( this )
	SV *this;
PREINIT:
	dMY_CXT;
	my_thread_var_t *tv;
PPCODE:
	if( ( tv = my_thread_var_find( &MY_CXT, this ) ) == NULL ) return;
	_debug( __PACKAGE__ " destroying tv: 0x%08X\n", tv );
	my_thread_var_rem( &MY_CXT, tv );


#/*****************************************************************************
# * _cleanup()
# *****************************************************************************/

void
_cleanup()
PREINIT:
	dMY_CXT;
	my_thread_var_t *tv1, *tv2;
CODE:
	_debug( __PACKAGE__ " _cleanup\n" );
	tv1 = MY_CXT.first_thread;
	while( tv1 != NULL ) {
		tv2 = tv1->next;
		my_thread_var_free( tv1 );
		tv1 = tv2;
	}
	MY_CXT.first_thread = MY_CXT.last_thread = NULL;



( run in 0.533 second using v1.01-cache-2.11-cpan-5511b514fd6 )