tc(' ', fp); break; } putc(cprev = c, fp); /* */ state = TEXT; if(c == '\\') putc('e', fp); } s++; } /* */ putc ('\n', fp); } /* name */ void proceed (char *name) { FILE *fp; static unsigned char inp[2048]; /* */ if (strcmp(name, "-") == 0 ) fp = stdin; else if ((fp = fopen (name, "r")) == NULL) { fprintf (stderr, "Cannot read %s\n", name); return; } while (fgets (inp, sizeof inp, fp) != NULL) { register unsigned char *s, *p; int len = strlen (inp); if (len && inp[len - 1] == '\n') inp[--len] = '\0'; if (!*inp) { /* .sp N - N */ space: fprintf (fout, ".sp 1\n"); continue; } /* */ for(p = NULL, s = inp; *s; ++s){ if (!isspace (*s)) p = s; } if(p) p[1] = '\0'; else goto space; /* p */ /* : - , */ if (*p == '-' && p != inp /* */ && isalnum(UC(p[-1])) /* */ ){ int c; *p = '\0'; /* */ /* */ while (isspace (c = getc (fp))); ungetc (c, fp); while ((c = getc (fp)) != '\n' && !isspace (c)) *p++ = c; *p = '\0'; if (c != '\n' ){ /* */ /* */ while (isspace(c = getc (fp))); if(c != '\n') ungetc (c, fp); } } /* .pp - . */ if (isspace (*inp)) { fprintf (fout, ".pp\n"); for (s = inp; isspace (*s); s++); putstr (fout, s); } else { if (*inp == '.' || *inp == '\'') fprintf (fout, "\\&"); putstr (fout, inp); } } if( fp != stdin ) fclose (fp); } int main (int argc, char *argv[]) { int i; setlocale(LC_ALL, ""); for (i = 1; i < argc; i++) proceed (argv[i]); return 0; /* exit code */ } /* 5 */ /* , */ #include <stdio.h> #include <ctype.h> #include <string.h> #include <locale.h> #define MAXL 255 /* . */ /* ctype.h, * #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\f') */ main ( argc, argv ) char **argv;{ setlocale(LC_ALL, ""); if( argc == 1 ){ /* */ munch( "" ); }else{ /* - */ while( argv[ 1 ] ){ munch( argv[1] ); argv++; argc--; } } total(); exit(0); } /* name */ munch( name ) char *name; { char l[MAXL]; /* */ int len; /* */ char *words[50]; /* */ char **s; /* */ int nwords; /* */ FILE *fp; if( name == NULL || !*name ) fp = stdin; /* */ else if( (fp = fopen( name, "r" )) == NULL ){ fprintf( stderr, " %s\n", name ); return; } printf( "----------------------------%s----\n", name ); while( fgets( l, MAXL, fp ) != NULL ){ len = strlen( l ); if( len && l[len-1] == '\n' ) l[--len] = '\0' ; if( nwords = parse( l, words)){ /* */ for( --nwords; nwords >= 0; nwords-- ){ printf( "%s ", words[ nwords] ); add( words[ nwords ] ); } } putchar ('\n'); } if( fp != stdin ) fclose( fp ); } /* */ parse( s, tabl ) register unsigned char *s; unsigned char *tabl[]; { char eol = 0; int nwords = 0; while ( !eol ){ /* */ while(isspace(*s)) s++; if( !*s ) /* */ break; *tabl++ = s; nwords++; /* */ /* */ while( *s && !isspace(*s))s++; /* , */ if( ! *s ) eol ++; *s = '\0'; /* , */ s++; } *tabl = NULL; return nwords; } /* , */ #define MAXWORDS 1024 struct W{ int ctr; /* */ char *wrd; /* */ }w [MAXWORDS]; /* */ int busy = 0 ; /* */ extern char *malloc(); /* */ add( word ) char *word; { register i; static alert = 1; /* ? */ /* - */ for( i = 0; i < busy ; i++ ){ if( !strcmp( word, w[i].wrd )){ w[i].ctr++; return; } } if( busy >= MAXWORDS ){ if( alert ){ fprintf( stderr, " \7\n"); alert = 0; } return; } /* , . : */ w[busy].wrd = malloc( strlen( word ) + 1 ); /* 1 \0 */ if( w[busy].wrd == NULL ){ fprintf( stderr, " \n"); busy = MAXWORDS+1; /* */ return; } w[busy].ctr = 1; strcpy( w[busy].wrd, word ); busy++; } compare( a, b ) struct W *a, *b; { return strcoll( a-> wrd, b-> wrd ); /* strcoll */ } /* , , */ total(){ register i; /* */ qsort( w, busy, sizeof(struct W), compare ); printf( "-----|--------------------------\n"); for( i=0; i < busy; i++ ) printf( "%4d | %s\n", w[i].ctr, w[i].wrd ); } /* 6 */ /* "" (bubble sort) */ #define YES 1 #define NO 0 bsort(s) char *s; { register i; /* */ register need = YES; /* ? */ while( need ){ need = NO; /* */ for(i=0; s[i+1]; i++ ) /* : i- i+1- , * i+1 */ if( s[i] > s[i+1] ){ /* */ swap( &s[i], &s[i+1] ); /* */ need = YES; /* - : * */ } } } /* , */ bpsort(s) char *s; { register char *p; register need = YES; while( need ){ need = NO; for( p = s; p[1] != '\0' ; p++ ) if( *p > *(p+1) ){ swap( p, p+1 ); need = YES; } } } /* , s1 s2 */ swap( s1, s2 ) register char *s1, *s2; { char tmp; /* temporary */ tmp = *s1; *s1 = *s2; *s2 = tmp; } char sample1[] = "Homo homini lupus est - ergo bibamus!"; char sample2[ sizeof sample1 ]; /* */ main(){ strcpy( sample2, sample1 ); /* */ bsort ( sample1 ); printf( "%s\n", sample1 ); bpsort( sample2 ); printf( "%s\n", sample2 ); } /* 7 */ /* -. , * * . */ #include <stdio.h> #include <string.h> /* prototype for strchr() */ extern void *malloc(unsigned size); /* : */ typedef unsigned char uchar; typedef uchar *VAL; typedef uchar *KEY; /* int HASHFUNC(KEY); int EQKEY(KEY, KEY); void FREEVAL(VAL); void SETVAL(VAL, VAL); void FREEKEY(KEY); void SETKEY(KEY, KEY); */ #define HASHSIZE 21 /* : 2**n */ uchar *strudup(const uchar *s){ /* "" */ uchar *p = (uchar *) malloc(strlen(s)+1); strcpy(p, s); return p; } /* - */ unsigned int hash; /* - */ int HASHFUNC(KEY key){ unsigned int i = 0; uchar *keysrc = key; while(*key){ i = (i << 1)|(i >> 15); /* ROL */ i ^= *key++; } hash = i % HASHSIZE; printf( "hash(%s)=%d\n", keysrc, hash); /* */ return hash; } #define EQKEY(s1, s2) (strcmp(s1, s2) == 0) #define FREEKEY(s) free(s) #define FREEVAL(s) free(s) #define SETVAL(at,s) at = strudup(s) #define SETKEY(at,s) at = strudup(s) #define KEYFMT "%s" #define VALFMT "%s" /* ================== - ================= */ struct cell { struct cell *next; /* */ KEY key; /* */ VAL val; /* */ } *hashtable[ HASHSIZE ]; /* - */ /* */ struct cell *get(KEY key){ struct cell *p; for(p = hashtable[HASHFUNC(key)]; p; p = p->next) if(EQKEY(p->key, key)) return p; return NULL; /* */ } /* : */ void set(KEY key, VAL val){ struct cell *p; /* - */ if((p = get(key)) == NULL){ /* */ if(!(p = (struct cell *) malloc(sizeof(*p)))) return; SETKEY(p->key, key); p->next = hashtable[hash]; /* hash get() */ hashtable[hash] = p; } else /* : */ FREEVAL(p->val); SETVAL(p->val, val); } /* */ int del(KEY key){ int indx = HASHFUNC(key); struct cell *p, *prev = NULL; if((p = hashtable[indx]) == NULL) return 0; for( ;p ;prev = p, p=p->next) if(EQKEY(p->key, key)){ FREEVAL(p->val); FREEKEY(p->key); if( p == hashtable[indx] ) /* */ hashtable[indx] = p->next; else prev->next = p->next; free((void *) p ); return 1; /* */ } return 0; /* */ } /* : */ void printcell(struct cell *ptr){ putchar('('); printf( KEYFMT, ptr->key ); putchar(','); printf( VALFMT, ptr->val ); putchar(')'); } /* ( ) */ void printtable(){ register i; struct cell *p; printf("----TABLE CONTENTS----\n"); for(i=0; i < HASHSIZE; i++) if((p = hashtable[i]) != NULL){ printf( "%d: ", i); for(; p; p=p->next) printcell(p), putchar(' '); putchar('\n'); } } /* */ struct celliter { int index; struct cell *ptr; }; /* */ struct cell *nextpair(struct celliter *ci){ struct cell *result; while((result = ci->ptr) == NULL){ if( ++(ci->index) >= HASHSIZE ) return NULL; /* */ ci->ptr = hashtable[ci->index]; } ci->ptr = result->next; return result; } /* */ struct cell *resetiter(struct celliter *ci){ ci->index = (-1); ci->ptr = NULL; return nextpair(ci); /* */ } /* =========================================================== */ void main(){ /* */ struct celliter ci; struct cell *cl; char key[40], value[40]; struct cell *val; extern FILE *popen(); FILE *fp; char *s ; /* popen() , 1- */ fp = popen( "ls -s", "r" ); while( fscanf( fp, "%s%s", value, key) == 2 ) set(key, value); pclose(fp); /* popen() pclose(); */ for(;;){ printf( "-> " ); /* */ if( !gets( key )) break; /* EOF */ if( *key == '-' ){ /* - : */ printf( del( key+1 ) ? "OK\n" : " \n"); continue; } if( !*key || !strcmp(key, "=")){ /* = : */ printtable(); continue; } if(s = strchr(key, '=')){ /* = : */ *s++ = '\0'; set(key, s); continue; } if((val = get( key )) == NULL) /* : */ printf( " \n"); else{ printf( " "); printf(VALFMT, val->val); putchar('\n'); } } /* */ for( cl = resetiter(&ci) ; cl ; cl = nextpair(&ci)) printcell(cl), putchar('\n'); } /* 8 */ /* . * . * , () * - . */ #include <stdio.h> /* */ #define VLEN 20 #define KEY_FREE (-13) /* . , */ struct data{ short b_key; /* */ char b_val[VLEN]; /* - */ }; char BASEF[] = ".base" ; /* */ FILE *fbase; /* pointer */ struct data tmp; /* */ void initBase (void){ /* fopen: r read () * w write (), . * (, , - ). * r+ ( ). * w+ ( ). * a append ( ), : * , * . * MS DOS * rb wb rb+ wb+ ab+ . */ if(( fbase = fopen( BASEF, "r+" )) == NULL ){ if(( fbase = fopen( BASEF, "w+" )) == NULL ){ fprintf( stderr, " %s\n", BASEF ); exit(1); } fprintf( stderr, " \n" ); } } void closeBase (void){ fclose( fbase ); } /* , , - ! : read(), fread() ( scanf- fgets-) */ /* . (-1), , - , . */ int bget (int key) { int n; /* */ rewind( fbase ); /* . fseek(fbase, 0L, 0); */ n = 0 ; /* int ____ = * fread( ___, * ___, * ____, ); * , , * '' */ while( fread( &tmp, sizeof( tmp ), 1, fbase ) == 1 ){ if( tmp.b_key == key ) return n; n++; } return (-1); /* */ } /* ind */ void bmod ( int ind, int key, /* */ char *val /* */ ) { struct data new; fseek( fbase, (long) sizeof( struct data ) * ind, 0 ); new.b_key = key; strncpy( new.b_val, val, VLEN ); /* int ____ = * fwrite( ___, * ___, * ___, ); */ if( fwrite( &new, sizeof new , 1, fbase ) != 1 ) fprintf( stderr, " .\n" ); } /* */ int bdel (int key){ int ind = bget( key ); if( ind == -1 ) return (-1); /* */ bmod( ind, KEY_FREE, "" ); /* */ return 0; } /* */ void bappend (int key, char *val) { struct data new; /* */ fseek( fbase, 0L, 2 ); /* */ new.b_key = key; strncpy( new.b_val, val, VLEN ); fwrite( &new, sizeof( struct data ) , 1, fbase ); } /* . - */ int bput (int key, char *val) { int i = bget( key ); if( i != -1 ) return (-1); /* */ /* */ i = bget( KEY_FREE ); if( i == -1 ) { /* */ bappend( key, val ); return 0; } /* . * */ bmod( i, key, val ); } /* */ void bprint (void){ int n; int here = 0; rewind( fbase ); n = 0; printf( "---------------------------\n" ); while( fread( &tmp, sizeof tmp, 1, fbase ) == 1 ){ if( tmp.b_key == KEY_FREE ){ n++; continue; } printf( "#%-2d| %6d\t| %s\n", n, tmp.b_key, tmp.b_val ); here ++; n++; } printf( "--------------------------------------------\n" ); printf( " :%d :%d\n\n", n, here ); } /* val key */ int bchange (int key, char *val) { int ind; ind = bget( key ); if( ind == -1 ){ /* */ /* */ bput( key, val ); return 0; } bmod( ind, key, val ); return 1; } /* , . * , - */ int bchg (int key, char *val) { struct data d; rewind( fbase ); /* */ while( fread( &d, sizeof d, 1, fbase ) == 1 ){ /* */ if( d.b_key == key ){ /* */ fseek( fbase, - (long) sizeof d, 1 ); /* (long)-sizeof d !!! */ d.b_key = key; strncpy( d.b_val, val, VLEN ); fwrite( &d, sizeof d, 1, fbase ); /* fread fwrite * fseek. ( !) */ fseek( fbase, 0L, 1); /* */ return 0; /* */ } } return (-1); /* */ } /* */ void main (void){ int i; initBase(); bprint(); bdel( 8 ); printf( " \n" ); bput( 1, " 1" ); bput( 2, " 2" ); bput( 3, " 3" ); bput( 4, " 4" ); bprint(); printf( " 1 3\n" ); bdel( 1 ); bdel( 3 ); bprint(); printf( " 5, 6 7\n" ); bput( 5, " 5" ); bput( 6, " 6" ); bput( 7, " 7" ); bprint(); printf( " 2\n" ); bchange( 2, " 2" ); bprint(); printf( " 4\n" ); bchg( 4, " 4" ); bprint(); printf( " 6 6 8\n" ); i = bget( 6 ); printf( " 6 \"%s\"\n", tmp.b_val ); bmod( i, 8, " 6/8" ); bprint(); closeBase(); } /* 9 */ /* / */ #include <stdio.h> #define INSERT_BEFORE 1 /* */ #define INSERT_AFTER 2 /* */ #define DELETE 3 /* */ #define REPLACE 4 /* */ /* linenum 1 !!! */ struct lineop { char op; /* */ long linenum; /* ( 0) */ char *str; /* ( NULL DELETE) */ }; long lineno; /* */ int fileChange (char *name, /* */ struct lineop ops[], /* */ int nops /* ops[] */ ){ FILE *fin, *fout; static char TMPNAME[] = " ? "; char buffer[BUFSIZ]; register i; struct lineop tmpop; if ((fin = fopen (name, "r")) == NULL) return (-1); if ((fout = fopen (TMPNAME, "w")) == NULL) { fclose (fin); return (-1); } lineno = 0L; while (fgets (buffer, BUFSIZ, fin) != NULL) { if( nops ) for (i = 0; i < nops; i++) if (lineno == ops[i].linenum) { switch (ops[i].op) { case DELETE: /* */ break; case INSERT_BEFORE: /* */ fprintf (fout, "%s\n", ops[i].str); fputs (buffer, fout); break; case INSERT_AFTER: /* */ fputs (buffer, fout); fprintf (fout, "%s\n", ops[i].str); break; case REPLACE: /* */ fprintf (fout, "%s\n", ops[i].str); break; } /* */ tmpop = ops[nops-1]; ops[nops-1] = ops[i]; ops[i] = tmpop; nops--; goto next; } /* ops[] : */ fputs (buffer, fout); next: lineno++; } fclose (fin); fclose (fout); rename (TMPNAME, name); return nops; /* (0 - ) */ } struct lineop myops[] = { { DELETE, 2L, NULL }, { INSERT_BEFORE, 0L, "inserted before 0" }, { INSERT_BEFORE, 10L, "inserted before 10" }, { INSERT_AFTER, 5L, "inserted after 5" }, { DELETE, 6L, NULL }, { INSERT_AFTER, 8L, "inserted after 8" }, { INSERT_AFTER, 12L, "inserted after 12" }, { REPLACE, 3L, "3 replaced" } }; void main( void ){ int n; n = fileChange( "aFile", myops, sizeof(myops)/sizeof(struct lineop)); printf( " : %ld; : %d\n", lineno, n); } /* line 0 inserted before 0 line 1 line 0 line 2 line 1 line 3 3 replaced line 4 line 4 line 5 line 5 line 6 inserted after 5 line 7 line 7 line 8 line 8 line 9 inserted after 8 line 10 line 9 inserted before 10 line 10 : 11; : 1 */ /* 10 */ /* : free(ptr) * , malloc()-. * : , * malloc(). * , * - . * * - * ! */ #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct _cell { void *addr; struct _cell *next; } Cell; typedef struct _entry { int length; int used; Cell *list; } Entry; /* */ #define NENTRIES 64 Entry aTab[NENTRIES]; /* - */ int aHash(void *addr){ unsigned long x = (unsigned long) addr; x >>= 3; /* 8, malloc() , double */ return(x % NENTRIES); /* , * : * x % (2**N) = x & 0b0001.....1 (N ) * , x % 64 = x & 0x3F; (6- ) */ } /* , */ void *aCalloc(int n, int m){ void *ptr = calloc(n, m); Entry *ep = &aTab[ aHash(ptr) ]; Cell *p; for(p=ep->list; p; p=p->next) if(p->addr == NULL){ /* : */ p->addr = ptr; ep->used++; return ptr; } /* , */ p = (Cell *) calloc(1, sizeof(Cell)); p->addr = ptr; p->next = ep->list; ep->list = p; ep->length++; ep->used++; return ptr; } /* */ int aFree(void *ptr){ Entry *ep = &aTab[ aHash(ptr) ]; Cell *p; for(p=ep->list; p; p=p->next) if(p->addr == ptr){ free(ptr); p->addr = NULL; /* , */ ep->used--; return 1; } /* , . * free() */ return 0; } /* */ void aStat(){ int i; int len_all; int used_all; for(i=len_all=used_all=0; i < NENTRIES; i++){ len_all += aTab[i].length; used_all += aTab[i].used; printf("%d/%d%s", aTab[i].used, aTab[i].length, i==NENTRIES-1 ? "\n":" "); } printf("%d/%d=%g%%\n", used_all, len_all, (double)used_all * 100 / len_all); } /* =================================================================*/ Cell *text; /* */ void fileIn(char *name){ char buf[10000]; FILE *fp; if((fp = fopen(name, "r")) == NULL){ printf("Cannot read %s\n", name); return; } while(fgets(buf, sizeof buf, fp) != NULL){ char *s; Cell *p; s = (char *) aCalloc(1, strlen(buf)+1); strcpy(s, buf); p = (Cell *) aCalloc(sizeof(Cell), 1); p->addr = s; p->next = text; text = p; } fclose(fp); } /* */ void killAll(){ Cell *ptr, *nxtp; ptr = text; while(ptr){ nxtp = ptr->next; if(!aFree(ptr->addr)) printf("No free(1)\n"); if(!aFree(ptr)) printf("No free(2)\n"); ptr = nxtp; } } /* , */ void randomKill(int *deleted){ unsigned char c = rand() % 256; Cell *ptr, *prevp; unsigned char *s; retry: prevp = NULL; ptr = text; while(ptr){ s = (unsigned char *) ptr->addr; if(*s == c){ /* */ if(!aFree(s)) printf("No free(3)\n"); /* */ if(prevp) prevp->next = ptr->next; else text = ptr->next; if(!aFree(ptr)) printf("No free(4)\n"); /* free if(!aFree(ptr+1)) printf("No free(5)\n"); */ (*deleted)++; goto retry; } prevp = ptr; ptr = ptr->next; } } int main(int ac, char *av[]){ int i, r, d; char buffer[4098]; srand(time(NULL)); for(i=1; i < ac; i++){ printf("File: %s\n", av[i]); fileIn(av[i]); aStat(); d = 0; for(r=0; r < 128; r++) randomKill(&d); printf("%d lines deleted\n", d); aStat(); } killAll(); aStat(); if(!aFree(buffer)) printf("buffer[] - .\n"); return 0; } /* 11 */ /* * , * . */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> /* O_RDWR */ #include <sys/types.h> #include <ctype.h> #include <locale.h> #define CHECKALL /* ----------------- <--------- ptr | red_zone | " " ----------------- | byte[0] | | ... | | byte[size-1] | | placeholder | ----------------- RedZoneType | red_zone | " " ----------------- : 1) , "". , - - . 2) malloc()- ; ( ). 3) STDIO , malloc() . */ typedef char *RedZoneType; /* */ /* double: typedef double RedZoneType; */ /* , */ typedef struct _allocFrame { RedZoneType red_zone; /* " " */ RedZoneType stuff[1]; /* */ /* " " */ } AllocFrame; const int RedZoneTypeSize = sizeof(RedZoneType); /* , malloc() * . */ typedef struct _memFileRecord { AllocFrame *ptr; /* */ size_t size, adjsize; /* */ /* (0,0) - " " */ int serial; } MemFileRecord; char red_table[] = { 0x01, 0x03, 0x02, 0x04, 0x11, 0x13, 0x12, 0x14, 0x21, 0x23, 0x22, 0x24, 0x31, 0x33, 0x32, 0x34 }; char free_table[] = { 'F', 'r', 'e', 'e', 'p', 't', 'r', '\0', 'F', 'r', 'e', 'e', 'p', 't', 'r', '\0' }; /* */ static int mem_fd = (-1); #define PTABLE "PointerTable.bin" #define NRECORDS 256 MemFileRecord memrecords[NRECORDS]; /* ============================================================= */ void MEMputTableRecord(AllocFrame *newptr, AllocFrame *oldptr, size_t size, size_t adjsize); void MEMputTableRecordKilled(AllocFrame *ptr); void MEMerasePreviousRecords(AllocFrame *ptr); int MEMcheckRecord(MemFileRecord *rec); int MEMcheck_consistency(AllocFrame *ptr); void MEMmakeRedZones(char *cptr, size_t size, size_t adjsize); void MEMopenFd(); /* ============================================================= */ /* */ void *MEMmalloc (size_t size); void *MEMrealloc(void *ptr, size_t size); void *MEMcalloc (size_t n, size_t size); void MEMfree (void *ptr); void MEMcheckAll(); /* */ /* ============================================================= */ void MEMopenFd(){ if(mem_fd < 0){ close(creat(PTABLE, 0644)); /* */ mem_fd = open(PTABLE, O_RDWR); /* + */ unlink(PTABLE); /* M_UNIX */ atexit(MEMcheckAll); setlocale(LC_ALL, ""); } } /* * . */ void MEMputTableRecord(AllocFrame *newptr, /* */ AllocFrame *oldptr, /* */ size_t size, /* */ size_t adjsize /* */ ){ MemFileRecord memrecord; static int serial = 0; memrecord.ptr = newptr; memrecord.size = size; memrecord.adjsize = adjsize; memrecord.serial = serial++; MEMopenFd(); #ifdef CHECKALL /* */ MEMerasePreviousRecords(oldptr); #endif lseek(mem_fd, 0L, SEEK_END); /* */ write(mem_fd, &memrecord, sizeof memrecord); /* */ } /* */ void MEMputTableRecordKilled(AllocFrame *ptr){ /* size=0, adjsize=0 */ MEMputTableRecord(ptr, ptr, 0, 0); } /* */ #define OK 0 /* */ #define DAMAGED 1 /* "" */ #define FREED 2 /* */ #define NOTHERE (-1) /* */ /* " " */ int MEMcheckRecord(MemFileRecord *rec){ int code = OK; char *cptr; register i; AllocFrame *ptr = rec->ptr; size_t size = rec->size; size_t adjsize = rec->adjsize; if(size == 0 && adjsize == 0){ printf("%p [%p] -- , " "record=#%d.\n", &ptr->stuff[0], ptr, rec->serial ); return FREED; } cptr = (char *) ptr; for(i=0; i < adjsize; i++){ if(i < RedZoneTypeSize || i >= RedZoneTypeSize + size ){ /* */ if( cptr[i] != red_table[ i % RedZoneTypeSize ] ){ printf("%p [%p] -- %4d [%4d]" "= 0x%02X '%c' record=#%d size=%lu.\n", &ptr->stuff[0], ptr, i - RedZoneTypeSize, i, cptr[i] & 0xFF, isprint(cptr[i] & 0xFF) ? cptr[i] & 0xFF : '?', rec->serial, size ); code = DAMAGED; } } } for(i=0; i < RedZoneTypeSize; i++) if(cptr[i] == free_table[i]){ printf("%p -- ?\n", ptr); code = FREED; } if(code != OK) putchar('\n'); return code; } /* ptr. */ int MEMcheck_consistency(AllocFrame *ptr){ MemFileRecord mr_found; int nrecords, i, found = 0; size_t size; MEMopenFd(); /* */ lseek(mem_fd, 0L, SEEK_SET); /* */ for(;;){ size = read(mem_fd, memrecords, sizeof memrecords); nrecords = size / sizeof(memrecords[0]); if(nrecords <= 0) break; for(i=0; i < nrecords; i++) if(memrecords[i].ptr == ptr){ /* * , * . */ mr_found = memrecords[i]; found++; } } if(found) { return MEMcheckRecord(&mr_found); } else { printf("%p -- .\n", ptr); return NOTHERE; } } /* ptr, adjsize=0 */ void MEMerasePreviousRecords(AllocFrame *ptr){ int nrecords, i, found; size_t size; MEMopenFd(); lseek(mem_fd, 0L, SEEK_SET); /* */ for(;;){ found = 0; size = read(mem_fd, memrecords, sizeof memrecords); nrecords = size / sizeof(memrecords[0]); if(nrecords <= 0) break; for(i=0; i < nrecords; i++) if(memrecords[i].ptr == ptr){ memrecords[i].adjsize = 0; /* memrecords[i].size = 0; */ found++; } if(found){ lseek(mem_fd, -size, SEEK_CUR); /* */ write(mem_fd, memrecords, size); /* */ } } } void MEMcheckAll(){ #ifdef CHECKALL int nrecords, i; size_t size; printf(" -------------\n"); MEMopenFd(); lseek(mem_fd, 0L, SEEK_SET); /* */ for(;;){ size = read(mem_fd, memrecords, sizeof memrecords); nrecords = size / sizeof(memrecords[0]); if(nrecords <= 0) break; for(i=0; i < nrecords; i++) if(memrecords[i].adjsize != 0) MEMcheckRecord(&memrecords[i]); } printf(" ---\n"); #endif } /* ============================================================= */ /* - " " */ void MEMmakeRedZones(char *cptr, size_t size, size_t adjsize){ register i; for(i=0; i < adjsize; i++){ if(i < RedZoneTypeSize || i >= RedZoneTypeSize + size ){ /* * + * RedZoneType- */ cptr[i] = red_table[ i % RedZoneTypeSize ]; } } } /* ============================================================= */ /* */ void *MEMmalloc(size_t size){ AllocFrame *retptr; int fullRedZoneTypes = (size + RedZoneTypeSize - 1) / RedZoneTypeSize; size_t adjustedSize = sizeof(retptr->red_zone) * 2 + /* */ fullRedZoneTypes * RedZoneTypeSize; retptr = (AllocFrame *) malloc(adjustedSize); if(retptr == NULL) return NULL; MEMmakeRedZones ((char *) retptr, size, adjustedSize); MEMputTableRecord(retptr, retptr, size, adjustedSize); return &retptr->stuff[0]; /* */ } void *MEMrealloc(void *ptr, size_t size){ AllocFrame *retptr; char *cptr = (char *)ptr - RedZoneTypeSize; /* AllocFrame */ AllocFrame *oldptr = (AllocFrame *) cptr; int fullRedZoneTypes = (size + RedZoneTypeSize - 1) / RedZoneTypeSize; size_t adjustedSize = sizeof(retptr->red_zone) * 2 + fullRedZoneTypes * RedZoneTypeSize; /* , realloc- */ MEMcheck_consistency(oldptr); retptr = (AllocFrame *) realloc((void *)oldptr, adjustedSize); if(retptr == NULL) return NULL; MEMmakeRedZones ((char *) retptr, size, adjustedSize); MEMputTableRecord(retptr, oldptr, size, adjustedSize); return &retptr->stuff[0]; } void *MEMcalloc(size_t n, size_t size){ size_t newsize = n * size; void *ptr = MEMmalloc(newsize); memset(ptr, '\0', newsize); return ptr; } /* . * ptr - AllocFrame, * - stuff[0]. */ void MEMfree(void *ptr){ char *cptr = (char *)ptr - RedZoneTypeSize; int i, code; code = MEMcheck_consistency((AllocFrame *) cptr); for(i=0; i < RedZoneTypeSize; i++) cptr[i] = free_table[i]; if(code != FREED) free((void *) cptr); MEMputTableRecordKilled((AllocFrame *) cptr); } /* ============================================================= */ /* */ /* ============================================================= */ #define MAXPTRS 512 char *testtable[MAXPTRS]; /* */ char *wildstring(int c){ #define N 1024 char teststring[N + 1]; int len, i; char *ptr; len = rand() % N; for(i=0; i < len; i++) teststring[i] = c; teststring[len] = '\0'; ptr = (char *) MEMmalloc(len + 1); if(ptr){ strcpy(ptr, teststring); } else printf("NULL wildstring()\n"); return ptr; } int main(int ac, char *av[]){ int ilen, len, n, i; srand(time(NULL)); for(n=0; n < MAXPTRS; n++) testtable[n] = wildstring('A'); #define DAMAGE (MAXPTRS/3*2-1) #ifdef DAMAGE /* */ len = strlen(testtable[DAMAGE]); testtable[DAMAGE][len+1] = 'x'; testtable[DAMAGE][-2] = 'y'; printf("ptr=%p len=%d\n", testtable[DAMAGE], len); #endif for(n=0; n < MAXPTRS/2; n++){ char *p = wildstring('B'); int length = strlen(p); char *ptr; i = rand() % MAXPTRS; /* realloc() * testtable[i] !!! */ testtable[i] = ptr = (char *) MEMrealloc(testtable[i], length + 1); if(ptr == NULL) printf(" realloc()\n"); else strcpy(ptr, p); #ifdef DAMAGE /* */ if(n == MAXPTRS/3){ ptr[length+2] = 'z'; } #endif MEMfree(p); } for(n=0; n < MAXPTRS; n++){ if(testtable[n]) MEMfree(testtable[n]); } #ifdef DAMAGE MEMfree(testtable[DAMAGE]); #endif return 0; } /* 12 */ /* , mv cp. . * , * . * : * cc cpmv.c -o copy ; ln copy move * . .. */ #include <stdio.h> /* / */ #include <sys/types.h> /* */ #include <sys/stat.h> /* struct stat */ #include <fcntl.h> /* O_RDONLY */ #include <errno.h> /* */ /* #define strrchr rindex /* (BSD) */ extern char *strrchr(char *, char); /* libc.a */ extern int errno; char MV[] = "move"; char CP[] = "copy"; #define OK 1 /* success - */ #define FAILED 0 /* failure - */ #define YES OK #define NO 0 /* : * ../wawa/xxx --> xxx * zzz --> zzz * / --> / */ char *basename( char *name ){ char *s = strrchr( name , '/' ); return (s == NULL) ? name : /* */ (s[1] == '\0') ? name : /* */ s + 1; } #define ECANTSTAT (-1) /* */ struct ftype { unsigned type; /* */ dev_t dev; /* , */ ino_t ino; /* */ }; /* */ struct ftype filetype( char *name /* */ ) { struct stat st; struct ftype f; if( stat( name, &st ) < 0 ){ f.type = ECANTSTAT; f.dev = f.ino = 0; } else { f.type = st.st_mode & S_IFMT; f.dev = st.st_dev; f.ino = st.st_ino; } return f; } /* , */ int unlinkd( char *name, unsigned type ) { if( type == S_IFBLK || type == S_IFCHR || type == S_IFDIR) return 0; return unlink( name ); } /* : */ int copyfile( int from, int to ) /* from - */ /* to - */ { char buffer[ BUFSIZ ]; int n; /* */ while(( n = read( from, buffer, BUFSIZ )) > 0 ) /* read , * 0 */ if( write( to, buffer, n ) != n ){ printf( "Write error.\n" ); return FAILED; } return OK; } /* */ int docopy(char *src, char *dst, unsigned typefrom, unsigned typeto) { int retc; int fdin, fdout; printf( "copy %s --> %s\n", src, dst ); if((fdin = open( src, O_RDONLY )) < 0 ){ printf( "an't read %s\n", src ); return FAILED; } if((fdout = creat( dst, 0644 )) < 0 ){ /* rw-r--r-- */ printf( "Can't create %s\n", dst ); return FAILED; } retc = copyfile( fdin, fdout ); close( fdin ); close( fdout ); return retc; } /* . OK, , FAILED - */ int mlink(char *src, char *dst, unsigned typefrom, unsigned typeto) { switch( typefrom ){ case S_IFDIR: /* */ printf( "rename directory %s --> %s\n", src, dst ); if( access( dst, 0 ) == 0 ){ /* 0 - */ printf( "%s exists already\n", dst ); /* */ return FAILED; } if( link( src, dst ) < 0 ){ printf( "Can't link to directory %s\n", dst ); perror( "link" ); /* , link() , * . */ return FAILED; } unlink( src ); return OK; default: /* dst - */ printf( "move %s --> %s\n", src, dst ); unlinkd( dst, typeto ); /* , .. lin