/*	listvar		1994(?)  G. Flierl(?)				*/
/*    Provide list of variables in a JGOFS object to stdout.  One	*/
/*  variable is listed on each line, preceded by 0 or more spaces.  The	*/
/*  number of spaces, divided by 2, is the JGOFS "level" of the		*/
/*  variable within the object						*/
/*    Input arg is object name in the several permissible formats	*/
/*  See code of jdb.c followed by dct.c for definitive info		*/
/*  	1. [//machine]/subdir_of_obj_root/obj_name			*/
/*	2. "object file entry" (ie, method(param1,param2,...))		*/
/*	3. datafile_name						*/
/*	4.   ??								*/

#define LISTVAR_ID "listvar version 1.4  9 Apr 2013"
/*   9 Apr 2013 - version 1.3b WJS					*/
/*	-1 switch - output all on one line. Tab separated - level info	*/
/*    lost).  Sorry about  -1  and  -l  , but it seems like the best	*/
/*    name ...								*/
/*	Fool w/ "Usage" printout					*/
/*	Fix potential buffer overflow for obj name > 1024		*/
/*	Note that this program is starting to use "magic characters"	*/
/*    The tab separator for  -1  output and the attribute delims should	*/
/*    really come from a  .h  file.  They are fundamental at "the jdb	*/
/*    level.  They're parametrized someplace (attrib stuff in core.h)	*/
/*    but I'm far too lazy to work on this now				*/
/*			[begin v 1.4]					*/

/*  30 Aug 2004 - version 1.3b WJS					*/
/*	jdbfuncdefns.h							*/
/*  25 Aug 2004 - version 1.3b WJS					*/
/*	Needs an err entry for utils.c routine errors			*/
/*  23 Apr 2004 - version 1.3b WJS                                      */
/*	Mods to "version-returning function".				*/
/*	  a) change from local to global to ensure it can't be "opti-	*/
/*	     mized out"							*/
/*	  b) don't want "version" in any function name since such       */
/* 	     names appear when grep'ping for "version"		        */
/*  11 Feb 2004 - version 1.3b WJS					*/
/*	Fixes to get rid of compiler warnings				*/
/*	Use core.h & get its ID into this module			*/

/*  16 Oct 2003 - version 1.3a WJS					*/
/*	Explicitly exit with status of 0 after normal run		*/

/*  28 Jul 1998 - version 1.3 clh					*/
/*	Add -l switch to output level at which variable occurs		*/
/* 	    format of output becomes X, variablename			*/
/*	    where X is the level of the var				*/

/*  23 Sep 97.  v 1.2.	WJS						*/
/*	Add some comments.						*/
/*	Add an ID string and print it in diagnostic situations		*/
/*	Add error message if jdbopen_ returns error status		*/
/*	Diagnose incorrect # args					*/
/*	Add -a switch to add attributes string after variable names	*/
/*	  Attributes are ; separated and enclosed in []s		*/
/*		[Begin 1.2]						*/
/*  1995(?)								*/
/*	include <string.h> (? this entry a surmise based on info from	*/
/*	  C Hammond)							*/
/************************************************************************/
#include INNEROPTIONS
#include "jdbfuncdefns.h"

void err(s,t)
char *s,*t;
{
    /*  Quick and dirty for now (1.3b) ...				*/
  printf ("%s\n%s\n",s,t);
  printf ("%s\n",LISTVAR_ID);
  exit(1);
}

char *listvar_return_vers()
/*  Dummy routine.  Exists only to force .h file version string into	*/
/*  this module.  Note string must not be global or we'll have con-	*/
/*  flicts if another routine similarly includes the version string	*/
{
  static char version[] = LISTVAR_ID"/"FULL_JDBFUNCDEFNSH_VERSION;
  return version;
}

void print_usage(program_as_invoked)
char *program_as_invoked;
{
  printf ("Usage: %s [  [-1] | [-l]  ]  [-a]  object\n",program_as_invoked);
  printf ("Options: \n");
  printf ("\t-1\tOutput variable names on one line.  Level information lost\n");
  printf ("\t\tBy default, variable names are output 1 to a line\n");
  printf ("\t-l\tPrecede each variable name with the level at which it occurs, as\n");
  printf ("\t\t\tL, variable\n");
  printf ("\t\tBy default, variable names are indented 2 spaces per level\n");
  printf ("\t-a\tfollow variable names with attributes\n");
  printf ("%s\n",LISTVAR_ID);
  exit(1);
}

int main(argc,argv)
int argc;
char *argv[];
{
char *obj;
int unit,maxlev,i,j;
char names[NVAR][VARNAMESIZE+1];
char attr[ATTRSIZE+1];
int num,buflen;
int namesize=VARNAMESIZE+1;	 /* Size of buffer, not max name	*/
int narg,nattr,attr_switch,level_switch,one_line_switch;

  /*  Get switches (each assumed to start with -).  Assume there is	*/
  /*	only 1 non-switch argument (namely, the object name)		*/
narg = 0;
attr_switch = 0;
level_switch = 0;
one_line_switch = 0;
for (i = 1; i < argc; i++) {
  if (*argv[i] == '-') {
    switch ( *(argv[i]+1) )   {
      case 'a':
	attr_switch = 1;
	break;
      case 'l':
	level_switch = 1;
	break;
      case '1':
	one_line_switch = 1;
	break;
      default:
	print_usage(argv[0]);
	break;
    }
      /*  Replace switch w/last arg so switches can occur anyplace	*/
      /*    and also so object ends up argv[1] as originally expected	*/
      /*  This logic fails if we ever add a second non-switch argument	*/
      /*    and depend on the order of the 2				*/
      /*  Non unix-like, but I hate having to put the switches first	*/
    argv[i--] = argv[--argc];
  } else {
    narg++;
  }
}
if (narg != 1) print_usage(argv[0]);
if (one_line_switch && level_switch) print_usage(argv[0]);

buflen = strlen(argv[1]) + 1;
obj = (char *)malloc(buflen);
if (obj == NULL)
	err ("Could not allocate space for copy of object name ",argv[1]);
strcpy (obj,argv[1]);

num= -NVAR;
unit = 1;
maxlev=jdbopen_(&unit,obj,names,&namesize,&num);
if(maxlev<0){
  printf ("jdbopen_: %d\n%s\n",maxlev,LISTVAR_ID);
  exit(1);
};

for(i=0;i<num;i++) {
  if (i > 0) {
      /*  Separators cannot appear in a varname or attribute list	*/
      /*  I think that tab and newline are about the only safe things	*/
    if (one_line_switch) printf ("\t");
    else printf ("\n");
  }
  j=jdblevel_(&unit,&i);
  if (level_switch) 
    printf("%d, %s",j,names[i]);
  else 
    printf("%*.*s%s",j*2,j*2," ",names[i]);

  nattr = 0;
  if (attr_switch) {
    while (jdbattributes_(&unit,&i,attr)) {
      if (nattr == 0) printf ("[");
      else printf (";");
      printf ("%s",attr);
      nattr++;
    }
    if (nattr > 0) printf ("]");
  }
};
printf ("\n");

jdbclose_(&unit);
exit(0);
}
