/* Copyright 1990,1991 Eric R. Smith. All rights reserved. */ /* * misc. utility routines */ #include "mint.h" /* * given an address, find the corresponding memory region in this program's * memory map */ MEMREGION * addr2mem(a) virtaddr a; { int i; for (i = 0; i < curproc->num_reg; i++) { if (a == curproc->addr[i]) return curproc->mem[i]; } return 0; } /* * given a pid, return the corresponding process */ PROC * pid2proc(pid) int pid; { PROC *p; for (p = proclist; p; p = p->gl_next) { if (p->pid == pid) return p; } return 0; } /* * return a new pid */ int newpid() { static int _maxpid = 1; int i; #ifndef NDEBUG int j = 0; #endif do { i = _maxpid++; if (_maxpid >= 1000) _maxpid = 1; assert(j++ < 1000); } while (pid2proc(i)); return i; } /* * zero out a block of memory, quickly; the block must be word-aligned, * and should be long-aligned for speed reasons */ void zero(place, size) char *place; long size; { long cruft, *lp; cruft = size % 256; /* quickzero does 256 byte blocks */ size = size / 256; while (cruft > 0) { *place++ = 0; cruft--; } lp = (long *)place; if (size > 0) { quickzero(place, size); } } #ifdef JUNK_MEM void fillwjunk(place, size) long *place; long size; { while (size > 0) { *place++ = size; size -= 4; } } #endif /* * kernel memory allocation routines */ #define KMAGIC ((MEMREGION *)0x87654321) #define KERMEM_THRESHOLD 264 void * kmalloc(size) long size; { MEMREGION *m = 0; MEMREGION **p; size += sizeof(m) + sizeof (m); /* * for small requests, we try kernel memory first, to cut down on fragmentation */ if (size <= KERMEM_THRESHOLD) m = get_region(ker, size); else m = get_region(alt, size); if (!m) m = get_region(core, size); if (!m) { if (size <= KERMEM_THRESHOLD) m = get_region(alt, size); else m = get_region(ker, size); } if (m) { p = (MEMREGION **)m->loc; *p++ = KMAGIC; *p++ = m; return (void *)p; } else { return 0; } } /* allocate from ST memory only */ void * kcore(size) long size; { MEMREGION *m = 0; MEMREGION **p; size += sizeof(m) + sizeof (m); m = get_region(core, size); if (m) { p = (MEMREGION **)m->loc; *p++ = KMAGIC; *p++ = m; return (void *)p; } else { return 0; } } void kfree(place) void *place; { MEMREGION **p; MEMREGION *m; if (!place) return; p = place; p -= 2; if (*p++ != KMAGIC) { FATAL("kfree: memory not allocated by kmalloc"); } m = *p++; if (--m->links != 0) { FATAL("kfree: block has %d links", m->links); } free_region(m); } /* * "user" memory allocation routines; the kernel can use these to * allocate/free memory that will be attached in some way to a process * (and freed automatically when the process exits) */ void * umalloc(size) long size; { return (void *)m_xalloc(size, 3); } void ufree(block) void *block; { (void)m_free((virtaddr)block); } /* * convert a time in milliseconds to a GEMDOS style date/time * timeptr[0] gets the time, timeptr[1] the date. * BUG/FEATURE: in the conversion, it is assumed that all months have * 30 days and all years have 360 days. */ void ms_time(ms, timeptr) ulong ms; short *timeptr; { ulong secs; short tsec, tmin, thour; short tday, tmonth, tyear; secs = ms / 1000; tsec = secs % 60; secs /= 60; /* secs now contains # of minutes */ tmin = secs % 60; secs /= 60; /* secs now contains # of hours */ thour = secs % 24; secs /= 24; /* secs now contains # of days */ tday = secs % 30; secs /= 30; tmonth = secs % 12; tyear = secs / 12; *timeptr++ = (thour << 11) | (tmin << 5) | (tsec >> 1); *timeptr = (tyear << 9) | ((tmonth + 1) << 5) | (tday+1); } /* * unixtim(time, date): convert a Dos style (time, date) pair into * a Unix time (seconds from midnight Jan 1., 1970) */ static int mth_start[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; long unixtim(time, date) unsigned time, date; { int sec, min, hour; int mday, mon, year; long y, s; sec = (time & 31) << 1; min = (time >> 5) & 63; hour = (time >> 11) & 31; mday = date & 31; mon = ((date >> 5) & 15) - 1; year = 80 + ((date >> 9) & 255); /* calculate tm_yday here */ y = (mday - 1) + mth_start[mon] + /* leap year correction */ ( ( (year % 4) != 0 ) ? 0 : (mon > 1) ); s = (sec) + (min * 60L) + (hour * 3600L) + (y * 86400L) + ((year - 70) * 31536000L) + ((year - 69)/4) * 86400L; return s; } /* convert a Unix time into a DOS time. The longword returned contains the time word first, then the date word. BUG: we completely ignore any time zone information. */ #define SECS_PER_MIN (60L) #define SECS_PER_HOUR (3600L) #define SECS_PER_DAY (86400L) #define SECS_PER_YEAR (31536000L) #define SECS_PER_LEAPYEAR (SECS_PER_DAY + SECS_PER_YEAR) static int days_per_mth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; long dostim(t) long t; { unsigned long time, date; int tm_hour, tm_min, tm_sec; int tm_year, tm_mon, tm_mday; int i; if (t <= 0) return 0; tm_year = 70; while (t >= SECS_PER_YEAR) { if ((tm_year & 0x3) == 0) { if (t < SECS_PER_LEAPYEAR) break; t -= SECS_PER_LEAPYEAR; } else { t -= SECS_PER_YEAR; } tm_year++; } tm_mday = t/SECS_PER_DAY; days_per_mth[1] = (tm_year & 0x3) ? 28 : 29; for (i = 0; tm_mday >= days_per_mth[i]; i++) tm_mday -= days_per_mth[i]; tm_mon = i+1; tm_mday++; t = t % SECS_PER_DAY; tm_hour = t/SECS_PER_HOUR; t = t % SECS_PER_HOUR; tm_min = t/SECS_PER_MIN; tm_sec = t % SECS_PER_MIN; if (tm_year < 80) { tm_year = 80; tm_mon = tm_mday = 1; tm_hour = tm_min = tm_sec = 0; } time = (tm_hour << 11) | (tm_min << 5) | (tm_sec >> 1); date = ((tm_year - 80) & 0x7f) << 9; date |= ((tm_mon) << 5) | (tm_mday); return (time << 16) | date; } /* * Case insensitive string comparison. note that this only returns * 0 (match) or nonzero (no match), and that the returned value * is not a reliable indicator of any "order". */ int strnicmp(str1, str2, len) register const char *str1, *str2; register int len; { register char c1, c2; do { c1 = *str1++; if (isupper(c1)) c1 = tolower(c1); c2 = *str2++; if (isupper(c2)) c2 = tolower(c2); } while (--len >= 0 && c1 && c1 == c2); if (len < 0 || c1 == c2) return 0; return c1 - c2; } int stricmp(str1, str2) const char *str1, *str2; { return strnicmp(str1, str2, 0x7fff); } /* * string utilities: strlwr() converts a string to lower case, strupr() * converts it to upper case */ char * strlwr(s) char *s; { char c; char *old = s; while ((c = *s) != 0) { if (isupper(c)) { *s = _tolower(c); } s++; } return old; } char * strupr(s) char *s; { char c; char *old = s; while ((c = *s) != 0) { if (islower(c)) { *s = _toupper(c); } s++; } return old; } #ifdef OWN_LIB /* * Case sensitive comparison functions. */ int strncmp(str1, str2, len) register const char *str1, *str2; register int len; { register char c1, c2; do { c1 = *str1++; c2 = *str2++; } while (--len >= 0 && c1 && c1 == c2); if (len < 0) return 0; return c1 - c2; } int strcmp(str1, str2) const char *str1, *str2; { register char c1, c2; do { c1 = *str1++; c2 = *str2++; } while (c1 && c1 == c2); return c1 - c2; } /* * some standard string functions */ char * strcat(dst, src) char *dst; const char *src; { register char *_dscan; for (_dscan = dst; *_dscan; _dscan++) ; while (*_dscan++ = *src++) ; return dst; } char * strcpy(dst, src) char *dst; const char *src; { register char *_dscan = dst; while (*_dscan++ = *src++) ; return dst; } char * strncpy(dst, src, len) char *dst; const char *src; int len; { register char *_dscan = dst; while (--len >= 0 && (*_dscan++ = *src++)) continue; while (--len >= 0) *_dscan++ = 0; return dst; } int strlen(scan) const char *scan; { register const char *_start = scan+1; while (*scan++) ; return (int)((long)scan - (long)_start); } /* * strrchr: find the last occurence of a character in a string */ char * strrchr(str, which) const char *str; register int which; { register unsigned char c, *s; register char *place; s = (unsigned char *)str; place = 0; do { c = *s++; if (c == which) place = (char *)s-1; } while (c); return place; } unsigned char _ctype[256] = { _CTc, _CTc, _CTc, _CTc, /* 0x00..0x03 */ _CTc, _CTc, _CTc, _CTc, /* 0x04..0x07 */ _CTc, _CTc|_CTs, _CTc|_CTs, _CTc|_CTs, /* 0x08..0x0B */ _CTc|_CTs, _CTc|_CTs, _CTc, _CTc, /* 0x0C..0x0F */ _CTc, _CTc, _CTc, _CTc, /* 0x10..0x13 */ _CTc, _CTc, _CTc, _CTc, /* 0x14..0x17 */ _CTc, _CTc, _CTc, _CTc, /* 0x18..0x1B */ _CTc, _CTc, _CTc, _CTc, /* 0x1C..0x1F */ _CTs, _CTp, _CTp, _CTp, /* 0x20..0x23 */ _CTp, _CTp, _CTp, _CTp, /* 0x24..0x27 */ _CTp, _CTp, _CTp, _CTp, /* 0x28..0x2B */ _CTp, _CTp, _CTp, _CTp, /* 0x2C..0x2F */ _CTd|_CTx, _CTd|_CTx, _CTd|_CTx, _CTd|_CTx, /* 0x30..0x33 */ _CTd|_CTx, _CTd|_CTx, _CTd|_CTx, _CTd|_CTx, /* 0x34..0x37 */ _CTd|_CTx, _CTd|_CTx, _CTp, _CTp, /* 0x38..0x3B */ _CTp, _CTp, _CTp, _CTp, /* 0x3C..0x3F */ _CTp, _CTu|_CTx, _CTu|_CTx, _CTu|_CTx, /* 0x40..0x43 */ _CTu|_CTx, _CTu|_CTx, _CTu|_CTx, _CTu, /* 0x44..0x47 */ _CTu, _CTu, _CTu, _CTu, /* 0x48..0x4B */ _CTu, _CTu, _CTu, _CTu, /* 0x4C..0x4F */ _CTu, _CTu, _CTu, _CTu, /* 0x50..0x53 */ _CTu, _CTu, _CTu, _CTu, /* 0x54..0x57 */ _CTu, _CTu, _CTu, _CTp, /* 0x58..0x5B */ _CTp, _CTp, _CTp, _CTp, /* 0x5C..0x5F */ _CTp, _CTl|_CTx, _CTl|_CTx, _CTl|_CTx, /* 0x60..0x63 */ _CTl|_CTx, _CTl|_CTx, _CTl|_CTx, _CTl, /* 0x64..0x67 */ _CTl, _CTl, _CTl, _CTl, /* 0x68..0x6B */ _CTl, _CTl, _CTl, _CTl, /* 0x6C..0x6F */ _CTl, _CTl, _CTl, _CTl, /* 0x70..0x73 */ _CTl, _CTl, _CTl, _CTl, /* 0x74..0x77 */ _CTl, _CTl, _CTl, _CTp, /* 0x78..0x7B */ _CTp, _CTp, _CTp, _CTc, /* 0x7C..0x7F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80..0x8F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90..0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0..0xAF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0..0xBF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0..0xCF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0..0xDF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0..0xEF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0..0xFF */ }; int toupper(c) int c; { return(islower(c) ? (c ^ 0x20) : (c)); } int tolower(c) int c; { return(isupper(c) ? (c ^ 0x20) : (c)); } /* * converts a decimal string to an integer */ int atoi(s) const char *s; { int d = 0; int negflag = 0; int c; while (*s && isspace(*s)) s++; while (*s == '-' || *s == '+') { if (*s == '-') negflag ^= 1; s++; } while ((c = *s++) && isdigit(c)) { d = 10 * d + (c - '0'); } if (negflag) d = -d; return d; } #endif /* OWN_LIB */