plug-ins/script-fu/tinyscheme/scheme.[ch] small changes to tinyscheme -

2007-08-30  Simon Budig  <simon@gimp.org>

	* plug-ins/script-fu/tinyscheme/scheme.[ch]
	* plug-ins/script-fu/tinyscheme/scheme-private.h: small changes
	to tinyscheme - mostly removing workarounds for message output.

	* plug-ins/script-fu/scheme-wrapper.[ch]: try to channel the
	output through a central function, have various output functions
	to handle the messages. Remove some hacks.

	* plug-ins/script-fu/script-fu-text-console.c
	* plug-ins/script-fu/script-fu-scripts.[ch]
	* plug-ins/script-fu/script-fu-interface.c
	* plug-ins/script-fu/script-fu.c
	* plug-ins/script-fu/script-fu-server.c
	* plug-ins/script-fu/script-fu-console.[ch]: use the new
	infrastructure. Remove more hacks.

	* plug-ins/script-fu/servertest.py: small script to test the
	communication with the script-fu-server.


svn path=/trunk/; revision=23400
This commit is contained in:
Simon Budig 2007-08-30 00:21:20 +00:00 committed by Simon Budig
parent 570577089e
commit 0928a32a21
15 changed files with 218 additions and 167 deletions

View File

@ -1,3 +1,24 @@
2007-08-30 Simon Budig <simon@gimp.org>
* plug-ins/script-fu/tinyscheme/scheme.[ch]
* plug-ins/script-fu/tinyscheme/scheme-private.h: small changes
to tinyscheme - mostly removing workarounds for message output.
* plug-ins/script-fu/scheme-wrapper.[ch]: try to channel the
output through a central function, have various output functions
to handle the messages. Remove some hacks.
* plug-ins/script-fu/script-fu-text-console.c
* plug-ins/script-fu/script-fu-scripts.[ch]
* plug-ins/script-fu/script-fu-interface.c
* plug-ins/script-fu/script-fu.c
* plug-ins/script-fu/script-fu-server.c
* plug-ins/script-fu/script-fu-console.[ch]: use the new
infrastructure. Remove more hacks.
* plug-ins/script-fu/servertest.py: small script to test the
communication with the script-fu-server.
2007-08-29 Raphaël Quinet <raphael@gimp.org>
* plug-ins/metadata/xmp-encode.c (gen_property): escape the text

View File

@ -47,7 +47,8 @@
#include "scheme-wrapper.h"
static int ts_console_mode;
static ts_output_func ts_output_handler = NULL;
static gpointer ts_output_data = NULL;
#undef cons
@ -188,27 +189,36 @@ struct named_constant const old_constants[] =
static scheme sc;
static FILE *ts_output;
/* wrapper functions */
FILE *
ts_get_output_file (void)
void
ts_register_output_func (ts_output_func func,
gpointer user_data)
{
return ts_output;
ts_output_handler = func;
ts_output_data = user_data;
}
void
ts_set_output_file (FILE *file)
ts_stdout_output_func (TsOutputType type,
const char *string,
int len,
gpointer user_data)
{
scheme_set_output_port_file (&sc, file);
ts_output = file;
if (len < 0)
len = strlen (string);
fprintf (stdout, "%.*s", len, string);
}
void
ts_set_console_mode (int flag)
ts_gstring_output_func (TsOutputType type,
const char *string,
int len,
gpointer user_data)
{
ts_console_mode = flag;
GString *gstr = (GString *) user_data;
g_string_append_len (gstr, string, len);
}
void
@ -220,8 +230,10 @@ ts_set_print_flag (gint print_flag)
void
ts_print_welcome (void)
{
fprintf (ts_output, "Welcome to TinyScheme, Version 1.38\n");
fprintf (ts_output, "Copyright (c) Dimitrios Souflis\n");
ts_output_string (TS_OUTPUT_NORMAL,
"Welcome to TinyScheme, Version 1.38\n", -1);
ts_output_string (TS_OUTPUT_NORMAL,
"Copyright (c) Dimitrios Souflis\n", -1);
}
void
@ -233,13 +245,6 @@ ts_interpret_stdin (void)
gint
ts_interpret_string (const gchar *expr)
{
port *pt = sc.outport->_object._port;
memset (sc.linebuff, '\0', LINESIZE);
pt->rep.string.curr = sc.linebuff;
/* Somewhere 'past_the_end' gets altered so it needs to be reset ~~~~~ */
pt->rep.string.past_the_end = &sc.linebuff[LINESIZE-1];
#if DEBUG_SCRIPTS
sc.print_output = 1;
sc.tracing = 1;
@ -250,12 +255,6 @@ ts_interpret_string (const gchar *expr)
return sc.retcode;
}
const char *
ts_get_error_msg (void)
{
return sc.linebuff;
}
const gchar *
ts_get_success_msg (void)
{
@ -265,14 +264,17 @@ ts_get_success_msg (void)
return "Success";
}
/* len is length of 'string' in bytes */
/* len is length of 'string' in bytes or -1 for null terminated strings */
void
ts_output_string (const char *string, int len)
ts_output_string (TsOutputType type,
const char *string,
int len)
{
g_return_if_fail (len >= 0);
if (len < 0)
len = strlen (string);
if (len > 0 && ts_console_mode)
script_fu_output_to_console (string, len);
if (ts_output_handler && len > 0)
(* ts_output_handler) (type, string, len, ts_output_data);
}
@ -286,7 +288,6 @@ tinyscheme_init (const gchar *path,
gboolean local_register_scripts)
{
register_scripts = local_register_scripts;
ts_output_routine = ts_output_string;
/* init the interpreter */
if (!scheme_init (&sc))
@ -296,11 +297,12 @@ tinyscheme_init (const gchar *path,
}
scheme_set_input_port_file (&sc, stdin);
ts_set_output_file (stdout);
scheme_set_output_port_file (&sc, stdout);
ts_register_output_func (ts_stdout_output_func, NULL);
/* Initialize the TinyScheme extensions */
init_ftx(&sc);
init_re(&sc);
init_ftx (&sc);
init_re (&sc);
/* register in the interpreter the gimp functions and types. */
init_constants ();
@ -590,19 +592,7 @@ convert_string (gchar *str)
static pointer
my_err (char *msg, pointer a)
{
if (ts_console_mode)
{
gchar *tmp = g_strdup_printf ("Error: %s\n", msg);
script_fu_output_to_console (tmp, -1);
g_free (tmp);
}
else
{
g_message (msg);
}
ts_output_string (TS_OUTPUT_ERROR, msg, -1);
return sc.NIL;
}

View File

@ -19,22 +19,38 @@
#ifndef SCHEME_WRAPPER_H
#define SCHEME_WRAPPER_H
FILE * ts_get_output_file (void);
void ts_set_output_file (FILE *file);
typedef enum { TS_OUTPUT_NORMAL, TS_OUTPUT_ERROR } TsOutputType;
void ts_set_console_mode (int flag);
typedef void (* ts_output_func) (TsOutputType type,
const char *string,
int len,
gpointer data);
void ts_register_output_func (ts_output_func func,
gpointer user_data);
void ts_stdout_output_func (TsOutputType type,
const char *string,
int len,
gpointer user_data);
void ts_gstring_output_func (TsOutputType type,
const char *string,
int len,
gpointer user_data);
void ts_set_print_flag (gint);
void ts_print_welcome (void);
const gchar * ts_get_error_msg (void);
const gchar * ts_get_success_msg (void);
void tinyscheme_init (const gchar *path,
gboolean local_register_scripts);
void tinyscheme_init (const gchar *path,
gboolean local_register_scripts);
void tinyscheme_deinit (void);
void ts_output_string (const char *string, int len);
void ts_output_string (TsOutputType type,
const char *string,
int len);
void ts_interpret_stdin (void);

View File

@ -88,16 +88,10 @@ static gboolean script_fu_cc_key_function (GtkWidget *widget,
GdkEventKey *event,
ConsoleInterface *console);
static void script_fu_open_ts_console (void);
static void script_fu_close_ts_console (void);
/*
* Local variables
*/
static GtkWidget *output = NULL;
static void script_fu_output_to_console (TsOutputType type,
const gchar *text,
gint len,
gpointer user_data);
/*
* Function definitions
@ -112,12 +106,9 @@ script_fu_console_run (const gchar *name,
{
static GimpParam values[1];
script_fu_open_ts_console ();
ts_set_print_flag (1);
script_fu_console_interface ();
script_fu_close_ts_console ();
*nreturn_vals = 1;
*return_vals = values;
@ -184,8 +175,6 @@ script_fu_console_interface (void)
console->text_view = gtk_text_view_new_with_buffer (console->console);
g_object_unref (console->console);
output = console->text_view;
gtk_text_view_set_editable (GTK_TEXT_VIEW (console->text_view), FALSE);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (console->text_view),
GTK_WRAP_WORD);
@ -267,8 +256,6 @@ script_fu_console_interface (void)
g_source_remove (console->input_id);
output = NULL;
if (console->save_dialog)
gtk_widget_destroy (console->save_dialog);
@ -521,21 +508,31 @@ script_fu_console_scroll_end (GtkWidget *view)
g_idle_add ((GSourceFunc) script_fu_console_idle_scroll_end, view);
}
void
script_fu_output_to_console (const gchar *text,
gint len)
static void
script_fu_output_to_console (TsOutputType type,
const gchar *text,
gint len,
gpointer user_data)
{
/* FIXME: This function needs to be passed a pointer to the console.
*/
if (output)
ConsoleInterface *console = user_data;
if (console && console->text_view)
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (output));
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (console->text_view));
GtkTextIter cursor;
gtk_text_buffer_get_end_iter (buffer, &cursor);
gtk_text_buffer_insert (buffer, &cursor, text, len);
script_fu_console_scroll_end (output);
if (type == TS_OUTPUT_NORMAL)
{
gtk_text_buffer_insert (buffer, &cursor, text, len);
}
else
{
gtk_text_buffer_insert_with_tags_by_name (console->console, &cursor,
text, len, "emphasis",
NULL);
}
script_fu_console_scroll_end (console->text_view);
}
}
@ -566,6 +563,7 @@ script_fu_cc_key_function (GtkWidget *widget,
GList *list;
gint direction = 0;
GtkTextIter cursor;
GString *output;
switch (event->keyval)
{
@ -597,11 +595,23 @@ script_fu_cc_key_function (GtkWidget *widget,
gtk_entry_set_text (GTK_ENTRY (console->cc), "");
output = g_string_new ("");
ts_register_output_func (ts_gstring_output_func, output);
if (ts_interpret_string (list->data) != 0)
gtk_text_buffer_insert_with_tags_by_name (console->console, &cursor,
ts_get_error_msg (), -1,
"emphasis",
NULL);
{
script_fu_output_to_console (TS_OUTPUT_ERROR,
output->str,
output->len,
console);
}
else
{
script_fu_output_to_console (TS_OUTPUT_NORMAL,
output->str,
output->len,
console);
}
g_string_free (output, TRUE);
gimp_displays_flush ();
@ -681,27 +691,6 @@ script_fu_cc_key_function (GtkWidget *widget,
return FALSE;
}
static void
script_fu_open_ts_console (void)
{
ts_set_print_flag (1);
ts_set_console_mode (1);
}
static void
script_fu_close_ts_console (void)
{
FILE *output_file;
ts_set_print_flag (0);
output_file = ts_get_output_file ();
if (output_file != stdout)
fclose (output_file);
ts_set_console_mode (0);
}
void
script_fu_eval_run (const gchar *name,
gint nparams,
@ -719,7 +708,7 @@ script_fu_eval_run (const gchar *name,
{
case GIMP_RUN_NONINTERACTIVE:
/* Disable Script-Fu output */
ts_set_output_file (stdout);
ts_register_output_func (NULL, NULL);
if (ts_interpret_string (params[1].data.d_string) != 0)
status = GIMP_PDB_EXECUTION_ERROR;
break;

View File

@ -31,8 +31,5 @@ void script_fu_eval_run (const gchar *name,
gint *nreturn_vals,
GimpParam **return_vals);
void script_fu_output_to_console (const gchar *text,
gint len);
#endif /* __SCRIPT_FU_CONSOLE__ */

View File

@ -762,7 +762,7 @@ static void
script_fu_ok (SFScript *script)
{
gchar *escaped;
GString *s;
GString *s, *output;
gchar *command;
gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
gint i;
@ -898,8 +898,11 @@ script_fu_ok (SFScript *script)
command = g_string_free (s, FALSE);
/* run the command through the interpreter */
output = g_string_new ("");
ts_register_output_func (ts_gstring_output_func, output);
if (ts_interpret_string (command))
script_fu_error_msg (command);
script_fu_error_msg (command, output->str);
g_string_free (output, TRUE);
g_free (command);
}

View File

@ -41,7 +41,6 @@
#include "script-fu-intl.h"
typedef struct
{
SFScript *script;
@ -126,14 +125,12 @@ script_fu_find_scripts (const gchar *path)
script_menu_list = NULL;
}
#if 1 /* ~~~~~ */
static pointer
my_err(scheme *sc, char *msg)
my_err (scheme *sc, char *msg)
{
g_printerr (msg);
ts_output_string (TS_OUTPUT_ERROR, msg, -1);
return sc->F;
}
#endif
pointer
script_fu_add_script (scheme *sc, pointer a)
@ -663,10 +660,10 @@ script_fu_add_menu (scheme *sc, pointer a)
}
void
script_fu_error_msg (const gchar *command)
script_fu_error_msg (const gchar *command, const gchar *msg)
{
g_message (_("Error while executing\n%s\n\n%s"),
command, ts_get_error_msg ());
command, msg);
}
@ -680,12 +677,16 @@ script_fu_load_script (const GimpDatafileData *file_data,
{
gchar *command;
gchar *escaped = g_strescape (file_data->filename, NULL);
GString *output;
command = g_strdup_printf ("(load \"%s\")", escaped);
g_free (escaped);
output = g_string_new ("");
ts_register_output_func (ts_gstring_output_func, output);
if (ts_interpret_string (command))
script_fu_error_msg (command);
script_fu_error_msg (command, output->str);
g_string_free (output, TRUE);
#ifdef G_OS_WIN32
/* No, I don't know why, but this is
@ -844,6 +845,7 @@ script_fu_script_proc (const gchar *name,
GimpRunMode run_mode;
SFScript *script;
gint min_args = 0;
GString *output;
run_mode = params[0].data.d_int32;
@ -1001,8 +1003,11 @@ script_fu_script_proc (const gchar *name,
command = g_string_free (s, FALSE);
/* run the command through the interpreter */
output = g_string_new ("");
ts_register_output_func (ts_gstring_output_func, output);
if (ts_interpret_string (command))
script_fu_error_msg (command);
script_fu_error_msg (command, output->str);
g_string_free (output, TRUE);
g_free (command);
}

View File

@ -22,6 +22,7 @@
void script_fu_find_scripts (const gchar *path);
pointer script_fu_add_script (scheme *sc, pointer a);
pointer script_fu_add_menu (scheme *sc, pointer a);
void script_fu_error_msg (const gchar *command);
void script_fu_error_msg (const gchar *command,
const gchar *msg);
#endif /* __SCRIPT_FU_SCRIPTS__ */

View File

@ -450,31 +450,29 @@ static gboolean
execute_command (SFCommand *cmd)
{
guchar buffer[RESPONSE_HEADER];
const gchar *response;
GString *response;
time_t clock1;
time_t clock2;
gint response_len;
gboolean error;
gint i;
server_log ("Processing request #%d\n", cmd->request_no);
time (&clock1);
response = g_string_new ("");
ts_register_output_func (ts_gstring_output_func, response);
/* run the command */
if (ts_interpret_string (cmd->command) != 0)
{
error = TRUE;
response = ts_get_error_msg ();
response_len = strlen (response);
server_log ("%s\n", response);
server_log ("%s\n", response->str);
}
else
{
error = FALSE;
response = ts_get_success_msg ();
response_len = strlen (response);
g_string_assign (response, ts_get_success_msg ());
time (&clock2);
server_log ("Request #%d processed in %f seconds, finishing on %s",
@ -483,8 +481,8 @@ execute_command (SFCommand *cmd)
buffer[MAGIC_BYTE] = MAGIC;
buffer[ERROR_BYTE] = error ? TRUE : FALSE;
buffer[RSP_LEN_H_BYTE] = (guchar) (response_len >> 8);
buffer[RSP_LEN_L_BYTE] = (guchar) (response_len & 0xFF);
buffer[RSP_LEN_H_BYTE] = (guchar) (response->len >> 8);
buffer[RSP_LEN_L_BYTE] = (guchar) (response->len & 0xFF);
/* Write the response to the client */
for (i = 0; i < RESPONSE_HEADER; i++)
@ -495,14 +493,16 @@ execute_command (SFCommand *cmd)
return FALSE;
}
for (i = 0; i < response_len; i++)
if (cmd->filedes > 0 && send (cmd->filedes, response + i, 1, 0) < 0)
for (i = 0; i < response->len; i++)
if (cmd->filedes > 0 && send (cmd->filedes, response->str + i, 1, 0) < 0)
{
/* Write error */
print_socket_api_error ("send");
return FALSE;
}
g_string_free (response, TRUE);
return FALSE;
}

View File

@ -42,7 +42,8 @@ script_fu_text_console_run (const gchar *name,
static GimpParam values[1];
/* Enable Script-Fu output */
ts_set_output_file (stdout);
ts_register_output_func (ts_stdout_output_func, NULL);
ts_print_welcome ();
/* Run the interface */

View File

@ -178,8 +178,6 @@ script_fu_run (const gchar *name,
path = script_fu_search_path ();
ts_set_console_mode (0);
/* Determine before we allow scripts to register themselves
* whether this is the base, automatically installed script-fu extension
*/
@ -230,7 +228,6 @@ script_fu_run (const gchar *name,
* The script-fu text console for interactive Scheme development
*/
ts_output_routine = NULL;
script_fu_text_console_run (name, nparams, param,
nreturn_vals, return_vals);
}

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python
import readline, socket, sys
if len (sys.argv) == 1:
HOST = 'localhost'
PORT = 10008
elif len (sys.argv) == 3:
HOST = sys.argv[1]
PORT = int (sys.argv[2])
else:
print >> sys.stderr, "Usage: %s <host> <port>" % sys.argv[0]
print >> sys.stderr, " (if omitted connect to localhost, port 10008)"
sys.exit ()
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.connect ((HOST, PORT))
try:
cmd = raw_input ("Script-Fu-Remote - Testclient\n> ")
while len (cmd) > 0:
sock.send ('G%c%c%s' % (len (cmd) / 256, len (cmd) % 256, cmd))
data = ""
while len (data) < 4:
data += sock.recv (4 - len (data))
if len (data) >= 4:
if data[0] == 'G':
l = ord (data[2]) * 256 + ord (data[3])
msg = ""
while len (msg) < l:
msg += sock.recv (l - len (msg))
if ord (data[1]):
print "(ERR):", msg
else:
print " (OK):", msg
else:
print "invalid magic: %s\n" % data
else:
print "short response: %s\n" % data
cmd = raw_input ("> ")
except EOFError:
print
sock.close

View File

@ -72,7 +72,6 @@ pointer safe_foreign; /* register to avoid gc problems */
int interactive_repl; /* are we in an interactive REPL? */
int print_output; /* set to 1 to print results and error messages */
int print_error; /* set to 1 while printing error messages */
struct cell _sink;
pointer sink; /* when mem. alloc. fails */
@ -117,7 +116,6 @@ char gc_verbose; /* if gc_verbose is not zero, print gc status */
char no_memory; /* Whether mem. alloc. has failed */
#define LINESIZE 1024
char linebuff[LINESIZE];
char strbuff[LINESIZE];
FILE *tmpfp;

View File

@ -46,6 +46,10 @@
#include "scheme-private.h"
#if !STANDALONE
#include "../scheme-wrapper.h"
#endif
/* Used for documentation purposes, to signal functions in 'interface' */
#define INTERFACE
@ -92,7 +96,7 @@ static int utf8_stricmp(const char *s1, const char *s2)
return result;
}
#define min(a, b) ((a <= b) ? a : b)
#define min(a, b) ((a) <= (b) ? (a) : (b))
#if USE_STRLWR
/*
@ -395,8 +399,6 @@ static void assign_proc(scheme *sc, enum scheme_opcodes, char *name);
scheme *scheme_init_new(void);
#if !STANDALONE
void scheme_call(scheme *sc, pointer func, pointer args);
void (*ts_output_routine) (const char *, int) = NULL;
#endif
#define num_ivalue(n) (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
@ -1544,7 +1546,6 @@ static void backchar(scheme *sc, gunichar c) {
static void putchars(scheme *sc, const char *chars, int char_cnt) {
int free_bytes; /* Space remaining in buffer (in bytes) */
int l;
char *s;
port *pt=sc->outport->_object._port;
if (char_cnt <= 0)
@ -1553,22 +1554,15 @@ static void putchars(scheme *sc, const char *chars, int char_cnt) {
/* Get length of 'chars' in bytes */
char_cnt = g_utf8_offset_to_pointer(chars, (long)char_cnt) - chars;
if (sc->print_error) {
l = strlen(sc->linebuff);
s = &sc->linebuff[l];
memcpy(s, chars, min(char_cnt, LINESIZE-l-1));
return;
}
if(pt->kind&port_file) {
#if STANDALONE
fwrite(chars,1,char_cnt,pt->rep.stdio.file);
fflush(pt->rep.stdio.file);
#else
/* If output is still directed to stdout (the default) it should be */
/* safe to redirect it to the routine pointed to by ts_output_routine. */
if (pt->rep.stdio.file == stdout && ts_output_routine != NULL)
(*ts_output_routine) (chars, char_cnt);
/* safe to redirect it to the registered output routine. */
if (pt->rep.stdio.file == stdout)
ts_output_string (TS_OUTPUT_NORMAL, chars, char_cnt);
else {
fwrite(chars,1,char_cnt,pt->rep.stdio.file);
fflush(pt->rep.stdio.file);
@ -3647,9 +3641,6 @@ static pointer opexe_4(scheme *sc, enum scheme_opcodes op) {
sc->args=cons(sc,mk_string(sc," -- "),sc->args);
setimmutable(car(sc->args));
}
if (sc->print_error == 0) /* Reset buffer if not already */
sc->linebuff[0] = '\0'; /* in error message output mode*/
sc->print_error = 1;
putstr(sc, "Error: ");
putstr(sc, strvalue(car(sc->args)));
sc->args = cdr(sc->args);
@ -3664,7 +3655,6 @@ static pointer opexe_4(scheme *sc, enum scheme_opcodes op) {
s_goto(sc,OP_P0LIST);
} else {
putstr(sc, "\n");
sc->print_error = 0;
if(sc->interactive_repl) {
s_goto(sc,OP_T0LVL);
} else {
@ -3964,8 +3954,7 @@ static pointer opexe_5(scheme *sc, enum scheme_opcodes op) {
s_return(sc,x);
}
default:
sprintf(sc->linebuff, "syntax error: illegal token %d", sc->tok);
Error_0(sc,sc->linebuff);
Error_1(sc, "syntax error: illegal token", mk_integer (sc, sc->tok));
}
break;
@ -4515,7 +4504,6 @@ int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
sc->nesting=0;
sc->interactive_repl=0;
sc->print_output=0;
sc->print_error=0;
if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
sc->no_memory=1;

View File

@ -114,10 +114,6 @@ typedef struct num {
} value;
} num;
#if !STANDALONE
SCHEME_EXPORT void (*ts_output_routine) (const char *, int);
#endif
SCHEME_EXPORT scheme *scheme_init_new();
SCHEME_EXPORT scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free);
SCHEME_EXPORT int scheme_init(scheme *sc);