C语言接口与实现[+]

该博客详细介绍了C语言中接口与实现的紧密关系,通过Arith接口、抽象数据类型Stack、原子、异常处理、内存管理等关键概念的实例解析,深入探讨了C语言编程中的核心要素。从原子接口到高级数据结构如链表、表格和集合,展示了C语言在构建高效程序中的应用。

第1章 简介

1. literate程序

2. 宏指令与条件编译指令

第2章 接口与实现

1. 接口与实现的关系

2. Arith接口及实现:

arith.h:

复制代码
/*  $Id: H:/drh/idioms/book/RCS/inter.doc,v 1.11 1997/02/21 19:42:15 drh Exp $  */
extern  int Arith_max( int x,  int y);
extern  int Arith_min( int x,  int y);
extern  int Arith_div( int x,  int y);
extern  int Arith_mod( int x,  int y);
extern  int Arith_ceiling( int x,  int y);
extern  int Arith_floor  ( int x,  int y);
复制代码

arith.c

 

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/inter.doc,v 1.11 1997/02/21 19:42:15 drh Exp $ ";
#include  " arith.h "
int Arith_max( int x,  int y) {
     return x > y ? x : y;
}
int Arith_min( int x,  int y) {
     return x > y ? y : x;
}
int Arith_div( int x,  int y) {
     if (- 13/ 5 == - 2
    &&    (x <  0) != (y <  0) && x%y !=  0)
         return x/y -  1;
     else
         return x/y;
}
int Arith_mod( int x,  int y) {
     if (- 13/ 5 == - 2
    &&    (x <  0) != (y <  0) && x%y !=  0)
         return x%y + y;
     else
         return x%y;
}
int Arith_floor( int x,  int y) {
     return Arith_div(x, y);
}
int Arith_ceiling( int x,  int y) {
     return Arith_div(x, y) + (x%y !=  0);
}
复制代码

 

3. 抽象数据类型Stack

4. 客户调用程序的责任

stack.h

View Code

stack.c 

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/inter.doc,v 1.11 1997/02/21 19:42:15 drh Exp $ ";
#include <stddef.h>
#include  " assert.h "
#include  " mem.h "
#include  " stack.h "
#define T Stack_T
struct T {
     int count;
     struct elem {
         void *x;
         struct elem *link;
    } *head;
};
T Stack_new( void) {
    T stk;
    NEW(stk);
    stk->count =  0;
    stk->head = NULL;
     return stk;
}
int Stack_empty(T stk) {
    assert(stk);
     return stk->count ==  0;
}
void Stack_push(T stk,  void *x) {
     struct elem *t;
    assert(stk);
    NEW(t);
    t->x = x;
    t->link = stk->head;
    stk->head = t;
    stk->count++;
}
void *Stack_pop(T stk) {
     void *x;
     struct elem *t;
    assert(stk);
    assert(stk->count >  0);
    t = stk->head;
    stk->head = t->link;
    stk->count--;
    x = t->x;
    FREE(t);
     return x;
}
void Stack_free(T *stk) {
     struct elem *t, *u;
    assert(stk && *stk);
     for (t = (*stk)->head; t; t = u) {
        u = t->link;
        FREE(t);
    }
    FREE(*stk);
}
复制代码

第3章 原子

1. 接口

atom.h: 

View Code

atom.c:

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/atom.doc,v 1.10 1997/02/21 19:42:46 drh Exp $ ";
#include  " atom.h "
#include < string.h>
#include  " assert.h "
#include <limits.h>
#include  " mem.h "
#define NELEMS(x) ((sizeof (x))/(sizeof ((x)[0])))
static  struct atom {
     struct atom *link;
     int len;
     char *str;
} *buckets[ 2048];
static unsigned  long scatter[] = {
2078917053143302914102710082719532103027552536312002600785,
14053902304524801110999515674338323502018585307438263339,
8135289291703199216618906479573714703766270699275680090,
151032044015835839261723401032196544332910981836821636505764,
980071615101159796164327927313154612751575840381069844923,
471560540890174431213147837149866136820422277461968401469,
13537785051300134328201364948030624642417339666781884751139,
7445097634000119591440466707136341624297372666359253759,
163909633233656345516428376851215013716154523136593537720,
7040358321134594751160513568113473151063025723791762719719,
269676381774132919185173716314828242191253106391746481261,
1303742040147908914489913194111699078721785335569485614972,
90717536438236168488562693120015842317457779271859353594,
2594121821237390611484334011902249868304920680202956538,
3483039401008956512133755128919534396212087879701640123668,
156867569347846435226677294012729292081961288571392083579,
8719268211117546963187117272417710587621399711871509024645,
1091900861047146551189138632999481701812473049751489680608,
70668696415067171575795875727551203661261483377884508252,
9580769041609787317189346476414814454514157432912102252735,
178826821483693533643323343920550411542109864544247038362,
2996410858343077171364585325233301614578828311504556512,
1532354806567072918404219416127625748815618899361651524391,
61845444812109325210107579001198042020876213618124757630,
208255027218342905221734544947182853138919824350681002804590,
1783300476162321963418397399266905026715307771401802120822,
316088629183041822548894489116806739541853748387946827723,
1037746818123861954515139006411441966234367393385928306929,
94600697798584783410494001811956764878364062061925613800,
208152250821189564791612420674166858380718000042201447372094,
52390475014358210489231080802161610281504871315306401572,
20182818511820959944213681979835974309413541502501843084537,
130657081724441342093422043467298781016863796551301613820,
1601294739484902984139978006503211273294184214176384212,
281341425228223074147857043189376209918968068821947861263,
119365054627322798412361986632116758626489389012593586330,
2756765513601872152670626262650127017199303101621212876,
2108097238202650112718656262978948340245520052901404522304,
489641965816381188942528818894220250902765436125855,
36532641579036907926434892951318345853664753113672163,
313561074173029807728690014715497597371699573055776289160,
214334606819752496061136476375262925046927786591856406685,
18841379235339224917354241651602280572
};
const  char *Atom_string( const  char *str) {
    assert(str);
     return Atom_new(str, strlen(str));
}
const  char *Atom_int( long n) {
     char str[ 43];
     char *s = str +  sizeof str;
    unsigned  long m;
     if (n == LONG_MIN)
        m = LONG_MAX +  1UL;
     else  if (n <  0)
        m = -n;
     else
        m = n;
     do
        *--s = m% 10 +  ' 0 ';
     while ((m /=  10) >  0);
     if (n <  0)
        *--s =  ' - ';
     return Atom_new(s, (str +  sizeof str) - s);
}
const  char *Atom_new( const  char *str,  int len) {
    unsigned  long h;
     int i;
     struct atom *p;
    assert(str);
    assert(len >=  0);
     for (h =  0, i =  0; i < len; i++)
        h = (h<< 1) + scatter[(unsigned  char)str[i]];
    h &= NELEMS(buckets)- 1;
     for (p = buckets[h]; p; p = p->link)
         if (len == p->len) {
             for (i =  0; i < len && p->str[i] == str[i]; )
                i++;
             if (i == len)
                 return p->str;
        }
    p = ALLOC( sizeof (*p) + len +  1);
    p->len = len;
    p->str = ( char *)(p +  1);
     if (len >  0)
        memcpy(p->str, str, len);
    p->str[len] =  ' \0 ';
    p->link = buckets[h];
    buckets[h] = p;
     return p->str;
}
int Atom_length( const  char *str) {
     struct atom *p;
     int i;
    assert(str);
     for (i =  0; i < NELEMS(buckets); i++)
         for (p = buckets[i]; p; p = p->link)
             if (p->str == str)
                 return p->len;
    assert( 0);
     return  0;
}
复制代码

第4章 异常与断言

except.h 

复制代码
/*  $Id: H:/drh/idioms/book/RCS/except.doc,v 1.10 1997/02/21 19:43:55 drh Exp $  */
#ifndef EXCEPT_INCLUDED
#define EXCEPT_INCLUDED
#include <setjmp.h>
#define T Except_T
typedef  struct T {
     char *reason;
} T;
typedef  struct Except_Frame Except_Frame;
struct Except_Frame {
    Except_Frame *prev;
    jmp_buf env;
     const  char *file;
     int line;
     const T *exception;
};
enum { Except_entered= 0, Except_raised,
       Except_handled,   Except_finalized };
#ifdef WIN32
__declspec(thread)
#endif
extern Except_Frame *Except_stack;
extern  const Except_T Assert_Failed;
void Except_raise( const T *e,  const  char *file, int line);
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
#define RERAISE Except_raise(Except_frame.exception, \
    Except_frame.file, Except_frame.line)
#define RETURN switch (Except_stack = Except_stack->prev,0) default: return
#define TRY do { \
     volatile  int Except_flag; \
    Except_Frame Except_frame; \
    Except_frame.prev = Except_stack; \
    Except_stack = &Except_frame;  \
    Except_flag = setjmp(Except_frame.env); \
     if (Except_flag == Except_entered) {
#define EXCEPT(e) \
         if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
    }  else  if (Except_frame.exception == &(e)) { \
        Except_flag = Except_handled;
#define ELSE \
         if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
    }  else { \
        Except_flag = Except_handled;
#define FINALLY \
         if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
    } { \
         if (Except_flag == Except_entered) \
            Except_flag = Except_finalized;
#define END_TRY \
         if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
        }  if (Except_flag == Except_raised) RERAISE; \
while ( 0)
#undef T
#endif
复制代码

except.c 

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/except.doc,v 1.10 1997/02/21 19:43:55 drh Exp $ ";
#include <stdlib.h>
#include <stdio.h>
#include  " assert.h "
#include  " except.h "
#define T Except_T
#ifdef WIN32
__declspec(thread)
#endif
Except_Frame *Except_stack = NULL;
void Except_raise( const T *e,  const  char *file,
     int line) {
    Except_Frame *p = Except_stack;
    assert(e);
     if (p == NULL) {
        fprintf(stderr,  " Uncaught exception ");
         if (e->reason)
            fprintf(stderr,  "  %s ", e->reason);
         else
            fprintf(stderr,  "  at 0x%p ", e);
         if (file && line >  0)
            fprintf(stderr,  "  raised at %s:%d\n ", file, line);
        fprintf(stderr,  " aborting...\n ");
        fflush(stderr);
        abort();
    }
    p->exception = e;
    p->file = file;
    p->line = line;
    Except_stack = Except_stack->prev;
    longjmp(p->env, Except_raised);
}
复制代码

assert.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/except.doc,v 1.10 1997/02/21 19:43:55 drh Exp $  */
#undef assert
#ifdef NDEBUG
#define assert(e) ((void)0)
#else
#include  " except.h "
extern  void assert( int e);
#define assert(e) ((void)((e)||(RAISE(Assert_Failed),0)))
#endif
复制代码

assert.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/except.doc,v 1.10 1997/02/21 19:43:55 drh Exp $ ";
#include  " assert.h "
const Except_T Assert_Failed = {  " Assertion failed " };
void (assert)( int e) {
    assert(e);
}
复制代码

 

第5章 内存管理

MEM分配接口

mem.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/mem.doc,v 1.12 1997/10/27 23:08:05 drh Exp $  */
#ifndef MEM_INCLUDED
#define MEM_INCLUDED
#include  " except.h "
extern  const Except_T Mem_Failed;
extern  void *Mem_alloc ( long nbytes,
     const  char *file,  int line);
extern  void *Mem_calloc( long count,  long nbytes,
     const  char *file,  int line);
extern  void Mem_free( void *ptr,
     const  char *file,  int line);
extern  void *Mem_resize( void *ptr,  long nbytes,
     const  char *file,  int line);
#define ALLOC(nbytes) \
    Mem_alloc((nbytes), __FILE__, __LINE__)
#define CALLOC(count, nbytes) \
    Mem_calloc((count), (nbytes), __FILE__, __LINE__)
#define  NEW(p) ((p) = ALLOC((long)sizeof *(p)))
#define NEW0(p) ((p) = CALLOC(1, (long)sizeof *(p)))
#define FREE(ptr) ((void)(Mem_free((ptr), \
    __FILE__, __LINE__), (ptr) =  0))
#define RESIZE(ptr, nbytes)     ((ptr) = Mem_resize((ptr), \
    (nbytes), __FILE__, __LINE__))
#endif
复制代码

 

 

mem.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/mem.doc,v 1.12 1997/10/27 23:08:05 drh Exp $ ";
#include <stdlib.h>
#include <stddef.h>
#include  " assert.h "
#include  " except.h "
#include  " mem.h "
const Except_T Mem_Failed = {  " Allocation Failed " };
void *Mem_alloc( long nbytes,  const  char *file,  int line){
     void *ptr;
    assert(nbytes >  0);
    ptr = malloc(nbytes);
     if (ptr == NULL)
        {
             if (file == NULL)
                RAISE(Mem_Failed);
             else
                Except_raise(&Mem_Failed, file, line);
        }
     return ptr;
}
void *Mem_calloc( long count,  long nbytes,
     const  char *file,  int line) {
     void *ptr;
    assert(count >  0);
    assert(nbytes >  0);
    ptr = calloc(count, nbytes);
     if (ptr == NULL)
        {
             if (file == NULL)
                RAISE(Mem_Failed);
             else
                Except_raise(&Mem_Failed, file, line);
        }
     return ptr;
}
void Mem_free( void *ptr,  const  char *file,  int line) {
     if (ptr)
        free(ptr);
}
void *Mem_resize( void *ptr,  long nbytes,
     const  char *file,  int line) {
    assert(ptr);
    assert(nbytes >  0);
    ptr = realloc(ptr, nbytes);
     if (ptr == NULL)
        {
             if (file == NULL)
                RAISE(Mem_Failed);
             else
                Except_raise(&Mem_Failed, file, line);
        }
     return ptr;
}
复制代码

 

第6章 进一步内存管理

arena.h

View Code

 

arena.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/arena.doc,v 1.10 1997/02/21 19:45:19 drh Exp $ ";
#include <stdlib.h>
#include < string.h>
#include  " assert.h "
#include  " except.h "
#include  " arena.h "
#define T Arena_T
const Except_T Arena_NewFailed =
    {  " Arena Creation Failed " };
const Except_T Arena_Failed    =
    {  " Arena Allocation Failed " };
#define THRESHOLD 10
struct T {
    T prev;
     char *avail;
     char *limit;
};
union align {
#ifdef MAXALIGN
     char pad[MAXALIGN];
#else
     int i;
     long l;
     long *lp;
     void *p;
     void (*fp)( void);
     float f;
     double d;
     long  double ld;
#endif
};
union header {
     struct T b;
    union align a;
};
static T freechunks;
static  int nfree;
T Arena_new( void) {
    T arena = malloc( sizeof (*arena));
     if (arena == NULL)
        RAISE(Arena_NewFailed);
    arena->prev = NULL;
    arena->limit = arena->avail = NULL;
     return arena;
}
void Arena_dispose(T *ap) {
    assert(ap && *ap);
    Arena_free(*ap);
    free(*ap);
    *ap = NULL;
}
void *Arena_alloc(T arena,  long nbytes,
     const  char *file,  int line) {
    assert(arena);
    assert(nbytes >  0);
    nbytes = ((nbytes +  sizeof (union align) -  1)/
        ( sizeof (union align)))*( sizeof (union align));
     while (nbytes > arena->limit - arena->avail) {
        T ptr;
         char *limit;
         if ((ptr = freechunks) != NULL) {
            freechunks = freechunks->prev;
            nfree--;
            limit = ptr->limit;
        }  else {
             long m =  sizeof (union header) + nbytes +  10* 1024;
            ptr = malloc(m);
             if (ptr == NULL)
                {
                     if (file == NULL)
                        RAISE(Arena_Failed);
                     else
                        Except_raise(&Arena_Failed, file, line);
                }
            limit = ( char *)ptr + m;
        }
        *ptr = *arena;
        arena->avail = ( char *)((union header *)ptr +  1);
        arena->limit = limit;
        arena->prev  = ptr;
    }
    arena->avail += nbytes;
     return arena->avail - nbytes;
}
void *Arena_calloc(T arena,  long count,  long nbytes,
     const  char *file,  int line) {
     void *ptr;
    assert(count >  0);
    ptr = Arena_alloc(arena, count*nbytes, file, line);
    memset(ptr,  ' \0 ', count*nbytes);
     return ptr;
}
void Arena_free(T arena) {
    assert(arena);
     while (arena->prev) {
         struct T tmp = *arena->prev;
         if (nfree < THRESHOLD) {
            arena->prev->prev = freechunks;
            freechunks = arena->prev;
            nfree++;
            freechunks->limit = arena->limit;
        }  else
            free(arena->prev);
        *arena = tmp;
    }
    assert(arena->limit == NULL);
    assert(arena->avail == NULL);
}
复制代码

 

第7章 链表

 

list.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/list.doc,v 1.11 1997/02/21 19:46:01 drh Exp $  */
#ifndef LIST_INCLUDED
#define LIST_INCLUDED
#define T List_T
typedef  struct T *T;
struct T {
    T rest;
     void *first;
};
extern T      List_append (T list, T tail);
extern T      List_copy   (T list);
extern T      List_list   ( void *x, ...);
extern T      List_pop    (T list,  void **x);
extern T      List_push   (T list,  void *x);
extern T      List_reverse(T list);
extern  int    List_length (T list);
extern  void   List_free   (T *list);
extern  void   List_map    (T list,
     void apply( void **x,  void *cl),  void *cl);
extern  void **List_toArray(T list,  void *end);
#undef T
#endif
复制代码

 

list.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/list.doc,v 1.11 1997/02/21 19:46:01 drh Exp $ ";
#include <stdarg.h>
#include <stddef.h>
#include  " assert.h "
#include  " mem.h "
#include  " list.h "
#define T List_T
T List_push(T list,  void *x) {
    T p;
    NEW(p);
    p->first = x;
    p->rest  = list;
     return p;
}
T List_list( void *x, ...) {
    va_list ap;
    T list, *p = &list;
    va_start(ap, x);
     for ( ; x; x = va_arg(ap,  void *)) {
        NEW(*p);
        (*p)->first = x;
        p = &(*p)->rest;
    }
    *p = NULL;
    va_end(ap);
     return list;
}
T List_append(T list, T tail) {
    T *p = &list;
     while (*p)
        p = &(*p)->rest;
    *p = tail;
     return list;
}
T List_copy(T list) {
    T head, *p = &head;
     for ( ; list; list = list->rest) {
        NEW(*p);
        (*p)->first = list->first;
        p = &(*p)->rest;
    }
    *p = NULL;
     return head;
}
T List_pop(T list,  void **x) {
     if (list) {
        T head = list->rest;
         if (x)
            *x = list->first;
        FREE(list);
         return head;
    }  else
         return list;
}
T List_reverse(T list) {
    T head = NULL, next;
     for ( ; list; list = next) {
        next = list->rest;
        list->rest = head;
        head = list;
    }
     return head;
}
int List_length(T list) {
     int n;
     for (n =  0; list; list = list->rest)
        n++;
     return n;
}
void List_free(T *list) {
    T next;
    assert(list);
     for ( ; *list; *list = next) {
        next = (*list)->rest;
        FREE(*list);
    }
}
void List_map(T list,
     void apply( void **x,  void *cl),  void *cl) {
    assert(apply);
     for ( ; list; list = list->rest)
        apply(&list->first, cl);
}
void **List_toArray(T list,  void *end) {
     int i, n = List_length(list);
     void **array = ALLOC((n +  1)* sizeof (*array));
     for (i =  0; i < n; i++) {
        array[i] = list->first;
        list = list->rest;
    }
    array[i] = end;
     return array;
}
复制代码

 

第8章 表格

table.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $  */
#ifndef TABLE_INCLUDED
#define TABLE_INCLUDED
#define T Table_T
typedef  struct T *T;
extern T    Table_new ( int hint,
     int cmp( const  void *x,  const  void *y),
    unsigned hash( const  void *key));
extern  void Table_free(T *table);
extern  int   Table_length(T table);
extern  void *Table_put   (T table,  const  void *key,
     void *value);
extern  void *Table_get   (T table,  const  void *key);
extern  void *Table_remove(T table,  const  void *key);
extern  void   Table_map    (T table,
     void apply( const  void *key,  void **value,  void *cl),
     void *cl);
extern  void **Table_toArray(T table,  void *end);
#undef T
#endif
复制代码

 

 

table.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $ ";
#include <limits.h>
#include <stddef.h>
#include  " mem.h "
#include  " assert.h "
#include  " table.h "
#define T Table_T
struct T {
     int size;
     int (*cmp)( const  void *x,  const  void *y);
    unsigned (*hash)( const  void *key);
     int length;
    unsigned timestamp;
     struct binding {
         struct binding *link;
         const  void *key;
         void *value;
    } **buckets;
};
static  int cmpatom( const  void *x,  const  void *y) {
     return x != y;
}
static unsigned hashatom( const  void *key) {
     return (unsigned  long)key>> 2;
}
T Table_new( int hint,
     int cmp( const  void *x,  const  void *y),
    unsigned hash( const  void *key)) {
    T table;
     int i;
     static  int primes[] = {  509509102120534093,
         8191163813277165521, INT_MAX };
    assert(hint >=  0);
     for (i =  1; primes[i] < hint; i++)
        ;
    table = ALLOC( sizeof (*table) +
        primes[i- 1]* sizeof (table->buckets[ 0]));
    table->size = primes[i- 1];
    table->cmp  = cmp  ?  cmp : cmpatom;
    table->hash = hash ? hash : hashatom;
    table->buckets = ( struct binding **)(table +  1);
     for (i =  0; i < table->size; i++)
        table->buckets[i] = NULL;
    table->length =  0;
    table->timestamp =  0;
     return table;
}
void *Table_get(T table,  const  void *key) {
     int i;
     struct binding *p;
    assert(table);
    assert(key);
    i = (*table->hash)(key)%table->size;
     for (p = table->buckets[i]; p; p = p->link)
         if ((*table->cmp)(key, p->key) ==  0)
             break;
     return p ? p->value : NULL;
}
void *Table_put(T table,  const  void *key,  void *value) {
     int i;
     struct binding *p;
     void *prev;
    assert(table);
    assert(key);
    i = (*table->hash)(key)%table->size;
     for (p = table->buckets[i]; p; p = p->link)
         if ((*table->cmp)(key, p->key) ==  0)
             break;
     if (p == NULL) {
        NEW(p);
        p->key = key;
        p->link = table->buckets[i];
        table->buckets[i] = p;
        table->length++;
        prev = NULL;
    }  else
        prev = p->value;
    p->value = value;
    table->timestamp++;
     return prev;
}
int Table_length(T table) {
    assert(table);
     return table->length;
}
void Table_map(T table,
     void apply( const  void *key,  void **value,  void *cl),
     void *cl) {
     int i;
    unsigned stamp;
     struct binding *p;
    assert(table);
    assert(apply);
    stamp = table->timestamp;
     for (i =  0; i < table->size; i++)
         for (p = table->buckets[i]; p; p = p->link) {
            apply(p->key, &p->value, cl);
            assert(table->timestamp == stamp);
        }
}
void *Table_remove(T table,  const  void *key) {
     int i;
     struct binding **pp;
    assert(table);
    assert(key);
    table->timestamp++;
    i = (*table->hash)(key)%table->size;
     for (pp = &table->buckets[i]; *pp; pp = &(*pp)->link)
         if ((*table->cmp)(key, (*pp)->key) ==  0) {
             struct binding *p = *pp;
             void *value = p->value;
            *pp = p->link;
            FREE(p);
            table->length--;
             return value;
        }
     return NULL;
}
void **Table_toArray(T table,  void *end) {
     int i, j =  0;
     void **array;
     struct binding *p;
    assert(table);
    array = ALLOC(( 2*table->length +  1)* sizeof (*array));
     for (i =  0; i < table->size; i++)
         for (p = table->buckets[i]; p; p = p->link) {
            array[j++] = ( void *)p->key;
            array[j++] = p->value;
        }
    array[j] = end;
     return array;
}
void Table_free(T *table) {
    assert(table && *table);
     if ((*table)->length >  0) {
         int i;
         struct binding *p, *q;
         for (i =  0; i < (*table)->size; i++)
             for (p = (*table)->buckets[i]; p; p = q) {
                q = p->link;
                FREE(p);
            }
    }
    FREE(*table);
}
复制代码

 

 

wf程序来统计单词的频率

getword.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $ ";
#include <ctype.h>
#include < string.h>
#include <stdio.h>
#include  " assert.h "
#include  " getword.h "
int getword(FILE *fp,  char *buf,  int size,
     int first( int c),  int rest( int c)) {
     int i =  0, c;
    assert(fp && buf && size >  1 && first && rest);
    c = getc(fp);
     for ( ; c != EOF; c = getc(fp))
         if (first(c)) {
            {
                 if (i < size -  1)
                    buf[i++] = c;
            }
            c = getc(fp);
             break;
        }
     for ( ; c != EOF && rest(c); c = getc(fp))
        {
             if (i < size -  1)
                buf[i++] = c;
        }
     if (i < size)
        buf[i] =  ' \0 ';
     else
        buf[size- 1] =  ' \0 ';
     if (c != EOF)
        ungetc(c, fp);
     return i >  0;
}
复制代码

 

wf.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $ ";
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include  " atom.h "
#include  " table.h "
#include  " mem.h "
#include  " getword.h "
#include < string.h>
void wf( char *, FILE *);
int first( int c);
int rest ( int c);
int compare( const  void *x,  const  void *y);
void vfree( const  void *,  void **,  void *);
int main( int argc,  char *argv[]) {
     int i;
     for (i =  1; i < argc; i++) {
        FILE *fp = fopen(argv[i],  " r ");
         if (fp == NULL) {
            fprintf(stderr,  " %s: can't open '%s' (%s)\n ",
                argv[ 0], argv[i], strerror(errno));
             return EXIT_FAILURE;
        }  else {
            wf(argv[i], fp);
            fclose(fp);
        }
    }
     if (argc ==  1) wf(NULL, stdin);
     return EXIT_SUCCESS;
}
void wf( char *name, FILE *fp) {
    Table_T table = Table_new( 0, NULL, NULL);
     char buf[ 128];
     while (getword(fp, buf,  sizeof buf, first, rest)) {
         const  char *word;
         int i, *count;
         for (i =  0; buf[i] !=  ' \0 '; i++)
            buf[i] = tolower(buf[i]);
        word = Atom_string(buf);
        count = Table_get(table, word);
         if (count)
            (*count)++;
         else {
            NEW(count);
            *count =  1;
            Table_put(table, word, count);
        }
    }
     if (name)
        printf( " %s:\n ", name);
    {  int i;
       void **array = Table_toArray(table, NULL);
      qsort(array, Table_length(table),  2* sizeof (*array),
          compare);
       for (i =  0; array[i]; i +=  2)
          printf( " %d\t%s\n ", *( int *)array[i+ 1],
              ( char *)array[i]);
      FREE(array); }
    Table_map(table, vfree, NULL);
    Table_free(&table);
}
int first( int c) {
     return isalpha(c);
}
int rest( int c) {
     return isalpha(c) || c ==  ' _ ';
}
int compare( const  void *x,  const  void *y) {
     return strcmp(*( char **)x, *( char **)y);
}
void vfree( const  void *key,  void **count,  void *cl) {
    FREE(*count);
}
复制代码

 

第9章 集合

集合的实现

set.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/set.doc,v 1.11 1996/06/26 23:02:01 drh Exp $  */
#ifndef SET_INCLUDED
#define SET_INCLUDED
#define T Set_T
typedef  struct T *T;
extern T    Set_new ( int hint,
     int cmp( const  void *x,  const  void *y),
    unsigned hash( const  void *x));
extern  void Set_free(T * set);
extern  int   Set_length(T  set);
extern  int   Set_member(T  setconst  void *member);
extern  void  Set_put   (T  setconst  void *member);
extern  void *Set_remove(T  setconst  void *member);
extern  void   Set_map    (T  set,
     void apply( const  void *member,  void *cl),  void *cl);
extern  void **Set_toArray(T  setvoid *end);
extern T Set_union(T s, T t);
extern T Set_inter(T s, T t);
extern T Set_minus(T s, T t);
extern T Set_diff (T s, T t);
#undef T
#endif
复制代码

 

 

set.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/set.doc,v 1.11 1996/06/26 23:02:01 drh Exp $ ";
#include <limits.h>
#include <stddef.h>
#include  " mem.h "
#include  " assert.h "
#include  " arith.h "
#include  " set.h "
#define T Set_T
struct T {
     int length;
    unsigned timestamp;
     int (*cmp)( const  void *x,  const  void *y);
    unsigned (*hash)( const  void *x);
     int size;
     struct member {
         struct member *link;
         const  void *member;
    } **buckets;
};
static  int cmpatom( const  void *x,  const  void *y) {
     return x != y;
}
static unsigned hashatom( const  void *x) {
     return (unsigned  long)x>> 2;
}
static T copy(T t,  int hint) {
    T  set;
    assert(t);
     set = Set_new(hint, t->cmp, t->hash);
    {  int i;
       struct member *q;
       for (i =  0; i < t->size; i++)
           for (q = t->buckets[i]; q; q = q->link)
        {
             struct member *p;
             const  void *member = q->member;
             int i = (* set->hash)(member)% set->size;
            NEW(p);
            p->member = member;
            p->link =  set->buckets[i];
             set->buckets[i] = p;
             set->length++;
        }
    }
     return  set;
}
T Set_new( int hint,
     int cmp( const  void *x,  const  void *y),
    unsigned hash( const  void *x)) {
    T  set;
     int i;
     static  int primes[] = {  509509102120534093,
         8191163813277165521, INT_MAX };
    assert(hint >=  0);
     for (i =  1; primes[i] < hint; i++)
        ;
     set = ALLOC( sizeof (* set) +
        primes[i- 1]* sizeof ( set->buckets[ 0]));
     set->size = primes[i- 1];
     set->cmp  = cmp  ?  cmp : cmpatom;
     set->hash = hash ? hash : hashatom;
     set->buckets = ( struct member **)( set +  1);
     for (i =  0; i <  set->size; i++)
         set->buckets[i] = NULL;
     set->length =  0;
     set->timestamp =  0;
     return  set;
}
int Set_member(T  setconst  void *member) {
     int i;
     struct member *p;
    assert( set);
    assert(member);
    i = (* set->hash)(member)% set->size;
     for (p =  set->buckets[i]; p; p = p->link)
         if ((* set->cmp)(member, p->member) ==  0)
             break;
     return p != NULL;
}
void Set_put(T  setconst  void *member) {
     int i;
     struct member *p;
    assert( set);
    assert(member);
    i = (* set->hash)(member)% set->size;
     for (p =  set->buckets[i]; p; p = p->link)
         if ((* set->cmp)(member, p->member) ==  0)
             break;
     if (p == NULL) {
        NEW(p);
        p->member = member;
        p->link =  set->buckets[i];
         set->buckets[i] = p;
         set->length++;
    }  else
        p->member = member;
     set->timestamp++;
}
void *Set_remove(T  setconst  void *member) {
     int i;
     struct member **pp;
    assert( set);
    assert(member);
     set->timestamp++;
    i = (* set->hash)(member)% set->size;
     for (pp = & set->buckets[i]; *pp; pp = &(*pp)->link)
         if ((* set->cmp)(member, (*pp)->member) ==  0) {
             struct member *p = *pp;
            *pp = p->link;
            member = p->member;
            FREE(p);
             set->length--;
             return ( void *)member;
        }
     return NULL;
}
int Set_length(T  set) {
    assert( set);
     return  set->length;
}
void Set_free(T * set) {
    assert( set && * set);
     if ((* set)->length >  0) {
         int i;
         struct member *p, *q;
         for (i =  0; i < (* set)->size; i++)
             for (p = (* set)->buckets[i]; p; p = q) {
                q = p->link;
                FREE(p);
            }
    }
    FREE(* set);
}
void Set_map(T  set,
     void apply( const  void *member,  void *cl),  void *cl) {
     int i;
    unsigned stamp;
     struct member *p;
    assert( set);
    assert(apply);
    stamp =  set->timestamp;
     for (i =  0; i <  set->size; i++)
         for (p =  set->buckets[i]; p; p = p->link) {
            apply(p->member, cl);
            assert( set->timestamp == stamp);
        }
}
void **Set_toArray(T  setvoid *end) {
     int i, j =  0;
     void **array;
     struct member *p;
    assert( set);
    array = ALLOC(( set->length +  1)* sizeof (*array));
     for (i =  0; i <  set->size; i++)
         for (p =  set->buckets[i]; p; p = p->link)
            array[j++] = ( void *)p->member;
    array[j] = end;
     return array;
}
T Set_union(T s, T t) {
     if (s == NULL) {
        assert(t);
         return copy(t, t->size);
    }  else  if (t == NULL)
         return copy(s, s->size);
     else {
        T  set = copy(s, Arith_max(s->size, t->size));
        assert(s->cmp == t->cmp && s->hash == t->hash);
        {  int i;
           struct member *q;
           for (i =  0; i < t->size; i++)
               for (q = t->buckets[i]; q; q = q->link)
            Set_put( set, q->member);
        }
         return  set;
    }
}
T Set_inter(T s, T t) {
     if (s == NULL) {
        assert(t);
         return Set_new(t->size, t->cmp, t->hash);
    }  else  if (t == NULL)
         return Set_new(s->size, s->cmp, s->hash);
     else  if (s->length < t->length)
         return Set_inter(t, s);
     else {
        T  set = Set_new(Arith_min(s->size, t->size),
            s->cmp, s->hash);
        assert(s->cmp == t->cmp && s->hash == t->hash);
        {  int i;
           struct member *q;
           for (i =  0; i < t->size; i++)
               for (q = t->buckets[i]; q; q = q->link)
             if (Set_member(s, q->member))
                {
                     struct member *p;
                     const  void *member = q->member;
                     int i = (* set->hash)(member)% set->size;
                    NEW(p);
                    p->member = member;
                    p->link =  set->buckets[i];
                     set->buckets[i] = p;
                     set->length++;
                }
        }
         return  set;
    }
}
T Set_minus(T t, T s) {
     if (t == NULL){
        assert(s);
         return Set_new(s->size, s->cmp, s->hash);
    }  else  if (s == NULL)
         return copy(t, t->size);
     else {
        T  set = Set_new(Arith_min(s->size, t->size),
            s->cmp, s->hash);
        assert(s->cmp == t->cmp && s->hash == t->hash);
        {  int i;
           struct member *q;
           for (i =  0; i < t->size; i++)
               for (q = t->buckets[i]; q; q = q->link)
             if (!Set_member(s, q->member))
                {
                     struct member *p;
                     const  void *member = q->member;
                     int i = (* set->hash)(member)% set->size;
                    NEW(p);
                    p->member = member;
                    p->link =  set->buckets[i];
                     set->buckets[i] = p;
                     set->length++;
                }
        }
         return  set;
    }
}
T Set_diff(T s, T t) {
     if (s == NULL) {
        assert(t);
         return copy(t, t->size);
    }  else  if (t == NULL)
         return copy(s, s->size);
     else {
        T  set = Set_new(Arith_min(s->size, t->size),
            s->cmp, s->hash);
        assert(s->cmp == t->cmp && s->hash == t->hash);
        {  int i;
           struct member *q;
           for (i =  0; i < t->size; i++)
               for (q = t->buckets[i]; q; q = q->link)
             if (!Set_member(s, q->member))
                {
                     struct member *p;
                     const  void *member = q->member;
                     int i = (* set->hash)(member)% set->size;
                    NEW(p);
                    p->member = member;
                    p->link =  set->buckets[i];
                     set->buckets[i] = p;
                     set->length++;
                }
        }
        { T u = t; t = s; s = u; }
        {  int i;
           struct member *q;
           for (i =  0; i < t->size; i++)
               for (q = t->buckets[i]; q; q = q->link)
             if (!Set_member(s, q->member))
                {
                     struct member *p;
                     const  void *member = q->member;
                     int i = (* set->hash)(member)% set->size;
                    NEW(p);
                    p->member = member;
                    p->link =  set->buckets[i];
                     set->buckets[i] = p;
                     set->length++;
                }
        }
         return  set;
    }
}
复制代码

 

实例:交叉引用列表

xref.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/set.doc,v 1.11 1996/06/26 23:02:01 drh Exp $ ";
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include  " table.h "
#include < string.h>
#include  " atom.h "
#include  " set.h "
#include  " mem.h "
#include  " getword.h "
#include <ctype.h>
int compare( const  void *x,  const  void *y);
void print(Table_T);
int cmpint( const  void *x,  const  void *y);
void xref( const  char *, FILE *, Table_T);
int first( int c);
int rest ( int c);
int      intcmp ( const  void *x,  const  void *y);
unsigned inthash( const  void *x);
int linenum;
int main( int argc,  char *argv[]) {
     int i;
    Table_T identifiers = Table_new( 0, NULL, NULL);
     for (i =  1; i < argc; i++) {
        FILE *fp = fopen(argv[i],  " r ");
         if (fp == NULL) {
            fprintf(stderr,  " %s: can't open '%s' (%s)\n ",
                argv[ 0], argv[i], strerror(errno));
             return EXIT_FAILURE;
        }  else {
            xref(argv[i], fp, identifiers);
            fclose(fp);
        }
    }
     if (argc ==  1) xref(NULL, stdin, identifiers);
    {
         int i;
         void **array = Table_toArray(identifiers, NULL);
        qsort(array, Table_length(identifiers),
             2* sizeof (*array), compare);
         for (i =  0; array[i]; i +=  2) {
            printf( " %s ", ( char *)array[i]);
            print(array[i+ 1]);
        }
        FREE(array);
    }
     return EXIT_SUCCESS;
}
int compare( const  void *x,  const  void *y) {
     return strcmp(*( char **)x, *( char **)y);
}
void print(Table_T files) {
     int i;
     void **array = Table_toArray(files, NULL);
    qsort(array, Table_length(files),  2* sizeof (*array),
        compare);
     for (i =  0; array[i]; i +=  2) {
         if (*( char *)array[i] !=  ' \0 ')
            printf( " \t%s: ", ( char *)array[i]);
        {
             int j;
             void **lines = Set_toArray(array[i+ 1], NULL);
            qsort(lines, Set_length(array[i+ 1]),  sizeof (*lines),
                cmpint);
             for (j =  0; lines[j]; j++)
                printf( "  %d ", *( int *)lines[j]);
            FREE(lines);
        }
        printf( " \n ");
    }
    FREE(array);
}
int cmpint( const  void *x,  const  void *y) {
     if (**( int **)x < **( int **)y)
         return - 1;
     else  if (**( int **)x > **( int **)y)
         return + 1;
     else
         return  0;
}
void xref( const  char *name, FILE *fp,
        Table_T identifiers){
     char buf[ 128];
     if (name == NULL)
        name =  "";
    name = Atom_string(name);
    linenum =  1;
     while (getword(fp, buf,  sizeof buf, first, rest)) {
        Set_T  set;
        Table_T files;
         const  char *id = Atom_string(buf);
        files = Table_get(identifiers, id);
         if (files == NULL) {
            files = Table_new( 0, NULL, NULL);
            Table_put(identifiers, id, files);
        }
         set = Table_get(files, name);
         if ( set == NULL) {
             set = Set_new( 0, intcmp, inthash);
            Table_put(files, name,  set);
        }
        {
             int *p = &linenum;
             if (!Set_member( set, p)) {
                NEW(p);
                *p = linenum;
                Set_put( set, p);
            }
        }
    }
}
int first( int c) {
     if (c ==  ' \n ')
        linenum++;
     return isalpha(c) || c ==  ' _ ';
}
int rest( int c) {
     return isalpha(c) || c ==  ' _ ' || isdigit(c);
}
int intcmp( const  void *x,  const  void *y) {
     return cmpint(&x, &y);
}
unsigned inthash( const  void *x) {
     return *( int *)x;
}
复制代码

 

 

第10章 动态数组

array.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/array.doc,v 1.11 1997/10/29 22:05:21 drh Exp $  */
#ifndef ARRAY_INCLUDED
#define ARRAY_INCLUDED
#define T Array_T
typedef  struct T *T;
extern T    Array_new ( int length,  int size);
extern  void Array_free(T *array);
extern  int Array_length(T array);
extern  int Array_size  (T array);
extern  void *Array_get(T array,  int i);
extern  void *Array_put(T array,  int i,  void *elem);
extern  void Array_resize(T array,  int length);
extern T    Array_copy  (T array,  int length);
#undef T
#endif
复制代码

 

array.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/array.doc,v 1.11 1997/10/29 22:05:21 drh Exp $ ";
#include <stdlib.h>
#include < string.h>
#include  " assert.h "
#include  " array.h "
#include  " arrayrep.h "
#include  " mem.h "
#define T Array_T
T Array_new( int length,  int size) {
    T array;
    NEW(array);
     if (length >  0)
        ArrayRep_init(array, length, size,
            CALLOC(length, size));
     else
        ArrayRep_init(array, length, size, NULL);
     return array;
}
void ArrayRep_init(T array,  int length,  int size,
     void *ary) {
    assert(array);
    assert(ary && length> 0 || length== 0 && ary==NULL);
    assert(size >  0);
    array->length = length;
    array->size   = size;
     if (length >  0)
        array->array = ary;
     else
        array->array = NULL;
}
void Array_free(T *array) {
    assert(array && *array);
    FREE((*array)->array);
    FREE(*array);
}
void *Array_get(T array,  int i) {
    assert(array);
    assert(i >=  0 && i < array->length);
     return array->array + i*array->size;
}
void *Array_put(T array,  int i,  void *elem) {
    assert(array);
    assert(i >=  0 && i < array->length);
    assert(elem);
    memcpy(array->array + i*array->size, elem,
        array->size);
     return elem;
}
int Array_length(T array) {
    assert(array);
     return array->length;
}
int Array_size(T array) {
    assert(array);
     return array->size;
}
void Array_resize(T array,  int length) {
    assert(array);
    assert(length >=  0);
     if (length ==  0)
        FREE(array->array);
     else  if (array->length ==  0)
        array->array = ALLOC(length*array->size);
     else
        RESIZE(array->array, length*array->size);
    array->length = length;
}
T Array_copy(T array,  int length) {
    T copy;
    assert(array);
    assert(length >=  0);
    copy = Array_new(length, array->size);
     if (copy->length >= array->length
    && array->length >  0)
        memcpy(copy->array, array->array, array->length);
     else  if (array->length > copy->length
    && copy->length >  0)
        memcpy(copy->array, array->array, copy->length);
     return copy;
}
复制代码

 

第11章 序列

seq.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/seq.doc,v 1.11 1997/02/21 19:48:24 drh Exp $  */
#ifndef SEQ_INCLUDED
#define SEQ_INCLUDED
#define T Seq_T
typedef  struct T *T;
extern T Seq_new( int hint);
extern T Seq_seq( void *x, ...);
extern  void Seq_free(T *seq);
extern  int Seq_length(T seq);
extern  void *Seq_get(T seq,  int i);
extern  void *Seq_put(T seq,  int i,  void *x);
extern  void *Seq_addlo(T seq,  void *x);
extern  void *Seq_addhi(T seq,  void *x);
extern  void *Seq_remlo(T seq);
extern  void *Seq_remhi(T seq);
#undef T
#endif
复制代码

 

seq.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/seq.doc,v 1.11 1997/02/21 19:48:24 drh Exp $ ";
#include <stdlib.h>
#include <stdarg.h>
#include < string.h>
#include  " assert.h "
#include  " seq.h "
#include  " array.h "
#include  " arrayrep.h "
#include  " mem.h "
#define T Seq_T
struct T {
     struct Array_T array;
     int length;
     int head;
};
static  void expand(T seq) {
     int n = seq->array.length;
    Array_resize(&seq->array,  2*n);
     if (seq->head >  0)
        {
             void **old = &(( void **)seq->array.array)[seq->head];
            memcpy(old+n, old, (n - seq->head)* sizeof ( void *));
            seq->head += n;
        }
}
T Seq_new( int hint) {
    T seq;
    assert(hint >=  0);
    NEW0(seq);
     if (hint ==  0)
        hint =  16;
    ArrayRep_init(&seq->array, hint,  sizeof ( void *),
        ALLOC(hint* sizeof ( void *)));
     return seq;
}
T Seq_seq( void *x, ...) {
    va_list ap;
    T seq = Seq_new( 0);
    va_start(ap, x);
     for ( ; x; x = va_arg(ap,  void *))
        Seq_addhi(seq, x);
    va_end(ap);
     return seq;
}
void Seq_free(T *seq) {
    assert(seq && *seq);
    assert(( void *)*seq == ( void *)&(*seq)->array);
    Array_free((Array_T *)seq);
}
int Seq_length(T seq) {
    assert(seq);
     return seq->length;
}
void *Seq_get(T seq,  int i) {
    assert(seq);
    assert(i >=  0 && i < seq->length);
     return (( void **)seq->array.array)[
               (seq->head + i)%seq->array.length];
}
void *Seq_put(T seq,  int i,  void *x) {
     void *prev;
    assert(seq);
    assert(i >=  0 && i < seq->length);
    prev = (( void **)seq->array.array)[
               (seq->head + i)%seq->array.length];
    (( void **)seq->array.array)[
        (seq->head + i)%seq->array.length] = x;
     return prev;
}
void *Seq_remhi(T seq) {
     int i;
    assert(seq);
    assert(seq->length >  0);
    i = --seq->length;
     return (( void **)seq->array.array)[
               (seq->head + i)%seq->array.length];
}
void *Seq_remlo(T seq) {
     int i =  0;
     void *x;
    assert(seq);
    assert(seq->length >  0);
    x = (( void **)seq->array.array)[
            (seq->head + i)%seq->array.length];
    seq->head = (seq->head +  1)%seq->array.length;
    --seq->length;
     return x;
}
void *Seq_addhi(T seq,  void *x) {
     int i;
    assert(seq);
     if (seq->length == seq->array.length)
        expand(seq);
    i = seq->length++;
     return (( void **)seq->array.array)[
               (seq->head + i)%seq->array.length] = x;
}
void *Seq_addlo(T seq,  void *x) {
     int i =  0;
    assert(seq);
     if (seq->length == seq->array.length)
        expand(seq);
     if (--seq->head <  0)
        seq->head = seq->array.length -  1;
    seq->length++;
     return (( void **)seq->array.array)[
               (seq->head + i)%seq->array.length] = x;
}
复制代码

 

第12章 环

ring.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/ring.doc,v 1.12 1997/02/21 19:49:24 drh Exp $  */
#ifndef RING_INCLUDED
#define RING_INCLUDED
#define T Ring_T
typedef  struct T *T;
extern T Ring_new ( void);
extern T Ring_ring( void *x, ...);
extern  void Ring_free  (T *ring);
extern  int  Ring_length(T  ring);
extern  void *Ring_get(T ring,  int i);
extern  void *Ring_put(T ring,  int i,  void *x);
extern  void *Ring_add(T ring,  int pos,  void *x);
extern  void *Ring_addlo(T ring,  void *x);
extern  void *Ring_addhi(T ring,  void *x);
extern  void *Ring_remove(T ring,  int i);
extern  void *Ring_remlo(T ring);
extern  void *Ring_remhi(T ring);
extern  void Ring_rotate(T ring,  int n);
#undef T
#endif
复制代码

 

ring.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/ring.doc,v 1.12 1997/02/21 19:49:24 drh Exp $ ";
#include <stdlib.h>
#include <stdarg.h>
#include < string.h>
#include  " assert.h "
#include  " ring.h "
#include  " mem.h "
#define T Ring_T
struct T {
     struct node {
         struct node *llink, *rlink;
         void *value;
    } *head;
     int length;
};
T Ring_new( void) {
    T ring;
    NEW0(ring);
    ring->head = NULL;
     return ring;
}
T Ring_ring( void *x, ...) {
    va_list ap;
    T ring = Ring_new();
    va_start(ap, x);
     for ( ; x; x = va_arg(ap,  void *))
        Ring_addhi(ring, x);
    va_end(ap);
     return ring;
}
void Ring_free(T *ring) {
     struct node *p, *q;
    assert(ring && *ring);
     if ((p = (*ring)->head) != NULL) {
         int n = (*ring)->length;
         for ( ; n-- >  0; p = q) {
            q = p->rlink;
            FREE(p);
        }
    }
    FREE(*ring);
}
int Ring_length(T ring) {
    assert(ring);
     return ring->length;
}
void *Ring_get(T ring,  int i) {
     struct node *q;
    assert(ring);
    assert(i >=  0 && i < ring->length);
    {
         int n;
        q = ring->head;
         if (i <= ring->length/ 2)
             for (n = i; n-- >  0; )
                q = q->rlink;
         else
             for (n = ring->length - i; n-- >  0; )
                q = q->llink;
    }
     return q->value;
}
void *Ring_put(T ring,  int i,  void *x) {
     struct node *q;
     void *prev;
    assert(ring);
    assert(i >=  0 && i < ring->length);
    {
         int n;
        q = ring->head;
         if (i <= ring->length/ 2)
             for (n = i; n-- >  0; )
                q = q->rlink;
         else
             for (n = ring->length - i; n-- >  0; )
                q = q->llink;
    }
    prev = q->value;
    q->value = x;
     return prev;
}
void *Ring_addhi(T ring,  void *x) {
     struct node *p, *q;
    assert(ring);
    NEW(p);
     if ((q = ring->head) != NULL)
        {
            p->llink = q->llink;
            q->llink->rlink = p;
            p->rlink = q;
            q->llink = p;
        }
     else
        ring->head = p->llink = p->rlink = p;
    ring->length++;
     return p->value = x;
}
void *Ring_addlo(T ring,  void *x) {
    assert(ring);
    Ring_addhi(ring, x);
    ring->head = ring->head->llink;
     return x;
}
void *Ring_add(T ring,  int pos,  void *x) {
    assert(ring);
    assert(pos >= -ring->length && pos<=ring->length+ 1);
     if (pos ==  1 || pos == -ring->length)
         return Ring_addlo(ring, x);
     else  if (pos ==  0 || pos == ring->length +  1)
         return Ring_addhi(ring, x);
     else {
         struct node *p, *q;
         int i = pos <  0 ? pos + ring->length : pos -  1;
        {
             int n;
            q = ring->head;
             if (i <= ring->length/ 2)
                 for (n = i; n-- >  0; )
                    q = q->rlink;
             else
                 for (n = ring->length - i; n-- >  0; )
                    q = q->llink;
        }
        NEW(p);
        {
            p->llink = q->llink;
            q->llink->rlink = p;
            p->rlink = q;
            q->llink = p;
        }
        ring->length++;
         return p->value = x;
    }
}
void *Ring_remove(T ring,  int i) {
     void *x;
     struct node *q;
    assert(ring);
    assert(ring->length >  0);
    assert(i >=  0 && i < ring->length);
    {
         int n;
        q = ring->head;
         if (i <= ring->length/ 2)
             for (n = i; n-- >  0; )
                q = q->rlink;
         else
             for (n = ring->length - i; n-- >  0; )
                q = q->llink;
    }
     if (i ==  0)
        ring->head = ring->head->rlink;
    x = q->value;
    q->llink->rlink = q->rlink;
    q->rlink->llink = q->llink;
    FREE(q);
     if (--ring->length ==  0)
        ring->head = NULL;
     return x;
}
void *Ring_remhi(T ring) {
     void *x;
     struct node *q;
    assert(ring);
    assert(ring->length >  0);
    q = ring->head->llink;
    x = q->value;
    q->llink->rlink = q->rlink;
    q->rlink->llink = q->llink;
    FREE(q);
     if (--ring->length ==  0)
        ring->head = NULL;
     return x;
}
void *Ring_remlo(T ring) {
    assert(ring);
    assert(ring->length >  0);
    ring->head = ring->head->rlink;
     return Ring_remhi(ring);
}
void Ring_rotate(T ring,  int n) {
     struct node *q;
     int i;
    assert(ring);
    assert(n >= -ring->length && n <= ring->length);
     if (n >=  0)
        i = n%ring->length;
     else
        i = n + ring->length;
    {
         int n;
        q = ring->head;
         if (i <= ring->length/ 2)
             for (n = i; n-- >  0; )
                q = q->rlink;
         else
             for (n = ring->length - i; n-- >  0; )
                q = q->llink;
    }
    ring->head = q;
}
复制代码

 

第13章 位向量

bit.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/bit.doc,v 1.15 1997/02/21 19:49:56 drh Exp $  */
#ifndef BIT_INCLUDED
#define BIT_INCLUDED
#define T Bit_T
typedef  struct T *T;
extern T   Bit_new   ( int length);
extern  int Bit_length(T  set);
extern  int Bit_count (T  set);
extern  void Bit_free(T * set);
extern  int Bit_get(T  setint n);
extern  int Bit_put(T  setint n,  int bit);
extern  void Bit_clear(T  setint lo,  int hi);
extern  void Bit_set  (T  setint lo,  int hi);
extern  void Bit_not  (T  setint lo,  int hi);
extern  int Bit_lt (T s, T t);
extern  int Bit_eq (T s, T t);
extern  int Bit_leq(T s, T t);
extern  void Bit_map(T  set,
      void apply( int n,  int bit,  void *cl),  void *cl);
extern T Bit_union(T s, T t);
extern T Bit_inter(T s, T t);
extern T Bit_minus(T s, T t);
extern T Bit_diff (T s, T t);
#undef T
#endif
复制代码

 

bit.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/bit.doc,v 1.15 1997/02/21 19:49:56 drh Exp $ ";
#include <stdarg.h>
#include < string.h>
#include  " assert.h "
#include  " bit.h "
#include  " mem.h "
#define T Bit_T
struct T {
     int length;
    unsigned  char *bytes;
    unsigned  long *words;
};
#define BPW (8*sizeof (unsigned long))
#define nwords(len) ((((len) + BPW - 1)&(~(BPW-1)))/BPW)
#define nbytes(len) ((((len) + 8 - 1)&(~(8-1)))/8)
#define setop(sequal, snull, tnull, op) \
     if (s == t) { assert(s);  return sequal; } \
     else  if (s == NULL) { assert(t);  return snull; } \
     else  if (t == NULL)  return tnull; \
     else { \
         int i; T  set; \
        assert(s->length == t->length); \
         set = Bit_new(s->length); \
         for (i = nwords(s->length); --i >=  0; ) \
             set->words[i] = s->words[i] op t->words[i]; \
         return  set; }
unsigned  char msbmask[] = {
     0xFF0xFE0xFC0xF8,
     0xF00xE00xC00x80
};
unsigned  char lsbmask[] = {
     0x010x030x070x0F,
     0x1F0x3F0x7F0xFF
};
static T copy(T t) {
    T  set;
    assert(t);
     set = Bit_new(t->length);
     if (t->length >  0)
        memcpy( set->bytes, t->bytes, nbytes(t->length));
     return  set;
}
T Bit_new( int length) {
    T  set;
    assert(length >=  0);
    NEW( set);
     if (length >  0)
         set->words = CALLOC(nwords(length),
             sizeof (unsigned  long));
     else
         set->words = NULL;
     set->bytes = (unsigned  char *) set->words;
     set->length = length;
     return  set;
}
void Bit_free(T * set) {
    assert( set && * set);
    FREE((* set)->words);
    FREE(* set);
}
int Bit_length(T  set) {
    assert( set);
     return  set->length;
}
int Bit_count(T  set) {
     int length =  0, n;
     static  char count[] = {
         0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
    assert( set);
     for (n = nbytes( set->length); --n >=  0; ) {
        unsigned  char c =  set->bytes[n];
        length += count[c& 0xF] + count[c>> 4];
    }
     return length;
}
int Bit_get(T  setint n) {
    assert( set);
    assert( 0 <= n && n <  set->length);
     return (( set->bytes[n/ 8]>>(n% 8))& 1);
}
int Bit_put(T  setint n,  int bit) {
     int prev;
    assert( set);
    assert(bit ==  0 || bit ==  1);
    assert( 0 <= n && n <  set->length);
    prev = (( set->bytes[n/ 8]>>(n% 8))& 1);
     if (bit ==  1)
         set->bytes[n/ 8] |=    1<<(n% 8);
     else
         set->bytes[n/ 8] &= ~( 1<<(n% 8));
     return prev;
}
void Bit_set(T  setint lo,  int hi) {
        assert( set);
        assert( 0 <= lo && hi <  set->length);
        assert(lo <= hi);
     if (lo/ 8 < hi/ 8) {
         set->bytes[lo/ 8] |= msbmask[lo% 8];
        {
             int i;
             for (i = lo/ 8+ 1; i < hi/ 8; i++)
                 set->bytes[i] =  0xFF;
        }
         set->bytes[hi/ 8] |= lsbmask[hi% 8];
    }  else
         set->bytes[lo/ 8] |= (msbmask[lo% 8]&lsbmask[hi% 8]);
}
void Bit_clear(T  setint lo,  int hi) {
        assert( set);
        assert( 0 <= lo && hi <  set->length);
        assert(lo <= hi);
     if (lo/ 8 < hi/ 8) {
         int i;
         set->bytes[lo/ 8] &= ~msbmask[lo% 8];
         for (i = lo/ 8+ 1; i < hi/ 8; i++)
             set->bytes[i] =  0;
         set->bytes[hi/ 8] &= ~lsbmask[hi% 8];
    }  else
         set->bytes[lo/ 8] &= ~(msbmask[lo% 8]&lsbmask[hi% 8]);
}
void Bit_not(T  setint lo,  int hi) {
        assert( set);
        assert( 0 <= lo && hi <  set->length);
        assert(lo <= hi);
     if (lo/ 8 < hi/ 8) {
         int i;
         set->bytes[lo/ 8] ^= msbmask[lo% 8];
         for (i = lo/ 8+ 1; i < hi/ 8; i++)
             set->bytes[i] ^=  0xFF;
         set->bytes[hi/ 8] ^= lsbmask[hi% 8];
    }  else
         set->bytes[lo/ 8] ^= (msbmask[lo% 8]&lsbmask[hi% 8]);
}
void Bit_map(T  set,
     void apply( int n,  int bit,  void *cl),  void *cl) {
     int n;
    assert( set);
     for (n =  0; n <  set->length; n++)
        apply(n, (( set->bytes[n/ 8]>>(n% 8))& 1), cl);
}
int Bit_eq(T s, T t) {
     int i;
    assert(s && t);
    assert(s->length == t->length);
     for (i = nwords(s->length); --i >=  0; )
         if (s->words[i] != t->words[i])
             return  0;
     return  1;
}
int Bit_leq(T s, T t) {
     int i;
    assert(s && t);
    assert(s->length == t->length);
     for (i = nwords(s->length); --i >=  0; )
         if ((s->words[i]&~t->words[i]) !=  0)
             return  0;
     return  1;
}
int Bit_lt(T s, T t) {
     int i, lt =  0;
    assert(s && t);
    assert(s->length == t->length);
     for (i = nwords(s->length); --i >=  0; )
         if ((s->words[i]&~t->words[i]) !=  0)
             return  0;
         else  if (s->words[i] != t->words[i])
            lt |=  1;
     return lt;
}
T Bit_union(T s, T t) {
    setop(copy(t), copy(t), copy(s), |)
}
T Bit_inter(T s, T t) {
    setop(copy(t),
        Bit_new(t->length), Bit_new(s->length), &)
}
T Bit_minus(T s, T t) {
    setop(Bit_new(s->length),
        Bit_new(t->length), copy(s), & ~)
}
T Bit_diff(T s, T t) {
    setop(Bit_new(s->length), copy(t), copy(s), ^)
}
复制代码

 

fmt.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/fmt.doc,v 1.10 1996/06/26 23:02:01 drh Exp $  */
#ifndef FMT_INCLUDED
#define FMT_INCLUDED
#include <stdarg.h>
#include <stdio.h>
#include  " except.h "
#define T Fmt_T
typedef  void (*T)( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[ 256],  int width,  int precision);
extern  char *Fmt_flags;
extern  const Except_T Fmt_Overflow;
extern  void Fmt_fmt ( int put( int c,  void *cl),  void *cl,
     const  char *fmt, ...);
extern  void Fmt_vfmt( int put( int c,  void *cl),  void *cl,
     const  char *fmt, va_list ap);
extern  void Fmt_print ( const  char *fmt, ...);
extern  void Fmt_fprint(FILE *stream,
     const  char *fmt, ...);
extern  int Fmt_sfmt   ( char *buf,  int size,
     const  char *fmt, ...);
extern  int Fmt_vsfmt( char *buf,  int size,
     const  char *fmt, va_list ap);
extern  char *Fmt_string ( const  char *fmt, ...);
extern  char *Fmt_vstring( const  char *fmt, va_list ap);
extern T Fmt_register( int code, T cvt);
extern  void Fmt_putd( const  char *str,  int len,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[ 256],  int width,  int precision);
extern  void Fmt_puts( const  char *str,  int len,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[ 256],  int width,  int precision);
#undef T
#endif
复制代码

 

fmt.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/fmt.doc,v 1.10 1996/06/26 23:02:01 drh Exp $ ";
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include < string.h>
#include <limits.h>
#include < float.h>
#include <ctype.h>
#include <math.h>
#include  " assert.h "
#include  " except.h "
#include  " fmt.h "
#include  " mem.h "
#define T Fmt_T
struct buf {
     char *buf;
     char *bp;
     int size;
};
#define pad(n,c) do { int nn = (n); \
     while (nn-- >  0) \
        put((c), cl); }  while ( 0)
static  void cvt_s( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
     char *str = va_arg(*app,  char *);
    assert(str);
    Fmt_puts(str, strlen(str), put, cl, flags,
        width, precision);
}
static  void cvt_d( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
     int val = va_arg(*app,  int);
    unsigned m;
     char buf[ 43];
     char *p = buf +  sizeof buf;
     if (val == INT_MIN)
        m = INT_MAX +  1U;
     else  if (val <  0)
        m = -val;
     else
        m = val;
     do
        *--p = m% 10 +  ' 0 ';
     while ((m /=  10) >  0);
     if (val <  0)
        *--p =  ' - ';
    Fmt_putd(p, (buf +  sizeof buf) - p, put, cl, flags,
        width, precision);
}
static  void cvt_u( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
    unsigned m = va_arg(*app, unsigned);
     char buf[ 43];
     char *p = buf +  sizeof buf;
     do
        *--p = m% 10 +  ' 0 ';
     while ((m /=  10) >  0);
    Fmt_putd(p, (buf +  sizeof buf) - p, put, cl, flags,
        width, precision);
}
static  void cvt_o( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
    unsigned m = va_arg(*app, unsigned);
     char buf[ 43];
     char *p = buf +  sizeof buf;
     do
        *--p = (m& 0x7) +  ' 0 ';
     while ((m>>=  3) !=  0);
    Fmt_putd(p, (buf +  sizeof buf) - p, put, cl, flags,
        width, precision);
}
static  void cvt_x( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
    unsigned m = va_arg(*app, unsigned);
     char buf[ 43];
     char *p = buf +  sizeof buf;
     do
        *--p =  " 0123456789abcdef "[m& 0xf];
     while ((m>>=  4) !=  0);
    Fmt_putd(p, (buf +  sizeof buf) - p, put, cl, flags,
        width, precision);
}
static  void cvt_p( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
    unsigned  long m = (unsigned  long)va_arg(*app,  void*);
     char buf[ 43];
     char *p = buf +  sizeof buf;
    precision = INT_MIN;
     do
        *--p =  " 0123456789abcdef "[m& 0xf];
     while ((m>>=  4) !=  0);
    Fmt_putd(p, (buf +  sizeof buf) - p, put, cl, flags,
        width, precision);
}
static  void cvt_c( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
     if (width == INT_MIN)
        width =  0;
     if (width <  0) {
        flags[ ' - '] =  1;
        width = -width;
    }
     if (!flags[ ' - '])
        pad(width -  1'   ');
    put((unsigned  char)va_arg(*app,  int), cl);
     if ( flags[ ' - '])
        pad(width -  1'   ');
}
static  void cvt_f( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
     char buf[DBL_MAX_10_EXP+ 1+ 1+ 99+ 1];
     if (precision <  0)
        precision =  6;
     if (code ==  ' g ' && precision ==  0)
        precision =  1;
    {
         static  char fmt[] =  " %.dd? ";
        assert(precision <=  99);
        fmt[ 4] = code;
        fmt[ 3] =      precision% 10 +  ' 0 ';
        fmt[ 2] = (precision/ 10)% 10 +  ' 0 ';
        sprintf(buf, fmt, va_arg(*app,  double));
    }
    Fmt_putd(buf, strlen(buf), put, cl, flags,
        width, precision);
}
const Except_T Fmt_Overflow = {  " Formatting Overflow " };
static T cvt[ 256] = {
  /*    0-  7  */  0,      00,      0,      0,      0,      0,      0,
  /*    8- 15  */  0,      00,      0,      0,      0,      0,      0,
  /*   16- 23  */  0,      00,      0,      0,      0,      0,      0,
  /*   24- 31  */  0,      00,      0,      0,      0,      0,      0,
  /*   32- 39  */  0,      00,      0,      0,      0,      0,      0,
  /*   40- 47  */  0,      00,      0,      0,      0,      0,      0,
  /*   48- 55  */  0,      00,      0,      0,      0,      0,      0,
  /*   56- 63  */  0,      00,      0,      0,      0,      0,      0,
  /*   64- 71  */  0,      00,      0,      0,      0,      0,      0,
  /*   72- 79  */  0,      00,      0,      0,      0,      0,      0,
  /*   80- 87  */  0,      00,      0,      0,      0,      0,      0,
  /*   88- 95  */  0,      00,      0,      0,      0,      0,      0,
  /*   96-103  */  0,      00, cvt_c, cvt_d, cvt_f, cvt_f, cvt_f,
  /*  104-111  */  0,      00,      0,      0,      0,      0, cvt_o,
  /*  112-119  */ cvt_p,  00, cvt_s,      0, cvt_u,      0,      0,
  /*  120-127  */ cvt_x,  00,      0,      0,      0,      0,      0
};
char *Fmt_flags =  " -+ 0 ";
static  int outc( int c,  void *cl) {
    FILE *f = cl;
     return putc(c, f);
}
static  int insert( int c,  void *cl) {
     struct buf *p = cl;
     if (p->bp >= p->buf + p->size)
        RAISE(Fmt_Overflow);
    *p->bp++ = c;
     return c;
}
static  int append( int c,  void *cl) {
     struct buf *p = cl;
     if (p->bp >= p->buf + p->size) {
        RESIZE(p->buf,  2*p->size);
        p->bp = p->buf + p->size;
        p->size *=  2;
    }
    *p->bp++ = c;
     return c;
}
void Fmt_puts( const  char *str,  int len,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
    assert(str);
    assert(len >=  0);
    assert(flags);
     if (width == INT_MIN)
        width =  0;
     if (width <  0) {
        flags[ ' - '] =  1;
        width = -width;
    }
     if (precision >=  0)
        flags[ ' 0 '] =  0;
     if (precision >=  0 && precision < len)
        len = precision;
     if (!flags[ ' - '])
        pad(width - len,  '   ');
    {
         int i;
         for (i =  0; i < len; i++)
            put((unsigned  char)*str++, cl);
    }
     if ( flags[ ' - '])
        pad(width - len,  '   ');
}
void Fmt_fmt( int put( int c,  void *),  void *cl,
     const  char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    Fmt_vfmt(put, cl, fmt, ap);
    va_end(ap);
}
void Fmt_print( const  char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    Fmt_vfmt(outc, stdout, fmt, ap);
    va_end(ap);
}
void Fmt_fprint(FILE *stream,  const  char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    Fmt_vfmt(outc, stream, fmt, ap);
    va_end(ap);
}
int Fmt_sfmt( char *buf,  int size,  const  char *fmt, ...) {
    va_list ap;
     int len;
    va_start(ap, fmt);
    len = Fmt_vsfmt(buf, size, fmt, ap);
    va_end(ap);
     return len;
}
int Fmt_vsfmt( char *buf,  int size,  const  char *fmt,
    va_list ap) {
     struct buf cl;
    assert(buf);
    assert(size >  0);
    assert(fmt);
    cl.buf = cl.bp = buf;
    cl.size = size;
    Fmt_vfmt(insert, &cl, fmt, ap);
    insert( 0, &cl);
     return cl.bp - cl.buf -  1;
}
char *Fmt_string( const  char *fmt, ...) {
     char *str;
    va_list ap;
    assert(fmt);
    va_start(ap, fmt);
    str = Fmt_vstring(fmt, ap);
    va_end(ap);
     return str;
}
char *Fmt_vstring( const  char *fmt, va_list ap) {
     struct buf cl;
    assert(fmt);
    cl.size =  256;
    cl.buf = cl.bp = ALLOC(cl.size);
    Fmt_vfmt(append, &cl, fmt, ap);
    append( 0, &cl);
     return RESIZE(cl.buf, cl.bp - cl.buf);
}
void Fmt_vfmt( int put( int c,  void *cl),  void *cl,
     const  char *fmt, va_list ap) {
    assert(put);
    assert(fmt);
     while (*fmt)
         if (*fmt !=  ' % ' || *++fmt ==  ' % ')
            put((unsigned  char)*fmt++, cl);
         else
            {
                unsigned  char c, flags[ 256];
                 int width = INT_MIN, precision = INT_MIN;
                memset(flags,  ' \0 'sizeof flags);
                 if (Fmt_flags) {
                    unsigned  char c = *fmt;
                     for ( ; c && strchr(Fmt_flags, c); c = *++fmt) {
                        assert(flags[c] <  255);
                        flags[c]++;
                    }
                }
                 if (*fmt ==  ' * ' || isdigit(*fmt)) {
                     int n;
                     if (*fmt ==  ' * ') {
                        n = va_arg(ap,  int);
                        assert(n != INT_MIN);
                        fmt++;
                    }  else
                         for (n =  0; isdigit(*fmt); fmt++) {
                             int d = *fmt -  ' 0 ';
                            assert(n <= (INT_MAX - d)/ 10);
                            n =  10*n + d;
                        }
                    width = n;
                }
                 if (*fmt ==  ' . ' && (*++fmt ==  ' * ' || isdigit(*fmt))) {
                     int n;
                     if (*fmt ==  ' * ') {
                        n = va_arg(ap,  int);
                        assert(n != INT_MIN);
                        fmt++;
                    }  else
                         for (n =  0; isdigit(*fmt); fmt++) {
                             int d = *fmt -  ' 0 ';
                            assert(n <= (INT_MAX - d)/ 10);
                            n =  10*n + d;
                        }
                    precision = n;
                }
                c = *fmt++;
                assert(cvt[c]);
                (*cvt[c])(c, &ap, put, cl, flags, width, precision);
            }
}
T Fmt_register( int code, T newcvt) {
    T old;
    assert( 0 < code
        && code < ( int)( sizeof (cvt)/ sizeof (cvt[ 0])));
    old = cvt[code];
    cvt[code] = newcvt;
     return old;
}
void Fmt_putd( const  char *str,  int len,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
     int sign;
    assert(str);
    assert(len >=  0);
    assert(flags);
     if (width == INT_MIN)
        width =  0;
     if (width <  0) {
        flags[ ' - '] =  1;
        width = -width;
    }
     if (precision >=  0)
        flags[ ' 0 '] =  0;
     if (len >  0 && (*str ==  ' - ' || *str ==  ' + ')) {
        sign = *str++;
        len--;
    }  else  if (flags[ ' + '])
        sign =  ' + ';
     else  if (flags[ '   '])
        sign =  '   ';
     else
        sign =  0;
    {  int n;
       if (precision <  0)
          precision =  1;
       if (len < precision)
          n = precision;
       else  if (precision ==  0 && len ==  1 && str[ 0] ==  ' 0 ')
          n =  0;
       else
          n = len;
       if (sign)
          n++;
       if (flags[ ' - ']) {
           if (sign)
            put(sign, cl);
      }  else  if (flags[ ' 0 ']) {
           if (sign)
            put(sign, cl);
          pad(width - n,  ' 0 ');
      }  else {
          pad(width - n,  '   ');
           if (sign)
            put(sign, cl);
      }
      pad(precision - len,  ' 0 ');
      {
           int i;
           for (i =  0; i < len; i++)
              put((unsigned  char)*str++, cl);
      }
       if (flags[ ' - '])
          pad(width - n,  '   '); }
}
复制代码

 

str.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/str.doc,v 1.10 1996/06/26 23:02:01 drh Exp $  */
#ifndef STR_INCLUDED
#define STR_INCLUDED
#include <stdarg.h>
extern  char *Str_sub( const  char *s,  int i,  int j);
extern  char *Str_dup( const  char *s,  int i,  int j,  int n);
extern  char *Str_cat( const  char *s1,  int i1,  int j1,
     const  char *s2,  int i2,  int j2);
extern  char *Str_catv   ( const  char *s, ...);
extern  char *Str_reverse( const  char *s,  int i,  int j);
extern  char *Str_map    ( const  char *s,  int i,  int j,
     const  char * fromconst  char *to);
extern  int Str_pos( const  char *s,  int i);
extern  int Str_len( const  char *s,  int i,  int j);
extern  int Str_cmp( const  char *s1,  int i1,  int j1,
     const  char *s2,  int i2,  int j2);
extern  int Str_chr  ( const  char *s,  int i,  int j,  int c);
extern  int Str_rchr ( const  char *s,  int i,  int j,  int c);
extern  int Str_upto ( const  char *s,  int i,  int j,
     const  char * set);
extern  int Str_rupto( const  char *s,  int i,  int j,
     const  char * set);
extern  int Str_find ( const  char *s,  int i,  int j,
     const  char *str);
extern  int Str_rfind( const  char *s,  int i,  int j,
     const  char *str);
extern  int Str_any   ( const  char *s,  int i,
     const  char * set);
extern  int Str_many  ( const  char *s,  int i,  int j,
     const  char * set);
extern  int Str_rmany ( const  char *s,  int i,  int j,
     const  char * set);
extern  int Str_match ( const  char *s,  int i,  int j,
     const  char *str);
extern  int Str_rmatch( const  char *s,  int i,  int j,
     const  char *str);
extern  void Str_fmt( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision);
#undef T
#endif
复制代码

 

str.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/str.doc,v 1.10 1996/06/26 23:02:01 drh Exp $ ";
#include < string.h>
#include <limits.h>
#include  " assert.h "
#include  " fmt.h "
#include  " str.h "
#include  " mem.h "
#define idx(i, len) ((i) <= 0 ? (i) + (len) : (i) - 1)
#define convert(s, i, j) do { int len; \
    assert(s); len = strlen(s); \
    i = idx(i, len); j = idx(j, len); \
     if (i > j) {  int t = i; i = j; j = t; } \
    assert(i >=  0 && j <= len); }  while ( 0)
char *Str_sub( const  char *s,  int i,  int j) {
     char *str, *p;
    convert(s, i, j);
    p = str = ALLOC(j - i +  1);
     while (i < j)
        *p++ = s[i++];
    *p =  ' \0 ';
     return str;
}
char *Str_dup( const  char *s,  int i,  int j,  int n) {
     int k;
     char *str, *p;
    assert(n >=  0);
    convert(s, i, j);
    p = str = ALLOC(n*(j - i) +  1);
     if (j - i >  0)
         while (n-- >  0)
             for (k = i; k < j; k++)
                *p++ = s[k];
    *p =  ' \0 ';
     return str;
}
char *Str_reverse( const  char *s,  int i,  int j) {
     char *str, *p;
    convert(s, i, j);
    p = str = ALLOC(j - i +  1);
     while (j > i)
        *p++ = s[--j];
    *p =  ' \0 ';
     return str;
}
char *Str_cat( const  char *s1,  int i1,  int j1,
               const  char *s2,  int i2,  int j2) {
     char *str, *p;
    convert(s1, i1, j1);
    convert(s2, i2, j2);
    p = str = ALLOC(j1 - i1 + j2 - i2 +  1);
     while (i1 < j1)
        *p++ = s1[i1++];
     while (i2 < j2)
        *p++ = s2[i2++];
    *p =  ' \0 ';
     return str;
}
char *Str_catv( const  char *s, ...) {
     char *str, *p;
     const  char *save = s;
     int i, j, len =  0;
    va_list ap;
    va_start(ap, s);
     while (s) {
        i = va_arg(ap,  int);
        j = va_arg(ap,  int);
        convert(s, i, j);
        len += j - i;
        s = va_arg(ap,  const  char *);
    }
    va_end(ap);
    p = str = ALLOC(len +  1);
    s = save;
    va_start(ap, s);
     while (s) {
        i = va_arg(ap,  int);
        j = va_arg(ap,  int);
        convert(s, i, j);
         while (i < j)
            *p++ = s[i++];
        s = va_arg(ap,  const  char *);
    }
    va_end(ap);
    *p =  ' \0 ';
     return str;
}
char *Str_map( const  char *s,  int i,  int j,
     const  char * fromconst  char *to) {
     static  char map[ 256] = {  0 };
     if ( from && to) {
        unsigned c;
         for (c =  0; c <  sizeof map; c++)
            map[c] = c;
         while (* from && *to)
            map[(unsigned  char)* from++] = *to++;
        assert(* from ==  0 && *to ==  0);
    }  else {
        assert( from == NULL && to == NULL && s);
        assert(map[ ' a ']);
    }
     if (s) {
         char *str, *p;
        convert(s, i, j);
        p = str = ALLOC(j - i +  1);
         while (i < j)
            *p++ = map[(unsigned  char)s[i++]];
        *p =  ' \0 ';
         return str;
    }  else
         return NULL;
}
int Str_pos( const  char *s,  int i) {
     int len;
    assert(s);
    len = strlen(s);
    i = idx(i, len);
    assert(i >=  0 && i <= len);
     return i +  1;
}
int Str_len( const  char *s,  int i,  int j) {
    convert(s, i, j);
     return j - i;
}
int Str_cmp( const  char *s1,  int i1,  int j1,
     const  char *s2,  int i2,  int j2) {
    convert(s1, i1, j1);
    convert(s2, i2, j2);
    s1 += i1;
    s2 += i2;
     if (j1 - i1 < j2 - i2) {
         int cond = strncmp(s1, s2, j1 - i1);
         return cond ==  0 ? - 1 : cond;
    }  else  if (j1 - i1 > j2 - i2) {
         int cond = strncmp(s1, s2, j2 - i2);
         return cond ==  0 ? + 1 : cond;
    }  else
         return strncmp(s1, s2, j1 - i1);
}
int Str_chr( const  char *s,  int i,  int j,  int c) {
    convert(s, i, j);
     for ( ; i < j; i++)
         if (s[i] == c)
             return i +  1;
     return  0;
}
int Str_rchr( const  char *s,  int i,  int j,  int c) {
    convert(s, i, j);
     while (j > i)
         if (s[--j] == c)
             return j +  1;
     return  0;
}
int Str_upto( const  char *s,  int i,  int j,
     const  char * set) {
    assert( set);
    convert(s, i, j);
     for ( ; i < j; i++)
         if (strchr( set, s[i]))
             return i +  1;
     return  0;
}
int Str_rupto( const  char *s,  int i,  int j,
     const  char * set) {
    assert( set);
    convert(s, i, j);
     while (j > i)
         if (strchr( set, s[--j]))
             return j +  1;
     return  0;
}
int Str_find( const  char *s,  int i,  int j,
     const  char *str) {
     int len;
    convert(s, i, j);
    assert(str);
    len = strlen(str);
     if (len ==  0)
         return i +  1;
     else  if (len ==  1) {
         for ( ; i < j; i++)
             if (s[i] == *str)
                 return i +  1;
    }  else
         for ( ; i + len <= j; i++)
             if ((strncmp(&s[i], str, len) ==  0))
                 return i +  1;
     return  0;
}
int Str_rfind( const  char *s,  int i,  int j,
     const  char *str) {
     int len;
    convert(s, i, j);
    assert(str);
    len = strlen(str);
     if (len ==  0)
         return j +  1;
     else  if (len ==  1) {
         while (j > i)
             if (s[--j] == *str)
                 return j +  1;
    }  else
         for ( ; j - len >= i; j--)
             if (strncmp(&s[j-len], str, len) ==  0)
                 return j - len +  1;
     return  0;
}
int Str_any( const  char *s,  int i,  const  char * set) {
     int len;
    assert(s);
    assert( set);
    len = strlen(s);
    i = idx(i, len);
    assert(i >=  0 && i <= len);
     if (i < len && strchr( set, s[i]))
         return i +  2;
     return  0;
}
int Str_many( const  char *s,  int i,  int j,
     const  char * set) {
    assert( set);
    convert(s, i, j);
     if (i < j && strchr( set, s[i])) {
         do
            i++;
         while (i < j && strchr( set, s[i]));
         return i +  1;
    }
     return  0;
}
int Str_rmany( const  char *s,  int i,  int j,
     const  char * set) {
    assert( set);
    convert(s, i, j);
     if (j > i && strchr( set, s[j- 1])) {
         do
            --j;
         while (j >= i && strchr( set, s[j]));
         return j +  2;
    }
     return  0;
}
int Str_match( const  char *s,  int i,  int j,
     const  char *str) {
     int len;
    convert(s, i, j);
    assert(str);
    len = strlen(str);
     if (len ==  0)
         return i +  1
     else  if (len ==  1) {
         if (i < j && s[i] == *str)
             return i +  2;
    }  else  if (i + len <= j && (strncmp(&s[i], str, len) ==  0))
         return i + len +  1;
     return  0;
}
int Str_rmatch( const  char *s,  int i,  int j,
     const  char *str) {
     int len;
    convert(s, i, j);
    assert(str);
    len = strlen(str);
     if (len ==  0)
         return j +  1;
     else  if (len ==  1) {
         if (j > i && s[j- 1] == *str)
             return j;
    }  else  if (j - len >= i
    && strncmp(&s[j-len], str, len) ==  0)
         return j - len +  1;
     return  0;
}
void Str_fmt( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
     char *s;
     int i, j;
    assert(app && flags);
    s = va_arg(*app,  char *);
    i = va_arg(*app,  int);
    j = va_arg(*app,  int);
    convert(s, i, j);
    Fmt_puts(s + i, j - i, put, cl, flags,
        width, precision);
}
复制代码

 

ids.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/str.doc,v 1.10 1996/06/26 23:02:01 drh Exp $ ";
#include <stdlib.h>
#include <stdio.h>
#include  " fmt.h "
#include  " str.h "
int main( int argc,  char *argv[]) {
     char line[ 512];
     static  char  set[] =  " 0123456789_ "
         " abcdefghijklmnopqrstuvwxyz "
         " ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
    Fmt_register( ' S ', Str_fmt);
     while (fgets(line,  sizeof line, stdin) != NULL) {
         int i =  1, j;
         while ((i = Str_upto(line, i,  0, & set[ 10])) >  0){
            j = Str_many(line, i,  0set);
            Fmt_print( " %S\n ", line, i, j);
            i = j;
        }
    }
     return EXIT_SUCCESS;
}
复制代码

 

text.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/text.doc,v 1.10 1996/06/26 23:02:01 drh Exp $  */
#ifndef TEXT_INCLUDED
#define TEXT_INCLUDED
#include <stdarg.h>
#define T Text_T
typedef  struct T {
     int len;
     const  char *str;
} T;
typedef  struct Text_save_T *Text_save_T;
extern  const T Text_cset;
extern  const T Text_ascii;
extern  const T Text_ucase;
extern  const T Text_lcase;
extern  const T Text_digits;
extern  const T Text_null;
extern T     Text_put( const  char *str);
extern  char *Text_get( char *str,  int size, T s);
extern T     Text_box( const  char *str,  int len);
extern T Text_sub(T s,  int i,  int j);
extern  int Text_pos(T s,  int i);
extern T Text_cat    (T s1, T s2);
extern T Text_dup    (T s,  int n);
extern T Text_reverse(T s);
extern T Text_map(T s,  const T * fromconst T *to);
extern  int Text_cmp(T s1, T s2);
extern  int Text_chr  (T s,  int i,  int j,  int c);
extern  int Text_rchr (T s,  int i,  int j,  int c);
extern  int Text_upto (T s,  int i,  int j, T  set);
extern  int Text_rupto(T s,  int i,  int j, T  set);
extern  int Text_any  (T s,  int i, T  set);
extern  int Text_many (T s,  int i,  int j, T  set);
extern  int Text_rmany(T s,  int i,  int j, T  set);
extern  int Text_find  (T s,  int i,  int j, T str);
extern  int Text_rfind (T s,  int i,  int j, T str);
extern  int Text_match (T s,  int i,  int j, T str);
extern  int Text_rmatch(T s,  int i,  int j, T str);
extern  void Text_fmt( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision);
extern Text_save_T Text_save( void);
extern  void        Text_restore(Text_save_T *save);
#undef T
#endif
复制代码

 

text.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/text.doc,v 1.10 1996/06/26 23:02:01 drh Exp $ ";
#include < string.h>
#include <limits.h>
#include  " assert.h "
#include  " fmt.h "
#include  " text.h "
#include  " mem.h "
#define T Text_T
#define idx(i, len) ((i) <= 0 ? (i) + (len) : (i) - 1)
#define isatend(s, n) ((s).str+(s).len == current->avail\
    && current->avail + (n) <= current->limit)
#define equal(s, i, t) \
    (memcmp(&(s).str[i], (t).str, (t).len) ==  0)
struct Text_save_T {
     struct chunk *current;
     char *avail;
};
static  char cset[] =
     " \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017 "
     " \020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 "
     " \040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057 "
     " \060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077 "
     " \100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117 "
     " \120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137 "
     " \140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157 "
     " \160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177 "
     " \200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217 "
     " \220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237 "
     " \240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257 "
     " \260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277 "
     " \300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317 "
     " \320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337 "
     " \340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357 "
     " \360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377 "
    ;
const T Text_cset   = {  256, cset };
const T Text_ascii  = {  127, cset };
const T Text_ucase  = {   26, cset +  ' A ' };
const T Text_lcase  = {   26, cset +  ' a ' };
const T Text_digits = {   10, cset +  ' 0 ' };
const T Text_null   = {    0, cset };
static  struct chunk {
     struct chunk *link;
     char *avail;
     char *limit;
} head = { NULL, NULL, NULL }, *current = &head;
static  char *alloc( int len) {
    assert(len >=  0);
     if (current->avail + len > current->limit) {
        current = current->link = 
            ALLOC( sizeof (*current) +  10* 1024 + len);
        current->avail = ( char *)(current +  1);
        current->limit = current->avail +  10* 1024 + len;
        current->link = NULL;
    }
    current->avail += len;
     return current->avail - len;
}
int Text_pos(T s,  int i) {
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    assert(i >=  0 && i <= s.len);
     return i +  1;
}
T Text_box( const  char *str,  int len) {
    T text;
    assert(str);
    assert(len >=  0);
    text.str = str;
    text.len = len;
     return text;
}
T Text_sub(T s,  int i,  int j) {
    T text;
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
    text.len = j - i;
    text.str = s.str + i;
     return text;
}
T Text_put( const  char *str) {
    T text;
    assert(str);
    text.len = strlen(str);
    text.str = memcpy(alloc(text.len), str, text.len);
     return text;
}
char *Text_get( char *str,  int size, T s) {
    assert(s.len >=  0 && s.str);
     if (str == NULL)
        str = ALLOC(s.len +  1);
     else
        assert(size >= s.len +  1);
    memcpy(str, s.str, s.len);
    str[s.len] =  ' \0 ';
     return str;
}
T Text_dup(T s,  int n) {
    assert(s.len >=  0 && s.str);
    assert(n >=  0);
     if (n ==  0 || s.len ==  0)
         return Text_null;
     if (n ==  1)
         return s;
    {
        T text;
         char *p;
        text.len = n*s.len;
         if (isatend(s, text.len - s.len)) {
            text.str = s.str;
            p = alloc(text.len - s.len);
            n--;
        }  else
            text.str = p = alloc(text.len);
         for ( ; n-- >  0; p += s.len)
            memcpy(p, s.str, s.len);
         return text;
    }
}
T Text_cat(T s1, T s2) {
    assert(s1.len >=  0 && s1.str);
    assert(s2.len >=  0 && s2.str);
     if (s1.len ==  0)
         return s2;
     if (s2.len ==  0)
         return s1;
     if (s1.str + s1.len == s2.str) {
        s1.len += s2.len;
         return s1;
    }
    {
        T text;
        text.len = s1.len + s2.len;
         if (isatend(s1, s2.len)) {
            text.str = s1.str;
            memcpy(alloc(s2.len), s2.str, s2.len);
        }  else {
             char *p;
            text.str = p = alloc(s1.len + s2.len);
            memcpy(p,          s1.str, s1.len);
            memcpy(p + s1.len, s2.str, s2.len);
        }
         return text;
    } 
}
T Text_reverse(T s) {
    assert(s.len >=  0 && s.str);
     if (s.len ==  0)
         return Text_null;
     else  if (s.len ==  1)
         return s;
     else {
        T text;
         char *p;
         int i = s.len;
        text.len = s.len;
        text.str = p = alloc(s.len);
         while (--i >=  0)
            *p++ = s.str[i];
         return text;
    }
}
T Text_map(T s,  const T * fromconst T *to) {
     static  char map[ 256];
     static  int inited =  0;
    assert(s.len >=  0 && s.str);
     if ( from && to) {
         int k;
         for (k =  0; k < ( int) sizeof map; k++)
            map[k] = k;
        assert( from->len == to->len);
         for (k =  0; k <  from->len; k++)
            map[ from->str[k]] = to->str[k];
        inited =  1;
    }  else {
        assert( from == NULL && to == NULL);
        assert(inited);
    }
     if (s.len ==  0)
         return Text_null;
     else {
        T text;
         int i;
         char *p;
        text.len = s.len;
        text.str = p = alloc(s.len);
         for (i =  0; i < s.len; i++)
            *p++ = map[s.str[i]];
         return text;
    }
}
int Text_cmp(T s1, T s2) {
    assert(s1.len >=  0 && s1.str);
    assert(s2.len >=  0 && s2.str);
     if (s1.str == s2.str)
         return s1.len - s2.len;
     else  if (s1.len < s2.len) {
         int cond = memcmp(s1.str, s2.str, s1.len);
         return cond ==  0 ? - 1 : cond;
    }  else  if (s1.len > s2.len) {
         int cond = memcmp(s1.str, s2.str, s2.len);
         return cond ==  0 ? + 1 : cond;
    }  else
         return memcmp(s1.str, s2.str, s1.len);
}
Text_save_T Text_save( void) {
    Text_save_T save;
    NEW(save);
    save->current = current;
    save->avail = current->avail;
    alloc( 1);
     return save;
}
void Text_restore(Text_save_T *save) {
     struct chunk *p, *q;
    assert(save && *save);
    current = (*save)->current;
    current->avail = (*save)->avail;
    FREE(*save);
     for (p = current->link; p; p = q) {
        q = p->link;
        FREE(p);
    }
    current->link = NULL;
}
int Text_chr(T s,  int i,  int j,  int c) {
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     for ( ; i < j; i++)
         if (s.str[i] == c)
             return i +  1;
     return  0;
}
int Text_rchr(T s,  int i,  int j,  int c) {
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     while (j > i)
         if (s.str[--j] == c)
             return j +  1;
     return  0;
}
int Text_upto(T s,  int i,  int j, T  set) {
    assert( set.len >=  0 &&  set.str);
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     for ( ; i < j; i++)
         if (memchr( set.str, s.str[i],  set.len))
             return i +  1;
     return  0;
}
int Text_rupto(T s,  int i,  int j, T  set) {
    assert( set.len >=  0 &&  set.str);
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     while (j > i)
         if (memchr( set.str, s.str[--j],  set.len))
             return j +  1;
     return  0;
}
int Text_find(T s,  int i,  int j, T str) {
    assert(str.len >=  0 && str.str);
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     if (str.len ==  0)
         return i +  1;
     else  if (str.len ==  1) {
         for ( ; i < j; i++)
             if (s.str[i] == *str.str)
                 return i +  1;
    }  else
         for ( ; i + str.len <= j; i++)
             if (equal(s, i, str))
                 return i +  1;
     return  0;
}
int Text_rfind(T s,  int i,  int j, T str) {
    assert(str.len >=  0 && str.str);
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     if (str.len ==  0)
         return j +  1;
     else  if (str.len ==  1) {
         while (j > i)
             if (s.str[--j] == *str.str)
                 return j +  1;
    }  else
         for ( ; j - str.len >= i; j--)
             if (equal(s, j - str.len, str))
                 return j - str.len +  1;
     return  0;
}
int Text_any(T s,  int i, T  set) {
    assert(s.len >=  0 && s.str);
    assert( set.len >=  0 &&  set.str);
    i = idx(i, s.len);
    assert(i >=  0 && i <= s.len);
     if (i < s.len && memchr( set.str, s.str[i],  set.len))
         return i +  2;
     return  0;
}
int Text_many(T s,  int i,  int j, T  set) {
    assert( set.len >=  0 &&  set.str);
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     if (i < j && memchr( set.str, s.str[i],  set.len)) {
         do
            i++;
         while (i < j
        && memchr( set.str, s.str[i],  set.len));
         return i +  1;
    }
     return  0;
}
int Text_rmany(T s,  int i,  int j, T  set) {
    assert( set.len >=  0 &&  set.str);
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     if (j > i && memchr( set.str, s.str[j- 1],  set.len)) {
         do
            --j;
         while (j >= i
        && memchr( set.str, s.str[j],  set.len));
         return j +  2;
    }
     return  0;
}
int Text_match(T s,  int i,  int j, T str) {
    assert(str.len >=  0 && str.str);
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     if (str.len ==  0)
         return i +  1;
     else  if (str.len ==  1) {
         if (i < j && s.str[i] == *str.str)
             return i +  2;
    }  else  if (i + str.len <= j && equal(s, i, str))
         return i + str.len +  1;
     return  0;
}
int Text_rmatch(T s,  int i,  int j, T str) {
    assert(str.len >=  0 && str.str);
    assert(s.len >=  0 && s.str);
    i = idx(i, s.len);
    j = idx(j, s.len);
     if (i > j) {  int t = i; i = j; j = t; }
    assert(i >=  0 && j <= s.len);
     if (str.len ==  0)
         return j +  1;
     else  if (str.len ==  1) {
         if (j > i && s.str[j- 1] == *str.str)
             return j;
    }  else  if (j - str.len >= i
    && equal(s, j - str.len, str))
         return j - str.len +  1;
     return  0;
}
void Text_fmt( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
    T *s;
    assert(app && flags);
    s = va_arg(*app, T*);
    assert(s && s->len >=  0 && s->str);
    Fmt_puts(s->str, s->len, put, cl, flags,
        width, precision);
}
复制代码

 

xp.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/xp.doc,v 1.10 1996/06/26 23:02:01 drh Exp $  */
#ifndef XP_INCLUDED
#define XP_INCLUDED
#define T XP_T
typedef unsigned  char *T;
extern  int XP_add( int n, T z, T x, T y,  int carry);
extern  int XP_sub( int n, T z, T x, T y,  int borrow);
extern  int XP_mul(T z,  int n, T x,  int m, T y);
extern  int XP_div( int n, T q, T x,  int m, T y, T r,T tmp);
extern  int XP_sum     ( int n, T z, T x,  int y);
extern  int XP_diff    ( int n, T z, T x,  int y);
extern  int XP_product ( int n, T z, T x,  int y);
extern  int XP_quotient( int n, T z, T x,  int y);
extern  int XP_neg( int n, T z, T x,  int carry);
extern  int XP_cmp( int n, T x, T y);
extern  void XP_lshift( int n, T z,  int m, T x,
     int s,  int fill);
extern  void XP_rshift( int n, T z,  int m, T x,
     int s,  int fill);
extern  int           XP_length ( int n, T x);
extern unsigned  long XP_fromint( int n, T z,
    unsigned  long u);
extern unsigned  long XP_toint  ( int n, T x);
extern  int   XP_fromstr( int n, T z,  const  char *str,
     int  basechar **end);
extern  char *XP_tostr  ( char *str,  int size,  int  base,
     int n, T x);
#undef T
#endif
复制代码

 

xp.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/xp.doc,v 1.10 1996/06/26 23:02:01 drh Exp $ ";
#include <ctype.h>
#include < string.h>
#include  " assert.h "
#include  " xp.h "
#define T XP_T
#define BASE (1<<8)
static  char map[] = {
      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
     36363636363636,
     10111213141516171819202122,
     23242526272829303132333435,
     363636363636,
     10111213141516171819202122,
     23242526272829303132333435
};
unsigned  long XP_fromint( int n, T z, unsigned  long u) {
     int i =  0;
     do
        z[i++] = u%BASE;
     while ((u /= BASE) >  0 && i < n);
     for ( ; i < n; i++)
        z[i] =  0;
     return u;
}
unsigned  long XP_toint( int n, T x) {
    unsigned  long u =  0;
     int i = ( int) sizeof u;
     if (i > n)
        i = n;
     while (--i >=  0)
        u = BASE*u + x[i];
     return u;
}
int XP_length( int n, T x) {
     while (n >  1 && x[n- 1] ==  0)
        n--;
     return n;
}
int XP_add( int n, T z, T x, T y,  int carry) {
     int i;
     for (i =  0; i < n; i++) {
        carry += x[i] + y[i];
        z[i] = carry%BASE;
        carry /= BASE;
    }
     return carry;
}
int XP_sub( int n, T z, T x, T y,  int borrow) {
     int i;
     for (i =  0; i < n; i++) {
         int d = (x[i] + BASE) - borrow - y[i];
        z[i] = d%BASE;
        borrow =  1 - d/BASE;
    }
     return borrow;
}
int XP_sum( int n, T z, T x,  int y) {
     int i;
     for (i =  0; i < n; i++) {
        y += x[i];
        z[i] = y%BASE;
        y /= BASE;
    }
     return y;
}
int XP_diff( int n, T z, T x,  int y) {
     int i;
     for (i =  0; i < n; i++) {
         int d = (x[i] + BASE) - y;
        z[i] = d%BASE;
        y =  1 - d/BASE;
    }
     return y;
}
int XP_neg( int n, T z, T x,  int carry) {
     int i;
     for (i =  0; i < n; i++) {
        carry += (unsigned  char)~x[i];
        z[i] = carry%BASE;
        carry /= BASE;
    }
     return carry;
}
int XP_mul(T z,  int n, T x,  int m, T y) {
     int i, j, carryout =  0;
     for (i =  0; i < n; i++) {
        unsigned carry =  0;
         for (j =  0; j < m; j++) {
            carry += x[i]*y[j] + z[i+j];
            z[i+j] = carry%BASE;
            carry /= BASE;
        }
         for ( ; j < n + m - i; j++) {
            carry += z[i+j];
            z[i+j] = carry%BASE;
            carry /= BASE;
        }
        carryout |= carry;
    }
     return carryout;
}
int XP_product( int n, T z, T x,  int y) {
     int i;
    unsigned carry =  0;
     for (i =  0; i < n; i++) {
        carry += x[i]*y;
        z[i] = carry%BASE;
        carry /= BASE;
    }
     return carry;
}
int XP_div( int n, T q, T x,  int m, T y, T r, T tmp) {
     int nx = n, my = m;
    n = XP_length(n, x);
    m = XP_length(m, y);
     if (m ==  1) {
         if (y[ 0] ==  0)
             return  0;
        r[ 0] = XP_quotient(nx, q, x, y[ 0]);
        memset(r +  1' \0 ', my -  1);
    }  else  if (m > n) {
        memset(q,  ' \0 ', nx);
        memcpy(r, x, n);
        memset(r + n,  ' \0 ', my - n);
    }  else {
         int k;
        unsigned  char *rem = tmp, *dq = tmp + n +  1;
        assert( 2 <= m && m <= n);
        memcpy(rem, x, n);
        rem[n] =  0;
         for (k = n - m; k >=  0; k--) {
             int qk;
            {
                 int i;
                assert( 2 <= m && m <= k+m && k+m <= n);
                {
                     int km = k + m;
                    unsigned  long y2 = y[m- 1]*BASE + y[m- 2];
                    unsigned  long r3 = rem[km]*(BASE*BASE) +
                        rem[km- 1]*BASE + rem[km- 2];
                    qk = r3/y2;
                     if (qk >= BASE)
                        qk = BASE -  1;
                }
                dq[m] = XP_product(m, dq, y, qk);
                 for (i = m; i >  0; i--)
                     if (rem[i+k] != dq[i])
                         break;
                 if (rem[i+k] < dq[i])
                    dq[m] = XP_product(m, dq, y, --qk);
            }
            q[k] = qk;
            {
                 int borrow;
                assert( 0 <= k && k <= k+m);
                borrow = XP_sub(m +  1, &rem[k], &rem[k], dq,  0);
                assert(borrow ==  0);
            }
        }
        memcpy(r, rem, m);
        {
             int i;
             for (i = n-m+ 1; i < nx; i++)
                q[i] =  0;
             for (i = m; i < my; i++)
                r[i] =  0;
        }
    }
     return  1;
}
int XP_quotient( int n, T z, T x,  int y) {
     int i;
    unsigned carry =  0;
     for (i = n -  1; i >=  0; i--) {
        carry = carry*BASE + x[i];
        z[i] = carry/y;
        carry %= y;
    }
     return carry;
}
int XP_cmp( int n, T x, T y) {
     int i = n -  1;
     while (i >  0 && x[i] == y[i])
        i--;
     return x[i] - y[i];
}
void XP_lshift( int n, T z,  int m, T x,  int s,  int fill) {
    fill = fill ?  0xFF :  0;
    {
         int i, j = n -  1;
         if (n > m)
            i = m -  1;
         else
            i = n - s/ 8 -  1;
         for ( ; j >= m + s/ 8; j--)
            z[j] =  0;
         for ( ; i >=  0; i--, j--)
            z[j] = x[i];
         for ( ; j >=  0; j--)
            z[j] = fill;
    }
    s %=  8;
     if (s >  0)
        {
            XP_product(n, z, z,  1<<s);
            z[ 0] |= fill>>( 8-s);
        }
}
void XP_rshift( int n, T z,  int m, T x,  int s,  int fill) {
    fill = fill ?  0xFF :  0;
    {
         int i, j =  0;
         for (i = s/ 8; i < m && j < n; i++, j++)
            z[j] = x[i];
         for ( ; j < n; j++)
            z[j] = fill;
    }
    s %=  8;
     if (s >  0)
        {
            XP_quotient(n, z, z,  1<<s);
            z[n- 1] |= fill<<( 8-s);
        }
}
int XP_fromstr( int n, T z,  const  char *str,
     int  basechar **end) {
     const  char *p = str;
    assert(p);
    assert( base >=  2 &&  base <=  36);
     while (*p && isspace(*p))
        p++;
     if ((*p && isalnum(*p) && map[*p- ' 0 '] <  base)) {
         int carry;
         for ( ; (*p && isalnum(*p) && map[*p- ' 0 '] <  base); p++) {
            carry = XP_product(n, z, z,  base);
             if (carry)
                 break;
            XP_sum(n, z, z, map[*p- ' 0 ']);
        }
         if (end)
            *end = ( char *)p;
         return carry;
    }  else {
         if (end)
            *end = ( char *)str;
         return  0;
    }
}
char *XP_tostr( char *str,  int size,  int  base,
     int n, T x) {
     int i =  0;
    assert(str);
    assert( base >=  2 &&  base <=  36);
     do {
         int r = XP_quotient(n, x, x,  base);
        assert(i < size);
        str[i++] =
             " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ "[r];
         while (n >  1 && x[n- 1] ==  0)
            n--;
    }  while (n >  1 || x[ 0] !=  0);
    assert(i < size);
    str[i] =  ' \0 ';
    {
         int j;
         for (j =  0; j < --i; j++) {
             char c = str[j];
            str[j] = str[i];
            str[i] = c;
        }
    }
     return str;
}
复制代码

 

ap.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/ap.doc,v 1.11 1996/06/26 23:02:01 drh Exp $  */
#ifndef AP_INCLUDED
#define AP_INCLUDED
#include <stdarg.h>
#define T AP_T
typedef  struct T *T;
extern T AP_new    ( long  int n);
extern T AP_fromstr( const  char *str,  int  base,
     char **end);
extern  long  int AP_toint(T x);
extern  char    *AP_tostr( char *str,  int size,
     int  base, T x);
extern  void     AP_fmt( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision);
extern  void AP_free(T *z);
extern T AP_neg(T x);
extern T AP_add(T x, T y);
extern T AP_sub(T x, T y);
extern T AP_mul(T x, T y);
extern T AP_div(T x, T y);
extern T AP_mod(T x, T y);
extern T AP_pow(T x, T y, T p);
extern T    AP_addi(T x,  long  int y);
extern T    AP_subi(T x,  long  int y);
extern T    AP_muli(T x,  long  int y);
extern T    AP_divi(T x,  long  int y);
extern  long AP_modi(T x,  long  int y);
extern T AP_lshift(T x,  int s);
extern T AP_rshift(T x,  int s);
extern  int AP_cmp (T x, T y);
extern  int AP_cmpi(T x,  long  int y);
#undef T
#endif
复制代码

 

 

ap.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/ap.doc,v 1.11 1996/06/26 23:02:01 drh Exp $ ";
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
#include < string.h>
#include  " assert.h "
#include  " ap.h "
#include  " fmt.h "
#include  " xp.h "
#include  " mem.h "
#define T AP_T
struct T {
     int sign;
     int ndigits;
     int size;
    XP_T digits;
};
#define iszero(x) ((x)->ndigits==1 && (x)->digits[0]==0)
#define maxdigits(x,y) ((x)->ndigits > (y)->ndigits ? \
    (x)->ndigits : (y)->ndigits)
#define isone(x) ((x)->ndigits==1 && (x)->digits[0]==1)
static T normalize(T z,  int n);
static  int cmp(T x, T y);
static T mk( int size) {
    T z = CALLOC( 1sizeof (*z) + size);
    assert(size >  0);
    z->sign =  1;
    z->size = size;
    z->ndigits =  1;
    z->digits = (XP_T)(z +  1);
     return z;
}
static T  set(T z,  long  int n) {
     if (n == LONG_MIN)
        XP_fromint(z->size, z->digits, LONG_MAX +  1UL);
     else  if (n <  0)
        XP_fromint(z->size, z->digits, -n);
     else
        XP_fromint(z->size, z->digits, n);
    z->sign = n <  0 ? - 1 :  1;
     return normalize(z, z->size);
}
static T normalize(T z,  int n) {
    z->ndigits = XP_length(n, z->digits);
     return z;
}
static T add(T z, T x, T y) {
     int n = y->ndigits;
     if (x->ndigits < n)
         return add(z, y, x);
     else  if (x->ndigits > n) {
         int carry = XP_add(n, z->digits, x->digits,
            y->digits,  0);
        z->digits[z->size- 1] = XP_sum(x->ndigits - n,
            &z->digits[n], &x->digits[n], carry);
    }  else
        z->digits[n] = XP_add(n, z->digits, x->digits,
            y->digits,  0);
     return normalize(z, z->size);
}
static T sub(T z, T x, T y) {
     int borrow, n = y->ndigits;
    borrow = XP_sub(n, z->digits, x->digits,
        y->digits,  0);
     if (x->ndigits > n)
        borrow = XP_diff(x->ndigits - n, &z->digits[n],
            &x->digits[n], borrow);
    assert(borrow ==  0);
     return normalize(z, z->size);
}
static T mulmod(T x, T y, T p) {
    T z, xy = AP_mul(x, y);
    z = AP_mod(xy, p);
    AP_free(&xy);
     return z;
}
static  int cmp(T x, T y) {
     if (x->ndigits != y->ndigits)
         return x->ndigits - y->ndigits;
     else
         return XP_cmp(x->ndigits, x->digits, y->digits);
}
T AP_new( long  int n) {
     return  set(mk( sizeof ( long  int)), n);
}
void AP_free(T *z) {
    assert(z && *z);
    FREE(*z);
}
T AP_neg(T x) {
    T z;
    assert(x);
    z = mk(x->ndigits);
    memcpy(z->digits, x->digits, x->ndigits);
    z->ndigits = x->ndigits;
    z->sign = iszero(z) ?  1 : -x->sign;
     return z;
}
T AP_mul(T x, T y) {
    T z;
    assert(x);
    assert(y);
    z = mk(x->ndigits + y->ndigits);
    XP_mul(z->digits, x->ndigits, x->digits, y->ndigits,
        y->digits);
    normalize(z, z->size);
    z->sign = iszero(z)
        || ((x->sign^y->sign) ==  0) ?  1 : - 1;
     return z;
}
T AP_add(T x, T y) {
    T z;
    assert(x);
    assert(y);
     if (((x->sign^y->sign) ==  0)) {
        z = add(mk(maxdigits(x,y) +  1), x, y);
        z->sign = iszero(z) ?  1 : x->sign;
    }  else
         if (cmp(x, y) >  0) {
            z = sub(mk(x->ndigits), x, y);
            z->sign = iszero(z) ?  1 : x->sign;
        }
         else {
            z = sub(mk(y->ndigits), y, x);
            z->sign = iszero(z) ?  1 : -x->sign;
        }
     return z;
}
T AP_sub(T x, T y) {
    T z;
    assert(x);
    assert(y);
     if (!((x->sign^y->sign) ==  0)) {
        z = add(mk(maxdigits(x,y) +  1), x, y);
        z->sign = iszero(z) ?  1 : x->sign;
    }  else
         if (cmp(x, y) >  0) {
            z = sub(mk(x->ndigits), x, y);
            z->sign = iszero(z) ?  1 : x->sign;
        }  else {
            z = sub(mk(y->ndigits), y, x);
            z->sign = iszero(z) ?  1 : -x->sign;
        }
     return z;
}
T AP_div(T x, T y) {
    T q, r;
    assert(x);
    assert(y);
    assert(!iszero(y));
    q = mk(x->ndigits);
    r = mk(y->ndigits);
    {
        XP_T tmp = ALLOC(x->ndigits + y->ndigits +  2);
        XP_div(x->ndigits, q->digits, x->digits,
            y->ndigits, y->digits, r->digits, tmp);
        FREE(tmp);
    }
    normalize(q, q->size);
    normalize(r, r->size);
    q->sign = iszero(q)
        || ((x->sign^y->sign) ==  0) ?  1 : - 1;
     if (!((x->sign^y->sign) ==  0) && !iszero(r)) {
         int carry = XP_sum(q->size, q->digits,
            q->digits,  1);
        assert(carry ==  0);
        normalize(q, q->size);
    }
    AP_free(&r);
     return q;
}
T AP_mod(T x, T y) {
    T q, r;
    assert(x);
    assert(y);
    assert(!iszero(y));
    q = mk(x->ndigits);
    r = mk(y->ndigits);
    {
        XP_T tmp = ALLOC(x->ndigits + y->ndigits +  2);
        XP_div(x->ndigits, q->digits, x->digits,
            y->ndigits, y->digits, r->digits, tmp);
        FREE(tmp);
    }
    normalize(q, q->size);
    normalize(r, r->size);
    q->sign = iszero(q)
        || ((x->sign^y->sign) ==  0) ?  1 : - 1;
     if (!((x->sign^y->sign) ==  0) && !iszero(r)) {
         int borrow = XP_sub(r->size, r->digits,
            y->digits, r->digits,  0);
        assert(borrow ==  0);
        normalize(r, r->size);
    }
    AP_free(&q);
     return r;
}
T AP_pow(T x, T y, T p) {
    T z;
    assert(x);
    assert(y);
    assert(y->sign ==  1);
    assert(!p || p->sign== 1 && !iszero(p) && !isone(p));
     if (iszero(x))
         return AP_new( 0);
     if (iszero(y))
         return AP_new( 1);
     if (isone(x))
         return AP_new((((y)->digits[ 0]& 1) ==  0) ?  1 : x->sign);
     if (p)
         if (isone(y))
            z = AP_mod(x, p);
         else {
            T y2 = AP_rshift(y,  1), t = AP_pow(x, y2, p);
            z = mulmod(t, t, p);
            AP_free(&y2);
            AP_free(&t);
             if (!(((y)->digits[ 0]& 1) ==  0)) {
                z = mulmod(y2 = AP_mod(x, p), t = z, p);
                AP_free(&y2);
                AP_free(&t);
            }
        }
     else
         if (isone(y))
            z = AP_addi(x,  0);
         else {
            T y2 = AP_rshift(y,  1), t = AP_pow(x, y2, NULL);
            z = AP_mul(t, t);
            AP_free(&y2);
            AP_free(&t);
             if (!(((y)->digits[ 0]& 1) ==  0)) {
                z = AP_mul(x, t = z);
                AP_free(&t);
            }
        }
     return z;
}
int AP_cmp(T x, T y) {
    assert(x);
    assert(y);
     if (!((x->sign^y->sign) ==  0))
         return x->sign;
     else  if (x->sign ==  1)
         return cmp(x, y);
     else
         return cmp(y, x);
}
T AP_addi(T x,  long  int y) {
    unsigned  char d[ sizeof (unsigned  long)];
     struct T t;
    t.size =  sizeof d;
    t.digits = d;
     return AP_add(x,  set(&t, y));
}
T AP_subi(T x,  long  int y) {
    unsigned  char d[ sizeof (unsigned  long)];
     struct T t;
    t.size =  sizeof d;
    t.digits = d;
     return AP_sub(x,  set(&t, y));
}
T AP_muli(T x,  long  int y) {
    unsigned  char d[ sizeof (unsigned  long)];
     struct T t;
    t.size =  sizeof d;
    t.digits = d;
     return AP_mul(x,  set(&t, y));
}
T AP_divi(T x,  long  int y) {
    unsigned  char d[ sizeof (unsigned  long)];
     struct T t;
    t.size =  sizeof d;
    t.digits = d;
     return AP_div(x,  set(&t, y));
}
int AP_cmpi(T x,  long  int y) {
    unsigned  char d[ sizeof (unsigned  long)];
     struct T t;
    t.size =  sizeof d;
    t.digits = d;
     return AP_cmp(x,  set(&t, y));
}
long  int AP_modi(T x,  long  int y) {
     long  int rem;
    T r;
    unsigned  char d[ sizeof (unsigned  long)];
     struct T t;
    t.size =  sizeof d;
    t.digits = d;
    r = AP_mod(x,  set(&t, y));
    rem = XP_toint(r->ndigits, r->digits);
    AP_free(&r);
     return rem;
}
T AP_lshift(T x,  int s) {
    T z;
    assert(x);
    assert(s >=  0);
    z = mk(x->ndigits + ((s+ 7)&~ 7)/ 8);
    XP_lshift(z->size, z->digits, x->ndigits,
        x->digits, s,  0);
    z->sign = x->sign;
     return normalize(z, z->size);
}
T AP_rshift(T x,  int s) {
    assert(x);
    assert(s >=  0);
     if (s >=  8*x->ndigits)
         return AP_new( 0);
     else {
        T z = mk(x->ndigits - s/ 8);
        XP_rshift(z->size, z->digits, x->ndigits,
            x->digits, s,  0);
        normalize(z, z->size);
        z->sign = iszero(z) ?  1 : x->sign;
         return z;
    }
}
long  int AP_toint(T x) {
    unsigned  long u;
    assert(x);
    u = XP_toint(x->ndigits, x->digits)%(LONG_MAX +  1UL);
     if (x->sign == - 1)
         return -( long)u;
     else
         return  ( long)u;
}
T AP_fromstr( const  char *str,  int  basechar **end) {
    T z;
     const  char *p = str;
     char *endp, sign =  ' \0 ';
     int carry;
    assert(p);
    assert( base >=  2 &&  base <=  36);
     while (*p && isspace(*p))
        p++;
     if (*p ==  ' - ' || *p ==  ' + ')
        sign = *p++;
    {
         const  char *start;
         int k, n =  0;
         for ( ; *p ==  ' 0 ' && p[ 1] ==  ' 0 '; p++)
            ;
        start = p;
         for ( ; (   ' 0 ' <= *p && *p <=  ' 9 ' && *p <  ' 0 ' +  base
            ||  ' a ' <= *p && *p <=  ' z ' && *p <  ' a ' +  base -  10
            ||  ' A ' <= *p && *p <=  ' Z ' && *p <  ' A ' +  base -  10); p++)
            n++;
         for (k =  1; ( 1<<k) <  base; k++)
            ;
        z = mk(((k*n +  7)&~ 7)/ 8);
        p = start;
    }
    carry = XP_fromstr(z->size, z->digits, p,
         base, &endp);
    assert(carry ==  0);
    normalize(z, z->size);
     if (endp == p) {
        endp = ( char *)str;
        z = AP_new( 0);
    }  else
        z->sign = iszero(z) || sign !=  ' - ' ?  1 : - 1;
     if (end)
        *end = ( char *)endp;
     return z;
}
char *AP_tostr( char *str,  int size,  int  base, T x) {
    XP_T q;
    assert(x);
    assert( base >=  2 &&  base <=  36);
    assert(str == NULL || size >  1);
     if (str == NULL) {
        {
             int k;
             for (k =  5; ( 1<<k) >  base; k--)
                ;
            size = ( 8*x->ndigits)/k +  1 +  1;
             if (x->sign ==  1)
                size++;
        }
        str = ALLOC(size);
    }
    q = ALLOC(x->ndigits);
    memcpy(q, x->digits, x->ndigits);
     if (x->sign == - 1) {
        str[ 0] =  ' - ';
        XP_tostr(str +  1, size -  1base, x->ndigits, q);
    }  else
        XP_tostr(str, size,  base, x->ndigits, q);
    FREE(q);
     return str;
}
void AP_fmt( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision) {
    T x;
     char *buf;
    assert(app && flags);
    x = va_arg(*app, T);
    assert(x);
    buf = AP_tostr(NULL,  010, x);
    Fmt_putd(buf, strlen(buf), put, cl, flags,
        width, precision);
    FREE(buf);
}
复制代码

 

calc.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/ap.doc,v 1.11 1996/06/26 23:02:01 drh Exp $ ";
#include <ctype.h>
#include <stdio.h>
#include < string.h>
#include <stdlib.h>
#include  " stack.h "
#include  " ap.h "
#include  " fmt.h "
Stack_T sp;
AP_T pop( void) {
     if (!Stack_empty(sp))
         return Stack_pop(sp);
     else {
        Fmt_fprint(stderr,  " ?stack underflow\n ");
         return AP_new( 0);
    }
}
int main( int argc,  char *argv[]) {
     int c;
    sp = Stack_new();
    Fmt_register( ' D ', AP_fmt);
     while ((c = getchar()) != EOF)
         switch (c) {
         case  '   'case  ' \t 'case  ' \n 'case  ' \f 'case  ' \r ':
             break;
         case  ' 0 'case  ' 1 'case  ' 2 'case  ' 3 'case  ' 4 ':
         case  ' 5 'case  ' 6 'case  ' 7 'case  ' 8 'case  ' 9 ': {
             char buf[ 512];
            {
                 int i =  0;
                 for ( ; c != EOF && isdigit(c); c = getchar(), i++)
                     if (i < ( int) sizeof (buf) -  1)
                        buf[i] = c;
                 if (i > ( int) sizeof (buf) -  1) {
                    i = ( int) sizeof (buf) -  1;
                    Fmt_fprint(stderr,
                         " ?integer constant exceeds %d digits\n ", i);
                }
                buf[i] =  0;
                 if (c != EOF)
                    ungetc(c, stdin);
            }
            Stack_push(sp, AP_fromstr(buf,  10, NULL));
             break;
        }
         case  ' + ': {
            AP_T y = pop(), x = pop();
            Stack_push(sp, AP_add(x, y));
            AP_free(&x);
            AP_free(&y);
             break;
        }
         case  ' - ': {
            AP_T y = pop(), x = pop();
            Stack_push(sp, AP_sub(x, y));
            AP_free(&x);
            AP_free(&y);
             break;
        }
         case  ' * ': {
            AP_T y = pop(), x = pop();
            Stack_push(sp, AP_mul(x, y));
            AP_free(&x);
            AP_free(&y);
             break;
        }
         case  ' / ': {
            AP_T y = pop(), x = pop();
             if (AP_cmpi(y,  0) ==  0) {
                Fmt_fprint(stderr,  " ?/ by 0\n ");
                Stack_push(sp, AP_new( 0));
            }  else
                Stack_push(sp, AP_div(x, y));
            AP_free(&x);
            AP_free(&y);
             break;
        }
         case  ' % ': {
            AP_T y = pop(), x = pop();
             if (AP_cmpi(y,  0) ==  0) {
                Fmt_fprint(stderr,  " ?%% by 0\n ");
                Stack_push(sp, AP_new( 0));
            }  else
                Stack_push(sp, AP_mod(x, y));
            AP_free(&x);
            AP_free(&y);
             break;
        }
         case  ' ^ ': {
            AP_T y = pop(), x = pop();
             if (AP_cmpi(y,  0) <=  0) {
                Fmt_fprint(stderr,  " ?nonpositive power\n ");
                Stack_push(sp, AP_new( 0));
            }  else
                Stack_push(sp, AP_pow(x, y, NULL));
            AP_free(&x);
            AP_free(&y);
             break;
        }
         case  ' d ': {
            AP_T x = pop();
            Stack_push(sp, x);
            Stack_push(sp, AP_addi(x,  0));
             break;
        }
         case  ' p ': {
            AP_T x = pop();
            Fmt_print( " %D\n ", x);
            Stack_push(sp, x);
             break;
        }
         case  ' f ':
             if (!Stack_empty(sp)) {
                Stack_T tmp = Stack_new();
                 while (!Stack_empty(sp)) {
                    AP_T x = pop();
                    Fmt_print( " %D\n ", x);
                    Stack_push(tmp, x);
                }
                 while (!Stack_empty(tmp))
                    Stack_push(sp, Stack_pop(tmp));
                Stack_free(&tmp);
            }
             break;
         case  ' ~ ': {
            AP_T x = pop();
            Stack_push(sp, AP_neg(x));
            AP_free(&x);
             break;
        }
         case  ' c 'while (!Stack_empty(sp)) {
                  AP_T x = Stack_pop(sp);
                  AP_free(&x);
              }  break;
         case  ' q 'while (!Stack_empty(sp)) {
                  AP_T x = Stack_pop(sp);
                  AP_free(&x);
              }
              Stack_free(&sp);
               return EXIT_SUCCESS;
         default:
             if (isprint(c))
                Fmt_fprint(stderr,  " ?'%c' ", c);
             else
                Fmt_fprint(stderr,  " ?'\\%03o' ", c);
            Fmt_fprint(stderr,  "  is unimplemented\n ");
             break;
        }
     while (!Stack_empty(sp)) {
        AP_T x = Stack_pop(sp);
        AP_free(&x);
    }
    Stack_free(&sp);
     return EXIT_SUCCESS;
}
复制代码

 

mp.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/mp.doc,v 1.11 1996/06/26 23:02:01 drh Exp $  */
#ifndef MP_INCLUDED
#define MP_INCLUDED
#include <stdarg.h>
#include <stddef.h>
#include  " except.h "
#define T MP_T
typedef unsigned  char *T;
extern  const Except_T MP_Overflow;
extern  const Except_T MP_Dividebyzero;
extern  int MP_set( int n);
extern T MP_new(unsigned  long u);
extern T MP_fromint (T z,  long v);
extern T MP_fromintu(T z, unsigned  long u);
extern unsigned  long MP_tointu(T x);
extern           long MP_toint (T x);
extern T MP_cvt ( int m, T z, T x);
extern T MP_cvtu( int m, T z, T x);
extern T MP_add (T z, T x, T y);
extern T MP_sub (T z, T x, T y);
extern T MP_mul (T z, T x, T y);
extern T MP_div (T z, T x, T y);
extern T MP_mod (T z, T x, T y);
extern T MP_neg (T z, T x);
extern T MP_addu(T z, T x, T y);
extern T MP_subu(T z, T x, T y);
extern T MP_mulu(T z, T x, T y);
extern T MP_divu(T z, T x, T y);
extern T MP_modu(T z, T x, T y);
extern T MP_mul2u(T z, T x, T y);
extern T MP_mul2 (T z, T x, T y);
extern T MP_addi (T z, T x,  long y);
extern T MP_subi (T z, T x,  long y);
extern T MP_muli (T z, T x,  long y);
extern T MP_divi (T z, T x,  long y);
extern T MP_addui(T z, T x, unsigned  long y);
extern T MP_subui(T z, T x, unsigned  long y);
extern T MP_mului(T z, T x, unsigned  long y);
extern T MP_divui(T z, T x, unsigned  long y);
extern           long MP_modi (T x,           long y);
extern unsigned  long MP_modui(T x, unsigned  long y);
extern  int MP_cmp  (T x, T y);
extern  int MP_cmpi (T x,  long y);
extern  int MP_cmpu (T x, T y);
extern  int MP_cmpui(T x, unsigned  long y);
extern T MP_and (T z, T x, T y);
extern T MP_or  (T z, T x, T y);
extern T MP_xor (T z, T x, T y);
extern T MP_not (T z, T x);
extern T MP_andi(T z, T x, unsigned  long y);
extern T MP_ori (T z, T x, unsigned  long y);
extern T MP_xori(T z, T x, unsigned  long y);
extern T MP_lshift(T z, T x,  int s);
extern T MP_rshift(T z, T x,  int s);
extern T MP_ashift(T z, T x,  int s);
extern T     MP_fromstr(T z,  const  char *str,
     int  basechar **end);
extern  char *MP_tostr  ( char *str,  int size,
     int  base, T x);
extern  void  MP_fmt    ( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision);
extern  void  MP_fmtu   ( int code, va_list *app,
     int put( int c,  void *cl),  void *cl,
    unsigned  char flags[],  int width,  int precision);
#undef T
#endif
复制代码

mpcalc.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/mp.doc,v 1.11 1996/06/26 23:02:01 drh Exp $ ";
#include <ctype.h>
#include <stdio.h>
#include < string.h>
#include <stdlib.h>
#include <limits.h>
#include  " mem.h "
#include  " seq.h "
#include  " fmt.h "
#include  " mp.h "
Seq_T sp;
int ibase =  10;
int obase =  10;
struct {
     char *fmt;
    MP_T (*add)(MP_T, MP_T, MP_T);
    MP_T (*sub)(MP_T, MP_T, MP_T);
    MP_T (*mul)(MP_T, MP_T, MP_T);
    MP_T (*div)(MP_T, MP_T, MP_T);
    MP_T (*mod)(MP_T, MP_T, MP_T);
} s = {  " %D\n ",
    MP_add,  MP_sub,  MP_mul,  MP_div,  MP_mod  },
  u = {  " %U\n ",
    MP_addu, MP_subu, MP_mulu, MP_divu, MP_modu },
 *f = &s;
MP_T pop( void) {
     if (Seq_length(sp) >  0)
         return Seq_remhi(sp);
     else {
        Fmt_fprint(stderr,  " ?stack underflow\n ");
         return MP_new( 0);
    }
}
int main( int argc,  char *argv[]) {
     int c;
    sp = Seq_new( 0);
    Fmt_register( ' D ', MP_fmt);
    Fmt_register( ' U ', MP_fmtu);
     while ((c = getchar()) != EOF) {
        MP_T x = NULL, y = NULL, z = NULL;
        TRY
              switch (c) {
             default:
                 if (isprint(c))
                    Fmt_fprint(stderr,  " ?'%c' ", c);
                 else
                    Fmt_fprint(stderr,  " ?'\\%03o' ", c);
                Fmt_fprint(stderr,  "  is unimplemented\n ");
                 break;
             case  '   'case  ' \t 'case  ' \n 'case  ' \f 'case  ' \r ':
                 break;
             case  ' c 'while (Seq_length(sp) >  0) {
                      MP_T x = Seq_remhi(sp);
                      FREE(x);
                  }  break;
             case  ' q 'while (Seq_length(sp) >  0) {
                      MP_T x = Seq_remhi(sp);
                      FREE(x);
                  }
                  Seq_free(&sp);
                   return EXIT_SUCCESS;
             case  ' 0 'case  ' 1 'case  ' 2 'case  ' 3 'case  ' 4 ':
             case  ' 5 'case  ' 6 'case  ' 7 'case  ' 8 'case  ' 9 ': {
                 char buf[ 512];
                z = MP_new( 0);
                {
                     int i =  0;
                     for ( ;  strchr(& " zyxwvutsrqponmlkjihgfedcba9876543210 "[ 36-ibase],
                            tolower(c)); c = getchar(), i++)
                         if (i < ( int) sizeof (buf) -  1)
                            buf[i] = c;
                     if (i > ( int) sizeof (buf) -  1) {
                        i = ( int) sizeof (buf) -  1;
                        Fmt_fprint(stderr,
                             " ?integer constant exceeds %d digits\n ", i);
                    }
                    buf[i] =  ' \0 ';
                     if (c != EOF)
                        ungetc(c, stdin);
                }
                MP_fromstr(z, buf, ibase, NULL);
                 break;
            }
             case  ' + ': y = pop(); x = pop();
                  z = MP_new( 0); (*f->add)(z, x, y);  break;
             case  ' - ': y = pop(); x = pop();
                  z = MP_new( 0); (*f->sub)(z, x, y);  break;
             case  ' * ': y = pop(); x = pop();
                  z = MP_new( 0); (*f->mul)(z, x, y);  break;
             case  ' / ': y = pop(); x = pop();
                  z = MP_new( 0); (*f->div)(z, x, y);  break;
             case  ' % ': y = pop(); x = pop();
                  z = MP_new( 0); (*f->mod)(z, x, y);  break;
             case  ' & ': y = pop(); x = pop();
                  z = MP_new( 0);    MP_and(z, x, y);  break;
             case  ' | ': y = pop(); x = pop();
                  z = MP_new( 0);    MP_or (z, x, y);  break;
             case  ' ^ ': y = pop(); x = pop();
                  z = MP_new( 0);    MP_xor(z, x, y);  break;
             case  ' ! ': z = pop(); MP_not(z, z);  break;
             case  ' ~ ': z = pop(); MP_neg(z, z);  break;
             case  ' i 'case  ' o ': {
                 long n;
                x = pop();
                n = MP_toint(x);
                 if (n <  2 || n >  36)
                    Fmt_fprint(stderr,  " ?%d is an illegal base\n ",n);
                 else  if (c ==  ' i ')
                    ibase = n;
                 else
                    obase = n;
                 if (obase ==  2 || obase ==  8 || obase ==  16)
                    f = &u;
                 else
                    f = &s;
                 break;
                }
             case  ' p ':
                Fmt_print(f->fmt, z = pop(), obase);
                 break;
             case  ' f ': {
                 int n = Seq_length(sp);
                 while (--n >  0)
                    Fmt_print(f->fmt, Seq_get(sp, n), obase);
                 break;
            }
             case  ' < ': {  long s;
                    y = pop();
                    z = pop();
                    s = MP_toint(y);
                     if (s <  0 || s > INT_MAX) {
                        Fmt_fprint(stderr,
                             " ?%d is an illegal shift amount\n ", s);
                         break;
                    }; MP_lshift(z, z, s);  break; }
             case  ' > ': {  long s;
                    y = pop();
                    z = pop();
                    s = MP_toint(y);
                     if (s <  0 || s > INT_MAX) {
                        Fmt_fprint(stderr,
                             " ?%d is an illegal shift amount\n ", s);
                         break;
                    }; MP_rshift(z, z, s);  break; }
             case  ' k ': {
                 long n;
                x = pop();
                n = MP_toint(x);
                 if (n <  2 || n > INT_MAX)
                    Fmt_fprint(stderr,
                         " ?%d is an illegal precision\n ", n);
                 else  if (Seq_length(sp) >  0)
                    Fmt_fprint(stderr,  " ?nonempty stack\n ");
                 else
                    MP_set(n);
                 break;
                }
             case  ' d ': {
                MP_T x = pop();
                z = MP_new( 0);
                Seq_addhi(sp, x);
                MP_addui(z, x,  0);
                 break;
                }
            }
        EXCEPT(MP_Overflow)
            Fmt_fprint(stderr,  " ?overflow\n ");
        EXCEPT(MP_Dividebyzero)
            Fmt_fprint(stderr,  " ?divide by 0\n ");
        END_TRY;
         if (z)
            Seq_addhi(sp, z);
        FREE(x);
        FREE(y);
    }
     while (Seq_length(sp) >  0) {
        MP_T x = Seq_remhi(sp);
        FREE(x);
    }
    Seq_free(&sp);
     return EXIT_SUCCESS;
}
复制代码

 

thread.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/thread.doc,v 1.11 1997/02/21 19:50:51 drh Exp $  */
#ifndef THREAD_INCLUDED
#define THREAD_INCLUDED
#include  " except.h "
#define T Thread_T
typedef  struct T *T;
extern  const Except_T Thread_Failed;
extern  const Except_T Thread_Alerted;
extern  int  Thread_init ( int preempt, ...);
extern T    Thread_new  ( int apply( void *),
                 void *args,  int nbytes, ...);
extern  void Thread_exit ( int code);
extern  void Thread_alert(T t);
extern T    Thread_self ( void);
extern  int  Thread_join (T t);
extern  void Thread_pause( void);
#undef T
#endif
复制代码

 

sem.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/thread.doc,v 1.11 1997/02/21 19:50:51 drh Exp $  */
#ifndef SEM_INCLUDED
#define SEM_INCLUDED
#define T Sem_T
typedef  struct T {
     int count;
     void *queue;
} T;
#define LOCK(mutex) do { Sem_T *_yymutex = &(mutex); \
    Sem_wait(_yymutex);
#define END_LOCK Sem_signal(_yymutex); } while (0)
extern  void Sem_init  (T *s,  int count);
extern T   *Sem_new   ( int count);
extern  void Sem_wait  (T *s);
extern  void Sem_signal(T *s);
#undef T
#endif
复制代码

 

thread.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/thread.doc,v 1.11 1997/02/21 19:50:51 drh Exp $ ";
#include <stdio.h>
#include <stdlib.h>
#include < string.h>
#include </usr/include/signal.h>
#include <sys/time.h>
#include  " assert.h "
#include  " mem.h "
#include  " thread.h "
#include  " sem.h "
void _MONITOR( void) {}
extern  void _ENDMONITOR( void);
#define T Thread_T
#define isempty(q) ((q) == NULL)
struct T {
    unsigned  long *sp;                         /*  must be first  */
    T link;
    T *inqueue;
    T handle;
    Except_Frame *estack;
     int code;
    T join;
    T next;
     int alerted;
};
static T ready = NULL;
static T current;
static  int nthreads;
static  struct Thread_T root;
static T join0;
static T freelist;
const Except_T Thread_Alerted = {  " Thread alerted " };
const Except_T Thread_Failed =
    {  " Thread creation failed " };
static  int critical;
extern  void _swtch(T  from, T to);
static  void put(T t, T *q) {
    assert(t);
    assert(t->inqueue == NULL && t->link == NULL);
     if (*q) {
        t->link = (*q)->link;
        (*q)->link = t;
    }  else
        t->link = t;
    *q = t;
    t->inqueue = q;
}
static T  get(T *q) {
    T t;
    assert(!isempty(*q));
    t = (*q)->link;
     if (t == *q)
        *q = NULL;
     else
        (*q)->link = t->link;
    assert(t->inqueue == q);
    t->link = NULL;
    t->inqueue = NULL;
     return t;
}
static  void delete(T t, T *q) {
    T p;
    assert(t->link && t->inqueue == q);
    assert(!isempty(*q));
     for (p = *q; p->link != t; p = p->link)
        ;
     if (p == t)
        *q = NULL;
     else {
        p->link = t->link;
         if (*q == t)
            *q = p;
    }
    t->link = NULL;
    t->inqueue = NULL;
}
static  void run( void) {
    T t = current;
    current =  get(&ready);
    t->estack = Except_stack;
    Except_stack = current->estack;
    _swtch(t, current);
}
static  void testalert( void) {
     if (current->alerted) {
        current->alerted =  0;
        RAISE(Thread_Alerted);
    }
}
static  void release( void) {
    T t;
     do { critical++;
     while ((t = freelist) != NULL) {
        freelist = t->next;
        FREE(t);
    }
    critical--; }  while ( 0);
}
#if linux
#include <asm/sigcontext.h>
static  int interrupt( int sig,  struct sigcontext_struct sc) {
     if (critical ||
       sc.eip >= (unsigned  long)_MONITOR
    && sc.eip <= (unsigned  long)_ENDMONITOR)
         return  0;
    put(current, &ready);
     do { critical++;
    sigsetmask(sc.oldmask);
    critical--; }  while ( 0);
    run();
     return  0;
}
#else
static  int interrupt( int sig,  int code,
     struct sigcontext *scp) {
     if (critical ||
       scp->sc_pc >= (unsigned  long)_MONITOR
    && scp->sc_pc <= (unsigned  long)_ENDMONITOR)
         return  0;
    put(current, &ready);
    sigsetmask(scp->sc_mask);
    run();
     return  0;
}
#endif
int Thread_init( int preempt, ...) {
    assert(preempt ==  0 || preempt ==  1);
    assert(current == NULL);
    root.handle = &root;
    current = &root;
    nthreads =  1;
     if (preempt) {
        {
             struct sigaction sa;
            memset(&sa,  ' \0 'sizeof sa);
            sa.sa_handler = ( void (*)())interrupt;
             if (sigaction(SIGVTALRM, &sa, NULL) <  0)
                 return  0;
        }
        {
             struct itimerval it;
            it.it_value.tv_sec     =   0;
            it.it_value.tv_usec    =  50;
            it.it_interval.tv_sec  =   0;
            it.it_interval.tv_usec =  50;
             if (setitimer(ITIMER_VIRTUAL, &it, NULL) <  0)
                 return  0;
        }
    }
     return  1;
}
T Thread_self( void) {
    assert(current);
     return current;
}
void Thread_pause( void) {
    assert(current);
    put(current, &ready);
    run();
}
int Thread_join(T t) {
    assert(current && t != current);
    testalert();
     if (t) {
         if (t->handle == t) {
            put(current, &t->join);
            run();
            testalert();
             return current->code;
        }  else
             return - 1;
    }  else {
        assert(isempty(join0));
         if (nthreads >  1) {
            put(current, &join0);
            run();
            testalert();
        }
         return  0;
    }
}
void Thread_exit( int code) {
    assert(current);
    release();
     if (current != &root) {
        current->next = freelist;
        freelist = current;
    }
    current->handle = NULL;
     while (!isempty(current->join)) {
        T t =  get(&current->join);
        t->code = code;
        put(t, &ready);
    }
     if (!isempty(join0) && nthreads ==  2) {
        assert(isempty(ready));
        put( get(&join0), &ready);
    }
     if (--nthreads ==  0)
        exit(code);
     else
        run();
}
void Thread_alert(T t) {
    assert(current);
    assert(t && t->handle == t);
    t->alerted =  1;
     if (t->inqueue) {
        delete(t, t->inqueue);
        put(t, &ready);
    }
}
T Thread_new( int apply( void *),  void *args,
     int nbytes, ...) {
     T t;
    assert(current);
    assert(apply);
    assert(args && nbytes >=  0 || args == NULL);
     if (args == NULL)
        nbytes =  0;
    {
         int stacksize = ( 16* 1024+ sizeof (*t)+nbytes+ 15)&~ 15;
        release();
         do { critical++;
        TRY
            t = ALLOC(stacksize);
            memset(t,  ' \0 'sizeof *t);
        EXCEPT(Mem_Failed)
            t = NULL;
        END_TRY;
        critical--; }  while ( 0);
         if (t == NULL)
            RAISE(Thread_Failed);
        t->sp = ( void *)(( char *)t + stacksize);
         while (((unsigned  long)t->sp)& 15)
            t->sp--;
    }
    t->handle = t;
     if (nbytes >  0) {
        t->sp -= ((nbytes +  15U)&~ 15)/ sizeof (*t->sp);
         do { critical++;
        memcpy(t->sp, args, nbytes);
        critical--; }  while ( 0);
        args = t->sp;
    }
#if alpha
    {  extern  void _start( void);
      t->sp -=  112/ 8;
      t->sp[( 48+ 24)/ 8] = (unsigned  long)Thread_exit;
      t->sp[( 48+ 16)/ 8] = (unsigned  long)args;
      t->sp[( 488)/ 8] = (unsigned  long)apply;
      t->sp[( 480)/ 8] = (unsigned  long)_start; }
#elif mips
    {  extern  void _start( void);
      t->sp -=  16/ 4;
      t->sp -=  88/ 4;
      t->sp[( 48+ 20)/ 4] = (unsigned  long)Thread_exit;
      t->sp[( 48+ 28)/ 4] = (unsigned  long)args;
      t->sp[( 48+ 32)/ 4] = (unsigned  long)apply;
      t->sp[( 48+ 36)/ 4] = (unsigned  long)_start; }
#elif sparc
    {      int i;  void *fp;  extern  void _start( void);
           for (i =  0; i <  8; i++)
              *--t->sp =  0;
          *--t->sp = (unsigned  long)args;
          *--t->sp = (unsigned  long)apply;
          t->sp -=  64/ 4;
          fp = t->sp;
          *--t->sp = (unsigned  long)_start -  8;
          *--t->sp = (unsigned  long)fp;
          t->sp -=  64/ 4; }
#elif linux && i386
    {  extern  void _thrstart( void);
      t->sp -=  4/ 4;
      *t->sp = (unsigned  long)_thrstart;
      t->sp -=  16/ 4;
      t->sp[ 4/ 4]  = (unsigned  long)apply;
      t->sp[ 8/ 4]  = (unsigned  long)args;
      t->sp[ 12/ 4] = (unsigned  long)t->sp + ( 4+ 16)/ 4; }
#else
    Unsupported platform
#endif
    nthreads++;
    put(t, &ready);
     return t;
}
#undef T
#define T Sem_T
T *Sem_new( int count) {
    T *s;
    NEW(s);
    Sem_init(s, count);
     return s;
}
void Sem_init(T *s,  int count) {
    assert(current);
    assert(s);
    s->count = count;
    s->queue = NULL;
}
void Sem_wait(T *s) {
    assert(current);
    assert(s);
    testalert();
     if (s->count <=  0) {
        put(current, (Thread_T *)&s->queue);
        run();
        testalert();
    }  else
        --s->count;
}
void Sem_signal(T *s) {
    assert(current);
    assert(s);
     if (s->count ==  0 && !isempty(s->queue)) {
        Thread_T t =  get((Thread_T *)&s->queue);
        assert(!t->alerted);
        put(t, &ready);
    }  else
        ++s->count;
}
#undef T
复制代码

 

thread-nt.c

复制代码
#include <stdio.h>
#include <stdlib.h>
#include < string.h>
#include <limits.h>
#include <windows.h>
#include <process.h>
#include  " assert.h "
#include  " mem.h "
#include  " thread.h "
#include  " sem.h "

static  char rcsid[] =  " $Id: thread-nt.c,v 1.5 1997/07/29 17:10:25 drh Exp $ ";

#define T Thread_T
struct T {
    DWORD IDThread;         /*  Win 32 thread identifier  */
    T handle;         /*  self pointer  */
     int code;         /*  exit code  */
    HANDLE join;         /*  join semaphore  */
    T joinlist;         /*  threads waiting on join  */
    T link;             /*  next thread on this join list  */
    T next;             /*  next thread on this hash chain  */
     int alerted;         /*  1 if this thread has been alerted  */
     int (*apply)( void *);     /*  initial function for this thread  */
     void *args;         /*  argument for apply  */
};

const Except_T Thread_Alerted = {  " Thread alerted " };
const Except_T Thread_Failed  = {  " Thread creation failed " };

static T allthreads[ 317];
#define HASH(id) ((int)((id)%(sizeof allthreads/sizeof allthreads[0])))
static  int nthreads;         /*  number of threads in allthreads  */
static T root;
static HANDLE join0;         /*  Thread_join(NULL) semaphore  */
static  int join0count;         /*  number of threads waiting on join0; always 0 or 1  */

static  int critical;
static CRITICAL_SECTION csection;
#define ENTERCRITICAL EnterCriticalSection(&csection); assert(critical == 0); critical++
#define LEAVECRITICAL   critical--; assert(critical == 0); LeaveCriticalSection(&csection)

static T getThreadByID(DWORD id) {
    T t;

    ENTERCRITICAL;
     for (t = allthreads[HASH(id)]; t != NULL; t = t->next)
         if (t->IDThread == id)
             break;
    LEAVECRITICAL;
    assert(t);
     return t;
}

static  void removeThread(T t) {
    T *q;

    ENTERCRITICAL;
    q = &allthreads[HASH(t->IDThread)];
     for ( ; *q != NULL && *q != t; q = &(*q)->next)
        ;
    assert(*q == t);
    *q = t->next;
    nthreads--;
    t->handle = NULL;
    LEAVECRITICAL;
}

static  void addThread(T t) {
    T *q;

    ENTERCRITICAL;
    q = &allthreads[HASH(t->IDThread)];
    t->next = *q;
    *q = t;
    nthreads++;
    t->handle = t;
    LEAVECRITICAL;
}

static  void testalert(T t) {
    ENTERCRITICAL;
     if (t->alerted) {
        t->alerted =  0;
        LEAVECRITICAL;
        RAISE(Thread_Alerted);
    }
    LEAVECRITICAL;
}

int Thread_init( int preempt, ...) {
    assert(preempt ==  0 || preempt ==  1);
    assert(root == NULL);
    TRY
        NEW0(root);
    EXCEPT(Mem_Failed)
         return - 1;
    END_TRY;
    join0 = CreateSemaphore(NULL,  01, NULL);
     if (join0 == NULL)
         return - 1;
    root->join = CreateSemaphore(NULL,  0, INT_MAX, NULL);
     if (root->join == NULL) {
        BOOL result = CloseHandle(join0);
        assert(result == TRUE);
         return - 1;
    }
    InitializeCriticalSection(&csection);
    root->IDThread = GetCurrentThreadId();
    addThread(root);
     /*  handle preempt == 0  */
     return  1;
}

T Thread_self( void) {
    assert(root);
     return getThreadByID(GetCurrentThreadId());
}

void Thread_pause( void) {
    assert(root);
    Sleep( 0);
}

int Thread_join(T t) {
    T current = Thread_self();

    assert(root);
    assert(t != current);
    testalert(current);
     if (t != NULL) {
        ENTERCRITICAL;
         if (t->handle == t) {
            HANDLE join = t->join;
            DWORD result;
            assert(current->link == NULL);
            current->link = t->joinlist;
            t->joinlist = current;
            LEAVECRITICAL;
            result = WaitForSingleObject(join, INFINITE);
            assert(result != WAIT_FAILED);
            testalert(current);
             return current->code;
        }  else {
            LEAVECRITICAL;
             return - 1;
        }
    }
    ENTERCRITICAL;
     if (nthreads >  1) {
        DWORD result;
        assert(join0count ==  0);
        join0count++;
        LEAVECRITICAL;
        result = WaitForSingleObject(join0, INFINITE);
        assert(result != WAIT_FAILED);
        ENTERCRITICAL;
        join0count--;
        LEAVECRITICAL;
        testalert(current);
    }  else {
        assert(join0count ==  0);
        LEAVECRITICAL;
         return  0;
    }
}

void Thread_exit( int code) {
    BOOL result;
    T current = Thread_self();

    removeThread(current);
    ENTERCRITICAL;
     if (current->joinlist != NULL) {
        T t, n;
         int count =  0;
        assert(current->join);
         for (t = current->joinlist; t != NULL; t = n) {
            t->code = code;
            n = t->link;
            t->link = NULL;
            count++;
        }
        current->joinlist = NULL;
        result = ReleaseSemaphore(current->join, count, NULL);
        assert(result == TRUE);
    }
    result = CloseHandle(current->join);
    assert(result == TRUE);
    current->join = NULL;
     if (join0count >  0 && nthreads ==  1) {
        assert(join0count ==  1);
        result = ReleaseSemaphore(join0,  1, NULL);
        assert(result == TRUE);
    }
     if (nthreads ==  0) {
        result = CloseHandle(join0);
        assert(result == TRUE);
    }
    FREE(current);
    LEAVECRITICAL;
    _endthreadex(code);
}

void Thread_alert(T t) {
    assert(root);
    ENTERCRITICAL;
    assert(t && t->handle == t);
    t->alerted =  1;
    LEAVECRITICAL;
}

static unsigned __stdcall start( void *p) {
    T t = p;

    Except_stack = NULL;
    Thread_exit((*t->apply)(t->args));
     return  0;
}

T Thread_new( int apply( void *),  void *args,  int nbytes, ...) {
    T t;
    HANDLE hThread;

    assert(root);
    assert(apply);
    assert(args && nbytes >=  0 || args == NULL);
     if (args == NULL)
        nbytes =  0;
    TRY
        t = ALLOC(( sizeof (*t) + nbytes +  15)&~ 15);
        memset(t,  ' \0 'sizeof *t);
    EXCEPT(Mem_Failed)
        RAISE(Thread_Failed);
    END_TRY;
    t->join = CreateSemaphore(NULL,  0, INT_MAX, NULL);
     if (t->join == NULL) {
        FREE(t);
        RAISE(Thread_Failed);
    }
     if (nbytes >  0) {
        t->args = t +  1;
        memcpy(t->args, args, nbytes);
    }  else
        t->args = args;
    t->apply = apply;
    hThread = (HANDLE)_beginthreadex(
        NULL,         /*  default security attributes  */
         0,         /*  default stack size  */
        start,         /*  initial function  */
        t,         /*  start's argument  */
         0,         /*  default thread creation flags  */
        &t->IDThread     /*  where to store the thread id  */
        );
     if (hThread == NULL) {
        CloseHandle(t->join);
        FREE(t);
        RAISE(Thread_Failed);
    }
    CloseHandle(hThread);
    addThread(t);
     return t;
}
#undef T

#define T Sem_T
T *Sem_new( int count) {
    T *s;

    NEW(s);
    Sem_init(s, count);
     return s;
}

void Sem_init(T *s,  int count) {
    assert(root);
    assert(s);
    assert(count >=  0);
    s->count =  0;
    s->queue = CreateSemaphore(NULL, count, INT_MAX, NULL);
    assert(s->queue);
}

void Sem_wait(T *s) {
    DWORD result;
    Thread_T current = Thread_self();

    assert(s);
    testalert(current);
    result = WaitForSingleObject(s->queue, INFINITE);
    assert(result != WAIT_FAILED);
    ENTERCRITICAL;
     if (current->alerted) {
        BOOL result;
        current->alerted =  0;
        LEAVECRITICAL;
        result = ReleaseSemaphore(s->queue,  1, NULL);
        assert(result == TRUE);
        RAISE(Thread_Alerted);
    }
    LEAVECRITICAL;
}

void Sem_signal(T *s) {
    BOOL result;

    assert(root);
    assert(s);
    result = ReleaseSemaphore(s->queue,  1, NULL);
    assert(result == TRUE);
}
#undef T
复制代码

 

 

chan.h

复制代码
/*  $Id: H:/drh/idioms/book/RCS/thread.doc,v 1.11 1997/02/21 19:50:51 drh Exp $  */
#ifndef CHAN_INCLUDED
#define CHAN_INCLUDED
#define T Chan_T
typedef  struct T *T;
extern T   Chan_new    ( void);
extern  int Chan_send   (T c,  const  void *ptr,  int size);
extern  int Chan_receive(T c,        void *ptr,  int size);
#undef T
#endif
复制代码

 

chain.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/thread.doc,v 1.11 1997/02/21 19:50:51 drh Exp $ ";
#include < string.h>
#include  " assert.h "
#include  " mem.h "
#include  " chan.h "
#include  " sem.h "
#define T Chan_T
struct T {
     const  void *ptr;
     int *size;
    Sem_T send, recv, sync;
};
T Chan_new( void) {
    T c;
    NEW(c);
    Sem_init(&c->send,  1);
    Sem_init(&c->recv,  0);
    Sem_init(&c->sync,  0);
     return c;
}
int Chan_send(Chan_T c,  const  void *ptr,  int size) {
    assert(c);
    assert(ptr);
    assert(size >=  0);
    Sem_wait(&c->send);
    c->ptr = ptr;
    c->size = &size;
    Sem_signal(&c->recv);
    Sem_wait(&c->sync);
     return size;
}
int Chan_receive(Chan_T c,  void *ptr,  int size) {
     int n;
    assert(c);
    assert(ptr);
    assert(size >=  0);
    Sem_wait(&c->recv);
    n = *c->size;
     if (size < n)
        n = size;
    *c->size = n;
     if (n >  0)
        memcpy(ptr, c->ptr, n);
    Sem_signal(&c->sync);
    Sem_signal(&c->send);
     return n;
}
复制代码

 

sort.c

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/thread.doc,v 1.11 1997/02/21 19:50:51 drh Exp $ ";
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include  " assert.h "
#include  " fmt.h "
#include  " thread.h "
#include  " mem.h "
struct args {
     int *a;
     int lb, ub;
};
int cutoff =  10000;
int partition( int a[],  int i,  int j) {
     int v, k, t;
    j++;
    k = i;
    v = a[k];
     while (i < j) {
        i++;  while (a[i] < v && i < j) i++;
        j--;  while (a[j] > v         ) j--;
         if (i < j) { t = a[i]; a[i] = a[j]; a[j] = t; }
    }
    t = a[k]; a[k] = a[j]; a[j] = t;
     return j;
}
int quick( void *cl) {
     struct args *p = cl;
     int lb = p->lb, ub = p->ub;
     if (lb < ub) {
         int k = partition(p->a, lb, ub);
        p->lb = lb;
        p->ub = k -  1;
         if (k - lb > cutoff) {
            Thread_T t;
            t = Thread_new(quick, p,  sizeof *p, NULL);
            Fmt_print( " thread %p sorted %d..%d\n ", t, lb, k -  1);
        }  else
            quick(p);
        p->lb = k +  1;
        p->ub = ub;
         if (ub - k > cutoff) {
            Thread_T t;
            t = Thread_new(quick, p,  sizeof *p, NULL);
            Fmt_print( " thread %p sorted %d..%d\n ", t, k +  1, ub);
        }  else
            quick(p);
    }
     return EXIT_SUCCESS;
}
void sort( int *x,  int n,  int argc,  char *argv[]) {
     struct args args;
     if (argc >=  3)
        cutoff = atoi(argv[ 2]);
    args.a = x;
    args.lb =  0;
    args.ub = n -  1;
    quick(&args);
    Thread_join(NULL);
}
main( int argc,  char *argv[]) {
     int i, n =  100000, *x, preempt;
    preempt = Thread_init( 1, NULL);
    assert(preempt ==  1);
     if (argc >=  2)
        n = atoi(argv[ 1]);
    x = CALLOC(n,  sizeof ( int));
    srand(time(NULL));
     for (i =  0; i < n; i++)
        x[i] = rand();
    sort(x, n, argc, argv);
     for (i =  1; i < n; i++)
         if (x[i] < x[i- 1])
             break;
    assert(i == n);
    Thread_exit(EXIT_SUCCESS);
     return EXIT_SUCCESS;
}
复制代码

 

 

 

 

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/thread.doc,v 1.11 1997/02/21 19:50:51 drh Exp $ ";
#include <stdio.h>
#include <stdlib.h>
#include  " assert.h "
#include  " fmt.h "
#include  " thread.h "
#include  " sem.h "
#define NBUMP 30000
struct args {
    Sem_T *mutex;
     int *ip;
};
int  unsafe( void *cl) {
     int i, *ip = cl;
     for (i =  0; i < NBUMP; i++)
        *ip = *ip +  1;
     return EXIT_SUCCESS;
}
int safe( void *cl) {
     struct args *p = cl;
     int i;
     for (i =  0; i < NBUMP; i++)
        LOCK(*p->mutex)
            *p->ip = *p->ip +  1;
        END_LOCK;
     return EXIT_SUCCESS;
}
int n;
int main( int argc,  char *argv[]) {
     int m =  5, preempt;
    preempt = Thread_init( 1, NULL);
    assert(preempt ==  1);
     if (argc >=  2)
        m = atoi(argv[ 1]);
    n =  0;
    {
         int i;
         for (i =  0; i < m; i++)
            Thread_new( unsafe, &n,  0, NULL);
        Thread_join(NULL);
    }
    Fmt_print( " %d == %d\n ", n, NBUMP*m);
    n =  0;
    {
         int i;
         struct args args;
        Sem_T mutex;
        Sem_init(&mutex,  1);
        args.mutex = &mutex;
        args.ip = &n;
         for (i =  0; i < m; i++)
            Thread_new(safe, &args,  sizeof args, NULL);
        Thread_join(NULL);
    }
    Fmt_print( " %d == %d\n ", n, NBUMP*m);
    Thread_exit(EXIT_SUCCESS);
     return EXIT_SUCCESS;
}
复制代码

 

 

复制代码
static  char rcsid[] =  " $Id: H:/drh/idioms/book/RCS/thread.doc,v 1.11 1997/02/21 19:50:51 drh Exp $ ";
#include <stdio.h>
#include <stdlib.h>
#include  " assert.h "
#include  " fmt.h "
#include  " thread.h "
#include  " chan.h "
struct args {
    Chan_T c;
     int n, last;
};
int source( void *cl) {
     struct args *p = cl;
     int i =  2;
     if (Chan_send(p->c, &i,  sizeof i))
         for (i =  3; Chan_send(p->c, &i,  sizeof i); )
            i +=  2;
     return EXIT_SUCCESS;
}
void filter( int primes[], Chan_T input, Chan_T output) {
     int j, x;
     for (;;) {
        Chan_receive(input, &x,  sizeof x);
         for (j =  0; primes[j] !=  0 && x%primes[j] !=  0; j++)
            ;
         if (primes[j] ==  0)
              if (Chan_send(output, &x,  sizeof x) ==  0)
                 break;
    }
    Chan_receive(input, &x,  0);
}
int sink( void *cl) {
     struct args *p = cl;
    Chan_T input = p->c;
     int i =  0, j, x, primes[ 256];
    primes[ 0] =  0;
     for (;;) {
        Chan_receive(input, &x,  sizeof x);
          for (j =  0; primes[j] !=  0 && x%primes[j] !=  0; j++)
            ;
         if (primes[j] ==  0) {
             if (x > p->last)
                 break;
            Fmt_print( "  %d ", x);
            primes[i++] = x;
            primes[i] =  0;
             if (i == p->n)
                {
                    p->c = Chan_new();
                    Thread_new(sink, p,  sizeof *p, NULL);
                    filter(primes, input, p->c);
                     return EXIT_SUCCESS;
                }
        }
    }
    Fmt_print( " \n ");
    Chan_receive(input, &x,  0);
      return EXIT_SUCCESS;
}
int main( int argc,  char *argv[]) {
     struct args args;
    Thread_init( 1, NULL);
    args.c = Chan_new();
    Thread_new(source, &args,  sizeof args, NULL);
    args.n    = argc >  2 ? atoi(argv[ 2]) :  5;
    args.last = argc >  1 ? atoi(argv[ 1]) :  1000;
    Thread_new(sink,   &args,  sizeof args, NULL);
    Thread_exit(EXIT_SUCCESS);
     return EXIT_SUCCESS;
}
复制代码
分类:  C/C++笔记
对于c语言接口网上的资料是少之又少,所以下面这些文字全是我一个字一个字打印上来的希望大家 能对的起我的付出: 现在的程序员都面临大量的关于应用程序接口(Application Programming Interface,API) 的信息,大多数人都会使用API和程序库,并在其所写的每一个应用程序中实现它们,但是很少人 会创建或发布新的能广泛应用的API,事实上,程序员似乎倾向循环使用他们自己的东西,而不 愿意查找,能满足他们要求的程序库,这或许是因为写特定应用程序代码要比查找设计好的API容易。 这里我所提到的是一种基于接口实现的设计方法,并且通过对24个接口及其实现的描述详细地演示了这种方法,这些接口涉及到计算机领域的很多知识,其中包括数据结构,算法,字符串处理 和并发程序,这些实现并不是简单的玩具----它们是为了在你们所设计的软件代码中使用而设计的。(当然了我会通过阅读量来看是否继续发下去,人要少了我就没有必要浪费时间了) c编程语言对基于接口设计方法的支持是极少的。 而面向对象的语言,如c++,Modula-3,则鼓励将接口实现分离,基于接口的设计独立任何特定 的语言,但是它要求程序员对像c一样的语言有更多的驾驭能力和更高的警惕性,因为这类语言很容易破坏带有隐含实现信息的接口,反之亦然。 然而一但掌握了基于接口的设计方法,就能够在服务于众多应用程序的通用接口基础上建立应用程序,从而加速开发,在一些c++环境中的基础类库就体现了这种效果。 增加对现有软件的重用---接口实现库,能够减少初始开发成本,同时还能减少维护成本,因为应用程序的更多部分都建立在经过良好测试的通用接口实现上,这里我提到的接口是针对数据结构的,但它并不是数据结构,我重点将放在算法引擎----包装数据结构以供应用程序使用----而不在数据结构算法本身,接口的示例和实现都以literate程序的方式给出,换句话说就是源代码及其解释是按照最适合理解代码的顺序交织出现的。 下面我将我想要给大家讲的内容分一下类: 基础 1,接口实现 2,异常断言 3,内寸管理 4,进一步内寸管理 数据结构 5,链表 6,表格 7,集合 8,动态数组 9,序列 10,环 11,位向量 字符串 12,原子 13,格式化 14,低级字符串 15,高级字符串 算法 16,扩展精度算法 17,任意精度算法 18,多精度算法 线程 19,线程 建议: 看到这里的朋友我相信对c语言都有了很长时间的学习 如果你还没有搞懂c语言的全部内容,我强烈建议你先别看这里
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值