Improved ast.c

Pascal J. Bourguignon [2013-01-30 00:01]
Improved ast.c
Filename
Makefile
ast.c
diff --git a/Makefile b/Makefile
index 37f9459..e1dde7e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-all:clang.lisp
+all:test-ast

 SWIG=/data/languages/swig/bin/swig
 INCLUDES=-I/usr/include
@@ -36,12 +36,15 @@ clean:
 	- rm -f clang-raw.lisp


-CC=/opt/llvm/bin/clang
+CC=/opt/llvm/bin/clang -isysroot /
 ast:ast.c Makefile
-	$(CC) -I. -L. -g3 -ggdb3 -o ast ast.c
+	@ true $(CC) -I. -g3 -ggdb3 -E -o /dev/stdout ast.c
+	@ $(CC) -I. -g3 -ggdb3 -o ast ast.c -L/opt/llvm/lib -lclang

 test-ast:ast
-	./ast example.c
+	@ LD_LIBRARY_PATH=/opt/llvm/lib:$LD_LIBRARY_PATH ./ast example.c
+
+# -I/opt/llvm/lib/clang/3.3/include

 #### THE END ####

diff --git a/ast.c b/ast.c
index 13fc638..81c8af1 100644
--- a/ast.c
+++ b/ast.c
@@ -1,191 +1,515 @@
 #include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <iso646.h>
 #include <clang-c/Index.h>
+#undef NDEBUG
+#include <assert.h>

+typedef enum {false=0,true=1} bool;
+#define INCF(x) (++(x))
+#define DECF(x) (--(x))
+
+
+
+
+
+void* memory_alloc(const char* fname,size_t size){
+    void* memory=malloc(size);
+    if(0==memory){
+        fprintf(stderr,"%s: out of memory\n",fname);
+        exit(1);}
+    return(memory);}
+
+
+int* compute_primes_to(int n){
+    if(n<2){
+        int* primes=memory_alloc(__FUNCTION__,1);
+        primes[0]=0;
+        return(primes);
+    }else if(2==n){
+        int* primes=memory_alloc(__FUNCTION__,2);
+        primes[0]=1;
+        primes[1]=2;
+        return(primes);
+    }else if(3==n){
+        int* primes=memory_alloc(__FUNCTION__,3);
+        primes[0]=1;
+        primes[1]=2;
+        primes[2]=3;
+        return(primes);
+    }else{
+        int bits_max;
+        int words_max;
+        int word_size=8*sizeof(int);
+        int* bits;
+        int bit;
+        int prime_count=2;
+        int cur_prime=3;
+        int* primes;
+
+        n-=(n%1)?3:2;
+        bits_max=n/2;
+        words_max=bits_max/word_size;
+        bits=memory_alloc(__FUNCTION__,words_max);
+        for(int i=0;i<words_max;i++){
+            bits[i]=(~0);}
+        while(cur_prime<n){
+           bit=cur_prime+(cur_prime-3)/2;
+           while(bit<bits_max){
+               bits[bit/word_size]&=(~(1<<bit%word_size));
+               bit+=cur_prime;}
+           bit=1+((cur_prime-3)/2);
+           int pos=bit;
+           while((pos<=bits_max) and (0==(bits[pos/word_size]&(1<<pos%word_size)))){
+                pos++; }
+           bit=pos;
+           if(bit<bits_max){
+              cur_prime=bit+bit+3;
+              prime_count++;
+           }else{
+               cur_prime=n;
+           }}
+        primes=memory_alloc(__FUNCTION__,prime_count*sizeof(int));
+        primes[0]=prime_count;
+        int curnum=1;
+        primes[curnum++]=2;
+        primes[curnum++]=3;
+        cur_prime=3;
+        bit=1;
+           while((bit<=bits_max) and (0==(bits[bit/word_size]&(1<<bit%word_size)))){
+                bit++; }
+        while(bit<bits_max){
+           cur_prime=bit+bit+3;
+           primes[curnum++]=cur_prime;
+           bit++;
+           while((bit<=bits_max) and (0==(bits[bit/word_size]&(1<<bit%word_size)))){
+                bit++; }}
+        return(primes);}}
+
+
+
+int* primes=0;
+
+int ceiling_to_nearest_prime(int n){
+    if((0==primes) or (primes[primes[0]-1]<n)){
+        primes=compute_primes_to(n*2);
+    }
+    int min=1;
+    int max=primes[0];
+    int ind=(min+max)/2;
+    int ord=(n==primes[ind])?0:(n<primes[ind])?-1:1;
+    while((0!=ord) and (min!=ind)){
+       if(ord<0){
+                    max=ind;
+        }else{
+        min=ind;
+        }
+        ind=(min+max)/2;
+        ord=(n==primes[ind])?0:(n<primes[ind])?-1:1;}
+    if((1<ind)and(ord<0)){
+        ord=1;
+        ind--;}
+    if(ord<0){
+       return(primes[1]);
+    }else{
+       return(primes[ind+1]);
+    }}
+
+
+int argv_count(const char* const* argv){
+    int cnt=0;
+    while(argv[cnt]){
+        cnt++;
+    }
+    return(cnt);}
+
+
+const char* const* argv_concat(const char* const* argv1,const char* const* argv2){
+    int cnt1=argv_count(argv1);
+    int cnt2=argv_count(argv2);
+    const char** result=memory_alloc(__FUNCTION__,(1+cnt1+cnt2)*sizeof(char*));
+    int s=0;
+    int d=0;
+    for(s=0;s<cnt1;s++){
+        result[d++]=argv1[s];}
+    for(s=0;s<cnt2;s++){
+        result[d++]=argv2[s];}
+    result[d]=0;
+    return(result);}
+
+
+
+typedef enum {
+    ot_nil=0,
+    ot_CXCursor,  // CXCursor*
+    ot_int,       // int
+    ot_cons,      // cons*
+    ot_hashtable, // hashtable*
+} object_type;
+
+const char* type_name(object_type type){
+    switch(type){
+      case ot_nil: return("null");
+      case ot_CXCursor: return("CXCursor");
+      case ot_int: return("integer");
+      case ot_cons: return("cons");
+      case ot_hashtable: return("hashtable");
+      default: return("#<UNKNOWN TYPE>");}}
+
+void error_type(const char* fname,object_type expected,object_type got){
+    fprintf(stderr,"%s: got an object of type %s, expected type %s\n",
+            fname,type_name(got),type_name(expected));
+    exit(1);}
+
+void error_signal(const char* fname,const char* message){
+    fprintf(stderr,"%s: %s\n",fname,message);
+    exit(1);}
+
+typedef struct {
+    object_type type;
+    union {
+        CXCursor cursor;
+        struct hashtable* hashtable;
+        struct cons* cons;
+        int integer;
+    } value;
+} object;
+
+
+object* box(object_type type,...){
+    object* o=memory_alloc(__FUNCTION__,sizeof(*o));
+    o->type=type;
+    va_list ap;
+    va_start(ap,type);
+    switch(type){
+      case ot_CXCursor:  o->value.cursor=(*(va_arg(ap,CXCursor*)));         break;
+      case ot_int:       o->value.integer=va_arg(ap,int);                   break;
+      case ot_cons:      o->value.cons=va_arg(ap,struct cons*);             break;
+      case ot_hashtable: o->value.hashtable=va_arg(ap,struct hashtable*);   break;
+      default: error_signal(__FUNCTION__,"unexpected object type.");        break;}
+    va_end(ap);
+    return(o);}
+
+
+void* nil=0;
+
+bool null(void* object){
+    return(0==object);}
+
+
+
+typedef struct cons {
+    object* car;
+    object* cdr;
+} kons;
+
+object* cons(object* a,object* d){
+    kons* cell=memory_alloc(__FUNCTION__,sizeof(*cell));
+    cell->car=a;
+    cell->cdr=d;
+    return(box(ot_cons,cell));}
+
+object* car(object* cell){
+    if(0==cell){ return(cell); }
+    else if(ot_cons==cell->type){ return(cell->value.cons->car); }
+    else{ error_type(__FUNCTION__,ot_cons,cell->type); return(nil); }}
+
+object* cdr(object* cell){
+    if(0==cell){ return(cell); }
+    else if(ot_cons==cell->type){ return(cell->value.cons->cdr); }
+    else{ error_type(__FUNCTION__,ot_cons,cell->type); return(nil); }}
+
+object* setcar(object* cell,object* a){
+    if(0==cell){ error_type(__FUNCTION__,ot_cons,ot_nil); return(nil); }
+    else if(ot_cons==cell->type){ cell->value.cons->car=a; return(a); }
+    else{ error_type(__FUNCTION__,ot_cons,cell->type); return(nil); }}
+
+object* setcdr(object* cell,object* d){
+    if(0==cell){ error_type(__FUNCTION__,ot_cons,ot_nil); return(nil); }
+    else if(ot_cons==cell->type){ cell->value.cons->cdr=d; return(d); }
+    else{ error_type(__FUNCTION__,ot_cons,cell->type); return(nil); }}
+
+
+
+bool equal(object* a,object* b){
+    if(a->type==b->type){
+        switch(a->type){
+          case ot_nil:       return(true);
+          case ot_CXCursor:  return(clang_equalCursors(a->value.cursor,b->value.cursor));
+          case ot_int:       return(a->value.integer==b->value.integer);
+          case ot_cons:      return(equal(car(a),car(b)) and equal(cdr(a),cdr(b)));
+          case ot_hashtable: return(a->value.hashtable==b->value.hashtable);}
+    }else{
+        return(false);}}
+
+
+
+typedef struct hashtable {
+    int count;
+    int size;
+    float rehash_size;
+    float rehash_threshold;
+    object** entries;
+} hashtable;
+
+unsigned hashtable_hash(hashtable*);
+
+unsigned sxhash(object* o){
+    switch(o->type){
+      case ot_nil:       return(0);
+      case ot_CXCursor:  return(clang_hashCursor(o->value.cursor));
+      case ot_int:       return(o->value.integer);
+      case ot_cons:      return(sxhash(car(o))+(sxhash(cdr(o))<<1));
+      case ot_hashtable: return(hashtable_hash(o->value.hashtable));}}
+
+
+hashtable* make_hashtable(int size){
+    hashtable* h=memory_alloc(__FUNCTION__,sizeof(*h));
+    h->count=0;
+    h->size=size;
+    h->rehash_size=2.0;
+    h->rehash_threshold=1.5;
+    h->entries=memory_alloc(__FUNCTION__,sizeof(*(h->entries))*size);
+    int i=0;
+    for(i=0;i<size;i++){
+        h->entries[i]=nil;}
+    return(h);}
+
+object* hashtable_get(hashtable* table,object* key){
+    unsigned h=sxhash(key);
+    int i=h%table->size;
+    while(not(null(table->entries[i])) and not(equal(key,table->entries[i]->value.cons->car))){
+        i=(i+1)%table->size;}
+    return(cdr(table->entries[i]));}
+
+unsigned hashtable_hash(hashtable* table){
+    return((table->size<<3)+table->count);}
+
+hashtable* hashtable_grow(hashtable* table){
+    int newsize=ceiling_to_nearest_prime(table->size*table->rehash_threshold);
+    object** newentries=memory_alloc(__FUNCTION__,newsize);
+    for(int j=0;j<newsize;j++){
+        newentries[j]=nil;}
+    for(int i=0;i<table->size;i++){
+        object* entry=table->entries[i];
+        if(entry){
+            unsigned h=sxhash(car(entry));
+            int j=h%newsize;
+            while(not(null(newentries[j]))){
+                j=(j+1)%newsize;}
+            newentries[j]=entry;}}
+    table->size=newsize;
+    table->entries=newentries;
+    return(table);}
+
+object* hashtable_set(hashtable* table,object* key,object* value){
+    if(table->count*table->rehash_size<table->size){
+        unsigned hash=sxhash(key);
+        int i=hash%table->size;
+        while(not(null(table->entries[i])) and not(equal(key,car(table->entries[i])))){
+            i=(i+1)%table->size;}
+        if(null(table->entries[i])){
+            INCF(table->count);
+            table->entries[i]=cons(key,value);
+        }else{
+            setcdr(table->entries[i],value);
+        }
+        return(value);
+    }else{
+        hashtable_grow(table);
+        return(hashtable_set(table,key,value));}}
+
+
+
+static const char* Includes[]={"-I/opt/llvm/lib/clang/3.3/include",0};

 const char* cursorSymbol(int cursorKind){
     switch(cursorKind){
-    case CXCursor_UnexposedDecl:                      return ":unexposed-decl";
-    case CXCursor_StructDecl:                         return ":struct-decl";
-    case CXCursor_UnionDecl:                          return ":union-decl";
-    case CXCursor_ClassDecl:                          return ":class-decl";
-    case CXCursor_EnumDecl:                           return ":enum-decl";
-    case CXCursor_FieldDecl:                          return ":field-decl";
-    case CXCursor_EnumConstantDecl:                   return ":enum-constant-decl";
-    case CXCursor_FunctionDecl:                       return ":function-decl";
-    case CXCursor_VarDecl:                            return ":var-decl";
-    case CXCursor_ParmDecl:                           return ":parm-decl";
-    case CXCursor_ObjCInterfaceDecl:                  return ":objc-interface-decl";
-    case CXCursor_ObjCCategoryDecl:                   return ":objc-category-decl";
-    case CXCursor_ObjCProtocolDecl:                   return ":objc-protocol-decl";
-    case CXCursor_ObjCPropertyDecl:                   return ":objc-property-decl";
-    case CXCursor_ObjCIvarDecl:                       return ":objc-ivar-decl";
-    case CXCursor_ObjCInstanceMethodDecl:             return ":objc-instance-method-decl";
-    case CXCursor_ObjCClassMethodDecl:                return ":objc-class-method-decl";
-    case CXCursor_ObjCImplementationDecl:             return ":objc-implementation-decl";
-    case CXCursor_ObjCCategoryImplDecl:               return ":objc-category-impl-decl";
-    case CXCursor_TypedefDecl:                        return ":typedef-decl";
-    case CXCursor_CXXMethod:                          return ":cxx-method";
-    case CXCursor_Namespace:                          return ":namespace";
-    case CXCursor_LinkageSpec:                        return ":linkage-spec";
-    case CXCursor_Constructor:                        return ":constructor";
-    case CXCursor_Destructor:                         return ":destructor";
-    case CXCursor_ConversionFunction:                 return ":conversion-function";
-    case CXCursor_TemplateTypeParameter:              return ":template-type-parameter";
-    case CXCursor_NonTypeTemplateParameter:           return ":non-type-template-parameter";
-    case CXCursor_TemplateTemplateParameter:          return ":template-template-parameter";
-    case CXCursor_FunctionTemplate:                   return ":function-template";
-    case CXCursor_ClassTemplate:                      return ":class-template";
-    case CXCursor_ClassTemplatePartialSpecialization: return ":class-template-partial-specialization";
-    case CXCursor_NamespaceAlias:                     return ":namespace-alias";
-    case CXCursor_UsingDirective:                     return ":using-directive";
-    case CXCursor_UsingDeclaration:                   return ":using-declaration";
-    case CXCursor_TypeAliasDecl:                      return ":type-alias-decl";
-    case CXCursor_ObjCSynthesizeDecl:                 return ":objc-synthesize-decl";
-    case CXCursor_ObjCDynamicDecl:                    return ":objc-dynamic-decl";
-    case CXCursor_CXXAccessSpecifier:                 return ":cxx-access-specifier";
-    case CXCursor_ObjCSuperClassRef:                  return ":objc-super-class-ref";
-    case CXCursor_ObjCProtocolRef:                    return ":objc-protocol-ref";
-    case CXCursor_ObjCClassRef:                       return ":objc-class-ref";
-    case CXCursor_TypeRef:                            return ":type-ref";
-    case CXCursor_CXXBaseSpecifier:                   return ":cxx-base-specifier";
-    case CXCursor_TemplateRef:                        return ":template-ref";
-    case CXCursor_NamespaceRef:                       return ":namespace-ref";
-    case CXCursor_MemberRef:                          return ":member-ref";
-    case CXCursor_LabelRef:                           return ":label-ref";
-    case CXCursor_OverloadedDeclRef:                  return ":overloaded-decl-ref";
-    case CXCursor_VariableRef:                        return ":variable-ref";
-    case CXCursor_InvalidFile:                        return ":invalid-file";
-    case CXCursor_NoDeclFound:                        return ":no-decl-found";
-    case CXCursor_NotImplemented:                     return ":not-implemented";
-    case CXCursor_InvalidCode:                        return ":invalid-code";
-    case CXCursor_UnexposedExpr:                      return ":unexposed-expr";
-    case CXCursor_DeclRefExpr:                        return ":decl-ref-expr";
-    case CXCursor_MemberRefExpr:                      return ":member-ref-expr";
-    case CXCursor_CallExpr:                           return ":call-expr";
-    case CXCursor_ObjCMessageExpr:                    return ":objc-message-expr";
-    case CXCursor_BlockExpr:                          return ":block-expr";
-    case CXCursor_IntegerLiteral:                     return ":integer-literal";
-    case CXCursor_FloatingLiteral:                    return ":floating-literal";
-    case CXCursor_ImaginaryLiteral:                   return ":imaginary-literal";
-    case CXCursor_StringLiteral:                      return ":string-literal";
-    case CXCursor_CharacterLiteral:                   return ":character-literal";
-    case CXCursor_ParenExpr:                          return ":paren-expr";
-    case CXCursor_UnaryOperator:                      return ":unary-operator";
-    case CXCursor_ArraySubscriptExpr:                 return ":array-subscript-expr";
-    case CXCursor_BinaryOperator:                     return ":binary-operator";
-    case CXCursor_CompoundAssignOperator:             return ":compound-assign-operator";
-    case CXCursor_ConditionalOperator:                return ":conditional-operator";
-    case CXCursor_CStyleCastExpr:                     return ":cstyle-cast-expr";
-    case CXCursor_CompoundLiteralExpr:                return ":compound-literal-expr";
-    case CXCursor_InitListExpr:                       return ":init-list-expr";
-    case CXCursor_AddrLabelExpr:                      return ":addr-label-expr";
-    case CXCursor_StmtExpr:                           return ":stmt-expr";
-    case CXCursor_GenericSelectionExpr:               return ":generic-selection-expr";
-    case CXCursor_GNUNullExpr:                        return ":gnunull-expr";
-    case CXCursor_CXXStaticCastExpr:                  return ":cxx-static-cast-expr";
-    case CXCursor_CXXDynamicCastExpr:                 return ":cxx-dynamic-cast-expr";
-    case CXCursor_CXXReinterpretCastExpr:             return ":cxx-reinterpret-cast-expr";
-    case CXCursor_CXXConstCastExpr:                   return ":cxx-const-cast-expr";
-    case CXCursor_CXXFunctionalCastExpr:              return ":cxx-functional-cast-expr";
-    case CXCursor_CXXTypeidExpr:                      return ":cxx-typeid-expr";
-    case CXCursor_CXXBoolLiteralExpr:                 return ":cxx-bool-literal-expr";
-    case CXCursor_CXXNullPtrLiteralExpr:              return ":cxx-null-ptr-literal-expr";
-    case CXCursor_CXXThisExpr:                        return ":cxx-this-expr";
-    case CXCursor_CXXThrowExpr:                       return ":cxx-throw-expr";
-    case CXCursor_CXXNewExpr:                         return ":cxx-new-expr";
-    case CXCursor_CXXDeleteExpr:                      return ":cxx-delete-expr";
-    case CXCursor_UnaryExpr:                          return ":unary-expr";
-    case CXCursor_ObjCStringLiteral:                  return ":objc-string-literal";
-    case CXCursor_ObjCEncodeExpr:                     return ":objc-encode-expr";
-    case CXCursor_ObjCSelectorExpr:                   return ":objc-selector-expr";
-    case CXCursor_ObjCProtocolExpr:                   return ":objc-protocol-expr";
-    case CXCursor_ObjCBridgedCastExpr:                return ":objc-bridged-cast-expr";
-    case CXCursor_PackExpansionExpr:                  return ":pack-expansion-expr";
-    case CXCursor_SizeOfPackExpr:                     return ":size-of-pack-expr";
-    case CXCursor_LambdaExpr:                         return ":lambda-expr";
-    case CXCursor_ObjCBoolLiteralExpr:                return ":objc-bool-literal-expr";
-    case CXCursor_UnexposedStmt:                      return ":unexposed-stmt";
-    case CXCursor_LabelStmt:                          return ":label-stmt";
-    case CXCursor_CompoundStmt:                       return ":compound-stmt";
-    case CXCursor_CaseStmt:                           return ":case-stmt";
-    case CXCursor_DefaultStmt:                        return ":default-stmt";
-    case CXCursor_IfStmt:                             return ":if-stmt";
-    case CXCursor_SwitchStmt:                         return ":switch-stmt";
-    case CXCursor_WhileStmt:                          return ":while-stmt";
-    case CXCursor_DoStmt:                             return ":do-stmt";
-    case CXCursor_ForStmt:                            return ":for-stmt";
-    case CXCursor_GotoStmt:                           return ":goto-stmt";
-    case CXCursor_IndirectGotoStmt:                   return ":indirect-goto-stmt";
-    case CXCursor_ContinueStmt:                       return ":continue-stmt";
-    case CXCursor_BreakStmt:                          return ":break-stmt";
-    case CXCursor_ReturnStmt:                         return ":return-stmt";
-    case CXCursor_GCCAsmStmt:                         return ":gccasm-stmt";
-    case CXCursor_ObjCAtTryStmt:                      return ":objc-at-try-stmt";
-    case CXCursor_ObjCAtCatchStmt:                    return ":objc-at-catch-stmt";
-    case CXCursor_ObjCAtFinallyStmt:                  return ":objc-at-finally-stmt";
-    case CXCursor_ObjCAtThrowStmt:                    return ":objc-at-throw-stmt";
-    case CXCursor_ObjCAtSynchronizedStmt:             return ":objc-at-synchronized-stmt";
-    case CXCursor_ObjCAutoreleasePoolStmt:            return ":objc-autorelease-pool-stmt";
-    case CXCursor_ObjCForCollectionStmt:              return ":objc-for-collection-stmt";
-    case CXCursor_CXXCatchStmt:                       return ":cxx-catch-stmt";
-    case CXCursor_CXXTryStmt:                         return ":cxx-try-stmt";
-    case CXCursor_CXXForRangeStmt:                    return ":cxx-for-range-stmt";
-    case CXCursor_SEHTryStmt:                         return ":seh-try-stmt";
-    case CXCursor_SEHExceptStmt:                      return ":seh-except-stmt";
-    case CXCursor_SEHFinallyStmt:                     return ":seh-finally-stmt";
-    case CXCursor_MSAsmStmt:                          return ":msasm-stmt";
-    case CXCursor_NullStmt:                           return ":null-stmt";
-    case CXCursor_DeclStmt:                           return ":decl-stmt";
-    case CXCursor_TranslationUnit:                    return ":translation-unit";
-    case CXCursor_UnexposedAttr:                      return ":unexposed-attr";
-    case CXCursor_IBActionAttr:                       return ":ibaction-attr";
-    case CXCursor_IBOutletAttr:                       return ":iboutlet-attr";
-    case CXCursor_IBOutletCollectionAttr:             return ":iboutlet-collection-attr";
-    case CXCursor_CXXFinalAttr:                       return ":cxx-final-attr";
-    case CXCursor_CXXOverrideAttr:                    return ":cxx-override-attr";
-    case CXCursor_AnnotateAttr:                       return ":annotate-attr";
-    case CXCursor_AsmLabelAttr:                       return ":asm-label-attr";
-    case CXCursor_PreprocessingDirective:             return ":preprocessing-directive";
-    case CXCursor_MacroDefinition:                    return ":macro-definition";
-    case CXCursor_MacroExpansion:                     return ":macro-expansion";
-    case CXCursor_InclusionDirective:                 return ":inclusion-directive";
-    case CXCursor_ModuleImportDecl:                   return ":module-import-decl";
-    default:                                          return ":invalid";}}
+      case CXCursor_UnexposedDecl:                      return ":unexposed-decl";
+      case CXCursor_StructDecl:                         return ":struct-decl";
+      case CXCursor_UnionDecl:                          return ":union-decl";
+      case CXCursor_ClassDecl:                          return ":class-decl";
+      case CXCursor_EnumDecl:                           return ":enum-decl";
+      case CXCursor_FieldDecl:                          return ":field-decl";
+      case CXCursor_EnumConstantDecl:                   return ":enum-constant-decl";
+      case CXCursor_FunctionDecl:                       return ":function-decl";
+      case CXCursor_VarDecl:                            return ":var-decl";
+      case CXCursor_ParmDecl:                           return ":parm-decl";
+      case CXCursor_ObjCInterfaceDecl:                  return ":objc-interface-decl";
+      case CXCursor_ObjCCategoryDecl:                   return ":objc-category-decl";
+      case CXCursor_ObjCProtocolDecl:                   return ":objc-protocol-decl";
+      case CXCursor_ObjCPropertyDecl:                   return ":objc-property-decl";
+      case CXCursor_ObjCIvarDecl:                       return ":objc-ivar-decl";
+      case CXCursor_ObjCInstanceMethodDecl:             return ":objc-instance-method-decl";
+      case CXCursor_ObjCClassMethodDecl:                return ":objc-class-method-decl";
+      case CXCursor_ObjCImplementationDecl:             return ":objc-implementation-decl";
+      case CXCursor_ObjCCategoryImplDecl:               return ":objc-category-impl-decl";
+      case CXCursor_TypedefDecl:                        return ":typedef-decl";
+      case CXCursor_CXXMethod:                          return ":cxx-method";
+      case CXCursor_Namespace:                          return ":namespace";
+      case CXCursor_LinkageSpec:                        return ":linkage-spec";
+      case CXCursor_Constructor:                        return ":constructor";
+      case CXCursor_Destructor:                         return ":destructor";
+      case CXCursor_ConversionFunction:                 return ":conversion-function";
+      case CXCursor_TemplateTypeParameter:              return ":template-type-parameter";
+      case CXCursor_NonTypeTemplateParameter:           return ":non-type-template-parameter";
+      case CXCursor_TemplateTemplateParameter:          return ":template-template-parameter";
+      case CXCursor_FunctionTemplate:                   return ":function-template";
+      case CXCursor_ClassTemplate:                      return ":class-template";
+      case CXCursor_ClassTemplatePartialSpecialization: return ":class-template-partial-specialization";
+      case CXCursor_NamespaceAlias:                     return ":namespace-alias";
+      case CXCursor_UsingDirective:                     return ":using-directive";
+      case CXCursor_UsingDeclaration:                   return ":using-declaration";
+      case CXCursor_TypeAliasDecl:                      return ":type-alias-decl";
+      case CXCursor_ObjCSynthesizeDecl:                 return ":objc-synthesize-decl";
+      case CXCursor_ObjCDynamicDecl:                    return ":objc-dynamic-decl";
+      case CXCursor_CXXAccessSpecifier:                 return ":cxx-access-specifier";
+      case CXCursor_ObjCSuperClassRef:                  return ":objc-super-class-ref";
+      case CXCursor_ObjCProtocolRef:                    return ":objc-protocol-ref";
+      case CXCursor_ObjCClassRef:                       return ":objc-class-ref";
+      case CXCursor_TypeRef:                            return ":type-ref";
+      case CXCursor_CXXBaseSpecifier:                   return ":cxx-base-specifier";
+      case CXCursor_TemplateRef:                        return ":template-ref";
+      case CXCursor_NamespaceRef:                       return ":namespace-ref";
+      case CXCursor_MemberRef:                          return ":member-ref";
+      case CXCursor_LabelRef:                           return ":label-ref";
+      case CXCursor_OverloadedDeclRef:                  return ":overloaded-decl-ref";
+      case CXCursor_VariableRef:                        return ":variable-ref";
+      case CXCursor_InvalidFile:                        return ":invalid-file";
+      case CXCursor_NoDeclFound:                        return ":no-decl-found";
+      case CXCursor_NotImplemented:                     return ":not-implemented";
+      case CXCursor_InvalidCode:                        return ":invalid-code";
+      case CXCursor_UnexposedExpr:                      return ":unexposed-expr";
+      case CXCursor_DeclRefExpr:                        return ":decl-ref-expr";
+      case CXCursor_MemberRefExpr:                      return ":member-ref-expr";
+      case CXCursor_CallExpr:                           return ":call-expr";
+      case CXCursor_ObjCMessageExpr:                    return ":objc-message-expr";
+      case CXCursor_BlockExpr:                          return ":block-expr";
+      case CXCursor_IntegerLiteral:                     return ":integer-literal";
+      case CXCursor_FloatingLiteral:                    return ":floating-literal";
+      case CXCursor_ImaginaryLiteral:                   return ":imaginary-literal";
+      case CXCursor_StringLiteral:                      return ":string-literal";
+      case CXCursor_CharacterLiteral:                   return ":character-literal";
+      case CXCursor_ParenExpr:                          return ":paren-expr";
+      case CXCursor_UnaryOperator:                      return ":unary-operator";
+      case CXCursor_ArraySubscriptExpr:                 return ":array-subscript-expr";
+      case CXCursor_BinaryOperator:                     return ":binary-operator";
+      case CXCursor_CompoundAssignOperator:             return ":compound-assign-operator";
+      case CXCursor_ConditionalOperator:                return ":conditional-operator";
+      case CXCursor_CStyleCastExpr:                     return ":cstyle-cast-expr";
+      case CXCursor_CompoundLiteralExpr:                return ":compound-literal-expr";
+      case CXCursor_InitListExpr:                       return ":init-list-expr";
+      case CXCursor_AddrLabelExpr:                      return ":addr-label-expr";
+      case CXCursor_StmtExpr:                           return ":stmt-expr";
+      case CXCursor_GenericSelectionExpr:               return ":generic-selection-expr";
+      case CXCursor_GNUNullExpr:                        return ":gnunull-expr";
+      case CXCursor_CXXStaticCastExpr:                  return ":cxx-static-cast-expr";
+      case CXCursor_CXXDynamicCastExpr:                 return ":cxx-dynamic-cast-expr";
+      case CXCursor_CXXReinterpretCastExpr:             return ":cxx-reinterpret-cast-expr";
+      case CXCursor_CXXConstCastExpr:                   return ":cxx-const-cast-expr";
+      case CXCursor_CXXFunctionalCastExpr:              return ":cxx-functional-cast-expr";
+      case CXCursor_CXXTypeidExpr:                      return ":cxx-typeid-expr";
+      case CXCursor_CXXBoolLiteralExpr:                 return ":cxx-bool-literal-expr";
+      case CXCursor_CXXNullPtrLiteralExpr:              return ":cxx-null-ptr-literal-expr";
+      case CXCursor_CXXThisExpr:                        return ":cxx-this-expr";
+      case CXCursor_CXXThrowExpr:                       return ":cxx-throw-expr";
+      case CXCursor_CXXNewExpr:                         return ":cxx-new-expr";
+      case CXCursor_CXXDeleteExpr:                      return ":cxx-delete-expr";
+      case CXCursor_UnaryExpr:                          return ":unary-expr";
+      case CXCursor_ObjCStringLiteral:                  return ":objc-string-literal";
+      case CXCursor_ObjCEncodeExpr:                     return ":objc-encode-expr";
+      case CXCursor_ObjCSelectorExpr:                   return ":objc-selector-expr";
+      case CXCursor_ObjCProtocolExpr:                   return ":objc-protocol-expr";
+      case CXCursor_ObjCBridgedCastExpr:                return ":objc-bridged-cast-expr";
+      case CXCursor_PackExpansionExpr:                  return ":pack-expansion-expr";
+      case CXCursor_SizeOfPackExpr:                     return ":size-of-pack-expr";
+      case CXCursor_LambdaExpr:                         return ":lambda-expr";
+      case CXCursor_ObjCBoolLiteralExpr:                return ":objc-bool-literal-expr";
+      case CXCursor_UnexposedStmt:                      return ":unexposed-stmt";
+      case CXCursor_LabelStmt:                          return ":label-stmt";
+      case CXCursor_CompoundStmt:                       return ":compound-stmt";
+      case CXCursor_CaseStmt:                           return ":case-stmt";
+      case CXCursor_DefaultStmt:                        return ":default-stmt";
+      case CXCursor_IfStmt:                             return ":if-stmt";
+      case CXCursor_SwitchStmt:                         return ":switch-stmt";
+      case CXCursor_WhileStmt:                          return ":while-stmt";
+      case CXCursor_DoStmt:                             return ":do-stmt";
+      case CXCursor_ForStmt:                            return ":for-stmt";
+      case CXCursor_GotoStmt:                           return ":goto-stmt";
+      case CXCursor_IndirectGotoStmt:                   return ":indirect-goto-stmt";
+      case CXCursor_ContinueStmt:                       return ":continue-stmt";
+      case CXCursor_BreakStmt:                          return ":break-stmt";
+      case CXCursor_ReturnStmt:                         return ":return-stmt";
+      case CXCursor_GCCAsmStmt:                         return ":gccasm-stmt";
+      case CXCursor_ObjCAtTryStmt:                      return ":objc-at-try-stmt";
+      case CXCursor_ObjCAtCatchStmt:                    return ":objc-at-catch-stmt";
+      case CXCursor_ObjCAtFinallyStmt:                  return ":objc-at-finally-stmt";
+      case CXCursor_ObjCAtThrowStmt:                    return ":objc-at-throw-stmt";
+      case CXCursor_ObjCAtSynchronizedStmt:             return ":objc-at-synchronized-stmt";
+      case CXCursor_ObjCAutoreleasePoolStmt:            return ":objc-autorelease-pool-stmt";
+      case CXCursor_ObjCForCollectionStmt:              return ":objc-for-collection-stmt";
+      case CXCursor_CXXCatchStmt:                       return ":cxx-catch-stmt";
+      case CXCursor_CXXTryStmt:                         return ":cxx-try-stmt";
+      case CXCursor_CXXForRangeStmt:                    return ":cxx-for-range-stmt";
+      case CXCursor_SEHTryStmt:                         return ":seh-try-stmt";
+      case CXCursor_SEHExceptStmt:                      return ":seh-except-stmt";
+      case CXCursor_SEHFinallyStmt:                     return ":seh-finally-stmt";
+      case CXCursor_MSAsmStmt:                          return ":msasm-stmt";
+      case CXCursor_NullStmt:                           return ":null-stmt";
+      case CXCursor_DeclStmt:                           return ":decl-stmt";
+      case CXCursor_TranslationUnit:                    return ":translation-unit";
+      case CXCursor_UnexposedAttr:                      return ":unexposed-attr";
+      case CXCursor_IBActionAttr:                       return ":ibaction-attr";
+      case CXCursor_IBOutletAttr:                       return ":iboutlet-attr";
+      case CXCursor_IBOutletCollectionAttr:             return ":iboutlet-collection-attr";
+      case CXCursor_CXXFinalAttr:                       return ":cxx-final-attr";
+      case CXCursor_CXXOverrideAttr:                    return ":cxx-override-attr";
+      case CXCursor_AnnotateAttr:                       return ":annotate-attr";
+      case CXCursor_AsmLabelAttr:                       return ":asm-label-attr";
+      case CXCursor_PreprocessingDirective:             return ":preprocessing-directive";
+      case CXCursor_MacroDefinition:                    return ":macro-definition";
+      case CXCursor_MacroExpansion:                     return ":macro-expansion";
+      case CXCursor_InclusionDirective:                 return ":inclusion-directive";
+      case CXCursor_ModuleImportDecl:                   return ":module-import-decl";
+      default:                                          return ":invalid";}}


 const char* cursorLinkage(int linkageKind){
     switch(linkageKind){
-    case CXLinkage_NoLinkage:      return ":no-linkage";
-    case CXLinkage_Internal:       return ":internal";
-    case CXLinkage_UniqueExternal: return ":unique-external";
-    case CXLinkage_External:       return ":external";
-    default:                       return ":invalid";}}
+      case CXLinkage_NoLinkage:      return ":no-linkage";
+      case CXLinkage_Internal:       return ":internal";
+      case CXLinkage_UniqueExternal: return ":unique-external";
+      case CXLinkage_External:       return ":external";
+      default:                       return ":invalid";}}


 const char* cursorLanguageKind(int languageKind){
     switch(languageKind){
-    case CXLanguage_Invalid:   return ":invalid";
-    case CXLanguage_C:         return ":c";
-    case CXLanguage_ObjC:      return ":objc";
-    case CXLanguage_CPlusPlus: return ":cxx"
-    default:                   return ":invalid";}}
+      case CXLanguage_Invalid:   return ":invalid";
+      case CXLanguage_C:         return ":c";
+      case CXLanguage_ObjC:      return ":objc";
+      case CXLanguage_CPlusPlus: return ":cxx";
+      default:                   return ":invalid";}}


-int main(int argc,char** argv){
-    printf("%d argc\n",argc);
-    return(0);
+void test_all(void);
+int main(int argc,const char* const* argv){
+    test_all();
+    const char* pname=argv[0];
     if(argc<2){
-        fprintf(stderr,"Missing source file argument.\n");
+        fprintf(stderr,"%s: missing source file argument.\n",pname);
         return(1);}

     const char* sourceFile=argv[1];
     argv+=2;
     argc-=2;
-
+    const char* const* subArgv=argv_concat(Includes,argv);
+    int subArgc=argv_count(subArgv);
     CXIndex idx=clang_createIndex(0,1);
-    CXTranslationUnit tu=clang_createTranslationUnitFromSourceFile(idx,sourceFile,argc,argv,0,0);
+    CXTranslationUnit tu=clang_createTranslationUnitFromSourceFile(idx,sourceFile,subArgc,subArgv,0,0);
     if(0==tu){
-        fprintf(stderr,"Cannot create the translation unit.");
+        fprintf(stderr,"%s: cannot create the translation unit.",pname);
         return(1);}

     CXCursor cursor=clang_getTranslationUnitCursor(tu);
@@ -202,7 +526,7 @@ int main(int argc,char** argv){
         unsigned column;
         unsigned offset;

-        clang_getSpellingLocation(location,&file,&line,&column,&offset)
+        clang_getSpellingLocation(location,&file,&line,&column,&offset);
         CXString fileName=clang_getFileName(file);
         printf("\n :location (location :file \"%s\" :line %u :column %u :offset %u)",clang_getCString(fileName),line,column,offset);
         clang_disposeString(fileName);
@@ -211,14 +535,14 @@ int main(int argc,char** argv){
         CXSourceLocation start=clang_getRangeStart(range);
         CXSourceLocation end=clang_getRangeEnd(range);

-        clang_getSpellingLocation(start,&file,&line,&column,&offset)
-        CXString fileName=clang_getFileName(file);
+        clang_getSpellingLocation(start,&file,&line,&column,&offset);
+        fileName=clang_getFileName(file);
         printf("\n :range (range :start (location :file \"%s\" :line %u :column %u :offset %u)",clang_getCString(fileName),line,column,offset);
         clang_disposeString(fileName);

-        clang_getSpellingLocation(end,&file,&line,&column,&offset)
-        CXString fileName=clang_getFileName(file);
-        printf("\n                :end (location :file \"%s\" :line %u :column %u :offset %u))",clang_getCString(fileName),line,column,offset);
+        clang_getSpellingLocation(end,&file,&line,&column,&offset);
+        fileName=clang_getFileName(file);
+        printf("\n               :end   (location :file \"%s\" :line %u :column %u :offset %u))",clang_getCString(fileName),line,column,offset);
         clang_disposeString(fileName);


@@ -228,3 +552,55 @@ int main(int argc,char** argv){
     }
     clang_disposeTranslationUnit(tu);
     return(0);}
+
+
+
+//// tests
+
+int test_primes[]={
+    172,
+    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
+    67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
+    139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
+    223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
+    293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
+    383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
+    463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563,
+    569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643,
+    647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
+    743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
+    839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
+    941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021};
+
+#define testing(BODY)                                                   \
+    do{                                                                 \
+        printf("%s",__FUNCTION__);                                      \
+        { BODY }                                                        \
+        printf(" [OK]\n");                                              \
+    } while(0)
+
+
+void test_compute_primes_to(void){
+    testing({
+                 int* primes=compute_primes_to(1024);
+                 for(int i=0;i<=test_primes[0];i++){
+                     assert(test_primes[i]==primes[i]);}
+             });}
+
+void test_ceiling_to_nearest_prime(void){
+    testing({
+                 for(int i=1;i<test_primes[0];i++){
+                     int n=test_primes[i]-1;
+                     int ceiling=ceiling_to_nearest_prime(n);
+                     assert(ceiling==test_primes[i]);}
+             });}
+
+
+void test_all(void){
+    testing({
+                 test_compute_primes_to();
+                 test_ceiling_to_nearest_prime();
+             });}
+
+
+//// THE END ////
ViewGit