/*
 * This file is part of an snmp query application.
 * This file contains routines that manage the variable lists.
 *
 * Copyright 1990 by the Massachusetts Institute of Technology.
 *
 * For copying and distribution information, please see the file
 * <mit-copyright.h>.
 *
 * Tom Coppeto
 * MIT Network Services
 * 15 April 1990
 *
 *    $Source: /afs/net.mit.edu/tools/src/simon/RCS/class.c,v $
 *    $Author: tom $
 *    $Locker:  $
 *    $Log:	class.c,v $
 * Revision 1.6  91/02/21  13:53:05  tom
 * changed array to link list
 * 
 * Revision 1.5  90/07/27  15:19:23  tom
 * do proper variable conversion in list_class_variables()
 * 
 * Revision 1.4  90/07/25  10:28:17  tom
 * ? will list classes in prompt_for_class()
 * get_class() will search for both the symbolic & numeric variable and the 
 * other functions modified to support the numeric representation of a
 * variable as a separete entity
 * 
 * Revision 1.3  90/07/20  23:45:40  tom
 * compiler warning
 * 
 * Revision 1.2  90/07/20  21:37:14  tom
 * static/extern compiler warning fixed
 * 
 * Revision 1.1  90/07/20  21:17:29  tom
 * Initial revision
 * 
 *
 */

#ifndef lint
static char *rcsid = "$Header: /afs/net.mit.edu/tools/src/simon/RCS/class.c,v 1.6 91/02/21 13:53:05 tom Exp $";
#endif


#include <simon.h>
#include <mit-copyright.h>


CLASS *ClassList = (CLASS *) NULL;

/*
 * callbacks
 */


/*
 * Function:    cmd_change_class()
 * Description:
 */

void
cmd_create_class(argc, argv)
     int argc;
     char *argv[];
{
  char *new = (char *) NULL;
  VARIABLE v;
  CLASS *c;

  pname = argv[0];
  bzero(cmdbuf, sizeof(cmdbuf));
  bzero(&v, sizeof(v));

  while (*++argv)
    {
      if(**argv != '-')
        {
          if(new == (char *) NULL)
            {
              strncpy(cmdbuf, *argv, sizeof(cmdbuf)-1);
	      new = &cmdbuf[0];
              continue;
            }
          else
            fprintf(stderr, "Too many classes specified on command line.\n");
        }
      else
        if(strcmp(*argv, "-help") != 0)
          fprintf(stderr, "Unknown option \"%s\".\n", *argv);

      printf("usage: %s [<variable class name>]\n", pname);
      return;
    }

  if(!new)
    {
      if(!(new = prompt_string("name of new class: ", "")))
        {
          printf("Request cancelled.\n");
          return;
       }
    }

  if(is_class(new))
    {
      fprintf(stderr, "\"%s\" is already an assigned class.\n", new);
      free(new);
      return;
    }

  if(!(c = create_class(new)))
    {
      fprintf(stderr, "Unable to create class \"%s\".\n", new);
      return;
    }
  
  while(make_variable(c, &v) == SUCCESS)
    bzero(&v, sizeof(v));

  printf("Variable class \"%s\" created.\n", new);
  return;
}




/*
 * Function:    cmd_add_class()
 * Description: 
 */

void 
cmd_delete_class(argc, argv)
     int argc;
     char *argv[];
{
  int i, j;

  pname = argv[0];

  if(!ClassList)
    {
      fprintf(stderr, "There are no classes to delete.\n");
      return;
    }

  i = 0;
  while (*++argv)
    {
      if(**argv != '-')
        {
	  if((argptr[i++] = 
	      (char *) prompt_for_class("class to delete: ", *argv)) 
	     == (char *) NULL)
	    {
	      printf("continuing...\n");
	      continue;
	    }
	  continue;
	}
      else
        if(strcmp(*argv, "-help") != 0)
          fprintf(stderr, "Unknown option \"%s\".\n", *argv);
      
      printf("usage: %s [<variable classes>]\n", pname);
      return;
    }
  
  if(i == 0)
    if((argptr[i++] = (char *) prompt_for_class("class to delete: ", NULL)) 
       == (char *) NULL)
      {
	printf("OK, nothing changed.\n");
	return;
      }

  for(j = 0; j < i; j++)
    if(delete_class((CLASS *) argptr[j]) != SUCCESS)
      fprintf(stderr, "Unable to delete class \"%s\".\n", 
	      ((CLASS *) argptr[j])->name);
    else
      printf("Class \"%s\" deleted.\n", ((CLASS *) argptr[j])->name);

  return;
}




/*
 * Function:    cmd_show_classes()
 * Description: 
 */

void 
cmd_show_classes(argc, argv)
     int argc;
     char *argv[];
{
  CLASS *class;
  char *name = (char *) NULL;

  pname = argv[0];
  bzero(cmdbuf, sizeof(cmdbuf));

  while (*++argv)
    {
      if(**argv != '-')
	{
	  if(name == (char *) NULL)
	    {
	      strncpy(cmdbuf, *argv, sizeof(cmdbuf)-1);
	      name = &cmdbuf[0];
	      continue;
	    }
	  else
	    fprintf(stderr, "Too many classes specified.\n");
	}
      
      if(strcmp(*argv, "-help") != 0)
	fprintf(stderr, "Unknown option \"%s\".\n", *argv);
    
      printf("usage: %s [<variable class name>]\n", pname);
      return;
    }

  if(!name)
    {
      if((class = prompt_for_class("class to list: ", name)) == (CLASS *) NULL)
	{
	  printf("Request cancelled.\n");
	  return;
	}
      
      list_class_variables(class);
      return;
    }
  list_classes();	      
}




/*
 * Function:    cmd_show_unknown_classes()
 * Description: 
 */

void 
cmd_show_unknown_classes(argc, argv)
     int argc;
     char *argv[];
{
  CLASS *cptr;
  int i = 0;

  pname = argv[0];
  while (*++argv)
    {
      if(**argv == '-')
        {
          if(strcmp(*argv, "-help") != 0)
            fprintf(stderr, "Unknown option \"%s\".\n", *argv);
          printf("usage: %s\n", pname);
          return;
        }
    }

  if(!ClassList)
    printf("No unknown classes exist.\n");
  else
    {
      cptr = ClassList;
      while(cptr)
	{
	  printf("%3d: %-30s\n", i++ +1, cptr->name);
	  cptr = cptr->next;
	}
    }
  return;
}



/*
 * utilities
 */




CLASS *
prompt_for_class(prompt, name)
     char *prompt;
     char *name;
{
  CLASS *class;
  int   confused;
  char  buf[BUF_SIZE];

  if(!ClassList)
    return((CLASS *) NULL);
    
  while((name == (char *) NULL) || (*name == '?') ||
	((class = get_class(name)) == (CLASS *) NULL))
    {
      confused = TRUE;
      if(name != (char *) NULL)
	 fprintf(stderr, "\"%s\" is not a registered class.\n", name);
      while(confused == TRUE)
	{
	  get_prompted_input(prompt, buf, sizeof(buf));
	  if(*buf == '\0')
	    return((CLASS *) NULL);
	  
	  if(strcmp(buf, "?") == 0)
	    {
	      printf("choose a class from the following:\n");
	      list_classes();
	      printf("or hit <return> to abort.\n");
	      continue;
	    }

	  name = &buf[0];
	  confused = MAYBE;
	}
    }
  return(class);
}





void
list_classes()
{
  CLASS *cptr;
  int i = 0;

  if(!ClassList)
    printf("You have no class.\n");
  else
    {
      putchar('\n');
      cptr = ClassList;
      while(cptr)
	{
	  printf("%3d: %-30s\n", i++ +1, cptr->name);
	  cptr = cptr->next;
	}
      putchar('\n');
    }
  return;
}





void
list_class_variables(class)
     CLASS *class;
{
  VARIABLE *vptr;
  char     pbuf[BUF_SIZE];
  int      plen = 0;
  int      i = 0;
  char     *p;

  vptr = class->vars;
  putchar ('\n');

  if((stuff.dispmode & UNIQUE) && (stuff.dispmode & SYMBOLIC))
    {
      strncpy(pbuf, vptr->variable, strlen(vptr->variable));
      vptr = class->vars;
      while(vptr->next)
	{
	  p = common_prefix(vptr->variable, vptr->next->variable, 
			    pbuf);
	  pbuf[(p - vptr->variable)+1] = '\0';
	  ++i;
	  vptr = vptr->next;
	}
      
      if(i > 0)
	{
	  printf("%s...\n", pbuf);
	  plen = strlen(pbuf);
	}
      else
	{
	  plen = 0;
	  if((p = rindex(pbuf, '_')) != (char *) NULL)
	    {
	      *p = '\0';
	      if((p = rindex(pbuf, '_')) != (char *) NULL)
		{
		  printf("%s...\n", pbuf);
		  plen = strlen(pbuf);
		}
	    }
	}	  
    }
  else
    if((stuff.dispmode & STANDARD) && (stuff.dispmode & SYMBOLIC) && 
       stuff.prefix)
      {
	printf("%s...\n", stuff.prefix);
	plen = strlen(stuff.prefix);
      }


  i = 1;
  vptr = class->vars; 
  while(vptr->next)
    {
      printf(" %3d: ", i++);

      if(vptr->variable == (char *) NULL)
	vptr->variable = copy_string(numstrtosym(vptr->nvariable));

      if(!(stuff.dispmode & SYMBOLIC) || (vptr->variable == (char *) NULL))
	{
	  if(vptr->nvariable == (char *) NULL)
	    vptr->nvariable = copy_string(symtonumstr(vptr->variable));
	  printf("%s\t", vptr->nvariable);
	}
      else
	if((stuff.dispmode & LABEL) && (vptr->label))
	  printf("%-20s\t", vptr->label);
	else
	  if(stuff.dispmode & STANDARD)
	    {
	      if(stuff.prefix != (char *) NULL)
		{
		  if(strncmp(vptr->variable, stuff.prefix, 
			     strlen(stuff.prefix)) == 0)
		    printf("..%-50s\t", (vptr->variable + plen));
		  else
		    printf("%s\t", vptr->variable);
		}
	      else
		printf("%s\t", vptr->variable);
	    }
	  else
	    if(stuff.dispmode & TRUNCATED)
	      printf("%-25s\t", truncate(vptr->variable));
	    else
	      if(stuff.dispmode & UNIQUE)
		printf("%-50s\t", (vptr->variable + plen));	      
	      else
		printf("%s\t", vptr->variable);
      
      if(vptr->abbrev != (char *) NULL)
	printf("%-10s\n",  vptr->abbrev);
      else
	putchar('\n');
      vptr = vptr->next;
    }
  putchar('\n');
}




CLASS *
get_default_class()
{
  return(ClassList);
}



/*
 * Function:    add_class()
 * Description:
 */

CLASS *
create_class(class)
     char *class;
{
  CLASS *c;
  CLASS *s;

  if(!(c = (CLASS *) malloc(sizeof(CLASS))))
    {
      perror("add_class");
      return((CLASS *) NULL);
    }

  bzero(c, sizeof(CLASS));
  c->name = copy_string(class);
  if(!ClassList)
    ClassList = c;
  else
    {
      s = ClassList;
      while(s->next)
	s = s->next;
      s->next = c;
    }
  return(c);
}



/*
 * Function:    delete_class()
 * Description:
 */

int
delete_class(class)
     CLASS *class;
{
  CLASS *c;
  CLASS *s;

  c = ClassList;
  s = (CLASS *) NULL;
  while(c)
    {
      if(c == class)
	{
	  if(stuff.class == c)
	    stuff.class = (CLASS *) NULL;
	  c = c->next;
	  (void) free_class(s->next);
	  s->next = c;
	  return(SUCCESS);
	}
      s = c;
      c = c->next;
    }
  return(ERROR);
}




/*
 * Function:    is_class()
 * Description:
 */

int
is_class(a)
     char *a;
{
  CLASS *c;

  c = ClassList;
  while(c)
    {
      if(strcmp(a, c->name) == 0)
	return(TRUE);
      c = c->next;
    }
  return(FALSE);
}




CLASS *
get_class(class)
     char *class;
{
  CLASS *c;
  int i = 0;
  int num;

  if(class == (char *) NULL)
    return((CLASS *) NULL);

  c = ClassList;
  while(c)
    if(strcmp(class, c->name) == 0)
      return(c);
    else
      c = c->next;

  if(isnumber(class))
    {
      num = atoi(class);
      if(num > 0)
	{
	  c = ClassList;
	  while(c && (i < num))
	    {
	      ++i;
	      c = c->next;
	    }
	  return(c);
	}
    }
  return((CLASS *) NULL);
}




void 
free_class(c)
     CLASS *c;
{
  VARIABLE *v, *w;
  
  if(c == (CLASS *) NULL)
    return;

  if(c->name != (char *) NULL)
    free(c->name);
  
  v = c->vars;

  while(v != (VARIABLE *) NULL)
    {
      w = v->next;
      free_variable(v);
      v = w;
    }
  return;
}






