Calling newLISP from C

For the Compleat Fan
Locked
itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Calling newLISP from C

Post by itistoday »

Note: If you're wondering why there's a space in between semi-colons and parenthesis it's because this forum cannot handle them. It took me a while to figure this out. Try posting this: 'exec(asdf)' (no quotes) followed immediately by a semi-colon. Just try it.

Update: Woah.. and apparently it doesn't like the ".h" on the end of a header file either... Very very weird forum.


I wrote some convenience functions for dealing with newLISP in C. I use the term "dealing with" as opposed to "using" because currently it doesn't seem like newLISP is really designed to be called from C/C++ applications. It would be nice for example if C apps could have direct access to raw data types inside of the newLISP world instead of having to parse strings.

Here are some examples of using some of these functions:

nl_exec(const char *cmd, ...)

Code: Select all

nl_exec("(append {/tmp/} (lower-case (slice (join (find-all {[a-zA-Z]+} {%s}) {-}) 0 10)) {.socket})", name) ;
int nl_copyresult(char *buff, int len, int options) ;

Code: Select all

char buff[100];
nl_copyresult(buff, 100, NL_NO_QUOTE) ;
There we passed NL_NO_QUOTE because since, again, the only interface you have to newLISP is what's output on the read-eval loop, strings will have quotes around them, and you probably don't want those.

char *nl_result(void) ;

Code: Select all

char *my_copy = strcpy(nl_result()) ;
Note: nl_result returns a pointer to newLISP's result buffer (with the \n removed), so you probably want to copy it.

Here's the code:

Header file:

Code: Select all

#define NL_NO_QUOTE		(1<<0)

int		nl_load(void) ;
bool	nl_loaded(void) ;
int 	nl_exec(const char *cmd, ...) ;
int		nl_error(void) ; // result of running nl_exec
char *	nl_result(void) ;
int		nl_copyresult(char *buff, int len, int options) ;
Implementation:

Code: Select all

#include <stdarg>

static bool newlisp_loaded = false;
static char * (*newlispEvalStr)(char *) ;
static char * nl_buff = NULL; // pointer to newlisp's result buffer
static int nl_err = 0;

int load_newlisp()
{
	// load newLISP.(dylib|so|dll) ...
	
	newlisp_loaded = true;
	nl_exec("(signal 2 true)") ; // default action for SIGINT, makes ^C work properly
	return 0;
}

bool nl_loaded()
{
	return newlisp_loaded;
}

#define CMD_BUFF_LEN 2048
int nl_exec(const char *cmd_fmt, ...)
{
	va_list data;
	static char cmd_buff[CMD_BUFF_LEN];
	
	if ( ! newlisp_loaded ) {
		log_err("nl_exec: newlisp not loaded") ;
		return -1;
	}
	
	va_start(data, cmd_fmt) ;
	vsnprintf(cmd_buff, CMD_BUFF_LEN-1, cmd_fmt, data) ;
	va_end(data) ;
	
	nl_buff = newlispEvalStr(cmd_buff) ;
	
	if (strncmp(nl_buff, "\nmissing", 8) != 0)
		nl_err = 0;
	else
		nl_err = -1; // error occurred, most likely command too long
	
	return nl_err;
}

char * nl_result()
{
	if ( ! newlisp_loaded ) {
		log_err("nl_result: newlisp not loaded") ;
		return NULL;
	}
	else if (nl_buff == NULL) {
		log_err("nl_result: nl_exec not called") ;
		return NULL;
	}
	
	char *ptr = nl_buff;
	while (*ptr != '\0') ++ptr;
	*(--ptr) = '\0'; // get rid of \n
		
	return nl_buff;
}

int nl_copyresult(char *buff, int len, int options)
{
	if ( ! newlisp_loaded ) {
		log_err("nl_copyresult: newlisp not loaded") ;
		return -1;
	}
	else if ( nl_buff == NULL ) {
		log_err("nl_copyresult: nl_exec not called") ;
		return -1;
	}
	
	char *ptr = nl_buff;
	int copied = 0;
	
	if ( (NL_NO_QUOTE & options) > 0 && *ptr == '"' )
		++ptr;
	
	while ( *ptr != '\0' && --len >= 0 ) {
		*buff = *ptr;
		++ptr; ++buff; ++copied;
	}
	
	if ( len > 0 )
	{
		if ( *(ptr-1) == '\n' ) {
			*(--buff) = '\0';
			--copied;
		}
		else *buff = '\0';
		
		if ( (NL_NO_QUOTE & options) > 0 && *(buff-1) == '"' ) {
			*(buff-1) = '\0';
			--copied;
		}
	}
	
	return copied;
}

int nl_error(void)
{
	return nl_err;
}
Last edited by itistoday on Fri Feb 29, 2008 7:57 pm, edited 1 time in total.
Get your Objective newLISP groove on.

Ryon
Posts: 248
Joined: Thu Sep 26, 2002 12:57 am

Post by Ryon »

The "semicolon-space" issue reported above is a quirk in the PHP software used by the newLISP Fan Club, and possibly also in the syntax of the C language whichAllows.multiple(elements);ToBeEntered_without(delimiting,spaces).

It is NOT a fault in newLISP itself.

itistoday
Posts: 429
Joined: Sun Dec 02, 2007 5:10 pm
Contact:

Post by itistoday »

Ryon wrote:It is NOT a fault in newLISP itself.
I don't think I said it was newLISP's fault did I?
Get your Objective newLISP groove on.

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

you're both right :)

Locked