/*
 *
 * Copyright 1998-1999, University of Notre Dame.
 * Authors: Jeffrey M. Squyres, Kinis L. Meyer with M. D. McNally 
 *          and Andrew Lumsdaine
 *
 * This file is part of the Notre Dame LAM implementation of MPI.
 *
 * You should have received a copy of the License Agreement for the
 * Notre Dame LAM implementation of MPI along with the software; see
 * the file LICENSE.  If not, contact Office of Research, University
 * of Notre Dame, Notre Dame, IN 46556.
 *
 * Permission to modify the code and to distribute modified code is
 * granted, provided the text of this NOTICE is retained, a notice that
 * the code was modified is included with the above COPYRIGHT NOTICE and
 * with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
 * file is distributed with the modified code.
 *
 * LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
 * By way of example, but not limitation, Licensor MAKES NO
 * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
 * PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
 * OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
 * OR OTHER RIGHTS.  
 *
 * Additional copyrights may follow.
 *
 * 
 * $Id: snprintf.c,v 6.13 1999/10/03 23:18:32 jsquyres Exp $ 
 *
 * This file is for systems that do not provide snprintf().  #@%$@#%$#@!!!
 * It was originally copied from:
 *
 *   http://www.cu-online.com/~jwthomp/downloads/jeffos/lib/snprintf.c
 *
 * Minor modifications made for portability reasons.
 * Original copyright and license below.
 */

/* Copyright 1997, Brian J. Swetland <swetland@neog.com>                 
** Free for non-commercial use.  Share and enjoy                         
**
** Minimal snprintf() function.
** %s - string     %d - signed int    %x - 32bit hex number (0 padded)
** %c - character  %u - unsigned int  %X -  8bit hex number (0 padded) 
*/

#include <lam_config.h>

#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif

static char hexmap[] = {
    '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 
};

int 
#if LAM_WANT_PROTOS
/* This used to be va_snprintf, but it didn't seem to want to work
   with the snprintf() wrapper on some arches (e.g., Solaris 2.5.1).
   Since we don't use va_snprintf(), the solution was simple
   enough...*/
lam_snprintf(char *b, int l, char *fmt, ...)
#else
lam_snprintf(b, l, fmt, va_alist)

char *b;
int l;
char *fmt;
va_dcl
#endif

{
  int n,i;
  int total = l;
  unsigned u;    
  char *t,d[10];    
  va_list pvar;
  
#if __STDC__
  va_start(pvar, fmt);
#else
  va_start(pvar);
#endif
  
  if(!fmt || !b || (l < 1)) return -1; 
  
  while(l && *fmt) {
    if(*fmt == '%'){
      fmt++;
      if(!(--l)) break;
      
      switch(*fmt){
      case 's': /* string */
	t = va_arg(pvar,char *);
	while(l && *t){
	  *b++ = *t++;
	  l--;
	}
	break;
	
      case 'c': /* single character */
	fmt++;                
	*b++ = va_arg(pvar,char);
	l--;                
	break;
	
      case 'x': /* 8 digit, unsigned 32bit hex integer */
	if(l < 8) { l = 0; break; }
	u = va_arg(pvar,unsigned int);
	for(i=7;i>=0;i--){
	  b[i] = hexmap[u & 0x0F];
	  u >>= 4;
	}
	b+=8;
	l-=8;                
	break;
	
      case 'd': /* signed integer */
	n = va_arg(pvar,int);
	if(n < 0) {
	  u = -n;
	  *b++ = '-';
	  if(!(--l)) break;                    
	} else {
	  u = n;
	}
	goto u2;                
	
      case 'u': /* unsigned integer */
	u = va_arg(pvar,unsigned int);                
      u2:
	i = 9;
	do {
	  d[i] = (u % 10) + '0';
	  u /= 10;
	  i--;
	} while(u && i >= 0);
	while(++i < 10){
	  *b++ = d[i];
	  if(!(--l)) break;                    
	}
	break;
	
      case 'U':
	u = va_arg(pvar,unsigned int);
	i = 9;
	d[8] = d[7] = d[6] = ' ';
	do {
	  d[i] = (u % 10) + '0';
	  u /= 10;
	  i--;
	} while(u && i >= 0);
	i = 5;
	while(++i < 10){
	  *b++ = d[i];
	  if(!(--l)) break;
	}
	break;
	
      case 'X': /* 2 digit, unsigned 8bit hex int */
	if(l < 2) { l = 0; break; }
	n = va_arg(pvar,int);
	*b++ = hexmap[(n & 0xF0) >> 4];
	*b++ = hexmap[n & 0x0F];
	l-=2;                
	break;
      default:
	*b++ = *fmt;                
      }
    } else {
      *b++ = *fmt;
      l--;            
    }
    fmt++;            
  }
  *b = 0;
  
  va_end(pvar);
  
  if (l <= 0)
    return -1;
  else
    return (total - l);
}

