Merge: doc: fixed some typos and other misc. corrections
[nit.git] / clib / nit_main.c
index 6f7daba..9b20edb 100644 (file)
 #include <stdarg.h>
 #include "gc.h"
 
+#ifdef ANDROID
+       #include <android/log.h>
+       #define PRINT_ERROR(...) ((void)__android_log_print(ANDROID_LOG_WARN, "nit", __VA_ARGS__))
+#else
+       #define PRINT_ERROR(...) ((void)fprintf(stderr, __VA_ARGS__))
+#endif
+
 bigint object_id_counter = 1000000;
 enum gc_option { large, gc_opt_malloc, boehm, nitgc } gc_option;
 
@@ -76,19 +83,14 @@ char **glob_argv;
 val_t G_sys;
 
 void exithandler(int s) {
-       fprintf(stderr, "Recieved signal %d\n", s);
+       PRINT_ERROR( "Recieved signal %d\n", s);
        nit_exit(1);
 }
 void initialize_gc_option(void) {
        /* GC default */
        char *def;
-#ifdef WITH_LIBGC
-       gc_option = boehm;
-       def = "boehm";
-#else
        gc_option = nitgc;
        def = "nitgc";
-#endif
 
        /* Process GC runtime selection */
        if (getenv("NIT_GC_OPTION") != NULL) {
@@ -97,7 +99,7 @@ void initialize_gc_option(void) {
 #ifdef WITH_LIBGC
                        gc_option = boehm;
 #else
-               fprintf(stderr, "Compiled without Boehm GC support. Using default '%s'.\n", def);
+               PRINT_ERROR( "Compiled without Boehm GC support. Using default '%s'.\n", def);
 #endif
                } else if (strcmp(opt, "nitgc")==0) {
                        gc_option = nitgc;
@@ -106,14 +108,14 @@ void initialize_gc_option(void) {
                } else if (strcmp(opt, "large")==0) {
                        gc_option = large;
                } else if (strcmp(opt, "help")==0) {
-                       fprintf(stderr, "NIT_GC_OPTION accepts 'nitgc'"
+                       PRINT_ERROR( "NIT_GC_OPTION accepts 'nitgc'"
 #ifdef WITH_LIBGC
                                        ", 'boehm'"
 #endif
                                        ", 'large', 'malloc'. Default is '%s'.\n", def);
                        exit(1);
                } else {
-                       fprintf(stderr, "Invalid GC option in NIT_GC_OPTION environment variable. Using default '%s'.\n", def);
+                       PRINT_ERROR( "Invalid GC option in NIT_GC_OPTION environment variable. Using default '%s'.\n", def);
                }
        }
 
@@ -125,6 +127,9 @@ void initialize_gc_option(void) {
                case nitgc: Nit_gc_init(); break;
                default: break; /* Nothing */
        }
+
+       /* Initialize global references list */
+       nitni_global_ref_list_init();
 }
 void prepare_signals(void) {
        initialize_gc_option();
@@ -141,22 +146,23 @@ struct stack_frame_t *stack_frame_head = NULL;
 void nit_exit(int i) {
        char *opt=getenv("NIT_NO_STACK");
        if (opt == NULL || strcmp(opt, "0")==0) {
-               fprintf(stderr, ",---- Stack trace -- - -  -\n");
+               PRINT_ERROR( ",---- Stack trace -- - -  -\n");
                while(stack_frame_head != NULL) {
-                       fprintf(stderr, "| %s (%s:%d)\n", stack_frame_head->meth, stack_frame_head->file, stack_frame_head->line);
+                       PRINT_ERROR( "| %s (%s:%d)\n", stack_frame_head->meth, stack_frame_head->file, stack_frame_head->line);
                        if (stack_frame_head == stack_frame_head->prev) break;
                        stack_frame_head = stack_frame_head->prev;
                }
-               fprintf(stderr, "`------------------- - -  -\n");
+               PRINT_ERROR( "`------------------- - -  -\n");
        }
        exit(i);
 }
 
 void nit_abort(const char* s, const char* msg, const char* loc, int line) {
-       fprintf(stderr, s, msg);
-       fprintf(stderr, " (%s", loc);
-       if (line != 0) fprintf(stderr, ":%d", line);
-       fprintf(stderr, ")\n");
+       PRINT_ERROR( "Runtime error: ");
+       PRINT_ERROR( s, msg);
+       PRINT_ERROR( " (%s", loc);
+       if (line != 0) PRINT_ERROR( ":%d", line);
+       PRINT_ERROR( ")\n");
        nit_exit(1);
 }
 
@@ -198,7 +204,9 @@ void nitni_local_ref_clean( void ) {
        while ( link != NULL )
        {
                for ( i = 0; i < link->count; i ++ ) {
-                       free( link->reg[ i ] );
+                       if ( link->reg[i]->count == 0 ) { /* not registered globally */
+                               free( link->reg[ i ] );
+                       }
                }
 
                last_link = link;
@@ -212,3 +220,57 @@ void nitni_local_ref_clean( void ) {
 
        stack_frame_head->nitni_local_ref_head = NULL;
 }
+
+struct nitni_global_ref_list_t *nitni_global_ref_list;
+void nitni_global_ref_list_init() {
+       nitni_global_ref_list = (struct nitni_global_ref_list_t*)malloc(sizeof(struct nitni_global_ref_list_t));
+       nitni_global_ref_list->head = NULL;
+       nitni_global_ref_list->tail = NULL;
+}
+
+void nitni_global_ref_add( struct nitni_ref *ref ) {
+       if ( nitni_global_ref_list->head == NULL ) {
+               nitni_global_ref_list->head = ref;
+               ref->prev = NULL;
+       } else {
+               nitni_global_ref_list->tail->next = ref;
+               ref->prev = nitni_global_ref_list->tail;
+       }
+       nitni_global_ref_list->tail = ref;
+
+       ref->next = NULL;
+}
+
+void nitni_global_ref_remove( struct nitni_ref *ref ) {
+       if ( ref->prev == NULL ) {
+               nitni_global_ref_list->head = ref->next;
+       } else {
+               ref->prev->next = ref->next;
+       }
+
+       if ( ref->next == NULL ) {
+               nitni_global_ref_list->tail = ref->prev;
+       } else {
+               ref->next->prev = ref->prev;
+       }
+}
+
+extern void nitni_global_ref_incr( struct nitni_ref *ref ) {
+       if ( ref->count == 0 ) /* not registered */
+       {
+               /* add to list */
+               nitni_global_ref_add( ref );
+       }
+
+       ref->count ++;
+}
+
+extern void nitni_global_ref_decr( struct nitni_ref *ref ) {
+       if ( ref->count == 1 ) /* was last reference */
+       {
+               /* remove from list */
+               nitni_global_ref_remove( ref );
+       }
+
+       ref->count --;
+}