archie/prospero/user/menu/search.c
2024-05-27 16:13:40 +02:00

321 lines
7.5 KiB
C

/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* The menu API and client were written by Kwynn Buess (buess@isi.edu)
* Extensive modifications by Steven Augart (swa@ISI.EDU)
*/
#include <usc-license.h>
#include <usc-copyr.h>
#include <pfs.h>
#include <string.h>
#include "menu.h"
#include "p_menu.h"
struct q_arg_list {
char *name;
char *value;
struct q_arg_list *next;
};
typedef struct q_arg_list *QAL;
void display_query_doc(char*,PATTRIB);
char *return_arg_default(PATTRIB);
static TOKEN replace_args(TOKEN,QAL);
static char *replace_arg(TOKEN,QAL);
/* Returns a linked list of VLINKs. In case of error, display a message and
return null. */
VLINK
open_search(VLINK vl)
{
TOKEN q_tok = get_token(vl,"QUERY-METHOD");
QAL alist;
QAL get_query_args(TOKEN);
void fill_query_args(QAL,PATTRIB);
VDIR_ST dir_st;
VDIR dir = &dir_st;
TOKEN acomp;
VLINK retval; /* value to return. */
int tmp; /* return from p_get_dir() */
m_error = NULL; /* no error right now. */
if(q_tok && (q_tok->token)) display_query_doc(q_tok->token,vl->lattrib);
alist = get_query_args(q_tok);
fill_query_args(alist,vl->lattrib);
acomp = replace_args((q_tok->next ? q_tok->next->next : NULL),alist);
vdir_init(dir);
tmp = p_get_dir(vl,replace_arg(q_tok->next,alist),dir,0,&acomp);
if (tmp) {
perrmesg("Couldn't complete search:", 0, (char *) NULL);
printf("\n\nRepeating previous menu\n");
vdir_freelinks(dir);
retval = NULL;
goto cleanup;
}
retval = dir->links; dir->links = NULL;
vdir_freelinks(dir);
/* alist is a list of QAL's not freed on exit !!*/
cleanup:
tklfree(acomp); /* Was a nasty memory leak */
return retval;
}
static TOKEN
replace_args(TOKEN fill, QAL alist)
{
TOKEN ttok;
char *tstr;
if(!fill) return(NULL);
tstr = replace_arg(fill, alist);
ttok = tkalloc(NULL);
ttok->token = tstr;
ttok->next = replace_args(fill->next, alist);
return(ttok);
}
static char *
replace_arg(TOKEN fill, QAL alist)
{
TOKEN temp_fill_next;
QAL temp_al;
int size = 0;
char *the_arg;
int cnt_the,cnt_fill;
int done = 0;
char *close_br;
char *temp_value;
char *get_value(char *,QAL);
TOKEN new_token;
char *copy, *startcopy;
char *head;
if (fill == NULL) return(NULL);
if (fill->token == NULL) return(NULL);
startcopy = copy = stcopy(fill->token);
temp_al = alist;
while (temp_al != NULL) {
size += strlen(temp_al->value) + 1;
temp_al = temp_al->next;
}
size += strlen(copy);
head = the_arg = (char *)stalloc(sizeof(char) * size);
cnt_the = cnt_fill = 0;
while (!done) {
if (*copy == '$') {
if (*(copy +cnt_fill + 1) == '{'
&& *(copy + cnt_fill - 1) != '$')
{
copy += 2;
close_br = strchr(copy,'}');
*close_br = '\0';
temp_value = get_value(copy,alist);
*the_arg = '\0';
strcat(the_arg,temp_value);
the_arg += strlen(temp_value);
copy = close_br + 1;
continue;
}
else {
*the_arg++ = *copy++;
if (*(the_arg - 1) == '\0') done = 1;
}
}
else {
*the_arg++ = *copy++;
if (*(the_arg - 1) == '\0') done = 1;
}
}
/* Nasty memory leak - copy is at the end of the string*/
stfree(startcopy);
return(head);
}
char *
get_value(char *to_cmp, QAL list)
{
QAL temp = list;
while (temp != NULL) {
if (!strcmp(to_cmp,temp->name)) return temp->value;
temp = temp->next;
}
return NULL;
}
/* Interact with user to fill arguments to query */
void fill_query_args(QAL to_fill,PATTRIB all_attribs) {
QAL temp_tok = to_fill; /* Note temp_tok is not a TOKEN */
PATTRIB temp_atr = all_attribs;
char *get_line();
if (temp_tok == NULL) return;
if (all_attribs == NULL) return;
while (temp_tok != NULL) { /* Over all the to_fill structure */
temp_atr = all_attribs; /* Reset to look at head of pattribs */
/* Redundantly set at end of loop as well */
while (temp_atr != NULL) {
if (!strcmp(temp_atr->aname,"QUERY-ARGUMENT")) {
/* If attribute is QUERT-ARGUMENT matching this temp_tok */
if ((temp_atr->value.sequence != NULL) &&
(!strcmp(temp_atr->value.sequence->token,temp_tok->name))) {
enter_again: /* Lazy code - should be a while loop with break*/
printf("%s: ",temp_atr->value.sequence->next->token);
temp_tok->value = get_line();
if(!temp_tok->value || !*(temp_tok->value)) {
char *defval;
if(temp_tok->value) stfree(temp_tok->value);
/* Get default or tryagain */
defval = return_arg_default(temp_atr);
if(!defval) {
display_query_doc(temp_atr->value.sequence->token,
all_attribs);
goto enter_again;
}
temp_tok->value = stcopy(defval);
}
else if(strequal(temp_tok->value,"?")) {
display_query_doc(temp_atr->value.sequence->token,all_attribs);
stfree(temp_tok->value); temp_tok->value = NULL;
goto enter_again;
}
else if(*(temp_tok->value) == '\\') {
char *tptr;
tptr = stcopy((temp_tok->value)+1);
stfree(temp_tok->value);
temp_tok->value = tptr;
}
}
}
temp_atr = temp_atr -> next;
}
temp_tok = temp_tok->next;
temp_atr = all_attribs;
}
}
void display_query_doc(char *which,PATTRIB all_attribs)
{
PATTRIB temp_atr = all_attribs;
char *paren = strchr(which,'(');
while (temp_atr != NULL) {
if (!strcmp(temp_atr->aname,"QUERY-DOCUMENTATION"))
if (temp_atr->value.sequence != NULL)
if((paren && !strncmp(temp_atr->value.sequence->token,which,
paren - which)) ||
(!paren && !strcmp(temp_atr->value.sequence->token,which))){
printf("\n%s\n\n",temp_atr->value.sequence->next->token);
}
temp_atr = temp_atr -> next;
}
}
char *return_arg_default(PATTRIB qarg)
{
TOKEN element;
int count = 1;
if(!qarg) return(NULL);
if (!strequal(qarg->aname,"QUERY-ARGUMENT")) return (NULL);
element = qarg->value.sequence;
while(element) {
if(count++ == 6) return(element->token);
element = element->next;
}
return(NULL);
}
QAL get_query_args(TOKEN seq) {
char *func;
char *t_comma;
char *t2;
int done_loop = 0;
int args;
char *end_arg;
QAL head,current,chaser;
if (seq == NULL) return NULL;
if (seq->token == NULL) return NULL;
func = stcopy(seq->token);
t_comma = strchr(func,'(');
if (t_comma == NULL) return NULL;
else t_comma++;
if (strchr(t_comma,',') == NULL) { /* Determine whether there are any args */
done_loop = 0;
args = 0;
t2 = t_comma;
while (!done_loop) {
t2++;
if (*t2 == '\0' || *t2 == ')' || args) done_loop = 1;
if (!done_loop)
if (!(isspace(*t2) || *t2 == ')' || *t2 == '\0')) args = 1;
}
if (!args) return NULL;
}
head = (QAL) stalloc(sizeof(struct q_arg_list));
head->next = NULL;
head->value = NULL;
end_arg = strchr(t_comma,',');
if (end_arg == NULL) end_arg = strchr(t_comma,')');
*end_arg = '\0';
head->name = stcopy(t_comma);
t_comma = end_arg + 1;
chaser = head;
while (!done_loop) {
end_arg = strchr(t_comma,',');
if (end_arg == NULL) {
end_arg = strchr(t_comma,')');
done_loop = 1;
}
current = (QAL) stalloc(sizeof(struct q_arg_list));
current->next = NULL;
current->value = NULL;
*end_arg = '\0';
current->name = stcopy(t_comma);
chaser->next = current;
chaser = current;
t_comma = end_arg + 1;
}
stfree(func);
return head;
}