sxpr.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,231 行 · 第 1/2 页

C
1,231
字号
    }    for( ; i < d_n; i++){        if(!string_contains(s, s_n, d, i)){            return i;        }        d[i] = randchar();    }    return -1;}/** Print the bytes in a string as-is. * * @param io stream * @param str string * @param n length * @return bytes written or error code */int _string_print_raw(IOStream *io, char *str, int n){    int k = 0;    k = IOStream_write(io, str, n);    return k;}/** Print a string in counted data format. * * @param io stream * @param str string * @param n length * @return bytes written or error code */int _string_print_counted(IOStream *io, char *str, int n){    int k = 0;    k += IOStream_print(io, "%c%c%d%c",                        c_data_open, c_data_count, n, c_data_count);    k += IOStream_write(io, str, n);    return k;}  /** Print a string in quoted data format. * * @param io stream * @param str string * @param n length * @return bytes written or error code */int _string_print_quoted(IOStream *io, char *str, int n){    int k = 0;    char d[10];    int d_n;    d_n = string_delim(str, n, d, sizeof(d) - 1);    k += IOStream_print(io, "%c%c%s%c",                        c_data_open, c_data_quote, d, c_data_quote);    k += IOStream_write(io, str, n);    k += IOStream_print(io, "%c%s%c", c_data_quote, d, c_data_quote);    return k;}/** Print a string as a quoted string. * * @param io stream * @param str string * @param n length * @return bytes written or error code */int _string_print_string(IOStream *io, char *str, int n){    int k = 0;        k += IOStream_print(io, "\"");    if(str){        char *s, *t;        for(s = str, t = str + n; s < t; s++){            if(*s < ' ' || *s >= 127 ){                switch(*s){                case '\a': k += IOStream_print(io, "\\a");  break;                case '\b': k += IOStream_print(io, "\\b");  break;                case '\f': k += IOStream_print(io, "\\f");  break;                case '\n': k += IOStream_print(io, "\\n");  break;                case '\r': k += IOStream_print(io, "\\r");  break;                case '\t': k += IOStream_print(io, "\\t");  break;                case '\v': k += IOStream_print(io, "\\v");  break;                default:                    // Octal escape;                    k += IOStream_print(io, "\\%o", *s);                    break;                }            } else if(*s == c_double_quote ||                      *s == c_single_quote ||                      *s == c_escape){                k += IOStream_print(io, "\\%c", *s);            } else {                k+= IOStream_print(io, "%c", *s);            }        }    }    k += IOStream_print(io, "\"");    return k;}/** Print a string to a stream, with escapes if necessary. * * @param io stream to print to * @param str string * @param n string length * @param flags print flags * @return number of bytes written */int _string_print(IOStream *io, char *str, int n, unsigned flags){    int k = 0;    if((flags & PRINT_COUNTED)){        k = _string_print_counted(io, str, n);    } else if((flags & PRINT_RAW) || !needs_escapes(str, n, flags)){        k = _string_print_raw(io, str, n);    } else if(n > 50){        k = _string_print_quoted(io, str, n);    } else {        k = _string_print_string(io, str, n);    }    return k;}/** Print a string to a stream, with escapes if necessary. * * @param io stream to print to * @param obj string * @param flags print flags * @return number of bytes written */int string_print(IOStream *io, Sxpr obj, unsigned flags){    return _string_print(io,                         OBJ_STRING(obj)->data,                         OBJ_STRING(obj)->len,                         flags);}int string_eq(char *s, int s_n, char *t, int t_n){    return (s_n == t_n) && (memcmp(s, t, s_n) == 0);}/** Compare an sxpr with a string for equality. * * @param x string to compare with * @param y sxpr to compare * @return 1 if equal, 0 otherwise */int string_equal(Sxpr x, Sxpr y){    int ok = 0;    ok = eq(x,y);    if(ok) goto exit;    ok = has_type(y, T_STRING) &&        string_eq(OBJ_STRING(x)->data, OBJ_STRING(x)->len,                  OBJ_STRING(y)->data, OBJ_STRING(y)->len);    if(ok) goto exit;    ok = has_type(y, T_ATOM) &&        string_eq(OBJ_STRING(x)->data, OBJ_STRING(x)->len,                  atom_name(y), atom_length(y));  exit:    return ok;}/** Create a new cons cell. * The cell is ONOMEM if either argument is. * * @param car sxpr for the car * @param cdr sxpr for the cdr * @return new cons */Sxpr cons_new(Sxpr car, Sxpr cdr){    Sxpr obj;    if(NOMEMP(car) || NOMEMP(cdr)){        obj = ONOMEM;    } else {        obj = HALLOC(ObjCons, T_CONS);        if(!NOMEMP(obj)){            ObjCons *z = OBJ_CONS(obj);            z->car = car;            z->cdr = cdr;        }    }    return obj;}/** Push a new element onto a list. * * @param list list to add to * @param elt element to add * @return 0 if successful, error code otherwise */int cons_push(Sxpr *list, Sxpr elt){    Sxpr l;    l = cons_new(elt, *list);    if(NOMEMP(l)) return -ENOMEM;    *list = l;    return 0;}/** Free a cons. Recursively frees the car and cdr. * * @param obj to free */void cons_free(Sxpr obj){    Sxpr next;    for(; CONSP(obj); obj = next){        next = CDR(obj);        objfree(CAR(obj));        hfree(obj);    }    if(!NULLP(obj)){        objfree(obj);    }}/** Copy a cons. Recursively copies the car and cdr. * * @param obj to copy */Sxpr cons_copy(Sxpr obj){    Sxpr v = ONULL;    Sxpr l = ONULL, x = ONONE;    for(l = obj; CONSP(l); l = CDR(l)){        x = objcopy(CAR(l));        if(NOMEMP(x)) goto exit;        x = cons_new(x, v);        if(NOMEMP(x)) goto exit;        v = x;    }    v = nrev(v);  exit:    if(NOMEMP(x)){        objfree(v);        v = ONOMEM;    }    return v;}/** Free a cons and its cdr cells, but not the car sxprs. * Does nothing if called on something that is not a cons. * * @param obj to free */void cons_free_cells(Sxpr obj){    Sxpr next;    for(; CONSP(obj); obj = next){        next = CDR(obj);        hfree(obj);    }}/** Print a cons. * Prints the cons in list format if the cdrs are conses. * uses pair (dot) format if the last cdr is not a cons (or null). * * @param io stream to print to * @param obj to print * @param flags print flags * @return number of bytes written */int cons_print(IOStream *io, Sxpr obj, unsigned flags){    int first = 1;    int k = 0;    k += IOStream_print(io, "(");    for( ; CONSP(obj) ; obj = CDR(obj)){        if(first){             first = 0;        } else {            k += IOStream_print(io, " ");        }        k += objprint(io, CAR(obj), flags);    }    if(!NULLP(obj)){        k += IOStream_print(io, " . ");        k += objprint(io, obj, flags);    }    k += IOStream_print(io, ")");    return (IOStream_error(io) ? -1 : k);}/** Compare a cons with another sxpr for equality. * If y is a cons, compares the cars and cdrs recursively. * * @param x cons to compare * @param y sxpr to compare * @return 1 if equal, 0 otherwise */int cons_equal(Sxpr x, Sxpr y){    return CONSP(y) &&        objequal(CAR(x), CAR(y)) &&        objequal(CDR(x), CDR(y));}/** Return the length of a cons list. * * @param obj list * @return length */int cons_length(Sxpr obj){    int count = 0;    for( ; CONSP(obj); obj = CDR(obj)){        count++;    }    return count;}/** Destructively reverse a cons list in-place. * If the argument is not a cons it is returned unchanged. *  * @param l to reverse * @return reversed list */Sxpr nrev(Sxpr l){    if(CONSP(l)){        // Iterate down the cells in the list making the cdr of        // each cell point to the previous cell. The last cell         // is the head of the reversed list.        Sxpr prev = ONULL;        Sxpr cell = l;        Sxpr next;        while(1){            next = CDR(cell);            CDR(cell) = prev;            if(!CONSP(next)) break;            prev = cell;            cell = next;        }        l = cell;    }    return l;}/** Print the null sxpr.         * * @param io stream to print to * @param obj to print * @param flags print flags * @return number of bytes written */static int null_print(IOStream *io, Sxpr obj, unsigned flags){    return IOStream_print(io, "()");}/** Print the `unspecified' sxpr none. * * @param io stream to print to * @param obj to print * @param flags print flags * @return number of bytes written */static int none_print(IOStream *io, Sxpr obj, unsigned flags){    return IOStream_print(io, "<none>");}/** Print an integer. * * @param io stream to print to * @param obj to print * @param flags print flags * @return number of bytes written */static int int_print(IOStream *io, Sxpr obj, unsigned flags){    return IOStream_print(io, "%d", OBJ_INT(obj));}/** Print a boolean. * * @param io stream to print to * @param obj to print * @param flags print flags * @return number of bytes written */static int bool_print(IOStream *io, Sxpr obj, unsigned flags){    return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));}/** Print an error. * * @param io stream to print to * @param obj to print * @param flags print flags * @return number of bytes written */static int err_print(IOStream *io, Sxpr obj, unsigned flags){    int err = OBJ_INT(obj);    if(err < 0) err = -err;    return IOStream_print(io, "[error:%d:%s]", err, strerror(err));}/** Print the 'nomem' sxpr. * * @param io stream to print to * @param obj to print * @param flags print flags * @return number of bytes written */static int nomem_print(IOStream *io, Sxpr obj, unsigned flags){    return IOStream_print(io, "[ENOMEM]");}int sxprp(Sxpr obj, Sxpr name){    return CONSP(obj) && objequal(CAR(obj), name);}/** Get the name of an element. *  * @param obj element * @return name */Sxpr sxpr_name(Sxpr obj){    Sxpr val = ONONE;    if(CONSP(obj)){        val = CAR(obj);    } else if(STRINGP(obj) || ATOMP(obj)){        val = obj;    }    return val;}int sxpr_is(Sxpr obj, char *s){    if(ATOMP(obj)) return string_eq(atom_name(obj), atom_length(obj), s, strlen(s));    if(STRINGP(obj)) return string_eq(string_string(obj), string_length(obj), s, strlen(s));    return 0;}int sxpr_elementp(Sxpr obj, Sxpr name){    int ok = 0;    ok = CONSP(obj) && objequal(CAR(obj), name);    return ok;}/** Get the attributes of an sxpr. *  * @param obj sxpr * @return attributes */Sxpr sxpr_attributes(Sxpr obj){    Sxpr val = ONULL;    if(CONSP(obj)){        obj = CDR(obj);        if(CONSP(obj)){            obj = CAR(obj);            if(sxprp(obj, intern("@"))){                val = CDR(obj);            }        }    }    return val;}Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){    Sxpr val = ONONE;    val = assoc(sxpr_attributes(obj), key);    if(CONSP(val) && CONSP(CDR(val))){        val = CADR(def);    } else {        val = def;    }    return val;}/** Get the children of an sxpr. *  * @param obj sxpr * @return children */Sxpr sxpr_children(Sxpr obj){    Sxpr val = ONULL;    if(CONSP(obj)){        val = CDR(obj);        if(CONSP(val) && sxprp(CAR(val), intern("@"))){            val = CDR(val);        }    }    return val;}Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){    Sxpr val = ONONE;    Sxpr l;    for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){        if(sxprp(CAR(l), name)){            val = CAR(l);            break;        }    }    if(NONEP(val)) val = def;    return val;}Sxpr sxpr_child0(Sxpr obj, Sxpr def){    Sxpr val = ONONE;    Sxpr l = sxpr_children(obj);    if(CONSP(l)){        val = CAR(l);    } else {        val = def;    }    return val;}Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def){    Sxpr val = def;    Sxpr l;    int i;    for (i = 0, l = sxpr_children(obj); CONSP(l); i++, l = CDR(l)){        if(i == n){            val = CAR(l);            break;        }    }    return val;}    Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){    Sxpr val = ONONE;    val = sxpr_child(obj, name, ONONE);    if(NONEP(val)){        val = def;    } else {        val = sxpr_child0(val, def);    }    return val;}/** Table of interned symbols. Indexed by symbol name. */static HashTable *symbols = NULL;/** Hash function for entries in the symbol table. * * @param key to hash * @return hashcode */static Hashcode sym_hash_fn(void *key){    return hash_string((char*)key);}/** Key equality function for the symbol table. * * @param x to compare * @param y to compare * @return 1 if equal, 0 otherwise */static int sym_equal_fn(void *x, void *y){    return !strcmp((char*)x, (char*)y);}/** Entry free function for the symbol table. * * @param table the entry is in * @param entry being freed */static void sym_free_fn(HashTable *table, HTEntry *entry){    if(entry){        objfree(((ObjAtom*)entry->value)->name);        HTEntry_free(entry);    }}        /** Initialize the symbol table. * * @return 0 on sucess, error code otherwise */static int init_symbols(void){    symbols = HashTable_new(100);    if(symbols){        symbols->key_hash_fn = sym_hash_fn;        symbols->key_equal_fn = sym_equal_fn;        symbols->entry_free_fn = sym_free_fn;        return 0;    }    return -1;}/** Cleanup the symbol table. Frees the table and all its symbols. */void cleanup_symbols(void){    HashTable_free(symbols);    symbols = NULL;}/** Get the interned symbol with the given name. * No new symbol is created. * * @return symbol or null */Sxpr get_symbol(char *sym){    HTEntry *entry;    if(!symbols){        if(init_symbols()) return ONOMEM;        return ONULL;    }    entry = HashTable_get_entry(symbols, sym);    if(entry){        return OBJP(T_ATOM, entry->value);    } else {        return ONULL;    }}/** Get the interned symbol with the given name. * Creates a new symbol if necessary. * * @return symbol */Sxpr intern(char *sym){    Sxpr symbol = get_symbol(sym);    if(NULLP(symbol)){        if(!symbols) return ONOMEM;        symbol = atom_new(sym);        if(!NOMEMP(symbol)){            OBJ_ATOM(symbol)->interned = TRUE;            HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));        }    }    return symbol;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?