/* Elements derived from irssi (http://irssi.org) */ typedef struct plocal_t { pqueue_t *msgqueue; pqueue_t *log_msgs; int signal_fd; PerlInterpreter *my_perl; interpreter_t *interpreter; } plocal_t; typedef struct { void *major; void *minor; } ptr2_t; #define new_pv(a) \ (newSVpv((a) == NULL ? "" : (a), (a) == NULL ? 0 : strlen(a))) #define is_hvref(o) \ ((o) && SvROK(o) && SvRV(o) && (SvTYPE(SvRV(o)) == SVt_PVHV)) #define is_avref(o) \ ((o) && SvROK(o) && SvRV(o) && (SvTYPE(SvRV(o)) == SVt_PVAV)) #define hvref(o) \ (is_hvref(o) ? (HV *)SvRV(o) : NULL) #define avref(o) \ (is_avref(o) ? (AV *)SvRV(o) : NULL) #define arisa_boot(x) { \ extern void boot_Arisa__##x(pTHX_ CV *cv); \ arisa_callXS(boot_Arisa__##x, cv, mark); \ } #define perl_apply_settings(func,opt) \ do { \ STRLEN n_a; \ int i; \ if(((items-1) % 2) == 0) { \ for(i = 1; i < items; i += 2) { \ char *name = (char *)SvPV(ST(i), n_a); \ char *value = (char *)SvPV(ST(i+1), n_a);\ func(opt,name,value); \ } \ } \ } while(0) #define perl_read_settings(func,opt,hv) \ do { \ pqueue_t settings; \ pqueue_init(&settings,0); \ func(opt,&settings); \ hv_store_values(hv,&settings); \ } while(0) #define RET_REF(v) \ do { \ if(v != NULL) \ XPUSHs(sv_2mortal(newRV_noinc((SV*)v))); \ else \ XPUSHs(&PL_sv_undef); \ } while(0) #define RET_STRARR(strs,no_strs) \ do { \ int i; \ for(i = 0; i < no_strs; ++i) \ XPUSHs(sv_2mortal(new_pv(strs[i]))); \ } while(0) #define LOAD_RET_STRARR(strs,no_strs) \ do { \ if(items > 1) \ av_to_strarr(&(strs),&(no_strs),ST(1)); \ RET_STRARR(strs,no_strs); \ } while(0) void arisa_callXS(void (*subaddr)(pTHX_ CV* cv), CV *cv, SV **mark); void init_perl(plocal_t *l); void deinit_perl(plocal_t *l); void perl_handle_msg(plocal_t *l, se_msg_t *msg); void perl_handle_log_msg(plocal_t *l, char *msg); void perl_tick(plocal_t *l, struct timeval *now); SV *create_ptr_object(const char *package, void *ptr); SV *create_ptr2_object(const char *package, ptr2_t *ptr); SV *create_ptr2_object_p(const char *package, void *major, void *minor); void *fetch_object_ptr(SV *o); void fetch_object_ptr2(SV *o, ptr2_t *ptr); void hv_store_values(HV *hv, pqueue_t *values); AV *strarr_to_av(char **strs, int no_strs); void av_to_strarr(char ***strs, int *no_strs, SV *sv); HV *pack_to_hv(pack_t *p); HV *chat_to_hv(chat_t *c); HV *send_to_hv(send_t *s); HV *access_entry_to_hv(access_entry_t *ent); HV *ignore_entry_to_hv(ignore_entry_t *ent); SV *getSVarg(SV **sp, SV **mark, I32 ax, I32 items, const char *name); #define SVarg(x) getSVarg(sp,mark,ax,items,(x)) int getSvIVarg(SV **sp, SV **mark, I32 ax, I32 items, const char *name); #define SvIVarg(x) getSvIVarg(sp,mark,ax,items,(x)) unsigned int getSvUVarg(SV **sp, SV **mark, I32 ax, I32 items, const char *name); #define SvUVarg(x) getSvUVarg(sp,mark,ax,items,(x)) char *getSvPVarg(SV **sp, SV **mark, I32 ax, I32 items, const char *name); #define SvPVarg(x) getSvPVarg(sp,mark,ax,items,(x)) #define SvPTRarg(x) fetch_object_ptr(getSVarg(sp,mark,ax,items,(x))) SV *perl_access_add(SV **sp, SV **mark, I32 ax, I32 items, access_t *acc); SV *perl_access_check(SV **sp, SV **mark, I32 ax, I32 items, access_t *acc); SV *perl_access_del(SV **sp, SV **mark, I32 ax, I32 items, access_t *acc); SV *perl_access_mode(SV **sp, SV **mark, I32 ax, I32 items, access_t *acc); #define ACCESS_EXPAND(lck,acc_ptr,cond,func) \ do { \ access_t *acc = NULL; \ LOCK((lck)); \ if((cond)) \ acc = (acc_ptr); \ UNLOCK((lck)); \ if(acc != NULL) \ RETVAL = func(sp,mark,ax,items,acc); \ } while(0) #define ACCESS_ADD(l,ap,c) ACCESS_EXPAND(l,ap,c,perl_access_add) #define ACCESS_CHECK(l,ap,c) ACCESS_EXPAND(l,ap,c,perl_access_check) #define ACCESS_DEL(l,ap,c) ACCESS_EXPAND(l,ap,c,perl_access_del) #define ACCESS_MODE(l,ap,c) ACCESS_EXPAND(l,ap,c,perl_access_mode) #define ACCESS_LIST(lck,acc_ptr,cond) \ do { \ access_t *acc = NULL; \ int i; \ LOCK((lck)); \ if((cond)) \ acc = (acc_ptr); \ UNLOCK((lck)); \ if(acc != NULL) { \ LOCK(acc); \ for(i = 0; i < acc->no_entries; ++i) { \ XPUSHs(sv_2mortal(newRV_noinc( \ (SV*)access_entry_to_hv(acc->entries[i])))); \ } \ UNLOCK(acc); \ } \ } while(0) SV *perl_ignore_add(SV **sp, SV **mark, I32 ax, I32 items, ignore_list_t *l); SV *perl_ignore_del(SV **sp, SV **mark, I32 ax, I32 items, ignore_list_t *l); HV *perl_ignore_settings(SV **sp, SV **mark, I32 ax, I32 items, ignore_list_t *l); SV *perl_ignore_move(ignore_list_t *l, int src, int dst); #define IGNORE_EXPAND(lck,lptr,func) \ do { \ LOCK((lck)); \ RETVAL = func(sp,mark,ax,items,lptr); \ UNLOCK((lck)); \ } while(0) #define IGNORE_LIST_ADD(l,p) IGNORE_EXPAND(l,p,perl_ignore_add) #define IGNORE_LIST_DEL(l,p) IGNORE_EXPAND(l,p,perl_ignore_del) #define IGNORE_LIST_SETTINGS(l,p) IGNORE_EXPAND(l,p,perl_ignore_settings) #define IGNORE_LIST_WIPE(l,p) \ do { LOCK((l)); ignore_wipe(p); UNLOCK((l)); } while(0) #define IGNORE_LIST_LIST(l,p) \ do { \ int i; \ LOCK((l)); \ LOCK((p)); \ for(i = 0; i < (p)->no_entries; ++i) { \ XPUSHs(sv_2mortal(newRV_noinc( \ (SV*)ignore_entry_to_hv((p)->entries[i])))); \ } \ UNLOCK((p)); \ UNLOCK((l)); \ } while(0) #define IGNORE_LIST_MOVE(l,p,src,dst) \ do { \ LOCK((l)); \ RETVAL = perl_ignore_move(p,src,dst); \ UNLOCK((l)); \ } while(0)