]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - boehm-gc/cord/cordxtra.c
Imported gcc-4.4.3
[msp430-gcc.git] / boehm-gc / cord / cordxtra.c
diff --git a/boehm-gc/cord/cordxtra.c b/boehm-gc/cord/cordxtra.c
deleted file mode 100644 (file)
index a5be10d..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- *
- * Author: Hans-J. Boehm (boehm@parc.xerox.com)
- */
-/*
- * These are functions on cords that do not need to understand their
- * implementation.  They serve also serve as example client code for
- * cord_basics.
- */
-/* Boehm, December 8, 1995 1:53 pm PST */
-# include <stdio.h>
-# include <string.h>
-# include <stdlib.h>
-# include <stdarg.h>
-# include "cord.h"
-# include "ec.h"
-# define I_HIDE_POINTERS       /* So we get access to allocation lock. */
-                               /* We use this for lazy file reading,   */
-                               /* so that we remain independent        */
-                               /* of the threads primitives.           */
-# include "gc.h"
-
-/* For now we assume that pointer reads and writes are atomic,         */
-/* i.e. another thread always sees the state before or after   */
-/* a write.  This might be false on a Motorola M68K with       */
-/* pointers that are not 32-bit aligned.  But there probably   */
-/* aren't too many threads packages running on those.          */
-# define ATOMIC_WRITE(x,y) (x) = (y)
-# define ATOMIC_READ(x) (*(x))
-
-/* The standard says these are in stdio.h, but they aren't always: */
-# ifndef SEEK_SET
-#   define SEEK_SET 0
-# endif
-# ifndef SEEK_END
-#   define SEEK_END 2
-# endif
-
-# define BUFSZ 2048    /* Size of stack allocated buffers when         */
-                       /* we want large buffers.                       */
-
-typedef void (* oom_fn)(void);
-
-# define OUT_OF_MEMORY {  if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \
-                         ABORT("Out of memory\n"); }
-# define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
-
-CORD CORD_cat_char(CORD x, char c)
-{
-    register char * string;
-    
-    if (c == '\0') return(CORD_cat(x, CORD_nul(1)));
-    string = GC_MALLOC_ATOMIC(2);
-    if (string == 0) OUT_OF_MEMORY;
-    string[0] = c;
-    string[1] = '\0';
-    return(CORD_cat_char_star(x, string, 1));
-}
-
-CORD CORD_catn(int nargs, ...)
-{
-    register CORD result = CORD_EMPTY;
-    va_list args;
-    register int i;
-
-    va_start(args, nargs);
-    for (i = 0; i < nargs; i++) {
-        register CORD next = va_arg(args, CORD);
-        result = CORD_cat(result, next);
-    }
-    va_end(args);
-    return(result);
-}
-
-typedef struct {
-       size_t len;
-       size_t count;
-       char * buf;
-} CORD_fill_data;
-
-int CORD_fill_proc(char c, void * client_data)
-{
-    register CORD_fill_data * d = (CORD_fill_data *)client_data;
-    register size_t count = d -> count;
-    
-    (d -> buf)[count] = c;
-    d -> count = ++count;
-    if (count >= d -> len) {
-       return(1);
-    } else {
-       return(0);
-    }
-}
-
-int CORD_batched_fill_proc(const char * s, void * client_data)
-{
-    register CORD_fill_data * d = (CORD_fill_data *)client_data;
-    register size_t count = d -> count;
-    register size_t max = d -> len;
-    register char * buf = d -> buf;
-    register const char * t = s;
-    
-    while((buf[count] = *t++) != '\0') {
-        count++;
-        if (count >= max) {
-            d -> count = count;
-            return(1);
-        }
-    }
-    d -> count = count;
-    return(0);
-}
-
-/* Fill buf with len characters starting at i.                         */
-/* Assumes len characters are available.                               */ 
-void CORD_fill_buf(CORD x, size_t i, size_t len, char * buf)
-{
-    CORD_fill_data fd;
-    
-    fd.len = len;
-    fd.buf = buf;
-    fd.count = 0;
-    (void)CORD_iter5(x, i, CORD_fill_proc, CORD_batched_fill_proc, &fd);
-}
-
-int CORD_cmp(CORD x, CORD y)
-{
-    CORD_pos xpos;
-    CORD_pos ypos;
-    register size_t avail, yavail;
-    
-    if (y == CORD_EMPTY) return(x != CORD_EMPTY);
-    if (x == CORD_EMPTY) return(-1);
-    if (CORD_IS_STRING(y) && CORD_IS_STRING(x)) return(strcmp(x,y));
-    CORD_set_pos(xpos, x, 0);
-    CORD_set_pos(ypos, y, 0);
-    for(;;) {
-        if (!CORD_pos_valid(xpos)) {
-            if (CORD_pos_valid(ypos)) {
-               return(-1);
-            } else {
-                return(0);
-            }
-        }
-        if (!CORD_pos_valid(ypos)) {
-            return(1);
-        }
-        if ((avail = CORD_pos_chars_left(xpos)) <= 0
-            || (yavail = CORD_pos_chars_left(ypos)) <= 0) {
-            register char xcurrent = CORD_pos_fetch(xpos);
-            register char ycurrent = CORD_pos_fetch(ypos);
-            if (xcurrent != ycurrent) return(xcurrent - ycurrent);
-            CORD_next(xpos);
-            CORD_next(ypos);
-        } else {
-            /* process as many characters as we can    */
-            register int result;
-            
-            if (avail > yavail) avail = yavail;
-            result = strncmp(CORD_pos_cur_char_addr(xpos),
-                            CORD_pos_cur_char_addr(ypos), avail);
-            if (result != 0) return(result);
-            CORD_pos_advance(xpos, avail);
-            CORD_pos_advance(ypos, avail);
-        }
-    }
-}
-
-int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len)
-{
-    CORD_pos xpos;
-    CORD_pos ypos;
-    register size_t count;
-    register long avail, yavail;
-    
-    CORD_set_pos(xpos, x, x_start);
-    CORD_set_pos(ypos, y, y_start);
-    for(count = 0; count < len;) {
-        if (!CORD_pos_valid(xpos)) {
-            if (CORD_pos_valid(ypos)) {
-               return(-1);
-            } else {
-                return(0);
-            }
-        }
-        if (!CORD_pos_valid(ypos)) {
-            return(1);
-        }
-        if ((avail = CORD_pos_chars_left(xpos)) <= 0
-            || (yavail = CORD_pos_chars_left(ypos)) <= 0) {
-            register char xcurrent = CORD_pos_fetch(xpos);
-            register char ycurrent = CORD_pos_fetch(ypos);
-            if (xcurrent != ycurrent) return(xcurrent - ycurrent);
-            CORD_next(xpos);
-            CORD_next(ypos);
-            count++;
-        } else {
-            /* process as many characters as we can    */
-            register int result;
-            
-            if (avail > yavail) avail = yavail;
-            count += avail;
-            if (count > len) avail -= (count - len);
-            result = strncmp(CORD_pos_cur_char_addr(xpos),
-                            CORD_pos_cur_char_addr(ypos), (size_t)avail);
-            if (result != 0) return(result);
-            CORD_pos_advance(xpos, (size_t)avail);
-            CORD_pos_advance(ypos, (size_t)avail);
-        }
-    }
-    return(0);
-}
-
-char * CORD_to_char_star(CORD x)
-{
-    register size_t len = CORD_len(x);
-    char * result = GC_MALLOC_ATOMIC(len + 1);
-    
-    if (result == 0) OUT_OF_MEMORY;
-    CORD_fill_buf(x, 0, len, result);
-    result[len] = '\0';
-    return(result);
-}
-
-CORD CORD_from_char_star(const char *s)
-{
-    char * result;
-    size_t len = strlen(s);
-
-    if (0 == len) return(CORD_EMPTY);
-    result = GC_MALLOC_ATOMIC(len + 1);
-    if (result == 0) OUT_OF_MEMORY;
-    memcpy(result, s, len+1);
-    return(result);
-}
-
-const char * CORD_to_const_char_star(CORD x)
-{
-    if (x == 0) return("");
-    if (CORD_IS_STRING(x)) return((const char *)x);
-    return(CORD_to_char_star(x));
-}
-
-char CORD_fetch(CORD x, size_t i)
-{
-    CORD_pos xpos;
-    
-    CORD_set_pos(xpos, x, i);
-    if (!CORD_pos_valid(xpos)) ABORT("bad index?");
-    return(CORD_pos_fetch(xpos));
-}
-
-
-int CORD_put_proc(char c, void * client_data)
-{
-    register FILE * f = (FILE *)client_data;
-    
-    return(putc(c, f) == EOF);
-}
-
-int CORD_batched_put_proc(const char * s, void * client_data)
-{
-    register FILE * f = (FILE *)client_data;
-    
-    return(fputs(s, f) == EOF);
-}
-    
-
-int CORD_put(CORD x, FILE * f)
-{
-    if (CORD_iter5(x, 0, CORD_put_proc, CORD_batched_put_proc, f)) {
-        return(EOF);
-    } else {
-       return(1);
-    }
-}
-
-typedef struct {
-    size_t pos;                /* Current position in the cord */
-    char target;       /* Character we're looking for  */
-} chr_data;
-
-int CORD_chr_proc(char c, void * client_data)
-{
-    register chr_data * d = (chr_data *)client_data;
-    
-    if (c == d -> target) return(1);
-    (d -> pos) ++;
-    return(0);
-}
-
-int CORD_rchr_proc(char c, void * client_data)
-{
-    register chr_data * d = (chr_data *)client_data;
-    
-    if (c == d -> target) return(1);
-    (d -> pos) --;
-    return(0);
-}
-
-int CORD_batched_chr_proc(const char *s, void * client_data)
-{
-    register chr_data * d = (chr_data *)client_data;
-    register char * occ = strchr(s, d -> target);
-    
-    if (occ == 0) {
-       d -> pos += strlen(s);
-       return(0);
-    } else {
-       d -> pos += occ - s;
-       return(1);
-    }
-}
-
-size_t CORD_chr(CORD x, size_t i, int c)
-{
-    chr_data d;
-    
-    d.pos = i;
-    d.target = c;
-    if (CORD_iter5(x, i, CORD_chr_proc, CORD_batched_chr_proc, &d)) {
-        return(d.pos);
-    } else {
-       return(CORD_NOT_FOUND);
-    }
-}
-
-size_t CORD_rchr(CORD x, size_t i, int c)
-{
-    chr_data d;
-    
-    d.pos = i;
-    d.target = c;
-    if (CORD_riter4(x, i, CORD_rchr_proc, &d)) {
-        return(d.pos);
-    } else {
-       return(CORD_NOT_FOUND);
-    }
-}
-
-/* Find the first occurrence of s in x at position start or later.     */
-/* This uses an asymptotically poor algorithm, which should typically  */
-/* perform acceptably.  We compare the first few characters directly,  */
-/* and call CORD_ncmp whenever there is a partial match.               */
-/* This has the advantage that we allocate very little, or not at all. */
-/* It's very fast if there are few close misses.                       */
-size_t CORD_str(CORD x, size_t start, CORD s)
-{
-    CORD_pos xpos;
-    size_t xlen = CORD_len(x);
-    size_t slen;
-    register size_t start_len;
-    const char * s_start;
-    unsigned long s_buf = 0;   /* The first few characters of s        */
-    unsigned long x_buf = 0;   /* Start of candidate substring.        */
-                               /* Initialized only to make compilers   */
-                               /* happy.                               */
-    unsigned long mask = 0;
-    register size_t i;
-    register size_t match_pos;
-    
-    if (s == CORD_EMPTY) return(start);
-    if (CORD_IS_STRING(s)) {
-        s_start = s;
-        slen = strlen(s);
-    } else {
-        s_start = CORD_to_char_star(CORD_substr(s, 0, sizeof(unsigned long)));
-        slen = CORD_len(s);
-    }
-    if (xlen < start || xlen - start < slen) return(CORD_NOT_FOUND);
-    start_len = slen;
-    if (start_len > sizeof(unsigned long)) start_len = sizeof(unsigned long);
-    CORD_set_pos(xpos, x, start);
-    for (i = 0; i < start_len; i++) {
-        mask <<= 8;
-        mask |= 0xff;
-        s_buf <<= 8;
-        s_buf |= s_start[i];
-        x_buf <<= 8;
-        x_buf |= CORD_pos_fetch(xpos);
-        CORD_next(xpos);
-    }
-    for (match_pos = start; ; match_pos++) {
-       if ((x_buf & mask) == s_buf) {
-           if (slen == start_len ||
-               CORD_ncmp(x, match_pos + start_len,
-                         s, start_len, slen - start_len) == 0) {
-               return(match_pos);
-           }
-       }
-       if ( match_pos == xlen - slen ) {
-           return(CORD_NOT_FOUND);
-       }
-       x_buf <<= 8;
-        x_buf |= CORD_pos_fetch(xpos);
-        CORD_next(xpos);
-    }
-}
-
-void CORD_ec_flush_buf(CORD_ec x)
-{
-    register size_t len = x[0].ec_bufptr - x[0].ec_buf;
-    char * s;
-
-    if (len == 0) return;
-    s = GC_MALLOC_ATOMIC(len+1);
-    memcpy(s, x[0].ec_buf, len);
-    s[len] = '\0';
-    x[0].ec_cord = CORD_cat_char_star(x[0].ec_cord, s, len);
-    x[0].ec_bufptr = x[0].ec_buf;
-}
-
-void CORD_ec_append_cord(CORD_ec x, CORD s)
-{
-    CORD_ec_flush_buf(x);
-    x[0].ec_cord = CORD_cat(x[0].ec_cord, s);
-}
-
-/*ARGSUSED*/
-char CORD_nul_func(size_t i, void * client_data)
-{
-    return((char)(unsigned long)client_data);
-}
-
-
-CORD CORD_chars(char c, size_t i)
-{
-    return(CORD_from_fn(CORD_nul_func, (void *)(unsigned long)c, i));
-}
-
-CORD CORD_from_file_eager(FILE * f)
-{
-    register int c;
-    CORD_ec ecord;
-    
-    CORD_ec_init(ecord);
-    for(;;) {
-        c = getc(f);
-        if (c == 0) {
-          /* Append the right number of NULs   */
-          /* Note that any string of NULs is rpresented in 4 words,    */
-          /* independent of its length.                                        */
-            register size_t count = 1;
-            
-            CORD_ec_flush_buf(ecord);
-            while ((c = getc(f)) == 0) count++;
-            ecord[0].ec_cord = CORD_cat(ecord[0].ec_cord, CORD_nul(count));
-        }
-        if (c == EOF) break;
-        CORD_ec_append(ecord, c);
-    }
-    (void) fclose(f);
-    return(CORD_balance(CORD_ec_to_cord(ecord)));
-}
-
-/* The state maintained for a lazily read file consists primarily      */
-/* of a large direct-mapped cache of previously read values.           */
-/* We could rely more on stdio buffering.  That would have 2           */
-/* disadvantages:                                                      */
-/*     1) Empirically, not all fseek implementations preserve the      */
-/*        buffer whenever they could.                                  */
-/*     2) It would fail if 2 different sections of a long cord         */
-/*        were being read alternately.                                 */
-/* We do use the stdio buffer for read ahead.                          */
-/* To guarantee thread safety in the presence of atomic pointer                */
-/* writes, cache lines are always replaced, and never modified in      */
-/* place.                                                              */
-
-# define LOG_CACHE_SZ 14
-# define CACHE_SZ (1 << LOG_CACHE_SZ)
-# define LOG_LINE_SZ 9
-# define LINE_SZ (1 << LOG_LINE_SZ)
-
-typedef struct {
-    size_t tag;
-    char data[LINE_SZ];
-       /* data[i%LINE_SZ] = ith char in file if tag = i/LINE_SZ        */
-} cache_line;
-
-typedef struct {
-    FILE * lf_file;
-    size_t lf_current; /* Current file pointer value */
-    cache_line * volatile lf_cache[CACHE_SZ/LINE_SZ];
-} lf_state;
-
-# define MOD_CACHE_SZ(n) ((n) & (CACHE_SZ - 1))
-# define DIV_CACHE_SZ(n) ((n) >> LOG_CACHE_SZ)
-# define MOD_LINE_SZ(n) ((n) & (LINE_SZ - 1))
-# define DIV_LINE_SZ(n) ((n) >> LOG_LINE_SZ)
-# define LINE_START(n) ((n) & ~(LINE_SZ - 1))
-
-typedef struct {
-    lf_state * state;
-    size_t file_pos;   /* Position of needed character. */
-    cache_line * new_cache;
-} refill_data;
-
-/* Executed with allocation lock. */
-static char refill_cache(client_data)
-refill_data * client_data;
-{
-    register lf_state * state = client_data -> state;
-    register size_t file_pos = client_data -> file_pos;
-    FILE *f = state -> lf_file;
-    size_t line_start = LINE_START(file_pos);
-    size_t line_no = DIV_LINE_SZ(MOD_CACHE_SZ(file_pos));
-    cache_line * new_cache = client_data -> new_cache;
-    
-    if (line_start != state -> lf_current
-        && fseek(f, line_start, SEEK_SET) != 0) {
-           ABORT("fseek failed");
-    }
-    if (fread(new_cache -> data, sizeof(char), LINE_SZ, f)
-       <= file_pos - line_start) {
-       ABORT("fread failed");
-    }
-    new_cache -> tag = DIV_LINE_SZ(file_pos);
-    /* Store barrier goes here. */
-    ATOMIC_WRITE(state -> lf_cache[line_no], new_cache);
-    state -> lf_current = line_start + LINE_SZ;
-    return(new_cache->data[MOD_LINE_SZ(file_pos)]);
-}
-
-char CORD_lf_func(size_t i, void * client_data)
-{
-    register lf_state * state = (lf_state *)client_data;
-    register cache_line * volatile * cl_addr =
-               &(state -> lf_cache[DIV_LINE_SZ(MOD_CACHE_SZ(i))]);
-    register cache_line * cl = (cache_line *)ATOMIC_READ(cl_addr);
-    
-    if (cl == 0 || cl -> tag != DIV_LINE_SZ(i)) {
-       /* Cache miss */
-       refill_data rd;
-       
-        rd.state = state;
-        rd.file_pos =  i;
-        rd.new_cache = GC_NEW_ATOMIC(cache_line);
-        if (rd.new_cache == 0) OUT_OF_MEMORY;
-        return((char)(GC_word)
-                 GC_call_with_alloc_lock((GC_fn_type) refill_cache, &rd));
-    }
-    return(cl -> data[MOD_LINE_SZ(i)]);
-}    
-
-/*ARGSUSED*/
-void CORD_lf_close_proc(void * obj, void * client_data)  
-{
-    if (fclose(((lf_state *)obj) -> lf_file) != 0) {
-       ABORT("CORD_lf_close_proc: fclose failed");
-    }
-}                      
-
-CORD CORD_from_file_lazy_inner(FILE * f, size_t len)
-{
-    register lf_state * state = GC_NEW(lf_state);
-    register int i;
-    
-    if (state == 0) OUT_OF_MEMORY;
-    if (len != 0) {
-       /* Dummy read to force buffer allocation.       */
-       /* This greatly increases the probability       */
-       /* of avoiding deadlock if buffer allocation    */
-       /* is redirected to GC_malloc and the           */
-       /* world is multithreaded.                      */
-       char buf[1];
-
-       (void) fread(buf, 1, 1, f); 
-       rewind(f);
-    }
-    state -> lf_file = f;
-    for (i = 0; i < CACHE_SZ/LINE_SZ; i++) {
-        state -> lf_cache[i] = 0;
-    }
-    state -> lf_current = 0;
-    GC_REGISTER_FINALIZER(state, CORD_lf_close_proc, 0, 0, 0);
-    return(CORD_from_fn(CORD_lf_func, state, len));
-}
-
-CORD CORD_from_file_lazy(FILE * f)
-{
-    register long len;
-    
-    if (fseek(f, 0l, SEEK_END) != 0) {
-        ABORT("Bad fd argument - fseek failed");
-    }
-    if ((len = ftell(f)) < 0) {
-        ABORT("Bad fd argument - ftell failed");
-    }
-    rewind(f);
-    return(CORD_from_file_lazy_inner(f, (size_t)len));
-}
-
-# define LAZY_THRESHOLD (128*1024 + 1)
-
-CORD CORD_from_file(FILE * f)
-{
-    register long len;
-    
-    if (fseek(f, 0l, SEEK_END) != 0) {
-        ABORT("Bad fd argument - fseek failed");
-    }
-    if ((len = ftell(f)) < 0) {
-        ABORT("Bad fd argument - ftell failed");
-    }
-    rewind(f);
-    if (len < LAZY_THRESHOLD) {
-        return(CORD_from_file_eager(f));
-    } else {
-        return(CORD_from_file_lazy_inner(f, (size_t)len));
-    }
-}