/* findbr.c  94.10.29
 * Copyright 1983-1992   Albert Davis
 * find a branch with matching label
 * returns the branch pointer
 */
#include "ecah.h"
#include "branch.h"
#include "error.h"
#include "declare.h"
/*--------------------------------------------------------------------------*/
	branch_t *findbranch(const char*,int*,branch_t*,branch_t*);
	branch_t *findbranch_samescope(const char*,branch_t*);
	const branch_t *findbranch_sametype(const char*,const branch_t*);
	int	 wmatch(const char*,const char*);
/*--------------------------------------------------------------------------*/
extern const char e_int[];
/*--------------------------------------------------------------------------*/
/* findbranch: find a matching label, by (ugh) linear search
 * 	start searching at "start", stop at "stop"
 *	label to look for is in command line: &cmd[*cnt]
 * return pointer to match if exists (and eat input)
 *	  pointer to a non-existent branch if no match (don't eat input)
 * caution: caller must check return value before using
 */
branch_t *findbranch(const char *cmd,int *cnt,branch_t *start,branch_t *stop)
{
 int save;
 branch_t *brh;
 char labelwanted[BUFLEN+1];
 char thislabel[BUFLEN+1];
 char *dot;
 char *wanted;

 save = *cnt;				/* copy the name to local space	    */
 (void)ctostr(cmd, cnt, labelwanted, BUFLEN, TOKENTERM);

 if (!labelwanted[1]){
    *cnt = save;			/* don't match single letter	    */
    return (branch_t*)NULL;		/* probably a command		    */
 }

 labelwanted[BUFLEN] = thislabel[BUFLEN] = '\0';

 dot = strrchr(labelwanted,'.');	/* trim off front stuff for subckt  */
 if (dot){
    *dot = '\0';
    wanted = dot + 1;
 }else{
    wanted = labelwanted;
 }

 brh = start;
 do {
    int dummy = 0;
    (void)ctostr( brh->label, &dummy, thislabel, BUFLEN, TOKENTERM );
    if (wmatch(wanted,thislabel)){
       if (!dot){				/* found it */
          return (branch_t*)brh;
       }else{
          branch_t *subbrh;
	  dummy = 0;
          subbrh=findbranch(labelwanted,&dummy,brh->subckt,brh->subckt->prev);
	  if (exists(subbrh)){
	     return subbrh;
	  }else if (brh == stop){		/* found subckt but */
	     *cnt = save;			/* no match within it */
	     return (branch_t*)NULL;
	  }
       }
    }else if (brh == stop){
       *cnt = save;
       return (branch_t*)NULL;			/* didn't find it */
    }
 } while (brh = nextbranch_all(brh),  brh != start);

 error(bWARNING, e_int, "findbranch: no stop");
 *cnt = save;					/* trap endless loop */
 return (branch_t*)NULL;
}
/*--------------------------------------------------------------------------*/
/* findbranch_samescope: search for a match to "name" in the "list"
 * following same type thread
 * return ptr to it, or NULL if it fails
 */
branch_t *findbranch_samescope(const char *name, branch_t *list)
{
 branch_t *brh;
 brh = list;	
 for (;;){
    brh = brh->next;
    if (wmatch(name, brh->label)){
       return brh;				/* found it */
    }else if (brh == list){
       return (branch_t*)NULL;			/* failed */
    }
 }
 /*NOTREACHED*/
}
/*--------------------------------------------------------------------------*/
/* findbranch_sametype: search for a match to "name" in the "list"
 * following same type thread
 * return ptr to it, or NULL if it fails
 */
const branch_t *findbranch_sametype(const char *name, const branch_t *list)
{
 const branch_t *brh;
 brh = list;	
 for (;;){
    brh = brh->stnext;
    if (wmatch(name, brh->label)){
       return brh;				/* found it */
    }else if (brh == list){
       return (branch_t*)NULL;			/* failed */
    }
 }
 /*NOTREACHED*/
}
/*--------------------------------------------------------------------------*/
/* wmatch: string match with wild cards
 * s1 may have wild cards: ? any character matches; * any repeated 0 or more
 * returns YES or NO
 * normally not case sensitive,
 *	but \ before any letter in s1 forces exact match
 * recursive
 * in the wrong file, but it started here as a static.....
 */
int wmatch(const char *s1, const char *s2)
{
 for (   ;  (*s1 && *s2) || (*s1=='*');  s1++, s2++){
    if (*s1 == '?'){		    /* '?' matches anything		    */
       ;
    }else if (*s1 == '*'){	    /* '*' matches 0 or more of anything    */
       if (wmatch(s1+1,s2)){	    /* try '*' matches nothing		    */
	  return YES;
       }else{			    /* '*' matches at least one character   */
	  s1--;			    /* match it, try for more		    */
	  if (*s2 == '\0')	    /* there is more in s1.  If this were   */
	     return NO;		    /* all, the recursive call above would  */
       }			    /* have matched.			    */
    }else if (*s1 == '\\'){	    /* '\' requires an exact match	    */
       s1++;			    /* including case			    */
       if (*s1 != *s2)
	  return NO;
    }else if (to_lower(*s1) != to_lower(*s2)){
	return NO;		    /* try to match, ignoring case	    */
    }
 }
return *s1 == *s2;		    /* one of the strings ended		    */
}				    /* if match, both will be '\0'	    */
				    /*	    and return YES, otherwise NO    */
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
