/************************************************************************\ * * CLIB.C * * This file defines some ANSI C and SYSTEM V compatible library * routines for BSD UNIX, input buffer allocating and some system * dependant routines. \************************************************************************/ #include "system.h" unsigned maxbuf; uchar* buffer; /********************************************************************** * * d_free */ void d_free(void* ptr) { REG1 void** p = (void**)ptr; if (*p != NULL) { free(*p); *p = NULL; } } /********************************************************************** * * alloc_buffer * * Allocate I/O-buffer. */ void alloc_buffer(void) #if defined(__TURBOC__) || defined(M_I86) { buffer = sbrk(0); if ((int)buffer == -1) error("Input buffer allocation failed", 3); /* Calculate largest input buffer that doesn't cause pointer wraparound in boyer-moore. */ maxbuf = ((unsigned)(-((int)buffer)) >> 1) - MAXREGMUST; /* Starting from maxbuf, try to allocate input buffer. If allocation fails, cut the buffer size to half until we reach minimum buffer size. */ while (maxbuf >= 2*MAXREGMUST) { if (buffer == sbrk(maxbuf + 1)) return; maxbuf /= 2; } error("Out of memory when allocating input buffer", 3); } #else { maxbuf = MAXBUF; buffer = malloc(MAXBUF); if (buffer == NULL) error("Out of memory when allocating input buffer", 3); } #endif /* defined(__TURBOC__) || defined(M_I86) */ #if defined(__TURBOC__) #include /* time structure for a pseudo-random number */ static struct time tc_time; /********************************************************************** * * get_sec */ unsigned get_sec(void) { gettime(&tc_time); return (unsigned)tc_time.ti_sec; } /********************************************************************** * * putch */ #define putch(c) \ { \ _DL = (c); \ _AH = 2; \ geninterrupt(0x21); \ } /* Dummy function to save little code size */ void cdecl _setenvp (void) { } #endif /* defined(__TURBOC__) */ #if defined(__TURBOC__) || (defined(M_I86) && defined(MSDOS)) /********************************************************************** * * putstr */ void putstr(REG1 uchar* str) { REG2 int c; while ((c = *str++) != '\0') { if (c == '\n') putch('\r'); putch(c); } } #endif /* defined(__TURBOC__) || (defined(M_I86) && defined(MSDOS)) */ /********************************************************************** * * error */ void error(char* errmsg, int exit_value) { fputs("Error: ", stderr); fputs(errmsg, stderr); fputs("\n", stderr); exit(exit_value); } /********************************************************************** * * assertion_failure * * Own assert exit routine because many system asserts will link * fprintf. We don't want fprintf bacause we have worked hard to keep * the program as small as possible. */ void assertion_failure(char* file, int line) { char buf[10]; fputs("Internal error: ", stderr); fputs(file, stderr); fputs(", ", stderr); fputs(ultoa((ulong)line, buf, 10), stderr); fputs("\n", stderr); exit(3); } #ifdef TOUCH /********************************************************************** * * set_file_time */ #if defined(__TURBOC__) bool set_file_time(char* fname, int h) { struct date d; static struct ftime ft; static int first_time = TRUE; if (first_time) { first_time = FALSE; getdate(&d); gettime(&tc_time); ft.ft_tsec = tc_time.ti_sec; ft.ft_min = tc_time.ti_min; ft.ft_hour = tc_time.ti_hour; ft.ft_day = d.da_day; ft.ft_month = d.da_mon; ft.ft_year = d.da_year - 1980; } return setftime(h, &ft) != -1; } #else bool set_file_time(char* fname, int h) { static int first_time = TRUE; static utime_t u; if (first_time) { first_time = FALSE; u.modtime = time(NULL); u.actime = u.modtime; } return utime(fname, &u) == 0; } #endif #endif /* TOUCH */ #ifdef BSD /* BSD UNIX lacks mem(set|chr) */ /********************************************************************** * * memset */ void* memset(void* b, REG3 char ch, REG2 unsigned n) { REG1 uchar* s = (uchar*)b; while (n--) *s++ = ch; return b; } /************************************************************************ * * memchr */ void* memchr(void* b, REG3 char ch, REG2 unsigned n) { REG1 uchar* s = (uchar*)b; while (n--) if (*s++ == ch) return s - 1; return NULL; } #endif /* BSD */ /************************************************************************ * ultoa * * Even if the ultoa() were already defined in the library, redefinition * does not matter, because this version is excatly compatible with * it and this is also well fast enough. */ char* ultoa(ulong n, char* s, int radix) { static char itoc_xlate[] = { '0','1','2','3','4','5','6','7','8','9','A','B', 'C','D','E','F','G','H','I','J','K','L','M','N', 'O','P','Q','R','S','T','U','V','W','X','Y','Z' }; register char* s1; register char* s2; s1 = s2 = s; if ((unsigned)(radix - 2) <= (unsigned)(sizeof(itoc_xlate) - 2)) do { *s1++ = itoc_xlate[n % (ulong)radix]; } while (n /= (unsigned)radix); for (*s1 = '\0'; --s1 > s2; ++s2) *s1 ^= *s2 ^= *s1 ^= *s2; /* what on earth ??? */ return (s); }