/* * Copyright (c) 1991-1994 by the University of Southern California * * For copying and distribution information, please see the file * . * * The menu API and client were written by Kwynn Buess (buess@isi.edu) * Extensive modifications by Steven Augart (swa@ISI.EDU) */ #include #include #include #include #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; }