use crate::abi::structs::*;
use std::os::raw::c_int;
pub const XSLT_ERR_NONE: c_int = 0;
pub const XSLT_ERR_UNKNOWN: c_int = 1;
pub const XSLT_ERR_MISSING_NAMESPACE: c_int = 2;
pub const XSLT_ERR_INVALID_NAMESPACE: c_int = 3;
pub const XSLT_ERR_MISSING_ATTRIBUTE: c_int = 4;
pub const XSLT_ERR_INVALID_ATTRIBUTE: c_int = 5;
pub const XSLT_ERR_MISSING_ELEMENT: c_int = 6;
pub const XSLT_ERR_INVALID_ELEMENT: c_int = 7;
pub const XSLT_ERR_MISSING_MATCH: c_int = 8;
pub const XSLT_ERR_MISSING_NAME: c_int = 9;
pub const XSLT_ERR_MISSING_SELECT: c_int = 10;
pub const XSLT_ERR_MISSING_TEST: c_int = 11;
pub const XSLT_ERR_MISSING_USE: c_int = 12;
pub const XSLT_ERR_INVALID_MATCH: c_int = 13;
pub const XSLT_ERR_INVALID_SELECT: c_int = 14;
pub const XSLT_ERR_INVALID_TEST: c_int = 15;
pub const XSLT_ERR_INVALID_USE: c_int = 16;
pub const XSLT_ERR_MISSING_NS: c_int = 17;
pub const XSLT_ERR_CYCLIC_REFERENCE: c_int = 18;
pub const XSLT_ERR_RECURSION: c_int = 19;
pub const XSLT_ERR_INTERNAL: c_int = 20;
pub const XSLT_ERR_LEVEL_NONE: c_int = 0;
pub const XSLT_ERR_LEVEL_WARNING: c_int = 1;
pub const XSLT_ERR_LEVEL_ERROR: c_int = 2;
pub const XSLT_ERR_LEVEL_FATAL: c_int = 3;
pub type xsltTransformErrorFunc = Option<
unsafe extern "C" fn(
*mut std::ffi::c_void,
*mut std::ffi::c_void,
*mut _xsltStylesheet,
*const crate::abi::types::xmlChar,
...
),
>;
use std::sync::Mutex;
static LAST_XSLT_ERROR: Mutex<Option<Vec<u8>>> = Mutex::new(None);
static mut XSLT_GENERIC_DEBUG: Option<
unsafe extern "C" fn(*mut std::ffi::c_void, *const std::os::raw::c_char),
> = None;
#[no_mangle]
pub unsafe extern "C" fn xsltSetGenericDebugFunc(
ctx: *mut std::ffi::c_void,
handler: Option<unsafe extern "C" fn(*mut std::ffi::c_void, *const std::os::raw::c_char)>,
) {
unsafe {
XSLT_GENERIC_DEBUG_CONTEXT = ctx;
if handler.is_some() {
XSLT_GENERIC_DEBUG = handler;
}
}
}
static mut XSLT_GENERIC_DEBUG_CONTEXT: *mut std::ffi::c_void = std::ptr::null_mut();
#[no_mangle]
pub unsafe extern "C" fn xsltGenericDebug(
ctx: *mut std::ffi::c_void,
msg: *const std::os::raw::c_char,
) {
if ctx.is_null() || msg.is_null() {
return;
}
let len = libc::strlen(msg);
libc::write(2, msg as *const libc::c_void, len);
}
pub fn xsltSetTransformErrorFunc(
ctxt: *mut _xsltTransformContext,
ctx: *mut std::ffi::c_void,
handler: Option<unsafe extern "C" fn(*mut std::ffi::c_void, *const std::os::raw::c_char)>,
) {
if ctxt.is_null() {
return;
}
unsafe {
(*ctxt).errFunc = handler
.map(|h| h as *mut std::ffi::c_void)
.unwrap_or(std::ptr::null_mut());
(*ctxt).errCtxt = ctx;
}
}
pub fn xsltTransformError(
ctxt: *mut _xsltTransformContext,
style: *mut _xsltStylesheet,
inst: *mut _xmlNode,
msg: *const std::os::raw::c_char,
) {
if msg.is_null() {
return;
}
let bytes =
unsafe { core::slice::from_raw_parts(msg as *const u8, libc::strlen(msg) as usize) };
let text = String::from_utf8_lossy(bytes).into_owned();
if let Ok(mut last) = LAST_XSLT_ERROR.lock() {
*last = Some(text.clone().into_bytes());
}
let mut prefix = String::new();
if !inst.is_null() {
let node = unsafe { &*inst };
let doc = unsafe { &*node.doc };
if !doc.URL.is_null() {
let url = unsafe {
core::slice::from_raw_parts(
doc.URL as *const u8,
libc::strlen(doc.URL as *const libc::c_char) as usize,
)
};
prefix.push_str(&String::from_utf8_lossy(url));
prefix.push(':');
prefix.push_str(&node.line.to_string());
prefix.push_str(": ");
}
}
if !ctxt.is_null() {
let ctx = unsafe { &*ctxt };
if !ctx.errFunc.is_null() {
let handler: unsafe extern "C" fn(*mut std::ffi::c_void, *const std::os::raw::c_char) =
unsafe { std::mem::transmute(ctx.errFunc) };
let full = format!("{}{}", prefix, text);
let mut cmsg = full.into_bytes();
cmsg.push(0);
unsafe { handler(ctx.errCtxt, cmsg.as_ptr() as *const std::os::raw::c_char) };
return;
}
}
let full = format!("{}{}\n", prefix, text);
let _ = unsafe { libc::write(2, full.as_ptr() as *const libc::c_void, full.len()) };
let _ = style;
}
pub fn xsltGetLastError() -> *mut std::ffi::c_void {
let guard = match LAST_XSLT_ERROR.lock() {
Ok(g) => g,
Err(_) => return std::ptr::null_mut(),
};
match guard.as_ref() {
Some(bytes) => {
let len = bytes.len();
let p = unsafe { libc::malloc(len + 1) } as *mut u8;
if p.is_null() {
return std::ptr::null_mut();
}
unsafe {
core::ptr::copy_nonoverlapping(bytes.as_ptr(), p, len);
*p.add(len) = 0;
}
p as *mut std::ffi::c_void
}
None => std::ptr::null_mut(),
}
}