#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <support.h>
#include <netdb.h>
#include "gs_descr.h"


typedef char *charp;
typedef void *voidp;


static char *h_errno_names[] = {
  "",
  "HOST_NOT_FOUND",
  "TRY_AGAIN",
  "NO_RECOVERY",
  "NO_DATA"
};

void log_entry_fmt(char *line, const char *fmt, va_list ap)
{
  register const char *s;
  register char *t;
  char *u;
  void *v;
  long l;
  unsigned long ul;

  for (s = fmt, t = line; *s; s++) {
    if (*s != '%') {
      *t++ = *s;
      continue;
    }

    switch (*++s) {
      case '%':
	*t++ = '%';
	break;
      case 's':
	u = va_arg(ap, charp);
	if (!u)
	  strcpy(t, "<NULL>");
	else
	  strcpy(t, u);
	t += strlen(t);
	break;
      case 'S':
	l = (long)va_arg(ap, int);
	u = va_arg(ap, charp);
	if (!u) {
	  strcpy(t, "<NULL>");
	  t += strlen(t);
	} else {
	  strncpy(t, u, l);
	  t += l;
	}
	break;
      case 'i':
      case 'd':
	l = (long)va_arg(ap, int);
	_ltoa(l, t, 10);
	t += strlen(t);
	break;
      case 'x':
	*t++ = '0'; *t++ = 'x';
	l = (long)va_arg(ap, unsigned int);
	_ltoa(l, t, 16);
	t += strlen(t);
	break;
      case 'l':
	l = va_arg(ap, long);
	_ltoa(l, t, 10);
	t += strlen(t);
	break;
      case 'X':
	*t++ = '0'; *t++ = 'x';
	ul = va_arg(ap, unsigned long);
	_ultoa(ul, t, 16);
	t += strlen(t);
	break;
      case 'p':
	*t++ = '0'; *t++ = 'x';
	v = va_arg(ap, voidp);
	_ultoa((unsigned long)v, t, 16);
	t += strlen(t);
	break;
      case 'c':
	*t++ = va_arg(ap, int);
	break;
      case 'A':
	ul = va_arg(ap, unsigned long);
	_ultoa((unsigned long)(ul>>24), t, 10);
	t += strlen(t); *t++ = '.';
	_ultoa((unsigned long)((ul>>16)&0xFF), t, 10);
	t += strlen(t); *t++ = '.';
	_ultoa((unsigned long)((ul>>8)&0xFF), t, 10);
	t += strlen(t); *t++ = '.';
	_ultoa((unsigned long)(ul&0xFF), t, 10);
	t += strlen(t);
	break;
      case 'e':
	l = (long)va_arg(ap, int);
	_ltoa(l, t, 10);
	t += strlen(t);
	{
	  char *u = strerror(-l);
	  if (u) {
	    *t++ = ' ';
	    *t++ = '(';
	    strcpy(t, u);
	    t += strlen(t);
	    *t++ = ')';
	  }
	}
	break;
      case 'E':
	l = (long)va_arg(ap, int);
	_ltoa(l, t, 10);
	t += strlen(t);
	*t++ = ' ';
	*t++ = '(';
	strcpy(t, do_get_err_text(l));
	t += strlen(t);
	*t++ = ')';
	break;
      case 'H':
	l = (long)va_arg(ap, int);
	_ltoa(l, t, 10);
	t += strlen(t);
	if (l >= HOST_NOT_FOUND && l <= NO_DATA) {
	  *t++ = ' ';
	  *t++ = '(';
	  strcpy(t, h_errno_names[l]);
	  t += strlen(t);
	  *t++ = ')';
	}
	break;
      default:
	strcpy(t, "<<<");
	t[3] = *s;
	strcpy(t+4, ">>>");
	t += 7;
	break;
    }
  }
  *t++ = '\r'; *t++ = '\n'; *t = '\0';
}
