title C/Perl/Emacs/RE Library reference. author GPL(C) Mohsin Ahmed, http://www.cs.albany.edu/~mosh vim:ft=c: ============================================================ moshtag=gmtime +------------------+ --date--->| Kernel |---clock()-> +------------------+ | |time() gmtime() | localtime() v difftime() +-----------+ <-------------- +-----------+ =========> +-------+ |struct tm | | time_t | |Seconds| +-----------+ --------------> +-----------+ +-------+ | mktime() | | | | | asctime() +------------------+ | strftime()--> | string | <--ctime() +------------------+ ============================================================ time_example(){ time_t now, later; // Seconds since 1 Jan 1970 (UTC). struct tm *tp; printf( "File %s compiled on %s %s\n", __FILE__, __DATE__, __TIME__ ); // compile time. time( &now ); printf( "Running at time: %s", ctime( &now ) ); // run time. includes '\n' tp = localtime( &now ); tp-> tm_mday += 1000; later = mktime( tp ); printf( "1000 days from now = %s\n", ctime( later ) ); } moshtag=gmt_lmt lmt(){ time_t t; time(&t); printf(" LMT = %s", ctime(&t)); printf(" GMT = %s", asctime(gmtime(&t))); } julian(){ // time(NULL) gives seconds since 0 GMT 1-1-1970. printf("JD=%12.5f\n",(double)time(NULL)/(24*3600)+2440587.5); } time_delta(){ /* on each call, print delta time elapsed */ static time_t tstart,tdelta,tcurrent,ttmp=0; if( ttmp == 0 ){ tdelta=0; tcurrent = tstart = time(NULL); }else{ ttmp = time(NULL); tdelta = ttmp - tcurrent; tcurrent = ttmp; } printf("started=%d, delta since last call=%d.\n",tcurrent-tstart,tdelta ); } char random_char_from_string(char*str){ l = strlen(str); if(l<=1) return *str; return str[rand()%l]; } #include /* for unix time */ #include /* for unix time */ unsigned long timer(int what /* 0->start, 1->stop */ ) { static int started=0; static double start_time=0, end_time=0; /* in micro seconds */ static struct timeval tv; gettimeofday(&tv, NULL); if( !started++ || what==0 ){ start_time = (double) tv.tv_sec * 1000000 + tv.tv_usec; return 0; }else{ int unsigned long diff; end_time = (double) tv.tv_sec * 1000000 + tv.tv_usec; diff = (unsigned long) (end_time - start_time); printf("%u microseconds.\n", diff); return diff; } } unix_benchmark(){ timer(0); // long computation to benchmark goes here. timer(1); } unix_benchmark(){ double start_time, end_time; struct timeval tv; gettimeofday(&tv, NULL); start_time = (double) tv.tv_sec * 1000000 + tv.tv_usec; // long computation to benchmark goes here. gettimeofday(&tv, NULL); /* only on unix */ end_time = (double) tv.tv_sec * 1000000 + tv.tv_usec; printf("%10u microsec.\n", (unsigned long) (end_time - start_time)); } section Quick C moshtag=quickc,typedef,enum,struct,union,switch,continue { typedef oldT newT; // Note a decl converts to a typedef directly Eg. 'int *PI;' to 'typedef int *PI; PI p1;' Eg. typedef int (*PFIPCPC)(char*,char*); PFIPCPC f1, f2; // Note enum has commas, struct and unions have semi-colons. enum { A, B }; // A=0, B=1. enum { A=1, B, C }; // A=0, B=1, C=2. enum T { A=1, B=5, C=5 } V; struct { T:v; T:v } V, *pV; // Unnamed struct. struct s_tag { T:v; T:v }; // Decl. struct s_tag s1; typedef struct { T:v; T:v } ST, *PST; // Decl. ST s1; PST ps1 = &s1; struct { ... ;union{T:x;T:y}; .. } // Anon union saves space. struct { uint x:1; uint y:1; uint z:6;} // Bit fields. union u_tag { T:v; T:v } V; switch(V){ case V1: S; break; case V2: S; break; default: S; break; } if(C) S else S; // if(C){S;}else{S;} if(C) S; // if(C){S;} for(x;C;z) S; // x;while(C){S;z} while(C) S; // while(C){S;} do S while(C); // do{S}while(C); break; // exit from innermost loop or switch. continue; // goto closing '}' of innermost loop, // So evals C before reentering loop. eg. i++. } ========================================================== section OPERATOR_PRECEDENCE mostag=operators Top is higher prec, each block has same prec. Prec column one, then column two. Unary and assignment are right assoc, rest are left assoc. |----------------------------------|-------------------------------| | :: scope resolution | + - plus, minus | | :: global |-------------------------------| |----------------------------------| << >> shift left, right | | . member selection |-------------------------------| | -> member selection | < <= > >= Comparison | | [] subscripting |-------------------------------| | () function call | == != Equality | | () value cons |-------------------------------| | ++ -- post inc, dec | & Bit and | |----------------------------------|-------------------------------| | sizeof object | ^ Bit xor | | sizeof type |-------------------------------| | ++ -- pre inc/dec | | Bit or | | ~ complement |-------------------------------| | ! not | && Logical and | | - unary minus |-------------------------------| | + unary plus | || Logical or | | & address of |-------------------------------| | * deference | ? : Conditional Expr | | new create/alloc |-------------------------------| | delete destroy/delloc | = *= /= %= += -= | | delete[] destroy/delloc array | <<= >>= &= |= ^= Assignments | | () cast/type conversion |-------------------------------| |----------------------------------| throw | | .* member selection |-------------------------------| | ->* member selection | , Sequence | |--------------------------------- |-------------------------------| | * / % multiply,divide,modulo | | |----------------------------------|-------------------------------- ========================================================== section Precedence_Examples moshtag=precedence { a=b=c is a=(b=c) Right Assoc only =. a+b+c is (a+b)+c Left Assoc, all bin ops. *p++ is *(p++) NOT (*p)++ p.q->r is (p.q)->r Left assoc like +. &p->q is &(p->q) &p.q is &(p.q) *p.q is *(p.q) NOT p->q p->q++ is (p->q)++ ++p++ is ++(p++) a?b,c,d:e is a?(b,c,d):e a?b?c:d:e is a?(b?c:d):e a?b:c?d:e is a?b:(c?d:e) a?b?c?d:e:f:g is a?(b?(c?d:e):f):g format: a?b:c as ((a) ( IF(a) ? b THEN b : c ) ELSE c ) !0 is 1 = True ~0 is -1 (int) a+f(1) is ((int)a) + f(1) f( (1,2), 3 ) is f(2,3) first comma is sequencing. i<0 || i>max is (i<0) || (i>max). int ai[7] ai is an array of 7 int int *pi pi is a ptr to int int *api[5] api is an array of 5 ptr to int int (*pai)[] pai is a ptr to an array of int int *fpi(void*) fpi func : ptr to anything => ptr to int. int (*pf)(int*) pf is ptr to func : ptr to int => int. int fa()[] func fa returns an array of int. int (af[])() af is an array of funcs, f[i]: => int. int (*[])() array of ptr to funcs returning ints. } ============================================================ section Constants_Declarations moshtag=const { const char * pc = "ma"; pc[0]='M'; // pc is constant. char* const cp = "ma"; cp = "Ma"; // *cp is constant. const char * const cpc = "atal"; // cpc and *cpc both constants. char * strcpy( char* p, const char* q); // *q constant. Array_Vs_Ptr char *a = "123"; b[1] = '4'; // Const str, crash. char b[] = "123"; b[1] = '5'; // char array is modifiable. } ============================================================ section Precedence_Exercises moshtag=precedence { *p++ == *q++ is (*(p++)) == (*(q++)) *p++^*p++ is (*(p++)) ^ (*(q++)) ~*p++ || !*q | r == 1 is (~(*(p++))) || ((!(*q)) | (r==1) ) &p.q->*r++ is &(((p.q)->*(r++))); } ========================================================== section C_COMMON_ERRORS_AND_AMBIGUITIES moshtag=caveats,err { // Deep C Secrets, K&R. // C Traps and Pitfalls, Andrew Koenig. o *p.f is *( p.f ) o *a[] is *( a[] ) o *f() is *( f() ) o a&b == c is a & (b==c) o a&b != c is a & (b!=c) o a< 10 ) quad(x); o if( x < 0 ); printf("negative x"); o if( x & FLAG == FLAG ) printf("flags on"); o if( x = 0 ) print("x is zero!"); o assert( x = 0 ); o if( 0 < i < max ) i++; // Legal, < is left associative. o if( x > 0 ) #ifdef DEBUG printf("x ok."); #endif o #define trace(x) if(trace) printf(x) if( i < 0 ) trace("Negative x"); else i++; o struct x { ... } main( ){ ... } o y = x/* p /* */; is y = x; y = x/ *p /* */; is y = x/ *p; y = x/(*p) /* */; is y = x/ *p; o a + /* */ = 1 is a += 1, += are two tokens. a =+ 1 (old), single token. o p >> =a is p >>= a, >> = are two tokens. o p - > a is illegal, -> is single token. o printf("Hi") is char H[] = { 'H','i',0}; printf(H); o printf('H') gives run time error. o int f(); printf("%d",f); prints address of f, not f(). o while( x[i] ) y[i] = x[i++]; // RHS is NOT evaluated last! while( x[i] ) y[i] = x[i], i++; // Ok. for( ;x[i]; i++ ) // Ok. y[i] = x[i]; o The many roots of headless evil. double s; s = sqrt(2); // 4.19494e+006 s = sqrt(2.0); // 1.07374e+009 s = (double) sqrt( (double) 2.0 ); // 1.07374e+009 s = (double) sqrt( 2.0 ); // No s = sqrt( (double) 2.0 ); // No double sqrt(double); s = sqrt(2); // Yes 1.41421 printf("%g",s); Problem was: compiler was thinking int sqrt(int), and doing conversions, and then our conversions were useless. Solution: include that supplies the prototype for sqrt(). o short d; scanf("%d", &d ); o r = malloc( strlen(a) + strlen(b) ); // can fail? strcpy( r, a ); strcat( r, b ); // no space for NULL. o char c; while( (c=getchar()) != EOF ) // high 24 bits of c lost putchar(c); // before comparison. o macros evaluating arguments multiple times, and arguments have side effects. eg. max(2,i++); => 2>i++? 2 : i++; o macros args have no implicit parenthesis: eg. sqr(2+1) => 2+1*2+1 => 5 != expected 9. o macros are not typedefs #define PCHAR char* PCHAR a,b; => char* a, b; o char is int or unsigned? Important when coverting char to int, i = (unsigned char) c; // right. i = (unsigned ) c; // wrong. o Integer division: h = n % hashsize; if( h < 0 ) // or use: unsigned n; h += hashsize; o rand() is 16bit in ATT. // 00001b7b on VC++5/NT4. 32bit in BSD. // 5cc6113b on G++/SUNOS srand(time(0)); printf("%08x", rand() ); } moshtag=call_zero { (*0)(); // compile error: term does not evaluate to a function. (*(void(*)()) 0 )(); // ok. typedef void (*fp)(); (* (fp) 0 )(); // ok. } =========================================================== section signed chars moshtag=signed,unsigned,char,uchar,promotions Default char is signed on solaris c, win32/vc, hp. ANSI C Integer types: moshtag=ansi_int,promotions Must have four unsigned and signed integer types: ------------------- uchar char ushort short uint int ulong long ------------------- sizeof(int) >= 2 sizeof(short) >= 2 sizeof(long ) >= sizeof(int) sizeof(long ) >= 4 ------------------- Conversions: main(){ unsigned char uc=-1; int i; i = uc; printf("%d",i); // 255 or -1? Value_Preserving: uchar uc=ch; i = uc; // i = 255. Sign_Preserving: char sc=ch; i = ch; // i = -1. sign-extended. } main(){ int i=-1; unsigned char uc=2; unsigned int ui=2; if(uc>i) printf("value preserving"); else printf("unsigned preserving"); if(ui0? "non-":"ansi"); ANSI: result is signed. OLD : result is unsigned. // result = expr(float,float); ANSI: precision is float OLD: precision is double. // unsigned shifted left by 32. unsigned int j=0xffffffff,k=32,i=j>>k; printf("i=%08x",i); ANSI: i=ffffffff OLD: i=0; // Coverting char to int: i = (unsigned char) c; // right. i = (unsigned ) c; // wrong. ; Different assembly code generated for char/uchar to int. ; int si = char st; movsx edx, BYTE PTR _st$[ebp] mov DWORD PTR _si$[ebp], edx ; int si = uchar ut mov eax, DWORD PTR _ut$[ebp] and eax, 255 ; 000000ffH mov DWORD PTR _si$[ebp], eax show_sign_unsigned_chars() { #define PRINT(Y) printf("%08x " #Y "\n", Y ); unsigned char x = -1; char y = -1; PRINT( x); // 000000ff x <- zero extended PRINT( (unsigned ) x); // 000000ff (unsigned ) x PRINT( (unsigned char) x); // 000000ff (unsigned char) x PRINT( y); // ffffffff y <- sign extended. PRINT( (unsigned ) y); // ffffffff (unsigned ) y <- No help PRINT( (unsigned char) y); // 000000ff (unsigned char) y <- Works. } ============================================================ shifting moshtag=shifting { // Output: The char and short got sign extended. // >>, signed get 1s, unsigned get 0s. ULONG l=-1; LONG m=-1; UINT u=-1; INT i=-1; USHORT s=-1; SHORT j=-1; UCHAR c=-1; CHAR k=-1; #define P(T,V) printf(#T "is %8d %08x %u\n",V,V,V); P( ULONG , l ) // ULONG is -1 ffffffff 4294967295 P( LONG , m ) // LONG is -1 ffffffff 4294967295 P( UINT , u ) // UINT is -1 ffffffff 4294967295 P( INT , i ) // INT is -1 ffffffff 4294967295 P( USHORT, s ) // USHORT is 65535 0000ffff 65535 P( SHORT, j ) // SHORT is -1 ffffffff 4294967295 P( UCHAR , c ) // UCHAR is 255 000000ff 255 P( CHAR , k ) // CHAR is -1 ffffffff 4294967295 #define P(T,V) printf(#T "%08x %08x\n",V<<1,V>>1); P(UINT ,u) // UINT u<<1 is fffffffe u>>1 is 7fffffff P( INT ,i) // INT i<<1 is fffffffe i>>1 is ffffffff P(UCHAR,c) // UCHAR c<<1 is 000001fe c>>1 is 0000007f P( CHAR,k) // CHAR k<<1 is fffffffe k>>1 is ffffffff } ============================================================ section Number_comparators cmp_numbers() // moshtag=comparing { static const float EPS = 1.0e-6; /* epsilon */ static const float near_zero = 1.0e-10; #define is_zero(expr) ((fabs(expr))<(near_zero)) #define non_zero(expr) ((fabs(expr))>= (near_zero)) #define are_equal(a,b) ((fabs((a)-(b)))<(near_zero)) // if x is near zero, round it off. #define zeroed(x) ( (fabs(x) typedef char * va_list; #define va_start(ap,v) ((void) (ap=(va_list) &v +sizeof(v))) #define va_arg(ap,type) (*(type *)(ap)++) #define va_end(ap) ((void) (ap=0)) // var-arg #define eprintf(format, args...) fprintf (stderr, format, ## args) eprintf ("%s:%d: ", "Hello",26); } Example: int va_sum( int count, ... ) { int max=INT_MIN, i, sum; va_list ap; va_start(ap,count); for( i=0; i< count; ++i ) sum += va_arg(ap,int); va_end(ap); return sum; } section arrays arrays() // moshtag=array { #define TWO_DIM_ARRAY(a,n,i,j) a[n*((i)-1)+(j)-1] Given X[n][k], TWO_DIM_ARRAY(X,n,i,j) refers to X[i,j]. } section BIT_operations moshtag=bit,bitop { #define shl_onek( k) (1 << (k)) #define set_bitk( var,k) (var) |= shlone((k)) #define clear_bitk( var,k) (var) &= ~shlone((k)) #define togglebitk( var,k) (var) ^= shlone((k)) #define isset_bitk( var,k) (var) & shlone((k)) #define isclr_bitk( var,k) !((var) & shlone((k))) o Setting FLAG bits: var |= FLAG; Turn on FLAG var &= ~ FLAG; Turn off FLAG var ^= FLAG; Toggle all FLAG o Checking FLAG bits: (var & FLAG ); Check if some/any FLAG bits set. !(var & FLAG ); Check if no FLAG bits set. (FLAG==(var&FLAG)); Check if all FLAGs bits are set. (var == FLAG); Check only FLAG bits are set. (var ==(var&FLAG)). ((var&(var-1))==0) Check if atmost one bit is set. Since all bits upto LSB toggle on -1. o To find the smallest 1 bit in a word ((w) & (-(w))) Get lowest One Bit eg. ~~~~~~10---0 => 0----010---0 #define LowestOneBit(w) ((w) & (~(w)+1)) or #define LowestOneBit(w) ((w) & (-(w))) o #define haszerobyte(x) ((x+0xfefefeff)&(~x)&0x80808080) if ( ( x + 0xfefefeff ) & (~x) & 0x80808080 ) { // one of the bytes in a 4 byte word is zero } See K&R:149. eg. struct { // uint a : 1; // use as: flag.a = flag.b = 1; uint b : 1; // } flag; } ============================================================ char * ltoa( long num, long base ) { // See ltoa.c for details. static char buf[60]; char *p = &buf[59]; *p = '\0'; do{ *--p = "0123456789abcdef"[num % base]; }while(num/=base); return p; } int bitcount( long u ) { // untested, four at a time. static bitcounts[] = { 0,1,1,2, 1,2,2,3, 1,2,2,3, 2,3,3,4 }; int x = 0; for(; u != 0; u >>= 4 ) x += bitcounts[ u & 0xf]; return x; } int32 reverse_bits( int n ) { n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa); n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc); n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0); n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); return n; } Swap two numbers without any extra space: #define SWAP(a,b) { a ^= b; b ^= a; a ^= b; } ============================================================ section MACROS macros() moshtag=macros { /* See [K&R,A12,p228-233] Predefined: __FILE__ __DATE__ __TIME__ __STDC__ Inside macro expansion: #token is "token" -- Strung? tok1 ## tok2 is tok1tok2 -- Concatenate tokens. Sizeof a type without an instance of the object. Use the null pointer to deref the field and get its size: sizeof( ( (type *) 0)->field ). Also get the field's offset inside the object: size_t offsetof( StructName, MemberName ) #define offsetof( type, field ) ((size_t) &(((type *)0)->field)) Replacement of the trigraph sequence ??/ printf("Eh???/n"); => printf("Eh?\n"); moshtag=trigraph ??= # ??( [ ??< { ??/ \ ??) ] ??> } ??' ^ ??! | ??- ~ */ } ============================================================ section Macros Porting macros_porting() moshtag=macros_porting { #define max(a,b) (((a) > (b)) ? (a) : (b)) // Watch for c=max(a--,b); #define min(a,b) (((a) < (b)) ? (a) : (b)) #define clip(MIN,X,MAX) (((MIN)<(X))? (((X)<(MAX))? (X): (MAX)): (MIN)) #define swap(a,b,tmp) { (tmp)=(a); (a)=(b); (b)=(tmp); } #define swapt(a,b,T,t) { T t; t=(a),(a)=(b),(b)=t} #define for_upto(i,B,E) for(i=(B);i<=(E);i++) /* i in B..E, inclusive. */ #define for_down(i,E,B) for(i=(E);i>=(B);i--) /* i in E..B, inclusive. */ #define for_in(i,S) for(i=0;i<(S);i++) /* i in 0..S-1, c-loop */ #define for_count(i,S) for(i=1;i<(S);i++) /* i in 1..S, pascal-loop */ #define New(T) ((T*) malloc(sizeof(T))) #define Del(p) free(p) /* to be paired with New */ #define loop for(;;) #define forever while(1) #define CASE break;case #define unless(C) if(!(C)) #define repeat /* repeat */ #define until(C) while(!(C)) #define end(if) /* Usage: end(while), end(switch), end(for) */ #define and && // See iso646.h also. #define or || #define not ! #define equal == #define not_equal != #define neither(X,Y) (!(X)&&!(Y)) #define nullp(X) (!(X)) #define bit_and & #define bit_or | #define bit_not ~ #define bit_xor ^ #define function /* func defn */ #define procedure void /* proc defn */ #define local static /* local to the file, eg. func */ #define dynamic /* dynamic data, as opposed to static data */ #define data /* data structure defn */ #define type /* type declaration only */ #define IN /* input var to function */ #define OUT /* output var to function */ #define STREQU( s1, s2 ) ((*s1 == *s2) && !strcmp(s1,s2)) #define STRNEQ( s1, s2 ) ((*s1 != *s2) || strcmp(s1,s2)) #define ARRAY_LENGTH(A) (sizeof(A)/sizeof(A[0])) } section C_versus_CPP printf("%d\n", 2 //* //*/ 2 ); //========================================================== section NETWORKING tag networking() { #define INET_NTOA(IP) inet_ntoa(*((struct in_addr*) (IP) )) Example printing an ip address: long ipaddress; ... printf( "ipaddress=%s\n", inet_ntoa(*((struct in_addr*)&ipaddress))); printf( "ipaddress=%s\n", INET_NTOA(&ipaddress) ); To allow for multiple ntoa in printf use NTOA( char*, ulong* ), here we dup the static strings. #define NTOA(STR,ADDR) \ strncpy( STR, inet_ntoa(*(struct in_addr*)(&(ADDR))), 17 ) ulong a1, a2; char s1[18], s2[18]; ... printf( "s1=%s s2=%s", NTOA( s1, a1), NTOA( s2, a2) ); #define CLASSA(i) (i & 0x80000000) == 0 // Big endian #define CLASSB(i) (i & 0xc0000000) == 0x80000000 #define CLASSC(i) (i & 0xe0000000) == 0xc0000000 #define CLASSD(i) (i & 0xf0000000) == 0xe0000000 #define INADDR_LOOPBACK 0x7f000001 // 127.0.0.1 #define INADDR_BROADCAST 0xffffffff #define INADDR_ANY 0x00000000 struct sockaddr_in { short sin_family; // two bytes AF_INET == 2. u_short sin_port; // two bytes struct in_addr sin_addr; // four bytes in_addr.s_addr char sin_zero[8]; // zero pad. }; char is_big_endian( void ) { short x = 0x0100; // x = [0,1] on SUN. x = [1,0] on Intel. return *((char *) &x ); // Treat short as a char. } big endian: ibm370, 68000, sun. small endian: x86, vax, pdp11. Example of htonl: htonl is a NOP on big endian (Sun), but htonl swaps high/low bytes/words on small endian i386, ie. #define htonl(x) \ ((( x & 0xffL) << 24 ) | ((x & 0xff00L) << 8 ) | \ (( x & 0xff0000L) >> 8 ) | ((x & 0xff000000L) >> 24 ) ) Client/Server Example: struct sockaddr_in serv_addr, client_addr; int s, i; s = socket( AF_INET, SOCK_DGRAM, 0 ) if( s < 0 ) exit(-1); bzero( (char*) &client_addr, sizeof( client_addr ) ); client_addr.sin_family = AF_INET; client_addr.sin_addr.s_addr = htonl( INADDR_ANY ); client_addr.sin_port = htons( SERV_TCP_PORT ); i = bind( s, (struct sockaddr *) &client_addr, sizeof( client_addr ) ); if( i < 0 ) exit(-1); i = listen( s, 5 ); if( i < 0 ) exit(-1); for(;;){ int clilen = sizeof( client_addr ); int sa; char buf[1000]; // wait here till someone connects. sa = accept( s, (struct sockaddr *) &client_addr, &clilen ); if( sa < 0 ) continue; for(;;){ i = recv( sa, buff, sizeof(buff), 0 ); if( i < 0 ) break; show buff[ 0 .. i-1 ] } close( sa ); } Another Example, send "hello" to someone: s = socket( AF_INET, SOCK_DGRAM, 0 ) if( s < 0 ) exit(-1); bzero( (char*) &serv_addr, sizeof( serv_addr ) ); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr( "144.55.21.21" ); serv_addr.sin_port = htons( SERV_TCP_PORT ); i = connect( s, (struct sockaddr * ) &serv_addr, sizeof( serv_addr ) ); if( i < 0 ) exit(-1); i = send( s, "hello", strlen("hello")+1, 0 ); if( i < 0 ) exit(-1); close( s ); } // ========================================================== section OPTIMIZATION moshtag=OPTIMIZATION // Finding the smallest element (OCC/DL,C/H&S). // Avoid extra comparison for loop ending by making sure // final stop is a[0] (the current smallest element). int quick_min(int *a, int n) { int tmp = s = a[0]; // save a[0] as current smallest. int *p = a[n]; // start from a[n]. for(;;){ while(*--p > s ) // move back while larger. ; if( p == &a[0] ) // end of search? break; a[0] = s = *p; // Smaller found. } a[0] = tmp; // restore a[0]. return s; // return smallest. } // Finding if any one of four bytes of x is zero. int any_byte_zero() { // Method 1. Check each of four bytes (four jumps). char * p = (char*) x; if( ! y[0] || !y[1] || !y[2] || !y[3] ) ...; // Method 2. Check 32bits, one jump. #define has0byte(x) ((x)& 0x01010101 & (x) & (0x80808080)) if( has0byte(x) ) ...; } tag duffs_device() { // fast copy n bytes from s to d. switch( n & 7 ){ do{ case 7: *d++ = *s++; case 6: *d++ = *s++; case 5: *d++ = *s++; case 4: *d++ = *s++; case 3: *d++ = *s++; case 2: *d++ = *s++; case 1: *d++ = *s++; case 0: ; }while( n <= n -= 8 ); } } ================================================================== section MACHINE_DIFFERENCES moshtag=byte_order,alignment,enquire,int,short,long,SUN,NT,HP,LINUX,enquire.c { --- < SUN & NT: Dereferencing NULL causes a trap > HP: BEWARE! Dereferencing NULL doesn't cause a trap --- < SUN & NT: unsigned short promotes to signed int/long > HP: unsigned short promotes to unsigned int/long < SUN & Linux: Float expressions are evaluated in float precision > HP & NT: Float expressions are evaluated in double precision --- < SUN & HP: short: AB .. Byte Order Big Endian. < SUN & HP: int: ABCD < SUN & HP: long: ABCD < HP64: long: ABCDEFGH ! NT & Linux: short: BA .. Byte Order Small Endian. ! NT & Linux: int: DCBA ! NT & Linux: long: DCBA --- Need to diff Linux again: @ Linux Only: Float expressions are evaluated in long double precision @ Linux Only: Double expressions are evaluated in long double precision @ Linux Only: Strings are shared Linux SIZES char=8 bits, signed short=16 int=32 long=32 float=32 double=64 bits long double=96 bits char*=32 bits int* =32 bits func*=32 bits Type size_t is unsigned int/long Type wchar_t is signed int/long ALIGNMENTS char=1 short=2 int=4 long=4 float=4 double=4 long double=4 char*=4 int*=4 func*=4 Linux64 moshtag=linux64 char = 8 bits, signed short=16 int=32 long=64 float=32 double=64 bits long double=128 bits Type size_t is unsigned long ALIGNMENTS char=1 short=2 int=4 long=8 float=4 double=8 long double=16 char*=8 int*=8 func*=8 short: BA int: DCBA long: HGFEDCBA Maximum long = 9223372036854775807 (= 2**63-1) Minimum long = -9223372036854775808 Maximum unsigned short = 65535 Maximum unsigned int = 4294967295 Maximum unsigned long = 18446744073709551615 PROMOTIONS unsigned short promotes to signed int long+unsigned gives signed long HP64 ALIGNMENTS char=1 short=2 int=4 long=8 float=4 double=8 long double=16 char*=8 int*=8 func*=8 } ============================================================ LP64 moshtag=lp64,ilp32,64 A. Sizes Ansi sizeof() is always unsigned, try: if( 0-sizeof(int) > 0 ) printf("See: 0-sizeof(int) is unsigned!\n"); ILP32: win32 hp11 solaris linux ANSI C Integer Requirements, see C book. moshtag=ansi_int sizeof(int) >= sizeof(short) >= 2. sizeof(long) >=sizeof(int) sizeof(long) >= 4. LP64: hp11_64 solaris_64 (assume default for 64bit). New: sizeof(long)==sizeof(void*)==8, rest unchanged. P64: win64 New: sizeof(void*)==8, rest unchanged. B. Linting moshtag=lint linux64> gcc -m64 enquire.c .. crashes halfway ============================================= See mmap() to get more mem. > limit stack 16000 > limit stack stacksize 16000 kbytes ... 3+ GB should be available for data space ... moshtag=solaris_64,lint,linting see /usr/include/sys/isa_defs.h for _CHAR_IS_SIGNED _ILP32 _LP64 etc > cc -xarch=v9 enquire.c > lint -Xarch=v9 -errchk=longptr64 files.c Useful lint64 options on solaris: -F .. full filename -errtags=yes .. ID for error message type. -errchk=%all .. more messages -errfmt=src .. show src code. -errfmt=macro .. show src code along macro defn unfolded. -errhdr=%user .. check user's header files. -fd .. look for old style protos -flagsrc=file .. take options from file -h .. no stupid heuristics, just bugs. -Ncheck=%all -Nlevel=4 -Xarch=v9 -s .. one line of diagnostics for emacs/vim. SOLARIS_LINT_FLAGS="-s -F\ -errtags=yes \ -errfmt=macro\ -errhdr=%user \ -Ncheck=%all \ -Nlevel=4\ " SOLARIS64_LINT_FLAGS="$LINT_FLAGS \ -Xarch=v9 \ -errchk=longptr64 \ -D__LP64__\ " > make CC="lint $LINT_FLAGS64" > lint.log 2>&1 > lint $INCLUDES $DEFINES $LINT_FLAGS64 *.c > lint.log 2>&1 > make CC=lint file.c > lint.log 2>&1 > vim lint.log : so ~/vim/lint.vim "color and delete trivial warnings" : set isk+=. : set isk+=/ .. go to error using file tags. > perl -ne 'print if m/\)\serror\b|cannot.*file|variable.*number/' *.log .. lint wont go to pass2 if errors, fix and rerun. Purify/Quantify: moshtag=purify,quantify See ~/dotnt/kshrc PURIFY_FLAGS="-cache-dir=/tmp -best-effort -windows=no" PURECOV_FLAGS="-windows=no" QUANTIFY_FLAGS="-windows=no -cache-dir=/tmp" > touch *.c > make CC="purecov $PURECOV_FLAGS" > purecov.log 2>&1 > make CC="quantify $QUANTIFY_FLAGS" > quantify.log 2>&1 > make CC="purify $PURIFY_FLAGS" > purify.log 2>&1 > perl -i~ ~/alias/purify-log.pl purify.log # Delete junk from purify log > cat pure.log | egrep "^[A-Z][A-Z][A-Z]:" | egrep -v "MLK|FIU|PLK" > make > make.log 2>&1 & > make > make.log 2>&1 > vim -q make.log, :so ~/vim/gcc-warn.vim ============================================= Fixing warning from Emacs: moshtag=make-emacs > emacs M-x cd ~/src_dir M-x compile make -Wk file.c .. compile even if upto date. M-x delete-matching-lines .. delete trivial warnings. " unused " "not used" > C-c C-c .. to go src with warning. > M-x next-error .. See compilation-minor-mode help ============================================= moshtag=hp11_64 hp> lint -s -Aa enquire.c # -s portability, -Aa Ansi. HP1164_CC_WARN64_FLAGS="+DA2.0W +w1 +M2" > cc +DA2.0W +w1 +M2 enquire.c # +w1 for warnings, +M2 for 64bits long double=128 bits # Sort LP64 warning by problem: > make 2>&1 | grep LP64 | xsort 'warning:\s+\S+:' | align warn > lp64.log > vim lp64.log :set isk+=46 " Make . part of tag, so file.c is a keyword for tags" > emacs lp64.log > M-x compilation-minor-mode > M-x next-error ; if cant find files, set ; (setq compilation-search-path '("dir1" "dir2")) C-xC-e /714: Function "malloc" called with no prototype or definition in scope /724: Initialization converts default int return type to pointer /722:.*cast converts 32 bit constant to pointer /725:.*cast converts 32 bit integer to pointer /727:.*cast truncates pointer into 32 bit integer /729:.*converts int* to long* /732:.*different types treated as unsigned /740:.*casting to a smaller size may truncate /530:.*casting from loose to strict alignment /720:.*Assignment may overflow // Example > catt -n x.c 1 void main(){ 2 int *x, *q, i; 3 long l=-1; 4 x = malloc(sizeof(int)*10); 5 (int*)i; 6 (int) &i; 7 (long*)&i; 8 i = l; 9 } hp64> cc +DA2.0W +M2 +w1 -Aa x.c /* line 4: warning 714: Function "malloc" called with no prototype or definition in scope. line 4: warning 724: LP64 migration: Assignment converts default int return type to pointer "x". line 5: warning 725: LP64 migration: Cast converts 32 bit integer to pointer. line 6: warning 727: LP64 migration: Cast truncates pointer into 32 bit integer. line 7: warning 530: LP64 migration: Casting from loose to strict alignment: Resulting pointer may be misaligned. line 7: warning 729: LP64 migration: Cast converts int* to long*. line 8: warning 720: LP64 migration: Assignment may overflow integer "i". */ ============================================= LP64 Gotcha List ---------------- 1. sizeof long array can overflow on lp64. uchar n = sizeof( 50*sizeof(long)); // 200 bytes in ilp32, 400 bytes in lp64. 2. Use u U L l suffix on large const. long l = 1 <<32; // 0 on ilp32,lp64 long l = 1L<<32; // 2^32 on lp64, 0 on ilp32. Solaris: see /usr/include/sys/inttypes.h INT64_C(5) => 5ll for ILP32, and 5l for LP64. 0x80000000L ulong in lp32, long in lp64. 3. Bit fields are converted to int and sign-extended (or uint if too large) in expr. struct { uint b:19, r:13 }x; uint y = x.b<<13 // x.b first converted to int and sign extended! uint y = (uint)x.b << 13; // ok. 4. Integer Arithmetic on ptr, ptr is trucated to int32. char *p="x"; (int)p+1=='\0' // p is trunc to int32. (uintptr_t)p+1=='\0' // ok. 5. Unprotyped func returning ptr is trucated to int32. // int login(...); -- implicit C decl. char *p = getenv("HOME"); // p is trucated to int32, crash. 6. Saving ptr in int, losses upper 4 bytes of ptr. void *q; int p = (int)q; // truncated to int32 7. Unions with long. union { long x; int y; // on lp64, y gets lsb of x. } 8. Print format specifier char *p="x"; printf("p=0x%08x",p); // losses msb. printf("p=%p", p); // ok. long x=LONG_MAX; printf("x=%d ",x); // truncated, wrong. printf("x=%ld",x); // ok. 9. Casting *int into *long. int *i; long *p; p+1; // p+=4 on ilp32 p+1; // p+=8 on lp64 p = (long*) i; // p misaligned pointing to *i and *(i+1). i = ( int*) p; // i pointing to lsb of p. 10. Unsigned bit fields (default sign and alignment). struct { b:12, int:0, d:5 } x; // b is unsigned in lp64, signed in ilp32. // :0 affects alignment in ilp32, no effect in lp64. 11. LP64 Perf Problems Larger exe, need more TLB, cache, mem (wrt same src compiled as ILP32). Long div slow in lp64, eg. 1L/9. Int Array indexes are sign-ext on every use, need more instruction in LP64, eg. int i; a[i]; 12. Expression sizing: Example. int x,y; long z = x + y; // x+y done in 32bit, then assignment will resize result for z. Example. ulong y = (1 <<32); // overflows in lp32 and lp64. ulong y = (1L<<32); // overflows in lp32, ok 2^32 in lp64. 13. Promotions: result = a op b; // 1. type of tmp is of max of a and b. // 2. tmp = a op b // 3. promote tmp to type of result, ptmp. // 4. result = ptmp; Example. long l=-1; uint i=1; if( l > i ) printf("ilp32"); // -1 is promoted to uint32. else printf("lp64"); // both promoted to signed 64. if( l > (long)i ) // fix ...; Example. main(){ // k is -1 in LP32, 4294967295 in LP64 int i = -2; unsigned int j = 1; long k = i+j; printf("int %d+ uint %ld= long k is %ld\n",i,j,k); } 15. Prototype: // #include missing. int *i = malloc(sizeof(*i)); // Ok in lp32, Crash on lp64 because // malloc will return 32bit int value because of missing prototype. } ============================================= section VARIOUS_SNIPPETS moshtag=pi pi800(){ static int a=10000, b, c=2800, d, e, f[2801], g; for(;b-c;) f[b++]=a/5; for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a) for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b) ; } See http://remus.rutgers.edu/~rhoads/Code int gcd(int a, int b) { int g; while(b){ g = a % b; a = b; b = g; } return(a); } moshtag=argc,opt int option_processing(int argc,char* argv[]){ int ok, debug=0; for( ok = 0; ok < argc; ok++ ){ printf( "argv[%d]=%s.\n", ok, argv[ok] ); if( strstr( argv[1], "size=" ) ){ // eg. -size=1000 size = atoi( strstr( argv[ok], "=" ) + 1 ); continue; } if (argv[ok][0]=='-' ) { // eg. -x -y -d1 switch( argv[ok][1] ){ case 'd' : // eg. -d0xffffffff debug = strtol( &argv[ok][2], NULL, 0 ); break; default: printf("[%d] invalid option %s\n", ok, argv[ok] ); break; } continue; } FileName = argv[ok]; } } moshtag=environ,env int print_env1(int argc, char* argv[], char* envp[] ){ extern char *environ[]; for( int i=0; environ[i]; i++ ) printf("%s",environ[i]); } int print_env2(int argc, char* argv[], char* envp[] ){ int i; printf("Program and arguments:\n"); for(i=0; argv[i]; i++) printf("%d %s\n",i,argv[i]); printf("Environment:\n"); for(i=0; envp[i]; i++) printf("%d %s\n",i,envp[i]); } o Modification affects ps output write characters into argv[0][0..n] ( <= n chars only)> o get argv[0] from the environment, when real file name is not the given name. // Tom Christiansen extern char **environ; printf("argv[0]=%s\n", environ[-2]); o environ[-2] may be argv[argc - 1], not necessary equal to argv[0]. If you throw in some more nonportable assumptions about argc, integers, and pointers, I'd suggest: // Jutta Degner char ** argv(){ extern char ** environ; int ac = 1; while ((int)environ[ -2 - ac ] != ac) ac++; return environ - (1 + ac); } o On System V.4 you can ask the operation system. #include #include #include char* cmd_name(){ char fn[12]; int fd; static prpsinfo_t pr; sprintf(fn, "/proc/%05d", getpid()); if ((fd = open(fn, O_RDONLY)) == -1) perror(fn), exit(1); if (ioctl(fd, PIOCPSINFO, (void *)&pr) == -1) perror("ioctl(PIOCPSINFO)"), exit(1); return pr.pr_fname; } o Auto type converter for msdev watch window. watch saveregs(), and say saved_regs.eax.i moshtag=saveregs typedef union void_ptr { void *p; int i; FILE *fp; unsigned int ui; float *pf; short s; double *pd; unsigned short us; int *pi; long l; long *pl; unsigned long ul; short *ps; signed char c; unsigned char *puc; unsigned char uc; signed char *pc; float f; // double d; // sizeof(void_ptr)==sizeof(void*) } void_ptr; void_ptr p = { 0 }; typedef struct reg_set { void_ptr eax,ebx,ecx,edx,esi,edi,ebp,esp; } reg_set; reg_set saved_regs; // not static. __declspec( naked ) int save_regs( void ) { __asm { mov saved_regs.eax.l,eax mov saved_regs.ebx.l,ebx mov saved_regs.ecx.l,ecx mov saved_regs.edx.l,edx mov saved_regs.esi.l,esi mov saved_regs.edi.l,edi mov saved_regs.ebp.l,ebp mov saved_regs.esp.l,esp ret } } //========================================================== // Replaces argv/argc, with those in file z, when called with --argfile z // if lineargs, each line of z is one arg. moshtag=argv,argc,marg,main #include #include #include #define MAXARG #define MAXLINE void marg(int* pargc,char***pargv, char* argfilename, int lineargs) { int argc=1; char**argv; // new array of ptr same name! char buf[MAXLINE]; int i; FILE* ARGFILE; if( ! (ARGFILE = fopen(argfilename, "r" ))) return; argv = (char**) malloc(MAXARG * sizeof(char*)); for(i=0;i= MAXARG ) break; tok = strtok( NULL, seps ); } } if( argc >= MAXARG ) break; } fclose( ARGFILE ); *pargc = argc; *pargv = argv; } main(int argc,char**argv) { int i; for(i=0;i 1 && !strcmp(argv[1], "--argfile" ) ){ marg( &argc, &argv, argv[2], 1 ); } for(i=0;i max(x,y); let: N = x * y; let: p * s = 1 mod ( (x-1)(y-1) ); Destroy: x, y; Announce public key = p, N; Hide private key = s; } enc(plain_text: M; public_key p, N ){ return C = M^p mod N; } dec(cipher_text: C; private_key s, N ){ return M = C^s mod N; } //========================================================== section BASIC_DATA_TYPES_x86 tag datatype() { // from windef.h typedef int boolean; typedef unsigned char BYTE; typedef unsigned char UCHAR; typedef short int16; typedef unsigned short uint16; typedef unsigned short USHORT; typedef unsigned short WORD ; typedef long int32; typedef unsigned long uint32; typedef unsigned long ULONG; typedef unsigned long DWORD; typedef long long int64; typedef unsigned long long uint64; #define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8)) #define MAKELONG(a, b) ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16)) #define LOWORD(l) ((WORD)(l)) #define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) #define LOBYTE(w) ((BYTE)(w)) #define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) } section MISC section Memory Layout tag memory_layout() { ------+---------+------------+-------+------ Gb Mb win95 NT DOS ------+---------+------------+-------+------ 0- 0-1 Mb MSDOS 1-4 Mb 16bit Win -2Gb 4-2000 16/32 Apps 2-3Gb DLL/API 3-4Gb VXD/Drivers ------+---------+------------+-------+------ } IBM PC Power supply moshtag=power { + 5V Red +12V Yellow - 5V Blue -12V Brown GND Black PowerGood White } section Hungarian Notation: moshtag=hungarian { p pointer by byte, uchar. lp pointer w word, 16 bit. h Handle dw dword, 32 bit ulong. t typedef c char g global wc wide char fn function s string b bool sz string, 0 terminated. I Interface } section HEX_WORDS to fill blank memory. moshtag=hex_words { DC Dacca Dada Dec Decca Ed FAA FCC FDA Feb abe baba be bed cede dad dad dead deaf decade deed deeded deface ebb efface facade facaded face faced fad fade faded fed fed fee feed feeded aba abac abaca abaff abb abed acca accede ace adad add adda added ade adead aface affa baa baba babe bac bacaba bacca baccae bad bade bae baff bead beaded bebed bed bedad bedded bedead bedeaf bee beef cab caba cabda cad cade caeca caffa cede cee dab dabb dabba dace dad dada dade dae daff dead deaf deb decad decade dee deed deedeed deface ebb ecad edea efface facade face faced fad fade faded fae faff fed fee feed } moshtag=morse { +------------------------------+---------------------------+ | MORSE CODE | () -.--.- Any parens | | . .-.-.- period | , --..-- comma | | ? ..--.. question | : ---... colon | | ; -.-.-. semicolon | - -....- hyphen | | ! --..- exclamation | / -..-. slash | | " .-..-. double quote | ' .----. apostrophe | |------------------------------+---------------------------| | A .- |B -... |C -.-. |D -.. |E . |F ..-. | | G --. |H .... |I .. |J .--- |K -.- |L .-.. | | M -- |N -. |O --- |P .--. |Q --.- |R .-. | | S ... |T - |U ..- |V ...- |W .-- |X -..- | | Y -.-- |Z --.. | | | | | |----------+---------+---------+--------+--------+---------| | 1 .---- |2 ..--- |3 ...-- |4 ....- |5 ..... | | 6 -.... |7 --... |8 ---.. |9 ----. |0 ----- | +----------+---------+---------+--------+------------------+ } section ASCII_CODES moshtag=ascii { > cat ascii.bat perl -e \'printf "%#x\n", ord(shift)\' "^]" Non printable chars are 0-31 and 127; space is 32, 'a' & 0x1f == C-a ; C-a | 0x60 == 'a' 110_0001 & 001_1111 == 0001 ; 'A' & 0x1f == C-a ; C-a | 0x40 == 'A' 100_0001 & 0x1f == 0001 ; ^^^------- bits 765 is zero for control char. ^-------- 6th bit is case, if 1 then lowercase. CONTROL+keypressed & 0x1f .. Control key zeroes bits 6,7,8. SHIFT +keypressed & ~0x20 .. Shift key zeroes bit 6. Example: 'A' > 'a'. 'A' | 0x20 == 'a' == 110_0001 'a' & ~0x20 == 'A' == 100_0001 #define _toascii(c) ((c) &0x7f) #define _tolower(c) ((c)+'a'-'A') #define _toupper(c) ((c)+'A'-'a') } man_sections moshtag=man_sections See $DOC/linux.man for MAN break up 1 Shell Commands, eg. chown(1). 2 System calls, eg. open(2). 3 C Library calls, eg. qsort(3). 4 Special files in /dev, eg. tty(4). 5 File formats and conventions, eg. ftpusers(5). 6 Games, eg intro(6). 7 Macro packages and conventions, protocols etc, eg. bootparam(7). 8 System management commands, eg. mount(8) .. not in linux.man 9 Kernel routines .. not in linux.man -------------------------------------------------------------- [EOF]