chuck@trantor.harris-atd.com (Chuck Musciano) (01/29/91)
Submitted-by: chuck@trantor.harris-atd.com (Chuck Musciano) Posting-number: Volume 11, Issue 8 Archive-name: catcher/part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 5)." # Contents: catcher.c parse.y process.c # Wrapped by chuck@melmac on Wed Jan 16 13:10:29 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'catcher.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'catcher.c'\" else echo shar: Extracting \"'catcher.c'\" \(8151 characters\) sed "s/^X//" >'catcher.c' <<'END_OF_FILE' X/************************************************************************/ X/* Copyright 1987-1991 by Chuck Musciano and Harris Corporation */ X/* */ X/* Full ownership of this software, and all rights pertaining to */ X/* the for-profit distribution of this software, are retained by */ X/* Chuck Musciano and Harris Corporation. You are permitted to */ X/* use this software without fee. This software is provided "as */ X/* is" without express or implied warranty. You may redistribute */ X/* this software, provided that this copyright notice is retained, */ X/* and that the software is not distributed for profit. If you */ X/* wish to use this software in a profit-making venture, you must */ X/* first license this code and its underlying technology from */ X/* Harris Corporation. */ X/* */ X/* Bottom line: you can have this software, you can use it, you */ X/* can give it away. You just can't sell any or all parts of it */ X/* without prior permission from Harris Corporation. */ X/************************************************************************/ X X/************************************************************************/ X/* */ X/* catcher.c main control for catcher */ X/* */ X/************************************************************************/ X X#include <stdio.h> X X#include <xview/xview.h> X#include <xview/panel.h> X#include <xview/icon.h> X#include <xview/svrimage.h> X#include <xview/seln.h> X X#include <X11/Xlib.h> X#include <X11/Xutil.h> X X X#include "manifest.h" X#include "catcher.h" X#include "drag_drop.h" X XEXPORT Frame base; X XPUBLIC shutdown_windows(); X XPUBLIC int parse_errors_occured; X XPRIVATE short default_icon[] = { X#include "icons/catcher.icon" X }; XPRIVATE short default_mask[] = { X#include "icons/catcher_mask.icon" X }; X XPRIVATE char *drag_buffer = NULL; X X/************************************************************************/ XPRIVATE Seln_result read_selection(response) X XSeln_request *response; X X{ char *reply; X long total_size; X static int curr_size; X X reply = response->data; X if (*(response->requester.context)) { X reply += sizeof(SELN_REQ_BYTESIZE); X total_size = *((long *) reply); X reply += sizeof(long); X if ((drag_buffer = (char *) malloc(total_size + 1)) == NULL) X return(SELN_FAILED); X reply += sizeof(SELN_REQ_CONTENTS_ASCII); X *(response->requester.context) = FALSE; X curr_size = 0; X } X strcpy(drag_buffer + curr_size, reply); X curr_size += strlen(reply); X return(SELN_SUCCESS); X} X X/************************************************************************/ XPRIVATE Notify_value destroy(client, status) X XNotify_client client; XDestroy_status status; X X{ X if (status == DESTROY_CLEANUP) { X shutdown_windows(); X return(notify_next_destroy_func(client, status)); X } X return(NOTIFY_DONE); X} X X/************************************************************************/ XPRIVATE Notify_value catch_drop(win, event, arg, type) X XXv_Window win; XEvent *event; XNotify_arg arg; XNotify_event_type type; X X{ static Xv_server server = NULL; X XClientMessageEvent *raw_message; X Drag_message *message; X Atom actual_type; X int actual_format; X unsigned long nitems, bytes_after; X Seln_holder holder; X Seln_result result; X char *data, context = TRUE, *p, *q, *index(); X X if (server == NULL) X server = (Xv_server) xv_get(xv_get(win, XV_SCREEN), SCREEN_SERVER); X X switch (event_action(event)) { X case ACTION_DRAG_LOAD : raw_message = (XClientMessageEvent *) event_xevent(event); X message = (Drag_message *) &(raw_message->data); X if (message->property != NULL) X if (XGetWindowProperty(raw_message->display, message->window, message->property, 0L, 256, True, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &data) == Success) { X drag_buffer = strsave(data); X XFree(data); X break; X } X case ACTION_DRAG_MOVE : X case ACTION_DRAG_COPY : holder = selection_inquire(server, (event_action(event) == ACTION_PASTE)? SELN_SHELF : SELN_PRIMARY); X result = selection_query(server, &holder, read_selection, &context, SELN_REQ_BYTESIZE, NULL, SELN_REQ_CONTENTS_ASCII, NULL, NULL); X if (result == SELN_FAILED) X error("could not get selection for drag or paste operation"); X else X break; X default : return notify_next_event_func(win, event, arg, type); X } X X if (event_action(event) == ACTION_DRAG_MOVE) X selection_ask(server, &holder, SELN_REQ_DELETE, NULL, NULL); X if (event_action(event) == ACTION_DRAG_LOAD) { X for (p = drag_buffer; q = index(p, '\t'); p = q + 1) { X *q = '\0'; X process_file(p); X } X process_file(p); X } X else X process_text(drag_buffer); X free(drag_buffer); X return(NOTIFY_DONE); X} X X/************************************************************************/ Xmain(argc, argv) X Xint argc; Xchar **argv; X X{ Icon icon; X Server_image image, mask = NULL; X Command *cmd; X Option *opt; X Choice *c; X int x, y, w, diff; X char msg[256], *p, *rindex(); X XClassHint hints; X X xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL); X X if (argc == 1) X lex_init(NULL); X else if (argc == 2) { X if (!lex_init(argv[1])) X abend("could not read %s", argv[1]); X } X else X abend("usage: %s [<file>]", argv[0]); X yyparse(); X if (parse_errors_occured) X exit(1); X X base = (Frame) xv_create(NULL, FRAME, X FRAME_LABEL, config.label, X FRAME_SHOW_RESIZE_CORNER, FALSE, X FRAME_SHOW_FOOTER, config.message != NULL, X NULL); X X if (config.icon) { X if ((image = (Server_image) load_icon(config.icon, msg)) == NULL) X error("could not load icon from %s: %s", config.icon, msg); X else if (config.icon_mask) X if ((mask = (Server_image) load_icon(config.icon_mask, msg)) == NULL) X error("could not load icon mask from %s: %s", config.icon, msg); X } X else { X image = (Server_image) xv_create(NULL, SERVER_IMAGE, X SERVER_IMAGE_BITS, default_icon, X XV_WIDTH, 64, X XV_HEIGHT, 64, X NULL); X mask = (Server_image) xv_create(NULL, SERVER_IMAGE, X SERVER_IMAGE_BITS, default_mask, X XV_WIDTH, 64, X XV_HEIGHT, 64, X NULL); X } X icon = (Icon) xv_create(base, ICON, ICON_IMAGE, image, NULL); X if (mask) X xv_set(icon, ICON_MASK_IMAGE, mask, NULL); X xv_set(base, FRAME_ICON, icon, NULL); X X/* give the application a valid class and instance name */ X hints.res_class = "Catcher"; X hints.res_name = (p = rindex(argv[0], '/'))? p + 1 : argv[0]; X XSetClassHint(xv_get(base, XV_DISPLAY), xv_get(xv_get(base, XV_ROOT), XV_XID), &hints); X X X/* create the basic panels */ X for (y = w = 0, cmd = config.command; cmd; cmd = cmd->next) { X create_panel(base, cmd, y); X notify_interpose_event_func(cmd->panel, catch_drop, NOTIFY_SAFE); X y += (int) xv_get(cmd->panel, XV_HEIGHT) + PANEL_GAP; X } X X/* align all the widget label right edges */ X for (x = 0, cmd = config.command; cmd; cmd = cmd->next) X for (opt = cmd->option; opt; opt = opt->next) X if (x < (int) xv_get(opt->item, PANEL_VALUE_X)) X x = (int) xv_get(opt->item, PANEL_VALUE_X); X for (cmd = config.command; cmd; cmd = cmd->next) X for (opt = cmd->option; opt; opt = opt->next) { X diff = x - (int) xv_get(opt->item, PANEL_VALUE_X); X xv_set(opt->item, XV_X, (int) xv_get(opt->item, XV_X) + diff, NULL); X for (c = opt->choice; c; c = c->next) X if (c->parameter) X xv_set(c->item, XV_X, (int) xv_get(c->item, XV_X) + diff, NULL); X } X X/* fix all the panel widths */ X for (w = 0, cmd = config.command; cmd; cmd = cmd->next) { X window_fit(cmd->panel); X if (w < xv_get(cmd->panel, XV_WIDTH)) X w = (int) xv_get(cmd->panel, XV_WIDTH); X } X for (cmd = config.command; cmd; cmd = cmd->next) X xv_set(cmd->panel, XV_WIDTH, w, NULL); X window_fit(base); X X notify_interpose_event_func(base, catch_drop, NOTIFY_SAFE); X notify_interpose_event_func(xv_get(base, FRAME_ICON), catch_drop, NOTIFY_SAFE); X notify_interpose_destroy_func(base, destroy); X X xv_main_loop(base); X} END_OF_FILE if test 8151 -ne `wc -c <'catcher.c'`; then echo shar: \"'catcher.c'\" unpacked with wrong size! fi # end of 'catcher.c' fi if test -f 'parse.y' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'parse.y'\" else echo shar: Extracting \"'parse.y'\" \(9186 characters\) sed "s/^X//" >'parse.y' <<'END_OF_FILE' X/************************************************************************/ X/* Copyright 1987-1991 by Chuck Musciano and Harris Corporation */ X/* */ X/* Full ownership of this software, and all rights pertaining to */ X/* the for-profit distribution of this software, are retained by */ X/* Chuck Musciano and Harris Corporation. You are permitted to */ X/* use this software without fee. This software is provided "as */ X/* is" without express or implied warranty. You may redistribute */ X/* this software, provided that this copyright notice is retained, */ X/* and that the software is not distributed for profit. If you */ X/* wish to use this software in a profit-making venture, you must */ X/* first license this code and its underlying technology from */ X/* Harris Corporation. */ X/* */ X/* Bottom line: you can have this software, you can use it, you */ X/* can give it away. You just can't sell any or all parts of it */ X/* without prior permission from Harris Corporation. */ X/************************************************************************/ X X%{ X X#include <stdio.h> X#include <ctype.h> X X#include <xview/xview.h> X#include <xview/panel.h> X X#include "manifest.h" X#include "catcher.h" X XEXPORT int parse_errors_occured; X XEXPORT Catch config = {NULL, NULL, "Catcher", NULL, '$', '{', '}', NULL, NULL}; X XPRIVATE char *get_last_token(); X XPRIVATE char *curr_file; XPRIVATE int line_count = 1; XPRIVATE char ungetc = -1; X XPRIVATE Command *curr_cmd; XPRIVATE Option *curr_opt; XPRIVATE Choice *curr_cho; XPRIVATE Text text; X X%} X X%start configuration X X%union {Choice *chval; X char *cpval; X Command *cval; X int ival; X Option *oval; X } X X%token <cpval> STRING ID X%token <ival> INTEGER X X%token LBRACE RBRACE X X%token BY CHOICE COMMAND DEFAULT DELIMITER EXCLUSIVE FINISH HORIZONTAL ICON_ ICON_MASK INIT LABEL X%token MESSAGE NONEXCLUSIVE NUMERIC OPTIONAL OUTPUT PARAMETER START SUFFIX TEXT TO VALUE WINDOW_ X X%type <chval> anon_choice choice X%type <cpval> command_name delimiter icon icon_mask label message suffix text_init value X%type <cval> command X%type <ival> int_init X%type <oval> exclusive nonexclusive option text X X%% X Xconfiguration : prologue command_list X ; X Xprologue : prologue prologue_item X | empty X ; X Xprologue_item : delimiter X { if (strlen($1) != 3) X yyerror("delimiter must contain three characters"); X config.escape = $1[0]; X config.ldelim = $1[1]; X config.rdelim = $1[2]; X } X | icon X { config.icon = strsave($1); } X | icon_mask X { config.icon_mask = strsave($1); } X | label X { config.label = strsave($1); } X | message X { config.message = strsave($1); } X | output X | suffix X { config.suffix = strsave($1); } X ; X Xcommand_list : command X { config.command = $1; } X | command_list command X { Command *c; X X for (c = config.command; c->next; c = c->next) X ; X c->next = $2; X } X ; X Xcommand : COMMAND X { curr_cmd = (Command *) malloc(sizeof(Command)); X curr_cmd->command = NULL; X curr_cmd->label = NULL; X curr_cmd->optional = FALSE; X curr_cmd->option = NULL; X curr_cmd->next = NULL; X } X LBRACE command_info options RBRACE X { if (is_empty(curr_cmd->command)) X yyerror("no command specified"); X $$ = curr_cmd; X } X ; X Xcommand_info : command_info cmd_info_item X | empty X ; X Xcmd_info_item : command_name X { curr_cmd->command = strsave($1); } X | label X { curr_cmd->label = strsave($1); } X | optional X { curr_cmd->optional = TRUE; } X ; X Xoptions : options option X { Option *o; X X if (curr_cmd->option == NULL) X curr_cmd->option = $2; X else { X for (o = curr_cmd->option; o->next; o = o->next) X ; X o->next = $2; X } X } X | empty X ; X Xoption : exclusive X | nonexclusive X | text X ; X Xexclusive : EXCLUSIVE ID X { curr_opt = (Option *) malloc(sizeof(Option)); X curr_opt->id = strsave($2); X curr_opt->label = NULL; X curr_opt->type = OPT_EXCLUSIVE; X curr_opt->horizontal = FALSE; X curr_opt->choice = NULL; X curr_opt->next = NULL; X } X LBRACE option_info anon_choices RBRACE X { if (curr_opt->choice == NULL) X yyerror("no choices specified for exclusive option %s", curr_opt->id); X $$ = curr_opt; X } X ; X Xnonexclusive : NONEXCLUSIVE X { curr_opt = (Option *) malloc(sizeof(Option)); X curr_opt->id = NULL; X curr_opt->label = NULL; X curr_opt->type = OPT_NONEXCLUSIVE; X curr_opt->horizontal = FALSE; X curr_opt->choice = NULL; X curr_opt->next = NULL; X } X LBRACE option_info choices RBRACE X { if (curr_opt->choice == NULL) X yyerror("no choices specified for nonexclusive option %s", curr_opt->id); X $$ = curr_opt; X } X ; X Xtext : TEXT ID X { curr_opt = (Option *) malloc(sizeof(Option)); X curr_opt->id = strsave($2); X curr_opt->label = NULL; X curr_opt->type = OPT_TEXT; X curr_opt->choice = NULL; X curr_opt->next = NULL; X } X LBRACE option_info parm RBRACE X { curr_opt->text = text; X $$ = curr_opt; X } X ; X Xoption_info : option_info opt_info_item X | empty X ; X Xopt_info_item : label X { curr_opt->label = strsave($1); } X | X horizontal X { curr_opt->horizontal = TRUE; } X ; X Xchoices : choices choice X { Choice *c; X X if (curr_opt->choice == NULL) X curr_opt->choice = $2; X else { X for (c = curr_opt->choice; c->next; c = c->next) X ; X c->next = $2; X } X } X | empty X ; X Xchoice : CHOICE ID X { curr_cho = (Choice *) malloc(sizeof(Choice)); X curr_cho->id = strsave($2); X curr_cho->value = NULL; X curr_cho->label = NULL; X curr_cho->parameter = FALSE; X curr_cho->is_default = FALSE; X curr_cho->item = NULL; X curr_cho->next = NULL; X } X LBRACE choice_info RBRACE X { if (curr_cho->value == NULL) X yyerror("no value specified for choice"); X $$ = curr_cho; X } X ; X Xanon_choices : anon_choices anon_choice X { Choice *c; X X if (curr_opt->choice == NULL) X curr_opt->choice = $2; X else { X for (c = curr_opt->choice; c->next; c = c->next) X ; X c->next = $2; X } X } X | empty X ; X Xanon_choice : CHOICE X { curr_cho = (Choice *) malloc(sizeof(Choice)); X curr_cho->id = NULL; X curr_cho->value = NULL; X curr_cho->label = NULL; X curr_cho->parameter = FALSE; X curr_cho->is_default = FALSE; X curr_cho->item = NULL; X curr_cho->next = NULL; X } X LBRACE choice_info RBRACE X { if (curr_cho->value == NULL) X yyerror("no value specified for choice"); X $$ = curr_cho; X } X ; X Xchoice_info : choice_info cho_info_item X | empty X ; X Xcho_info_item : label X { curr_cho->label = strsave($1); } X | default X { curr_cho->is_default = TRUE; } X | parameter X { curr_cho->parameter = TRUE; X curr_cho->text = text; X curr_opt->horizontal = FALSE; X } X | value X { curr_cho->value = strsave($1); } X ; X Xparameter : PARAMETER parm X ; X Xparm : TEXT INTEGER text_init X { text.type = PARM_TEXT; X text.length = $2; X text.text_init = strsave($3); X } X | NUMERIC INTEGER INTEGER TO INTEGER X { text.type = PARM_NUMERIC; X text.length = $2; X text.low = $3; X text.high = $5; X if (text.low > text.high) X yyerror("numeric text field range is incorrect"); X } X int_init X { text.int_init = $7; X if (text.int_init < text.low || text.int_init > text.high) X yyerror("numeric text field initial value is out of range"); X } X ; X Xtext_init : INIT STRING X { $$ = $2; } X | empty X { $$ = NULL; } X ; X Xint_init : INIT INTEGER X { $$ = $2; } X | empty X { $$ = text.low; } X ; X Xcommand_name : COMMAND STRING X { $$ = $2; } X ; X Xdefault : DEFAULT X ; X Xdelimiter : DELIMITER STRING X { $$ = $2; } X ; X Xicon : ICON_ STRING X { $$ = $2; } X ; X Xicon_mask : ICON_MASK STRING X { $$ = $2; } X ; X Xhorizontal : HORIZONTAL X ; X Xlabel : LABEL STRING X { $$ = $2; } X ; X Xmessage : MESSAGE STRING X { $$ = $2; } X ; X Xoptional : OPTIONAL X ; X Xoutput : OUTPUT INTEGER BY INTEGER X { output_height = $2; X output_width = $4; X } X ; X Xsuffix : SUFFIX STRING X { $$ = $2; } X ; X Xvalue : VALUE STRING X { $$ = $2; } X ; X Xempty : ; X X%% X X/************************************************************************/ XPRIVATE yyerror(s1, s2, s3, s4, s5, s6, s7) X Xchar *s1, *s2, *s3, *s4, *s5, *s6, *s7; X X{ char buf1[1024], buf2[1024]; X X sprintf(buf1, "%s: line %d: ", curr_file, line_count - ((ungetc == '\n')? 1 : 0)); X sprintf(buf2, s1, s2, s3, s4, s5, s6, s7); X strcat(buf1, buf2); X if (strcmp(s1, "syntax error") == 0) { X strcat(buf1, " at or near "); X strcat(buf1, get_last_token()); X } X error(buf1); X yyclearin; X parse_errors_occured++; X} X X#include "lex.c" END_OF_FILE if test 9186 -ne `wc -c <'parse.y'`; then echo shar: \"'parse.y'\" unpacked with wrong size! fi # end of 'parse.y' fi if test -f 'process.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'process.c'\" else echo shar: Extracting \"'process.c'\" \(9815 characters\) sed "s/^X//" >'process.c' <<'END_OF_FILE' X/************************************************************************/ X/* Copyright 1987-1991 by Chuck Musciano and Harris Corporation */ X/* */ X/* Full ownership of this software, and all rights pertaining to */ X/* the for-profit distribution of this software, are retained by */ X/* Chuck Musciano and Harris Corporation. You are permitted to */ X/* use this software without fee. This software is provided "as */ X/* is" without express or implied warranty. You may redistribute */ X/* this software, provided that this copyright notice is retained, */ X/* and that the software is not distributed for profit. If you */ X/* wish to use this software in a profit-making venture, you must */ X/* first license this code and its underlying technology from */ X/* Harris Corporation. */ X/* */ X/* Bottom line: you can have this software, you can use it, you */ X/* can give it away. You just can't sell any or all parts of it */ X/* without prior permission from Harris Corporation. */ X/************************************************************************/ X X/************************************************************************/ X/* */ X/* process.c process files dropped on the catcher */ X/* */ X/************************************************************************/ X X#include <stdio.h> X#include <ctype.h> X X#include <xview/xview.h> X#include <xview/panel.h> X X#include "manifest.h" X#include "catcher.h" X XPUBLIC char *getenv(); X XPUBLIC Frame base; X X/************************************************************************/ XPRIVATE get_text_value(value, text, item) X Xchar *value; XText *text; XPanel_item item; X X{ int val; X X if (text->type == PARM_TEXT) X strcpy(value, xv_get(item, PANEL_VALUE)); X else { X val = (int) xv_get(item, PANEL_VALUE); X if (val < text->low) X val = text->low; X if (val > text->high) X val = text->high; X sprintf(value, "%d", val); X } X} X X/************************************************************************/ XPRIVATE int get_choice_value(value, choice, field, oname) X Xchar *value; XChoice *choice; Xchar *field; Xchar *oname; X X{ X if (field) X if (strcmp(field, "value") == 0) X if (choice->parameter) X get_text_value(value, &(choice->text), choice->item); X else if (choice->id == NULL) X *value = '\0'; X else{ X error("choice \"%s\" in option \"%s\" has no parameter defined", choice->id, oname); X return(FALSE); X } X else { X error("unknown field: \"%s\"", field); X return(FALSE); X } X else X strcpy(value, choice->value); X return(TRUE); X} X X/************************************************************************/ XPRIVATE int find_name(name, field, value, file, options) X Xchar *name; Xchar *field; Xchar *value; Xchar *file; XOption *options; X X{ Option *o; X Choice *c; X int i, val; X char *p; X X if (strcmp(name, "file") == 0) { X if (field) { X error("no fields are allowed with the \"file\" variable"); X return(FALSE); X } X strcpy(value, file); X } X else { X for (o = options; o; o = o->next) X if (o->type == OPT_NONEXCLUSIVE) { X for (i = 0, c = o->choice; c; c = c->next, i++) X if (strcmp(name, c->id) == 0) { X val = (int) xv_get(o->item, PANEL_VALUE); X if (val & (1 << i)) X return(get_choice_value(value, c, field, o->id)); X else X *value = '\0'; X break; X } X if (c) X break; X } X else if (strcmp(name, o->id) == 0) { X if (o->type == OPT_TEXT) X if (field) { X error("no fields are allowed with text variables"); X return(FALSE); X } X else { X get_text_value(value, &(o->text), o->item); X break; X } X else { X val = (int) xv_get(o->item, PANEL_VALUE); X for (i = 0, c = o->choice; i < val; c = c->next, i++) X ; X return(get_choice_value(value, c, field, o->id)); X } X } X if (o == NULL) X if ((p = getenv(name)) == NULL) { X error("undefined variable: \"%s\"", name); X return(FALSE); X } X else if (field) { X error("no fields are allowed with environment variables"); X return(FALSE); X } X else X strcpy(value, p); X } X return(TRUE); X} X X/************************************************************************/ XPRIVATE int apply_mods(value, mods) X Xchar *value; Xchar *mods; X X{ char *p, *q, *rindex; X X while (*mods) { X switch (*mods) { X case 'h' : for (p = value + strlen(value) - 1; p >= value; p--) X if (*p == '/') { X *p = '\0'; X break; X } X if (*value == '\0') X strcpy(value, "/"); X break; X case 'r' : for (p = value + strlen(value) - 1; p >= value; p--) X if (*p == '.') { X *p = '\0'; X break; X } X else if (*p == '/') X break; X break; X case 's' : for (p = value + strlen(value) - 1; p >= value; p--) X if (*p == '.') { X strcpy(value, p + 1); X break; X } X else if (*p == '/') X break; X if (p < value || *p == '/') X *value = '\0'; X break; X case 't' : for (p = value + strlen(value) - 1; p >= value; p--) X if (*p == '/') { X strcpy(value, p + 1); X break; X } X break; X default : error("invalid modifier: '%c'", *mods); X return(FALSE); X } X if (*++mods == ':') X ++mods; X } X return(TRUE); X} X X/************************************************************************/ XPRIVATE char *substitute(pattern, file, options) X Xchar *pattern; Xchar *file; XOption *options; X X{ char *name, *field, *mods, *p; X static char value[2048]; X X for (p = name = pattern; *p && *p != '.' && *p != ':'; p++) X ; X if (*p == '.') { X *p++ = '\0'; X for (field = p; *p && *p != ':'; p++) X ; X if (*p) X *p++ = '\0'; X } X else { X if (*p == ':') X *p++ = '\0'; X field = NULL; X } X mods = p; X if (!find_name(name, field, value, file, options)) X return(NULL); X if (!apply_mods(value, mods)) X return(NULL); X return(value); X} X X/************************************************************************/ XPRIVATE int build_command(result, command, option, file) X Xchar *result; Xchar *command; XOption *option; Xchar *file; X X{ char *template = NULL, buf[2048], *t, *r, *p, *q, c; X int changed, depth; X X do { X changed = FALSE; X if (template == NULL) X template = strsave(command); X else { X free(template); X template = strsave(result); X } X for (t = template, r = result; *t; ) X if (*t == config.escape) { X changed = TRUE; X if (*++t == config.ldelim) { X for (p = t + 1, depth = 1; *p && depth > 0; p++) X if (*p == config.ldelim) X depth++; X else if (*p == config.rdelim) X depth--; X if (depth > 0) { X error("erroneous substitution pattern: %s", t); X return(FALSE); X } X *--p = '\0'; X if (!build_command(buf, t + 1, option, file)) X return(FALSE); X if ((q = substitute(buf, file, option)) == NULL) X return(FALSE); X strcpy(r, q); X r += strlen(q); X t = p + 1; X } X else { X for (p = t; *p && (isalnum(*p) || *p == '_'); p++) X ; X c = *p; X *p = '\0'; X if ((q = substitute(t, file, option)) != NULL) { X strcpy(r, q); X r += strlen(q); X *p = c; X t = p; X } X else { X error("undefined variable: %s", t); X return(FALSE); X } X } X } X else X *r++ = *t++; X *r = '\0'; X } while (changed); X return(TRUE); X} X X/************************************************************************/ XEXPORT process_file(path) X Xchar *path; X X{ char *command = NULL, buf[2048]; X Command *cmd; X X for (cmd = config.command; cmd; cmd = cmd->next) { X if (cmd->optional && (int) xv_get(cmd->toggle, PANEL_VALUE) == 0) X continue; X if (!build_command(buf, cmd->command, cmd->option, path)) X return; X if (command == NULL) X command = strsave(buf); X else { X command = (char *) realloc(command, strlen(command) + strlen(buf) + 5); X strcat(command, " | "); X strcat(command, buf); X } X } X if (!is_empty(command)) { X if (config.message) { X if (build_command(buf, config.message, NULL, path)) X xv_set(base, FRAME_LEFT_FOOTER, buf, NULL); X } X execute(command, path); X free(command); X } X} X X/************************************************************************/ XEXPORT process_text(data) X Xchar *data; X X{ char *path; X FILE *f; X X path = (char *) malloc(strlen(config.suffix) + 22); X strcpy(path, "/tmp/catcher.XXXXXX"); X mktemp(path); X strcat(path, "."); X strcat(path, config.suffix); X if ((f = fopen(path, "w")) == NULL) X error("cannot open %s for writing: %s", path, sys_errlist[errno]); X else if (fwrite(data, 1, strlen(data), f) != strlen(data)) { X fclose(f); X error("error while writing to %s: %s", path, sys_errlist[errno]); X } X else { X fclose(f); X process_file(path); X } X free(path); X} END_OF_FILE if test 9815 -ne `wc -c <'process.c'`; then echo shar: \"'process.c'\" unpacked with wrong size! fi # end of 'process.c' fi echo shar: End of archive 3 \(of 5\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.