This is misc.c in view mode; [Download] [Up]
/* * Copyright (C) 1985-1992 New York University * * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for * warranty (none) and distribution info and also the GNU General Public * License for more details. */ /* misc.c - miscellaneous programs */ #ifdef PALLOC #define calloc pcalloc #define free pfree #define cfree pcfree #define malloc pmalloc #define realloc prealloc #endif #include "config.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include "time.h" #include "ifile.h" #include "miscprots.h" #ifndef LIBDIR #define LIBDIR "/usr/local/lib" #endif #ifdef vms #include <file.h> #include descrip #endif #ifdef ADALIB #ifdef vms /* #include "adalib.h" */ #endif #define EXIT_INTERNAL_ERROR #endif #ifdef BINDER #ifdef vms /* #include "adabind.h" */ #endif #define EXIT_INTERNAL_ERROR extern int adacomp_option; #endif #ifdef INT #ifdef vms /* #include "adaexec.h" */ #endif #define EXIT_INTERNAL_ERROR #endif #ifndef EXPORT #undef EXIT_INTERNAL_ERROR #endif #ifdef BSD #include <sys/file.h> #endif #ifdef vms char *DIRECTORY_START = "[."; /* used as the beginning of a VMS dir spec. */ #endif char *LIBRARY_PREFIX= ""; /* PREDEFNAME gives directory path to predef files. * libset() is used to toggle between libraries (the users and predef). * tname = libset(lname) sets library prefix for ifopen, etc. to lname * and returns prior setting in tname. */ static void openerr(char *filename, char *mode); static void fhlist(IFILE *, char *); #ifdef DEBUG #define IOT int malloctrace = 0; void trace_malloc() /*;trace_malloc*/ { malloctrace = 1; } #endif static int ifiles = 0; #ifdef SMALLOC unsigned int smalloc_free = 0; char *smalloc_ptr; #define SMALLOC_BLOCK 2000 char **smalloc_table = (char **)0; unsigned smalloc_blocks = 0; #endif char *smalloc(unsigned n) /*;smalloc*/ { /* variant of malloc for use for blocks that will never be freed, * primarily blocks used for small strings. This permits allocation * in larger blocks avoiding the malloc overhead required for each block. */ #ifndef SMALLOC return emalloct(n, "smalloc"); #else char *p; if (n & 1) n+= 1; #ifdef ALIGN4 if (n & 2) n+= 2; #endif if (n > SMALLOC_BLOCK) { /* large block allocated separately */ #ifdef DEBUG printf("smalloc: warning block %u exceeds %d SMALLOC_BLOCK\n", n, SMALLOC_BLOCK); #endif p = emalloct(n, "smalloc"); return p; } if (n > smalloc_free) { smalloc_ptr = emalloct(SMALLOC_BLOCK, "smalloc-block"); smalloc_free = SMALLOC_BLOCK; smalloc_blocks++; if (smalloc_blocks == 1) { smalloc_table = (char **) emalloct(sizeof (char **), "smalloc-table"); } else { /* reallocate blocks */ smalloc_table = (char **) erealloct((char *)smalloc_table, sizeof(char **) * (smalloc_blocks), "smalloc-table-realloc"); } smalloc_table[smalloc_blocks-1] = smalloc_ptr; } p = smalloc_ptr; smalloc_ptr += n; smalloc_free -= n; return p; #endif } #ifdef DEBUG void smalloc_list() { int i; char **st; st = smalloc_table; for (i = 0; i < smalloc_blocks; i++) { printf("%d %ld %x\n", i, *st, *st); st++; } } #endif int is_smalloc_block(char *p) /*;is_smalloc_block*/ { /* returns TRUE is p points within block allocated by smalloc */ #ifdef SMALLOC #ifdef IBM_PC /* for PC need to do 32 bit pointer comparisons */ /* pragma off(segmented_pointer_operations); */ #endif int i; char **st; st = smalloc_table; if (smalloc_blocks == 0) chaos("is_malloc_block - no blocks"); for (i = 0; i < smalloc_blocks; i++) { if (*st <= p && p < (*st+(SMALLOC_BLOCK-1))) return TRUE; st++; } return FALSE; #ifdef IBM_PC /* pragma on(segmented_pointer_operations); */ #endif #else return FALSE; #endif } void capacity(char *s) /*;capacity*/ { /* called when compiler capacity limit exceeded. * EXIT_INTERNAL_ERROR is defined when the module is run by itself * (not spawned from adacomp) and DEBUG is not defined. */ #ifdef EXIT_INTERNAL_ERROR #ifdef vms LIB$STOP(MSG_CAPACITY); #else fprintf(stderr, "capacity limit exceeded: %s\n", s); exitp(RC_INTERNAL_ERROR); #endif #else #ifdef DEBUG printf("capacity limit exceeded: %s\nexecution abandoned \n", s); #endif fprintf(stderr, "capacity limit exceeded: %s\n", s); exitp(RC_INTERNAL_ERROR); #endif } #ifdef CHAOS void chaos(char *s) /*;chaos*/ { /* called when internal logic error detected and it is not meaningful * to continue execution. This is never defined for the export version. */ fprintf(stderr, "chaos: %s\nexecution abandoned \n", s); printf("chaos: %s\nexecution abandoned \n", s); exitp(RC_INTERNAL_ERROR); } #else void exit_internal_error() /*;exit_internal_error*/ { /* called when internal logic error detected and it is not meaningful * to continue execution. This procedure is called by the export version. * EXIT_INTERNAL_ERROR is defined when the module is run by itself * (not spawned from adacomp) and EXPORT is defined. * Now that adabind is a separate module which can be called by itself * or spawned from adacomp, we must test the run time flag adacomp_option * to determine which case it is. */ #ifdef EXIT_INTERNAL_ERROR #ifdef vms LIB$STOP(MSG_CHAOS); #else #ifdef BINDER if (adacomp_option) #endif fprintf(stderr, "Adaed internal error - Please report.\n"); exit(RC_INTERNAL_ERROR); #endif #else exit(RC_INTERNAL_ERROR); #endif } #endif void exitp(int n) /*;exitp*/ { /* synonym for exit() used so can trap exit() calls with debugger */ exit(n); } char *ecalloc(unsigned nelem, unsigned nsize) /*;ecalloc */ { /* calloc with error check if no more */ char *p; if (nelem > 20000) chaos("ecalloc: ridiculous argument"); p = calloc (nelem, nsize); if (p == (char *) 0) capacity("out of memory \n"); return p; } char *emalloc(unsigned n) /*;emalloc */ { /* avoid BUGS - use calloc which presets result to zero ds 3 dec 84*/ /* malloc with error check if no more */ char *p; if (n > 50000) chaos("emalloc: ridiculous argument"); p = calloc (1, n); if (p == (char *) 0) capacity("out of memory \n"); return (p); } char *erealloc(char *ptr, unsigned size) /*;eralloc */ { /* realloc with error check if no more */ char *p; p = realloc (ptr, size); if (p == (char *) 0) capacity("erealloc: out of memory \n"); return (p); } char *strjoin(char *s1, char *s2) /*;strjoin */ { /* return string obtained by concatenating argument strings * watch for either argument being (char *)0 and treat this as null string */ char *s; if (s1 == (char *)0) s1= ""; if (s2 == (char *)0) s2 = ""; s = smalloc((unsigned) strlen(s1) + strlen(s2) + 1); strcpy(s, s1); strcat(s, s2); return s; } int streq(char *a, char *b) /*;streq*/ { /* test two strings for equality, allowing for null pointers */ if (a == (char *)0 && b == (char *)0) return TRUE; else if (a == (char *)0 || b == (char *)0) return FALSE; else return (strcmp(a, b) == 0); } char *substr(char *s, int i, int j) /*;substr */ { /* return substring s(i..j) if defined, else return null ptr*/ int n; char *ts, *t; if (s == (char *)0) return (char *) 0; n = strlen(s); if (!(i > 0 && j <= n && i <= j)) return (char *)0; /* allocate result, including null byte at end */ ts = smalloc((unsigned) j - i + 2); t = ts; s = s + (i - 1); /* point to start of source*/ for (; i <= j; i++) *t++ = *s++; /* copy characters */ *t = '\0'; /* terminate result */ return ts; } /* getopt(3) procedure obtained from usenet */ /* * getopt - get option letter from argv */ #ifdef IBM_PC #define nogetopt #endif #ifdef nogetopt char *optarg; /* Global argument pointer. */ int optind = 0; /* Global argv index. */ static char *scan = NULL; /* Private scan pointer. */ int getopt(int argc, char **argv, char *optstring) /*;getopt */ { register char c; register char *place; optarg = NULL; if (scan == NULL || *scan == '\0') { if (optind == 0) optind++; if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') return (EOF); if (strcmp (argv[optind], "--") == 0) { optind++; return (EOF); } scan = argv[optind] + 1; optind++; } c = *scan++; place = strchr (optstring, c); if (place == NULL || c == ':') { fprintf (stderr, "%s: unknown option -%c\n", argv[0], c); return ('?'); } place++; if (*place == ':') { if (*scan != '\0') { optarg = scan; scan = NULL; } else { optarg = argv[optind]; optind++; } } return (c); } #endif char *greentime(int un) /*;greentime*/ { /* get greenwich time in string of 23 characters. * format of result is as follows * 1984 10 02 16 30 36 nnn * 123456789a123456789b123 * year mo da hr mi se uni * * greenwich time is used to avoid problems with daylight savings time. * The last three characters are the compilation unit number * (left filled with zeros if necessary). * NOTE: changed to use local time to give approx. same time as * SETL version ds 20 nov 84 */ char *s; #ifndef IBM_PC long clock; #else /* IBM_PC (Metaware) */ time_t clock; #endif /*struct tm *gmtime();*/ struct tm *t; #ifndef IBM_PC clock = time(0); #else time(&clock); #endif s = smalloc(24); /*t = gmtime(&clock);*/ t = localtime(&clock); sprintf(s,"%04d %02d %02d %02d %02d %02d %03d", #ifdef IBM_PC /* needed until Metaware fixes bug in tm_year field (ds 6-19-86) */ t->tm_year , t->tm_mon + 1, t->tm_mday, #else t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, #endif t->tm_hour, t->tm_min, t->tm_sec, un); return s; } FILE *efopenl(char *filename, char *suffix, char *type, char *mode) /*;efopenl*/ { char *fname; FILE *f; fname = ifname(filename, suffix); f = efopen(fname, type, mode); efree(fname); return f; } FILE *efopen(char *filename, char *type, char *mode) /*;efopen*/ { FILE *f; #ifdef IBM_PC char *p; /* mode only meaningful for IBM PC for now */ p = emalloc((unsigned) (strlen(type) + strlen(mode) + 1)); strcpy(p, type); strcat(p, mode); f = fopen(filename, p); efree(p); #else f = fopen(filename, type); #endif if (f == (FILE *)0) openerr(filename, type); return f; } void efree(char *p) /*;efree*/ { /* free with check that not tryig to free null pointer*/ if (p == (char *)0) chaos("efree: trying to free null pointer"); free(p); } int strhash(char *s) /*;strhash*/ { /* Hashing function from strings to numbers */ register int hash = 0; /* add character values together, adding in the cumulative hash code * at each step so that 'ABC' and 'BCA' have different hash codes. */ while (*s) hash += hash + *s++; if (hash < 0) hash = - hash; /* to avoid negative hash code */ return hash; } char *unit_name_type(char *u) /*;unit_name_type*/ { int n; char *s; n = strlen(u); if (n < 2) { s = smalloc(1); *s = '\0'; return s; } /* otherwise, return first two characters */ s = smalloc(3); s[0] = u[0]; s[1] = u[1]; s[2] = '\0'; return s; } #ifdef BSD /* BSD doesn't support strchr() and strrchr(), but they are just * named index() and rindex(), respectively, so here is code for BSD */ char *strchr(char *s, int c) { return index(s, (char) c); } char *strrchr(char *s, int c) { return rindex(s, (char) c); } #endif char *libset(char *lname) /*;libset*/ { char *old_name; old_name = LIBRARY_PREFIX; LIBRARY_PREFIX = lname; return old_name; } char *ifname(char *filename, char *suffix) /*;ifname*/ { char *fname; /* allow room for library prefix, file name and suffix */ #ifdef vms if (strchr(LIBRARY_PREFIX, '[')) { fname = emalloc((unsigned) (strlen(LIBRARY_PREFIX) + strlen(filename) + strlen(suffix) + 2)); } else { fname = emalloc((unsigned) (strlen(LIBRARY_PREFIX) + strlen(filename) + strlen(suffix) + 3 + 2)); } #else fname = emalloc((unsigned) (strlen(LIBRARY_PREFIX) + strlen(filename) + strlen(suffix) + 3)); #endif if (strlen(LIBRARY_PREFIX)) { /* prepend library prefix if present */ #ifdef vms if (strchr(LIBRARY_PREFIX, '[')) { strcpy(fname, LIBRARY_PREFIX); } else { strcpy(fname, DIRECTORY_START); strcat(fname, LIBRARY_PREFIX); } #else strcpy(fname, LIBRARY_PREFIX); #endif #ifdef IBM_PC strcat(fname, "\\"); #endif #ifdef BSD strcat(fname, "/"); #endif #ifdef SYSTEM_V strcat(fname, "/"); #endif #ifdef vms if (!strchr(LIBRARY_PREFIX, '[')) strcat(fname, "]"); #endif strcat(fname, filename); } else { strcpy(fname, filename); /* copy name if no prefix */ } if (strlen(suffix)) { strcat(fname, "."); strcat(fname, suffix); } return fname; } IFILE *ifopen(char *filename, char *suffix, char *mode, char *typea, int trace, int pass) /*;ifopen*/ { #ifdef HI_LEVEL_IO FILE *file; #else int file; int flag; #endif char ftype, fversion, version; char type, modec; char *fname; long s = 0L; int nr, opened = FALSE, error = FALSE; IFILE *ifile; #ifdef IBM_PC char *t_name; #endif type = typea[0]; modec= mode[0]; #ifdef IOT if (trace) { printf("%s ", filename); } #endif fname = ifname(filename, suffix); /* expand file name */ #ifdef IBM_PC /* mode only meaningful for IBM PC for now */ t_name = emalloc((unsigned) (strlen(mode) + 2)); strcpy(t_name, mode); strcat(t_name, "b"); file = fopen(fname, t_name); efree(t_name); #else #ifdef HI_LEVEL_IO file = fopen(fname, mode); #else #ifdef vms if (modec == 'w') { while(~delete(strjoin(fname, ";"))); } #endif if (mode[0] == 'w' || mode[1] == '+') { flag = O_CREAT | O_RDWR; } else { /* ASSUMING only other possibility is "r" !! */ flag = O_RDONLY; } file = open(fname, flag, 0700); #endif #endif #ifdef HI_LEVEL_IO if (file == (FILE *)0) { #else if (file == -1) { #endif if (pass) return (IFILE *) 0; else openerr(fname, mode); } ifile = (IFILE *) emalloc(sizeof(IFILE)); version = (type == 'a') ? AIS_VERSION : (type == 't') ? TRE_VERSION : (type == 'l') ? LIB_VERSION : (type == 's') ? STUB_VERSION : (type == 'p') ? AST_VERSION : '?'; ifiles++; if (modec == 'w') { /* write header */ /* write long at start to later be replaced with slots offset */ ifile->fh_mode = modec; ifile->fh_type = type; ifile->fh_version = version; ifile->fh_slots = 0; ifile->fh_units_end = 0; #ifdef HI_LEVEL_IO /* will be upated on close */ fwrite((char *) ifile, sizeof(IFILE), 1, file); #else write(file, (char *)ifile, sizeof(IFILE)); #endif } else if (modec == 'r') { /* read and check header */ #ifdef HI_LEVEL_IO nr = fread((char *) ifile, sizeof(IFILE), 1, file); #else nr = read(file, (char *) ifile, sizeof(IFILE)); #endif #ifdef HI_LEVEL_IO if (nr != 1) { #else if (nr != sizeof(IFILE)) { #endif #ifdef DEBUG printf("ifopen - unable to read header\n"); #endif error = TRUE; } ftype = ifile->fh_type; if (!error && ftype != type) { #ifdef DEBUG printf("ifopen read wrong type\n"); #endif error = TRUE; } fversion = ifile->fh_version; if (!error && fversion != version) { #ifdef DEBUG printf("open file read wrong version\n"); #endif error = TRUE; } } if (error) { openerr(fname, mode); } ifile->fh_number = ifiles;/* set count so can match open and close*/ ifile->fh_trace = trace; ifile->fh_file = file; ifile->fh_mode = modec; #ifdef DEBUG if (ifile->fh_trace) fhlist(ifile, "open"); #endif efree(fname); return ifile; } static void openerr(char *filename, char *mode) /*;openerr*/ { /* EXIT_INTERNAL_ERROR is defined when the module is run by itself * (not spawned from adacomp) and DEBUG is not defined. */ #ifdef EXIT_INTERNAL_ERROR #ifdef vms struct dsc$descriptor_s file_name; file_name.dsc$w_length = strlen(filename); file_name.dsc$b_dtype = DSC$K_DTYPE_T; file_name.dsc$b_class = DSC$K_CLASS_S; file_name.dsc$a_pointer = filename; LIB$SIGNAL(MSG_NOTOPEN, 1, &file_name); exit(); #else fprintf(stderr, "Unable to open file %s for %s \n", filename, (strcmp(mode, "w") == 0 ? "writing" : (strcmp(mode, "r") == 0 ? "reading" : (strcmp(mode, "a") == 0 ? "appending" : mode)))); exit(RC_ABORT); #endif #else fprintf(stderr, "Unable to open file %s for %s \n", filename, (strcmp(mode, "w") == 0 ? "writing" : (strcmp(mode, "r") == 0 ? "reading" : (strcmp(mode, "a") == 0 ? "appending" : mode)))); exit(RC_ABORT); #endif } void ifclose(IFILE *ifile) /*;ifclose*/ { #ifdef HI_LEVEL_IO FILE *file; #else int file; #endif #ifdef DEBUG if (ifile->fh_trace) fhlist(ifile, "close"); #endif file = ifile->fh_file; /* write out file header if write mode */ if (ifile->fh_mode == 'w') { ifile->fh_trace = 0; /* trace and number fields internal use only */ ifile->fh_number = 0; ifile->fh_mode = '\0'; ifseek(ifile, "update-header", 0L, 0); #ifdef HI_LEVEL_IO fwrite((char *)ifile, sizeof(IFILE), 1, file); #else write(file, (char *)ifile, sizeof(IFILE)); #endif } #ifdef HI_LEVEL_IO if (file == (FILE *)0) chaos("ifclose: closing unopened file"); fclose(file); ifile->fh_file = (FILE *)0; #else if (file== -1) chaos("ifclose: closing unopened file"); close(file); ifile->fh_file = 0; #endif } void ifoclose(IFILE *ifile) /*;ifoclose*/ { /* close file if still open */ #ifdef HI_LEVEL_IO if (ifile != (IFILE *) 0 && ifile->fh_file != (FILE *) 0) { #else if (ifile != (IFILE *) 0 && ifile->fh_file != 0) { #endif ifclose(ifile); } } #ifdef DEBUG static void fhlist(IFILE *ifile, char *desc) /*;fhlist*/ { /* list file header if tracing */ printf("%s %c %d%c version %c trace %d", desc, ifile->fh_mode, ifile->fh_number, ifile->fh_type, ifile->fh_version, ifile->fh_trace); printf(" slots %ld units_end %ld\n", ifile->fh_slots, ifile->fh_units_end); } #endif long ifseek(IFILE *ifile, char *desc, long offset, int ptr) /*;ifseek*/ { long begpos, endpos, seekval; begpos = iftell(ifile); #ifdef HI_LEVEL_IO seekval = fseek(ifile->fh_file, offset, ptr); #else seekval = lseek(ifile->fh_file, offset, ptr); #endif if (seekval == -1) chaos("ifseek: improper seek"); endpos = iftell(ifile); #ifdef IOT if (ifile->fh_trace > 1 ) printf("%s seek %d%c from %ld to %ld\n", desc, ifile->fh_number, ifile->fh_type, begpos, endpos); #endif return endpos; } long iftell(IFILE *ifile) /*;iftell*/ { /* ftell, but arg is IFILE */ #ifdef HI_LEVEL_IO return ftell(ifile->fh_file); #else return lseek(ifile->fh_file, 0, 1); #endif } /* define MEAS_ALLOC to measure alloc performance */ #define MEAS_ALLOC /* this causes each malloc action to write a line to standard output * formatted as follows: * code:one of a, r, f * a allocate block * r reallocate block * f free block * the block address (integer) * the block length (or zero if not applicable) * the remainder of the line describes the action */ extern FILE *MALFILE; #ifndef EXPORT char *emalloct(unsigned n, char *s) /*;emalloct*/ { char *p; p = emalloc(n); #ifdef DEBUG if (malloctrace) fprintf(MALFILE, "a %ld %u %s\n", p, n, s); #endif return p; } #endif #ifndef EXPORT char *malloct(unsigned n, char *s) /*;malloct*/ { /* like emalloct, but ok if not able to allocate block */ char *p; p = malloc(n); #ifdef DEBUG if (p != (char *)0 && malloctrace) fprintf(MALFILE, "a %ld %u %s\n", p, n, s); #endif return p; } #endif #ifndef EXPORT char *ecalloct(unsigned n, unsigned m, char *msg) { char *p; p = ecalloc(n, m); #ifdef DEBUG if (malloctrace) fprintf(MALFILE, "a %ld %u %s\n", p, n*m, msg); #endif return p; } #endif #ifndef EXPORT char *erealloct(char *ptr, unsigned size, char *msg) /*;erealloct*/ { char *p; p = erealloc(ptr, size); #ifdef DEBUG if (p == ptr) return p; if (malloctrace) /* trace line includes old address before msg */ fprintf(MALFILE, "r %ld %u %ld %s\n", p, size, ptr, msg); #endif return p; } #endif #ifndef EXPORT void efreet(char *p, char *msg) /*;efreet*/ { #ifdef DEBUG if (malloctrace) fprintf(MALFILE, "f %ld 0 %s\n", p, msg); #endif efree(p); } #endif char *predef_env() /*;predef_env*/ { #ifndef IBM_PC char *s = getenv("ADAEDPREDEF"); if (s == (char *)0) s = get_libdir(); return s; #else char *getenv(); return getenv("ADAED"); #endif } char *get_libdir() { char *s = getenv("ADAED"); if (s == (char *)0) return LIBDIR; else return s; } char *parsefile(char *s, int *np, int *nb, int *ns) /*;parsefile*/ { /* Parse file name s, returning the length of prefix, base part, and * suffix in np, nb, and nl, respectively. A pointer to the start of * the base part is returned, or the null pointer if no base part. * The suffix is assumed to begin with period. * The prefix ends with the last instance of any of the prefix characters. */ #ifdef IBM_PC char *prefix_chars = ":/\\"; #endif #ifdef BSD char *prefix_chars = "/"; #endif #ifdef SYSTEM_V char *prefix_chars = "/"; #endif #ifdef vms char *prefix_chars = ":[]"; #endif int n,i; char *pb; char *p, *p2; char *suffix_chars = "."; int have_prefix = 0; n = strlen(s); pb = s; /* assume name starts with base */ *ns = 0; p = s + n; /* point to last (null) character in s */ /* find length of suffix */ /* but if find a prefix character first, then no suffix possible */ for (i = n - 1; i >= 0; i--) { p--; for (p2 = prefix_chars; *p2 !='\0';) { if (*p == *p2++) { /* (p-s) gives number of characters before suffix */ have_prefix = 1; break; } } if (!have_prefix) { for (p2 = suffix_chars; *p2 !='\0';) { if (*p == *p2++) { /* (p-s) gives number of characters before suffix */ *ns = n - (p - s); break; } } } } /* find length of prefix */ *np = 0; p = s + n; for (i = n - 1; i >= 0; i--) { p--; for (p2 = prefix_chars; *p2 !='\0';) { if (*p == *p2++) { p++; /* include last delimiter in prefix */ /* (p-s) now gives prefix length*/ *np = (p - s); pb = p; break; } } } /* base is what remains after removing prefix and suffix*/ *nb = n - (*np + *ns); if (*nb == 0) pb = (char *)0; /* if no base */ return pb; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.