/*======================================================================*\ |* Editor mined *| |* auxiliary functions *| \*======================================================================*/ #include "mined.h" #include "io.h" #include int panic_level = 0; /* To adjust error handling to situation */ /*======================================================================*\ |* Auxiliary routines *| \*======================================================================*/ /** Return the value of an environment variable. Do not return NULL. */ char * envvar (name) char * name; { char * val = getenv (name); if (val) { return val; } else { return ""; } } /* * Delete file. */ void delete_file (file) char * file; { #ifdef unix unlink (file); #endif #ifdef msdos unlink (file); #endif #ifdef vms delete (file); #endif } /* * Panic () is called with a mined error msg and an optional system error msg. * It is called when something unrecoverable has happened. * It writes the message to the terminal, resets the tty and exits. * Ask the user if he wants to save his file. */ static void panic_msg (msg) char * msg; { if (isscreenmode) { /* don't use status_msg here, msg may contain filename characters */ status_line (msg, NIL_PTR); sleep (2); } else { (void) printf ("%s\n", msg); } } static void panicking (message, err, signum) register char * message; register char * err; register int signum; { int panic_written; panic_level ++; /*printf ("panicking, panic_level -> %d\n", panic_level);*/ if (panic_level <= 2) { if (loading == False && modified) { panic_written = panicwrite (); if (panic_written == ERRORS) { sleep (2); build_string (text_buffer, "Error writing panic file %s", panic_file); } else { build_string (text_buffer, "Panic file %s written", panic_file); } ring_bell (); panic_msg (text_buffer); } if (signum != 0) { build_string (text_buffer, message, signum); } else if (err == NIL_PTR) { build_string (text_buffer, "%s", message); } else { build_string (text_buffer, "%s (%s)", message, err); } panic_msg (text_buffer); /* "normal" panic handling: */ if (loading == False) { QUED (); /* Try to save the file and quit */ /* QUED returned: something wrong */ sleep (2); panic_msg ("Aborted writing file in panic mode - trying to continue"); panic_level --; return; } } if (panic_level <= 3) { if (isscreenmode) { set_cursor (0, YMAX); putchar ('\n'); #ifdef unix clear_window_title (); #endif raw_mode (False); } delete_yank_files (); } exit (1) /* abort () sends IOT which would again be caught */; } void panic (message, err) register char * message; register char * err; { panicking (message, err, 0); } void panicio (message, err) register char * message; register char * err; { /* Should panic_level already be increased here ? */ panic (message, err); } /* * Bad_write () is called when a write failed. Notify the user. */ void bad_write (fd) int fd; { if (fd == output_fd) { /* Cannot write to terminal? */ panicio ("Write error on terminal", serror ()); } ring_bell (); error2 ("Write aborted (File incomplete): ", serror ()); } void catch_interrupt (signum) int signum; { catch_signals ((signalfunc) catch_interrupt); if (signum == SIGTERM && panic_level == 0) { panic_level ++; /*printf ("catch_interrupt -> EXMINED\n");*/ EXMINED (); panic_level --; } else { /*printf ("catch_interrupt -> panicking\n");*/ panicking ("External signal %d caught - terminating", NIL_PTR, signum); } } /*-------------------------------------------------------------------------*/ /* * Memory allocation */ #ifdef msdos # ifdef __TURBOC__ #include #define allocate farmalloc #define freemem farfree # else extern void * malloc (); extern void free (); #define allocate malloc #define freemem free # endif #else extern void * malloc (); extern void free (); #define allocate malloc #define freemem free #endif #define dont_debug_out_of_memory #ifdef debug_out_of_memory static int allocount = 0; #endif void * alloc (bytes) int bytes; { #ifdef debug_out_of_memory allocount ++; if (allocount == 500) { return NIL_PTR; } #endif return allocate ((unsigned) bytes); /* char * p; if ((p = allocate ((unsigned) bytes)) == NIL_PTR) { panic ("Out of memory", NIL_PTR); } return p; */ } void free_space (p) void * p; { freemem (p); } /* * free header list */ #define pointersize sizeof (void *) #define blocksizeof(typ) ((sizeof (typ) + pointersize - 1) / pointersize * pointersize) LINE * free_header_list = NIL_LINE; static void alloc_headerblock (n) int n; { LINE * new_header; LINE * new_list; int i = 0; new_list = alloc (n * blocksizeof (LINE)); if (new_list == NIL_LINE) { free_header_list = NIL_LINE; } else { while (i < n) { new_header = (LINE *) ((long) new_list + i * blocksizeof (LINE)); new_header->next = free_header_list; free_header_list = new_header; i ++; } } } LINE * alloc_header () { /* return alloc (sizeof (LINE)); */ LINE * new_header; if (free_header_list == NIL_LINE) { alloc_headerblock (64); if (free_header_list == NIL_LINE) { alloc_headerblock (16); if (free_header_list == NIL_LINE) { alloc_headerblock (4); if (free_header_list == NIL_LINE) { alloc_headerblock (1); if (free_header_list == NIL_LINE) { return NIL_LINE; } } } } } new_header = free_header_list; free_header_list = free_header_list->next; return new_header; } void free_header (hp) LINE * hp; { /* freemem (hp); */ hp->next = free_header_list; free_header_list = hp; } /* * Unnull () changes a NULL string pointer into an empty string pointer * to allow easy feading of string results into build_string / sprintf */ char * unnull (s) char * s; { if (s == NIL_PTR) { return ""; } else { return s; } } /* * Output an (unsigned) long in a 10 digit field without leading zeros. * It returns a pointer to the first digit in the buffer. */ static char * num_out (number, radix) long number; long radix; { static char num_buf [11]; /* Buffer to build number */ register long digit; /* Next digit of number */ register long pow; /* Highest radix power of long */ FLAG digit_seen = False; int i; int maxdigs; char * bufp = num_buf; if (radix == 16) { pow = 268435456L; maxdigs = 8; } else { pow = 1000000000L; maxdigs = 10; if (number < 0) { * bufp ++ = '-'; number = - number; } } for (i = 0; i < maxdigs; i ++) { digit = number / pow; /* Get next digit */ if (digit == 0L && digit_seen == False && i != 9) { } else { if (digit > 9) { * bufp ++ = 'A' + (char) (digit - 10); } else { * bufp ++ = '0' + (char) digit; } number -= digit * pow; /* Erase digit */ digit_seen = True; } pow /= radix; /* Get next digit */ } * bufp = '\0'; return num_buf; } char * dec_out (number) long number; { return num_out (number, 10); } /* * Build_string () prints the arguments as described in fmt, into the buffer. * %s indicates a string argument, %d indicates an integer argument. */ #ifndef build_string /* otherwise build_string is sprintf */ static char * hex_out (number) long number; { return num_out (number, 16); } /* VARARGS */ void build_string (buf, fmt, args) register char * buf; register char * fmt; int args; { int * argptr = & args; char * scanp; FLAG islong; int length = 0; while (* fmt) { if (* fmt == '%') { fmt ++; fmt = scan_int (fmt, & length); if (* fmt == 'l') { islong = True; fmt ++; } else { islong = False; } switch (* fmt ++) { case 's' : scanp = (char *) * argptr; break; case 'd' : if (islong) { scanp = dec_out ((long) * ((long *) argptr)); if (sizeof (long) > sizeof (int)) { argptr ++; } } else { scanp = dec_out ((long) * argptr); } break; case 'D' : scanp = dec_out ((long) * ((long *) argptr)); if (sizeof (long) > sizeof (int)) { argptr ++; } break; case 'x' : case 'X' : scanp = hex_out ((long) * ((long *) argptr)); if (sizeof (long) > sizeof (int)) { argptr ++; } break; default : scanp = ""; } while ((* buf ++ = * scanp ++)) {} buf --; argptr ++; } else { * buf ++ = * fmt ++; } } * buf = '\0'; } #endif /* ndef build_string */ /* * scan_int () converts a string into a natural number * returns the character pointer behind the last digit */ char * scan_int (str, nump) char * str; int * nump; { register char * chpoi = str; int negative = False; while (* chpoi == ' ') { chpoi ++; } if (* chpoi == '-') { negative = True; chpoi ++; } if (* chpoi >= '0' && * chpoi <= '9') { * nump = 0; } else { return str; } while (* chpoi >= '0' && * chpoi <= '9' && quit == False) { * nump *= 10; * nump += * chpoi - '0'; chpoi ++; } if (negative) { * nump = - * nump; } return chpoi; } /* * copy_string () copies the string 'from' into the string 'to' which must be long enough */ void copy_string (to, from) register char * to; register char * from; { while ((* to ++ = * from ++) != '\0') {} } /* * length_of () returns the number of bytes in the string 'string' * excluding the '\0'. */ int length_of (string) register char * string; { register int count = 0; if (string != NIL_PTR) { while (* string ++ != '\0') { count ++; } } return count; } /*======================================================================*\ |* System error retrieval *| \*======================================================================*/ #ifdef __GNUC__ #include #else /* ifdef __GNUC__ */ #ifdef vms /* #define includeerrno */ # ifdef includeerrno # include # else extern volatile int noshare errno; extern volatile int noshare vaxc$errno; /* VMS error code when errno = EVMSERR */ # define EVMSERR 65535 extern volatile int noshare sys_nerr; extern volatile char noshare * sys_errlist []; # endif #else /* #ifdef vms */ #ifdef __CYGWIN__ #include /* What's the purpose of this silly API renaming game ? */ #define sys_nerr _sys_nerr #define sys_errlist _sys_errlist /*const char *const *sys_errlist = _sys_errlist;*/ /* from a mail => initializer element is not constant */ #else /* #ifdef __CYGWIN__ */ #if (defined(BSD) && BSD >= 199306) #include #else # ifdef __linux__ # include # endif extern int errno; extern int sys_nerr; # ifndef __USE_BSD # ifndef __USE_GNU /* Why did those Linux kernel hackers have to change the interface here, inserting a completely superfluous "const"? All this voguish "assumedly-modern C" crap only increases portability problems and wastes developers' time. It's nothing but a nuisance. */ extern char * sys_errlist []; # endif # endif #endif /* #else BSD >= 199306 */ #endif /* #else __CYGWIN__ */ #endif /* #else vms */ #endif /* #else __GNUC__ */ /* * serrorof delivers the error message of the given errno value. * serror delivers the error message of the current errno value. * geterrno just returns the current errno value. */ char * serrorof (errnum) int errnum; { #ifdef __GNUC__ return strerror (errnum); #else if ((errnum < 0) || (errnum >= sys_nerr)) { static char s [20]; #ifdef vms if (errnum == EVMSERR) build_string (s, "VMS error %d", vaxc$errno); else #endif build_string (s, "Unknown error %d", errnum); return s; } else { return (char *) sys_errlist [errnum]; } /* Without the (char *) cast, on some systems, the compiler emits stupid warnings about some "const" crap, due to the nonsense that I complained about above */ #endif } char * serror () { return serrorof (errno); } int geterrno () { return errno; } /*======================================================================*\ |* End *| \*======================================================================*/