gi-server

Unnamed repository; edit this file 'description' to name the repository.
git clone https://logand.com/git/gi-server.git/
Log | Files | Refs

gi-server.c (6908B)


      1 #include <ctype.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <girepository.h>
      6 
      7 #define HSIZE (1024 * 1024)
      8 
      9 static char heap[HSIZE];
     10 static char *top;
     11 
     12 static void skip(void) {
     13   int c;
     14   while(isspace(c = getc(stdin)));
     15   ungetc(c, stdin);
     16 }
     17 
     18 enum {
     19   OUT_OF_MEMORY = 1,
     20   UNEXPECTED_EOF = 2,
     21   UNHANDLED_TYPE = 3,
     22   UNHANDLED_CASE = 4
     23 };
     24 
     25 static void put(char c) {
     26   if(heap + HSIZE <= top)
     27     exit(OUT_OF_MEMORY);
     28   *top++ = c;
     29 }
     30 
     31 static char *token(void) {
     32   skip();
     33   char *z = top;
     34   int c = getc(stdin);
     35   if('"' == c) {
     36     while('"' != (c = getc(stdin)) && EOF != c) {
     37       if(EOF == c)
     38         exit(UNEXPECTED_EOF);
     39       if('\\' == c) {
     40         c = getc(stdin);
     41         if(EOF == c)
     42           exit(UNEXPECTED_EOF);
     43       }
     44       put(c);
     45     }
     46     put(0);
     47     return z;
     48   } else {
     49     put(c);
     50     while(!isspace(c = getc(stdin)) && EOF != c)
     51       put(c);
     52     put(0);
     53     return !strcmp("null", z) ? (char *) NULL : z;
     54   };
     55 }
     56 
     57 static long integer(void) {return atol(token());}
     58 static void *pointer(void) {return (void *) integer();}
     59 
     60 static void to_argument(GIArgument *z, GIArgInfo *ai, GITypeInfo ti) {
     61   memset(z, 0, sizeof(GIArgument));
     62   char *t = token();
     63   GITypeTag tag = g_type_info_get_tag(&ti);
     64   switch(tag) {
     65   case GI_TYPE_TAG_VOID: break;
     66   case GI_TYPE_TAG_BOOLEAN: z->v_boolean = !!strcmp("false", t); break;
     67   case GI_TYPE_TAG_INT8: z->v_int8 = atol(t); break;
     68   case GI_TYPE_TAG_UINT8: z->v_uint8 = atol(t); break;
     69   case GI_TYPE_TAG_INT16: z->v_int16 = atol(t); break;
     70   case GI_TYPE_TAG_UINT16: z->v_uint16 = atol(t); break;
     71   case GI_TYPE_TAG_INT32: z->v_int32 = atol(t); break;
     72   case GI_TYPE_TAG_UINT32: z->v_uint32 = atol(t); break;
     73   case GI_TYPE_TAG_INT64:
     74   case GI_TYPE_TAG_UINT64:
     75   case GI_TYPE_TAG_FLOAT:
     76   case GI_TYPE_TAG_DOUBLE:
     77     fprintf(stderr, "unhandled type: %s %s\n", g_type_tag_to_string(tag), t);
     78     fflush(stderr);
     79     exit(UNHANDLED_TYPE);
     80     break;
     81   case GI_TYPE_TAG_GTYPE: z->v_pointer = (void *) atol(t); break;
     82   case GI_TYPE_TAG_UTF8: z->v_string = t; break;
     83   case GI_TYPE_TAG_FILENAME:
     84     fprintf(stderr, "unhandled type: %s %s\n", g_type_tag_to_string(tag), t);
     85     fflush(stderr);
     86     exit(UNHANDLED_TYPE);
     87     break;
     88   case GI_TYPE_TAG_ARRAY: z->v_pointer = NULL; break; // TODO
     89   case GI_TYPE_TAG_INTERFACE: z->v_pointer = (void *) atol(t); break;
     90   case GI_TYPE_TAG_GLIST:
     91   case GI_TYPE_TAG_GSLIST:
     92   case GI_TYPE_TAG_GHASH:
     93   case GI_TYPE_TAG_ERROR:
     94   case GI_TYPE_TAG_UNICHAR:
     95     fprintf(stderr, "unhandled type: %s %s\n", g_type_tag_to_string(tag), t);
     96     fflush(stderr);
     97     exit(UNHANDLED_TYPE);
     98     break;
     99   default:
    100     exit(UNHANDLED_CASE);
    101   }
    102 }
    103 
    104 static long event;
    105 
    106 static void handler(gpointer *object, gpointer *data) {
    107   event = (long) data;
    108 }
    109 
    110 int main(void) {
    111   GIRepository *r = g_irepository_get_default();
    112   long id = 0;
    113   event = 0;
    114   for(;;) {
    115     top = heap;
    116     fflush(stdout);
    117     char *cmd = token();
    118     if(!strcmp("find", cmd)) {
    119       char* namespace = token();
    120       char* name = token();
    121       GIBaseInfo *p = g_irepository_find_by_name(r, namespace, name);
    122       if(p) printf("ok %ld\n", (unsigned long) p);
    123       else printf("error in find: %s.%s\n", namespace, name);
    124     }
    125     else if(!strcmp("invoke", cmd)) {
    126       GIArgument z;
    127       GError *e = NULL;
    128       GICallableInfo *p = pointer();
    129       int i, iargc = 0, oargc = 0, argc = g_callable_info_get_n_args(p);
    130       for(i = 0; i < argc; i++) {
    131         GIArgInfo *ai = g_callable_info_get_arg(p, i);
    132         GIDirection d = g_arg_info_get_direction(ai);
    133         if(GI_DIRECTION_INOUT == d || GI_DIRECTION_IN == d)
    134           iargc++;
    135         if(GI_DIRECTION_INOUT == d || GI_DIRECTION_OUT == d)
    136           oargc++;
    137         g_base_info_unref(ai);
    138       }
    139       GIFunctionInfoFlags f = g_function_info_get_flags(p);
    140       if((f & GI_FUNCTION_IS_METHOD) && !(f & GI_FUNCTION_IS_CONSTRUCTOR))
    141         iargc++;
    142       GIArgument iargv[iargc], oargv[oargc];
    143       int j = 0;
    144       if((f & GI_FUNCTION_IS_METHOD) && !(f & GI_FUNCTION_IS_CONSTRUCTOR)) {
    145         iargv[j].v_pointer = (void *) atol(token());
    146         j++;
    147       }
    148       for(i = 0; i < argc; i++) {
    149         GIArgInfo *ai = g_callable_info_get_arg(p, i);
    150         GIDirection d = g_arg_info_get_direction(ai);
    151         if(GI_DIRECTION_INOUT == d || GI_DIRECTION_IN == d) {
    152           GITypeInfo ti;
    153           g_arg_info_load_type(ai, &ti);
    154           to_argument(&iargv[j], ai, ti);
    155           j++;
    156         }
    157         g_base_info_unref(ai);
    158       }
    159       if(g_function_info_invoke(p,
    160                                 0 < iargv ? iargv : NULL, iargc,
    161                                 0 < oargc ? oargv : NULL, oargc,
    162                                 &z, &e)) {
    163         printf("ok %ld\n", (unsigned long) z.v_pointer);
    164       }
    165       else printf("error in invoke: %s\n", e->message);
    166     }
    167     else if(!strcmp("require", cmd)) {
    168       GError *e = NULL;
    169       char *namespace = token();
    170       char *version = token();
    171       g_irepository_require(r, namespace, version, 0, &e);
    172       if(e) printf("error in require: %s\n", e->message);
    173       else printf("ok\n");
    174     }
    175     else if(!strcmp("unref", cmd)) {
    176       g_base_info_unref(pointer());
    177       printf("ok\n");
    178     }
    179     else if(!strcmp("type", cmd)) {
    180       GIInfoType z = g_base_info_get_type(pointer());
    181       printf("ok %d\n", z);
    182     }
    183     else if(!strcmp("method", cmd)) {
    184       GIObjectInfo* ptr = pointer();
    185       char* name = token();
    186       GIBaseInfo *p = NULL;
    187       for(; ptr; ptr = g_object_info_get_parent(ptr)) {
    188         p = g_object_info_find_method(ptr, name);
    189         if(p) break;
    190       }
    191       if(p) printf("ok %ld\n", (unsigned long) p);
    192       else printf("error in method: %s\n", name);
    193     }
    194     else if(!strcmp("flags", cmd)) {
    195       GIFunctionInfoFlags z = g_function_info_get_flags(pointer());
    196       printf("ok %d\n", z);
    197     }
    198     else if(!strcmp("vfunc", cmd)) {
    199       GIObjectInfo* ptr = pointer();
    200       char* name = token();
    201       GIBaseInfo *p = g_object_info_find_vfunc(ptr, name);
    202       if(p) printf("ok %ld\n", (unsigned long) p);
    203       else printf("error in vfunc: %s\n", name);
    204     }
    205     else if(!strcmp("connect", cmd)) {
    206       gpointer* object = pointer();
    207       gchar* signal = token();
    208       int after = integer();
    209       gulong z;
    210       if(after)
    211         z = g_signal_connect_after(object, signal, G_CALLBACK(handler), (gpointer) ++id);
    212       else
    213         z = g_signal_connect(object, signal, G_CALLBACK(handler), (gpointer) ++id);
    214       if(0 < z) printf("ok %ld\n", id);
    215       else printf("error in connect: %s\n", signal);
    216     }
    217     else if(!strcmp("callback", cmd)) {
    218       printf("ok %ld\n", event);
    219       event = 0;
    220     }
    221     else if(!strcmp("class", cmd)) {
    222       gpointer* object = pointer();
    223       printf("ok %ld\n", (long) G_OBJECT_GET_CLASS(object));
    224     }
    225     else if(!strcmp("exit", cmd)) {
    226       printf("ok\n");
    227       fflush(stdout);
    228       return 0;
    229     }
    230   }
    231   return 0;
    232 }