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 }