/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:utils.c 12.0$ */
/* $ACIS:utils.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/lib/tools/RCS/utils.c,v $ */

#ifndef lint
static char *rcsid = "$Header:utils.c 12.0$";
#endif

#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
#include "utils.h"

#define WHERE_AM_I   "utils.c"

/***===================================================================***/

int u_debug;

/***============================================================***/

#ifdef STRING_UTILS

u_strappend(arg,seperator,strvar,lenvar)
register1 char	*arg;
register6 char	*seperator;
register4 char	**strvar;
register5 int	*lenvar;
{
register2 char	*str;
register3 int	 len;

    D_ENTRY4(u_debug,"add_arg(%s,%s,0x%x,0x%x)\n",arg,seperator,strvar,lenvar);
    str=	*strvar;
    len=	*lenvar;
    if (len&&str&&str[0]) {
	if (strlen(str)+strlen(arg)+strlen(seperator)>len) {
	    len= *lenvar+=	strlen(arg)+strlen(seperator)+20;
	    str= *strvar=	u_realloc(str,len);
	}
	strcat(str,seperator);
    	strcat(str,arg);
    }
    else if (str) {
	len= *lenvar=		strlen(arg)+strlen(seperator)+strlen(str)+20;
	*strvar=		u_malloc(len);
	strcpy(*strvar,str);
	strcat(*strvar,seperator);
	strcat(*strvar,arg);
    }
    else {
	len= *lenvar=		strlen(arg)+20;
	str= *strvar=		u_malloc(len);
	strcpy(str,arg);
    }
    RETURN(TRUE);
}
    
#endif STRING_UTILS

/***===================================================================***/

#ifdef DEBUG_UTILS

static int		 u_args_knt= 0;
static u_debug_arg	*u_args_listed[10];

/***===================================================================***/

static
_u_AddArg(args,name)
register1 u_debug_arg args[];
register3 char *name;
{
register2 int knt;

    D_ENTRY2(u_debug,"_u_AddArg(0x%x,%s)\n",args,name);
    if (u_args_knt>=10) {
	warning("more than debugging variables listed in single arg\n");
	action1("ignoring %s\n",name);
	RETURN(FALSE);
    }
    knt=0;
    while (args[knt].u_name) {
	if (StrMatch(args[knt].u_name,name)) {
	    u_args_listed[u_args_knt++]= &args[knt];
	    RETURN(TRUE);
	}
	knt++;
    }
    RETURN(FALSE);
}

/***===================================================================***/

static
_u_IncrArgs()
{
register1 int knt;

    D_ENTRY(u_debug,"u_IncrArgs()\n");
    for (knt=0;knt<u_args_knt;knt++) {
	(*(u_args_listed[knt]->u_arg))+= 1;
    }
    u_args_knt= 0;
    RETURN(TRUE);
}

/***===================================================================***/

static
_u_SetArgs(lvl)
register2 int lvl;
{
register1 int knt;

    D_ENTRY1(u_debug,"u_SetArgs(%d)\n",lvl);
    for (knt=0;knt<u_args_knt;knt++) {
	(*(u_args_listed[knt]->u_arg))= lvl;
    }
    u_args_knt= 0;
    RETURN(TRUE);
}

/***===================================================================***/

u_SetDebug(argstr,numargs,d_args1,d_args2,d_args3)
register1 char		*argstr;
register6 int		 numargs;
register3 u_debug_arg	*d_args1;
register4 u_debug_arg	*d_args2;
register5 u_debug_arg	*d_args3;
{
register2 int knt;
int lvl;
char argname[11];

    D_ENTRY5(u_debug,"u_SetDebug(%s,%d,0x%x,0x%x,0x%x)\n",argstr,numargs,
						d_args1,d_args2,d_args3);
    DEBUG_ON();
    u_args_knt= 0;
    while (argstr[0]) {
	knt=0;
	while ((argstr[0])&&(argstr[0]!=',')&&(argstr[0]!='=')) {
	    if (knt<10)
	       argname[knt++]= argstr[0];
	    argstr++;
	}
	argname[knt++]= '\0';
	if (!_u_AddArg(d_args1,argname)) {
	    if ((numargs>1)&&(!_u_AddArg(d_args2,argname))) {
		if ((numargs>2)&&(!_u_AddArg(d_args3,argname))) {
		    warning1("unknown debugging variable %s specified\n",
								argname);
		    action("ignored.\n");
		}
	    }
	}
	if (argstr[0]=='\0') {
	    _u_IncrArgs();
	    break;
	}
	else if (argstr[0]=='=') {
	    if (sscanf(argstr,"=%d",&lvl)) {
		_u_SetArgs(lvl);
	    }
	    else {
		warning1("debugging variables set to %s\n",&argstr[1]);
		action("should be integer. ignored\n");
	    }
	    argstr++;
	    while (isdigit(argstr[0]))
	       argstr++;
	    if ((argstr[0]!=',')&&(argstr[0]!='\0')) {
	       warning1("debug arg syntax error (found '%c', expected ',')\n",
								argstr[0]);
	       action("ignoring rest of argument\n");
	       RETURN(TRUE);
	    }
	    if (argstr[0]=='\0')
	      break;
	}
	argstr++;
    }
    RETURN(TRUE);
}

int _DEBUG= FALSE;
FILE *u_debug_fil= stderr;

/*VARARGS*/
_DEBUG_MSG(fmt,a1,a2,a3,a4,a5)
register1 char  *fmt;
register2 int    a1,a2,a3,a4,a5;
{
    if (_DEBUG&&(u_debug_fil)) {
	fprintf(u_debug_fil,fmt,a1,a2,a3,a4,a5);
	fflush(u_debug_fil);
    }
}


#endif /* DEBUG_UTILS */

/***===================================================================***/

#ifdef ERROR_UTILS

FILE *u_error_fil= stderr;
int (*u_exitfunc)()= NULL;
int   u_error_level= U_INFO|U_WARNING|U_ERROR|U_FATAL|U_WSGO;

/*VARARGS*/
_errmsg(level,msg,arg1,arg2,arg3)
register2 int    level; 
register3 char  *msg;
register4 char  *arg1,*arg2,*arg3;
{
register1 int	 format;
static int last_level;

   if (!u_error_fil) u_error_fil= stderr;
   format= level;
   if (level==U_ACTION) {
       level= last_level;
   }
   else last_level= level;
   if ((!(level&U_FATAL))&&(!(level&U_WSGO))&&(!(level&u_error_level))) {
       RETURN(FALSE);
   }
       
   if 	   (format==U_INFO)	/* do nothing */;
   else if (format==U_ACTION)	fprintf(u_error_fil,"            ");
   else if (format==U_WARNING)	fprintf(u_error_fil,"Warning!    ");
   else if (format==U_ERROR)	fprintf(u_error_fil,"Error!      ");
   else if (format==U_FATAL)	fprintf(u_error_fil,"Fatal!      ");
   else if (format==U_WSGO)	fprintf(u_error_fil,"WSGO!       ");
   else				fprintf(u_error_fil,"Meta-error! ");
   fprintf(u_error_fil,msg,arg1,arg2,arg3);
   fflush(u_error_fil);
   if (level&U_FATAL) {
       fprintf(u_error_fil,"            Exiting.\n");
       fflush(u_error_fil);
       if (u_exitfunc)
          (*u_exitfunc)();
       abort();
   }
   return(TRUE);
}
#endif /* ERROR_UTILS */

/***===================================================================***/

#ifdef FILE_UTILS

int u_fdebug= FALSE;

static int uf_oknt=0;

FILE *
_u_fopen(file,mode,where)
register1 char *file;
register2 char *mode;
register4 char *where;
{
register3 FILE *fil;

    D_ENTRY3(u_fdebug,"u_fopen(%s,%s,%s)\n",file,mode,where);
    fil= fopen(file,mode);
    if (fil) uf_oknt++;
    DEBUG5(u_fdebug,3,"%s: u_fopen(%s,%s) #%d==> 0x%x\n",where,file,mode,
							    uf_oknt,fil);
    RETURN(fil);
}

/***===================================================================***/

FILE *
_u_freopen(file,mode,stream,where)
register1 char *file;
register2 char *mode;
register3 FILE *stream;
register5 char *where;
{
register4 FILE *fil;

    D_ENTRY4(u_fdebug,"u_freopen(%s,%s,%s,%s)\n",file,mode,stream,where);
    fil= freopen(file,mode,stream);
    DEBUG5(u_fdebug,3,"%s: u_freopen(%s,%s,0x%x)==> 0x%x\n",where,file,mode,
								stream,fil);
    RETURN(fil);
}

/***===================================================================***/

FILE *
_u_fdopen(des,mode,where)
register1 int   des;
register2 char *mode;
register4 char *where;
{
register3 FILE *fil;

    D_ENTRY3(u_fdebug,"u_fdopen(%d,%s,%s)\n",des,mode,where);
    fil= fdopen(des,mode);
    DEBUG4(u_fdebug,3,"%s: u_fdopen(%d,%s) ==> 0x%x\n",where,des,mode,fil);
    RETURN(fil);
}

/***===================================================================***/

FILE *
_u_popen(cmd,mode,where)
register1 char *cmd;
register2 char *mode;
register4 char *where;
{
register3 FILE *fil;

    D_ENTRY3(u_fdebug,"u_popen(%s,%s,%s)\n",cmd,mode,where);
    fil= popen(cmd,mode);
    DEBUG4(u_fdebug,3,"%s: u_popen(%s,%s) ==> 0x%x\n",where,cmd,mode,fil);
    RETURN(fil);
}

/***===================================================================***/

int
_u_fclose(fil,where)
register1 FILE *fil;
register3 char *where;
{
register2 int rtrn;

    D_ENTRY2(u_fdebug,"u_fclose(0x%x,%s)\n",fil,where);
    rtrn= fclose(fil);
    if (rtrn!=EOF)
       uf_oknt--;
    RETURN(rtrn);
}

#endif /* FILE_UTILS */

/***===================================================================***/

#ifdef ALLOC_UTILS

int	(*u_alloc_fix)()= NULL;
FILE	 *u_alloc_fil=    NULL;

char *
_u_malloc(size,where)
register2 unsigned  size;
register3 char     *where;
{
register1 char  *tmp= NULL;

   while (!tmp) {
      tmp= (char *)malloc(size);
      if (u_alloc_fil) {
         fprintf(u_alloc_fil,"%s: 0x%x  (%d)\n",where,tmp,size);
         fflush(u_alloc_fil);
      }
      if (!tmp) {
	  if ((u_alloc_fix)&&(!(*u_alloc_fix)())) {
	      error1("out of space in %s\n",where);
	      return(NULL);
	  }
      }
   }
   return(tmp);
}

/***===================================================================***/

char *
_u_calloc(num,size,where)
register2 unsigned   num,size;
register4 char *where;
{
register1 char  *tmp= NULL;

   while (!tmp) {
      tmp= (char *)calloc(num,size);
      if (u_alloc_fil) {
	  fprintf(u_alloc_fil,"%s: 0x%x  (%d x %d)\n",where,tmp,num,size);
          fflush(u_alloc_fil);
      }
      if (!tmp) {
	  if ((u_alloc_fix)&&(!(*u_alloc_fix)())) {
	      error1("out of space in %s\n",where);
	      return(NULL);
	  }
      }
   }
   return(tmp);
}

/***===================================================================***/

char *
_u_realloc(previous,size,where)
register2 char *previous;
register3 unsigned   size;
register4 char *where;
{
register1 char  *tmp= NULL;

   while (!tmp) {
      tmp= (char *)realloc(previous,size);
      if (u_alloc_fil) {
	  fprintf(u_alloc_fil,"%s: 0x%x  (0x%x:%d)\n",where,tmp,previous,size);
          fflush(u_alloc_fil);
      }
      if (!tmp) {
	  if ((u_alloc_fix)&&(!(*u_alloc_fix)())) {
	      error1("out of space in %s\n",where);
	      return(NULL);
	  }
      }
   }
   return(tmp);
}

/***===================================================================***/

_u_free(what,where)
register1 char *what;
register2 char *where;
{

   if (u_alloc_fil) {
       fprintf(u_alloc_fil,"%s: free 0x%x\n",where,what);
       fflush(u_alloc_fil);
      if (!what)
         fprintf(u_alloc_fil,"%s: not freed\n");
   }
   if (what)
      free(what);
   return(NULL);
}
#endif /* ifdef ALLOC_UTILS */

/***===================================================================***/

char *
u_Date()
{
struct timeval tp;
struct timezone tzp;
long   seconds;
register1 char *date,*tmp;

    D_ENTRY(u_debug,"u_Date()\n");
    gettimeofday(&tp,&tzp);
    seconds= tp.tv_sec;
    date= ctime(&seconds);
    tmp= index(date,'\n');
    if (tmp)
       *tmp='\0';
    RETURN(date);
}

/***============================================================***/
    
    /*\
    |*	NOTE:	this is implemented *only* for 4.2 -- I'm not sure
    |*		what this should look like for sys V or DOS or anything.
    |*		Should this ever be implemented for another system,
    |*		please use appropriate ifdef's
    \*/

#ifdef BSD42

char	*
u_get_hostname()
{
static	int	been_here;
static	char	name[255];
extern	char	*sys_errlist[];
extern	int	sys_nerr;
extern	int	errno;

    D_ENTRY(u_debug, "u_get_hostname()\n");
    if (!been_here) {
	if (gethostname(name, 255)) {
	    error1("gethostname failed: %s\n", sys_errlist[errno]);
	    action("returning \"unknown\"\n");
	    sprintf(name, "<unknown>");
	}
	been_here=  TRUE;
    }
    RETURN(name);
}

#endif /* BSD42 */

/***============================================================***/

u_isprefix(prefix,string)
register1 char *prefix;
register2 char *string;
{
    D_ENTRY2(u_debug,"u_isprefix(%s,%s)\n",string,prefix);
    while ((*prefix==*string)&&(*prefix)) {
	prefix++;
	string++;
    }
    RETURN(*prefix=='\0');
}

/***============================================================***/

int
u_SelectStr(strings,str,result)
register1 char	**strings;
register2 char	*str;
register3 char	**result;
{
register4 int	  found= FALSE;

    D_ENTRY3(u_debug,"u_SelectStr(0x%x,%s,0x%x)\n",strings,str,result);
    while (*strings) {
	if (u_isprefix(str,*strings)) {
	    if (!found) {
		*result= *strings;
		found= TRUE;
	    }
	    else found= -1;
	}
	strings++;
    }
    RETURN(found);
}

/***===================================================================***/

#ifdef OPT_UTILS
#ifdef BSD42

int   optional= '\0';
char *optarg= NULL;
int   optind= 0;
int   optany= FALSE;

/***=================================================================***/

static int
getarg(argc,argv)
register2 int    argc;
register1 char **argv;
{
    D_ENTRY2(u_debug,"getarg(%d,0x%x)\n",argc,argv);
    if (argv[optind][2]) optarg= &(argv[optind][2]);
    else {
	optind++;
	if (optind>argc) {
	    optarg=NULL;
	    return(FALSE);
	}
	optarg= argv[optind];
    }
    RETURN(TRUE);
}

/***=================================================================***/

int
getopt(argc,argv,optstring)
register7 int    argc;
register6 char **argv;
register4 char  *optstring;
{
register1 char   ch,optch,*opt;
register5 int    knt=0;

  D_ENTRY3(u_debug,"getopt(%d,0x%x,%s)\n",argc,argv,optstring);
  if (optind==0)    optind=1;
  if (optind>=argc) RETURN(EOF);
  opt= argv[optind];
  if (opt[0]!='-')  RETURN(EOF);
  optch= opt[1];
  while ((ch=optstring[knt])) {
       if (optch=='-') {
	   optind++;
	   RETURN(EOF);
       }
       if (ch==optch) {
	   if (optstring[knt+1]==':')
	       getarg(argc,argv);
	   else if (optional&&optstring[knt+1]==optional) {
	       if (opt[2]) getarg(argc,argv);
	       else        optarg= NULL;
	   }
	   else optarg= NULL;
	   optind++;
	   RETURN(ch);
       }
       else {
	   knt++;
           if      (optstring[knt]==':')
	      knt++;
	   else if (optional&&(optstring[knt]==optional))
	      knt++;
       }
  }
  if (optany)
     RETURN(ch);
  if (ch!='?')
     fprintf(stderr,"%s: unknown option '%c'\n",argv[0],opt[1]);
  RETURN('?');
}



#endif /* BSD42 */

/***===================================================================***/

#ifdef LATTICE

   /*\
   |* NOTE:  These functions are provided for DOS compilation.  They
   |*        may not function identically to their UNIX counterparts in
   |*        every case.
   |* realloc under DOS will function reliably ONLY for strings or NULL
   |*       terminated structures.
   \*/

char *
realloc(oldstr,newsize)
register5 char  *oldstr;
register6 int    newsize;
{
register1 int   knt,oldsize= strlen(oldstr),len;
register4 char  *newstr= (char *)u_calloc(newsize,1);

   if (oldsize>newsize) len= newsize;
   else                  len= oldsize;
   for (knt=0;knt<len;knt++) newstr[knt]= oldstr[knt];
   for (knt=len;knt<newsize;knt++) newstr[knt]= NULL;
   u_free(oldstr);
   return(newstr);
}

#endif /* BSD42 */
#endif /* OPT_UTILS */
