static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/util.c,v 1.7 90/10/16 07:56:29 jjc Exp $";

#include "util.h"

enum message_type history = INFORMATION;

#ifdef STDARG
void message(enum message_type type, char *format,...)
#else
void message(va_alist)
va_dcl
#endif
{
	int c, n;
	char *s;
#ifndef STDARG
	enum message_type type;
	char *format;
#endif
	va_list ap;
#ifdef STDARG
	va_start(ap, format);
#else
	va_start(ap);
	type = va_arg(ap, enum message_type);
	format = va_arg(ap, char *);
#endif
	if (program_name != NULL) {
		fputs(program_name, stderr);
		fputs(": ", stderr);
	}
	switch (type) {
	case FATAL_ERROR:
		fputs("fatal error: ", stderr);
		break;
	case ERROR:
		fputs("error: ", stderr);
		break;
	case WARNING:
		fputs("warning: ", stderr);
		break;
	}
	while ((c = *format++) != '\0')
		if (c == '%') {
			c = *format++;
			switch(c) {
			case '%':
				putc('%', stderr);
				break;
			case 'd':
				n = va_arg(ap, int);
				fprintf(stderr, "%d", n);
				break;
			case 's':
				s = va_arg(ap, char *);
				fputs(s, stderr);
				break;
			default:
				fprintf(stderr, "...whoops! error while handling error\n");
				exit(FATAL_ERROR);
			}
		}
		else
			putc(c, stderr);
	fputc('\n', stderr);
	va_end(ap);
	if (type == FATAL_ERROR)
		exit(FATAL_ERROR);
	if ((int)type > (int)history)
		history = type;
}

static int safecat(s1, s2, n)
char *s1, *s2;
int n;
{
	if (strlen(s1) + strlen(s2) + 1 > n)
		return FALSE;
	strcat(s1, s2);
	return TRUE;
}

/* does s1 end with s2 ? */
static int strends(s1, s2)
char *s1, *s2;
{
	int n2 = strlen(s2);
	int n1 = strlen(s1);
	if (n1 < n2)
		return FALSE;
#ifdef CASE_INSENSITIVE_FILENAMES
	return stricmp(s1 + n1 - n2, s2) == 0;
#else
	return strcmp(s1 + n1 - n2, s2) == 0;
#endif
}

/* if ext is not NULL and filename does not end with ext,
   ext will be appended to filename */

FILE *xfopen(filename, is_binary, al, ext)
char *filename, *al, *ext;
int is_binary;
{
	char path[FILENAME_MAX+1];
	static char list_sep[2] = {AREA_LIST_SEP, '\0'};
#ifdef AREA_SEP
	static char sep[2] = {AREA_SEP , '\0'};
#endif /* AREA_SEP */
	char *area;
	char area_list[FILENAME_MAX*4];
	if (al == NULL || FILENAME_HAS_AREA(filename)) {
		if (ext != NULL && !strends(filename, ext)) {
			path[0] = '\0';
			safecat(path, filename, sizeof(path));
			safecat(path, ext, sizeof(path));
			if (is_binary)
				return FOPEN_RB(path);
			else
				return fopen(path, "r");
		}
		else {
			if (is_binary)
				return FOPEN_RB(filename);
			else
				return fopen(filename, "r");
		}
	}
	if (strlen(al)+1 > sizeof(area_list))
		message(FATAL_ERROR, "directory list too long: %s", al);
	strcpy(area_list, al);
	for (area = strtok(area_list, list_sep);
		 area != NULL; 
		 area = strtok(NULL, list_sep)) {
#ifdef AREA_SEP
		char *p;
#endif /* AREA_SEP */
		FILE *fp;
		path[0] = '\0';
#ifndef POSTFIX_AREA
		if (!safecat(path, area, sizeof(path)))
			continue;
#ifdef AREA_SEP
		p = path + strlen(path);
		if (p > path && p[-1] != AREA_SEP
#ifdef AREA_SEP2
			&& p[-1] != AREA_SEP2
#endif /* AREA_SEP2 */
			) {
			if (!safecat(path, sep, sizeof(path)))
				continue;
		}
#endif /* AREA_SEP */
#endif /* not POSTFIX_AREA */
		if (!safecat(path, filename, sizeof(path)))
			continue;
		if (ext != NULL && !strends(filename, ext))
			safecat(path, ext, sizeof(path));
#ifdef POSTFIX_AREA
#ifdef AREA_SEP
		if (area[0] != AREA_SEP
#ifdef AREA_SEP2
			&& area[0] != AREA_SEP2
#endif /* AREA_SEP2 */
			) {
			if (!safecat(path, sep, sizeof(path)))
				continue;
		}
#endif /* AREA_SEP */
		if (!safecat(path, area, sizeof(path)))
			continue;
#endif /* POSTFIX_AREA */
		if (is_binary) {
			if ((fp = FOPEN_RB(path)) != NULL)
				return fp;
		}
		else {
			if ((fp = fopen(path, "r")) != NULL)
				return fp;
		}
	}
	return NULL;
}

#ifdef CASE_INSENSITIVE_FILENAMES

int stricmp(s1, s2)
char *s1, *s2;
{
	for (;;) {
		char c1 = *s1, c2 = *s2;
		if (c1 == '\0') {
			if (c2 == '\0')
				return 0;
			else
				return -1;
		}
		else if (c2 == '\0')
			return 1;
		if (isascii(c1) && isupper(c1))
			c1 = tolower(c1);
		if (isascii(c2) && isupper(c2))
			c2 = tolower(c2);
		if (c1 != c2)
			return c1 - c2;
		s1++;
		s2++;
	}
}

#endif /* CASE_INSENSITIVE_FILENAMES */

#ifdef NEED_MEM_FUNCTIONS

int memcmp(s1, s2, n)
char *s1, *s2;
int n;
{
  for (; --n >= 0; s1++, s2++)
    if (*s1 != *s2)
      return *s1 - *s2;
  return 0;
}

char *memcpy(s1, s2, n)
char *s1, *s2;
int n;
{
	char *p = s1;
	while (--n >= 0)
		*p++ = *s2++;
	return s1;
}

char *memset(s, c, n)
char *s;
int c, n;
{
	char *p = s;
	while (--n >= 0)
		*p++ = c;
	return s;
}

#endif /* NEED_MEM_FUNCTIONS */

#ifdef NEED_QSORT

/* This is a heap sort. */

void qsort(v, n, width, compar)
char *v;
int n, width;
int (*compar)();
{
	char *ip;
	char *buf;
	char *last = v + (n - 1)*width;
	if ((buf = malloc(width)) == 0)
		out_of_memory();
	for (ip = v + (n/2)*width; ip >= v; ip -= width) {
		char *jp = ip;
		memcpy(buf, ip, width);
		for (;;) {
			char *cp = jp + (jp - v) + width;
			if (cp < last) {
				char *ocp = cp + width;
				if ((*compar)(ocp, cp) > 0)
					cp = ocp;
			}
			else if (cp != last)
				break;
			if ((*compar)(buf, cp) >= 0)
				break;
			memcpy(jp, cp, width);
			jp = cp;
		}
		memcpy(jp, buf, width);
	}
	ip = last;
	while (ip > v) {
		char *jp = v;
		int j;
		memcpy(buf, ip, width);
		memcpy(ip, v, width);
		ip -= width;
		for (;;) {
			char *cp = jp + (jp - v) + width;
			if (cp < ip) {
				char *ocp = cp + width;
				if ((*compar)(ocp, cp) > 0)
					cp = ocp;
			}
			else if (cp != ip)
				break;
			memcpy(jp, cp, width);
			jp = cp;
		}
		j = (jp - v)/width;
		while (j != 0) {
			char *kp;
			j = (j - 1)/2;
			kp = v + j*width;
			if ((*compar)(kp, buf) >= 0)
				break;
			memcpy(jp, kp, width);
			jp = kp;
		}
		memcpy(jp, buf, width);
	}
	free(buf);
}

#endif /* NEED_QSORT */

#ifdef NEED_STRTOK

char *strtok(s1, s2)
char *s1, *s2;
{
	static char *next;
	register char *s = s1 != NULL ? s1 : next;
	char *start;
	for (;;) {
		register char *p;
		register char c = *s;
		if (c == '\0') {
			next = s;
			return NULL;
		}
		for (p = s2; *p != '\0' && *p != c; p++)
			;
		if (*p == '\0')
			break;
		s++;
	}
	start = s;
	for (;;) {
		register char *p;
		register char c = *++s;
		if (c == '\0') {
			next = s;
			return start;
		}
		for (p = s2; *p != '\0'; p++)
			if (*p == c) {
				*s = '\0';
				next = s + 1;
				return start;
			}
	}
}

#endif /* NEED_STRTOK */

#ifdef PRIMOS_GETENV

/* Prime C doesn't provide a getenv function, but there are 'global
variables' that are like enviroment variables. The routine gvget will
retrieve the value of one of these, so we can write a getenv using it.
*/


char *getenv(name)
char *name;
{
	char temp[32];
	extern char *strncat(), *gvget();
	
	strcpy(temp,".");
	return(gvget(strncat(temp,name,32)));
}

#endif /* PRIMOS_GETENV */

#ifdef EBCDIC
static int cnva[]={
  0,  1,  2,  3, 55, 45, 46, 47, 22,  5, 37, 11, 12, 13, 14, 15,
 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31,
 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97,
240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111,
124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214,
215,216,217,226,227,228,229,230,231,232,233,173,224,189,113,109,
121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150,
151,152,153,162,163,164,165,166,167,168,169,192, 79,208, 95,  7,
 32, 33, 34, 35, 36, 21,  6, 23, 40, 41, 42, 43, 44,  9, 10, 27,
 48, 49, 26, 51, 52, 53, 54,  8, 56, 57, 58, 59,  4, 20, 62,225,
 65, 66, 74,114, 69, 70, 71, 72, 73, 81, 82, 83, 84, 85, 86, 87,
 88, 89, 98, 99,100,101,102,103,104,105,112, 67, 68,115,116,117,
118,119,120,128,138,139,140,141,142,143,144,154,155,156,157,158,
159,160,170,171,172,161,174,175,176,177,178,179,180,181,182,183,
184,185,186,187,188,106,190,191,202,203,204,205,206,207,218,219,
220,221,222,223,234,235,236,237,238,239,250,251,252,253,254,255
  };

char atoe(char c)         /* convert the c from ascii to ebcdic */
{
 return(cnva[c]);
}
#endif /* EBCDIC */

/*
Local Variables:
c-indent-level: 4
c-continued-statement-offset: 4
c-brace-offset: -4
c-argdecl-indent: 0
c-label-offset: -4
tab-width: 4
End:
*/