girtobac  0.4
Create FB Headers from GObject Introspection *.gir files
 All Classes Files Functions Variables Enumerations Enumerator Macros Pages
girtobac.bas
Go to the documentation of this file.
1 
19 
20 
21 /'
22 
23 GLib provides a simple XML parser, that is here used to read the
24 context of the input files (*.gir) and the control files (*.GirToBac).
25 
26 '/
27 
28 #INCLUDE ONCE "../Gir/GLib-2.0.bi"
29 #INCLUDE ONCE "girtobac_text.bi"
30 
31 CONST OOP = 0
32 
33 
34 
41 ENUM TypeFlags
42  TYPE_VAR
43  TYPE_SUB
44  TYPE_FUN
46  TYPE_ARRAY
47  TYPE_LIST
48 END ENUM
49 
50 
56 TYPE Context
57  AS STRING _
58  FunNam _
59  , FunTyp _
60  , FunDll _
61  , FieldNam _
62  , FieldVal _
63  , OopDll _
64  , Check _
65  , NamSpace _
66  , NamDll _
67  , NextElm _
68  , ArrayTyp _
69  , Typ _
70  , TypC _
71  , ParaStr
72  AS gint32 _
73  ParaBy _
74  , ParaCnt _
75  , BlockCnt _
76  , type_flg _
77  , ArrayLen _
78  , FieldBits _
79  , PropRW _
80  , FnrBi _
81  , SkipElem
82  AS CONST gchar PTR _
83  FuncSkip _
84  , GErrr
85 
86  AS STRING _
87  Raus(15) _
88  , Nams(15)
89  AS gint32 _
90  Level = 1 _
91  , RausMax = 1
92 END TYPE
93 
94 
95 
107 FUNCTION find_value( _
108  BYVAL Nam AS CONST gchar PTR, _
109  BYVAL AttNams AS CONST gchar PTR PTR, _
110  BYVAL AttVals AS CONST gchar PTR PTR) AS CONST gchar PTR
111 
112  VAR i = 0
113  WHILE AttNams[i]
114  IF *AttNams[i] = *Nam THEN RETURN AttVals[i]
115  i += 1
116  WEND : RETURN NULL
117 END FUNCTION
118 
119 
120 
129 #MACRO _START_PARSER(_N_)
130  SUB start_##_N_ CDECL( _
131  BYVAL ctx AS GMarkupParseContext PTR, _
132  BYVAL element_name AS CONST gchar PTR, _
133  BYVAL AttNams AS CONST gchar PTR PTR, _
134  BYVAL AttVals AS CONST gchar PTR PTR, _
135  BYVAL UserData AS gpointer, _
136  BYVAL error_ AS GError PTR PTR)
137  WITH PEEK(Context, UserData)
138 #ENDMACRO
139 
140 
152 #MACRO _END_PARSER(_N_)
153  CASE ELSE
154  'PRINT #.FnrBi, NL " ' " & __FB_FUNCTION__ & " Skipping " & *element_name _
155  ' & " """ & *find_value("name", AttNams, AttVals) & """";
156  g_markup_parse_context_push(ctx, @Skip_parser, UserData) '& skip_parser();
157  END SELECT
158  END WITH
159  END SUB
160  SUB end_##_N_ CDECL( _
161  BYVAL ctx AS GMarkupParseContext PTR, _
162  BYVAL element_name AS CONST gchar PTR, _
163  BYVAL UserData AS gpointer, _
164  BYVAL error_ AS GError PTR PTR)
165  WITH PEEK(Context, UserData)
166 #ENDMACRO
167 
168 
169 
179 #MACRO _NEW_PARSER(_N_)
180  CASE ELSE
181  g_markup_parse_context_pop(ctx)
182  END SELECT
183  END WITH
184  END SUB
185  STATIC SHARED AS GMarkupParser _N_##_parser = TYPE(@start_##_N_, @end_##_N_, NULL, NULL, NULL)
186 #ENDMACRO
187 
188 
189 
190 STATIC SHARED AS GMarkupParser Skip_parser = TYPE(NULL, NULL, NULL, NULL, NULL)
191 
192 #INCLUDE ONCE "girtobac_RepData.bas"
193 
194 START_FUNC:
195 
201 #MACRO _START_FUNC()
202  .ParaCnt = 0 : .ParaStr = "(" : .FunTyp = ""
203  .GErrr = find_value("throws", AttNams, AttVals)
204  IF OOP THEN
205  .FunNam = *FB_NAM.rep(find_value("name", AttNams, AttVals))
206  .FunDll = *find_value("c:identifier", AttNams, AttVals)
207  ELSE
208  .FunNam = *FB_NAM.rep(find_value("c:identifier", AttNams, AttVals))
209  END IF
210  g_markup_parse_context_push(ctx, @Func_parser, UserData) '& func_parser();
211 #ENDMACRO
212 
213 
219 #MACRO _END_FUNC()
220  IF .GErrr THEN
221  IF .ParaCnt THEN .ParaStr &= ", "
222  .ParaStr &= "BYVAL AS GError PTR PTR" : .ParaCnt += 1
223  END IF
224  g_markup_parse_context_pop(ctx)
225  .type_flg = IIF(LEN(.FunTyp), TYPE_FUN, TYPE_SUB)
226  .ParaStr &= ")"
227 #ENDMACRO
228 
229 
230 
243 FUNCTION fb_type(BYVAL Ud AS ANY PTR) AS STRING
244  WITH PEEK(Context, Ud)
245  IF 0 = LEN(.TypC) THEN ' try to fix it (may be faulty)
246  SELECT CASE .Typ
247  CASE "utf8", "filename" : RETURN "/'!'/gchar PTR"
248  CASE ELSE
249  IF 0 = LEN(.Typ) THEN RETURN "/'!'/ any PTR"
250  .TypC = .Typ
251  END SELECT
252  ELSE
253  IF LEFT(.Typc, 9) = "volatile " THEN .TypC = MID(.TypC, 10)
254  IF .Typc = "gchar" THEN .TypC = "gint8"
255  END IF
256 
257  VAR ptrs = 0, i = LEN(.TypC) - 1
258  FOR i = i TO 0 STEP -1
259  IF .TypC[i] = ASC("*") THEN ptrs += 1 ELSE EXIT FOR
260  .TypC[i] = 0
261  NEXT
262 
263  IF OOP THEN .Typ = *FB_TYP.rep(.Typ) _
264  ELSE .Typ = *FB_TYP.rep(.TypC)
265 
266  FOR p AS INTEGER = 1 TO ptrs
267  .Typ &= " PTR"
268  NEXT : RETURN .Typ
269  END WITH
270 END FUNCTION
271 
272 
273 DECLARE SUB start_type CDECL( _
274  BYVAL AS GMarkupParseContext PTR, _
275  BYVAL AS CONST gchar PTR, _
276  BYVAL AS CONST gchar PTR PTR, _
277  BYVAL AS CONST gchar PTR PTR, _
278  BYVAL AS gpointer, _
279  BYVAL AS GError PTR PTR)
280 
281 
282 DECLARE SUB end_type CDECL( _
283  BYVAL AS GMarkupParseContext PTR, _
284  BYVAL AS CONST gchar PTR, _
285  BYVAL AS gpointer, _
286  BYVAL AS GError PTR PTR)
287 
288 
289 STATIC SHARED AS GMarkupParser _
290  Type_parser = TYPE(@start_type, @end_type, NULL, NULL, NULL)
291 
292 
293 
294 '& SUB_CDECL para_parser(){
295 Para_parser:
296 _START_PARSER(Para)
297 
298  SELECT CASE *element_name
299  CASE "parameter", "instance-parameter"
300  'if OOP then
301  'var d = find_value("direction", AttNams, AttVals)
302  '.ParaBy = iif(*d <> "in", 1, 0)
303  'end if
304  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
305 
306 _END_PARSER(Para)
307 
308  SELECT CASE *element_name
309  CASE "parameter", "instance-parameter"
310  g_markup_parse_context_pop(ctx)
311  IF .ParaCnt THEN .ParaStr &= ", "
312  IF .type_flg = TYPE_VARARG THEN
313  .ParaStr &= "..."
314  ELSE
315  IF .type_flg = TYPE_ARRAY ANDALSO LEN(.ArrayTyp) THEN .TypC = .ArrayTyp
316  IF OOP THEN
317  'if .ParaBy _
318  'then .ParaStr &= "BYREF" : .ParaBy = 0 _
319  'else .ParaStr &= "BYVAL"
320  '.ParaStr &= " P" & .ParaCnt & " AS " & fb_type(UserData)
321  .ParaStr &= "BYVAL P" & .ParaCnt & " AS " & fb_type(UserData)
322  ELSE
323  .ParaStr &= "BYVAL AS " & fb_type(UserData)
324  END IF
325  END IF : .type_flg = 0
326  .ParaCnt += 1
327 
328 _NEW_PARSER(Para)
329 '& };
330 
331 
332 '& SUB_CDECL func_parser(){
333 Func_parser:
334 _START_PARSER(Func)
335 
336  SELECT CASE *element_name
337  CASE "return-value"
338  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
339  CASE "parameters"
340  g_markup_parse_context_push(ctx, @Para_parser, UserData) '& para_parser();
341 
342 _END_PARSER(Func)
343 
344  SELECT CASE *element_name
345  CASE "return-value"
346  IF .type_flg = TYPE_ARRAY ANDALSO LEN(.ArrayTyp) THEN .TypC = .ArrayTyp
347  IF .Typ <> "none" THEN .FunTyp = fb_type(UserData)
348  g_markup_parse_context_pop(ctx)
349  CASE "parameters"
350  g_markup_parse_context_pop(ctx)
351 
352 _NEW_PARSER(Func)
353 '& };
354 
355 
356 '& SUB_CDECL type_parser(){
358 _START_PARSER(TYPE)
359 
360  SELECT CASE *element_name
361  CASE "type"
362  .Typ = *find_value("name", AttNams, AttVals)
363  VAR c = find_value("c:type", AttNams, AttVals) ' *< local variable
364  IF c THEN .TypC = *c ELSE .TypC = ""
365  SELECT CASE .Typ
366  CASE "GLib.List", "GLib.SList", "GLib.Array"
368  g_markup_parse_context_push(ctx, @Skip_parser, UserData) '& skip_parser();
369  CASE ELSE
370  .type_flg = TYPE_VAR
371  END SELECT
372  CASE "callback"
373  _START_FUNC()
374  CASE "array"
375  VAR n = find_value("name", AttNams, AttVals) ' *< local variable
376  VAR t = find_value("c:type", AttNams, AttVals) ' *< local variable
377  IF n THEN
378  .Typ = *n
379  IF t THEN .TypC = *t ELSE .TypC = ""
380  .ArrayLen = -1
381  g_markup_parse_context_push(ctx, @Skip_parser, UserData) '& skip_parser();
382  ELSE
383  n = find_value("length", AttNams, AttVals)
384  IF 0 = n THEN n = find_value("fixed-size", AttNams, AttVals)
385  IF t THEN .ArrayTyp = *t ELSE .ArrayTyp = ""
386  .ArrayLen = IIF(n, CUINT(*n), 0)
387  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
388  END IF
389  CASE "varargs"
390 
391 _END_PARSER(TYPE)
392 
393  SELECT CASE *element_name
394  CASE "type"
395  IF .Type_flg = TYPE_LIST THEN g_markup_parse_context_pop(ctx)
396  CASE "callback"
397  _END_FUNC()
398  CASE "array"
400  g_markup_parse_context_pop(ctx)
401  CASE "varargs"
403  CASE ELSE
404  g_markup_parse_context_pop(ctx)
405  END SELECT
406 
407 END WITH : END SUB ' no _P2() macro since we need the Type_parser above
408 '& };
409 
410 
411 '& SUB_CDECL class_parser(){
412 Class_parser:
413 _START_PARSER(CLASS)
414 
415  SELECT CASE *element_name
416  CASE "method", "function", "constructor"
417  _START_FUNC()
418  CASE "field"
419  .FieldNam = *FB_NAM.rep(find_value("name", AttNams, AttVals))
420  VAR bits = find_value("bits", AttNams, AttVals) ' *< local variable
421  .FieldBits = IIF(bits, CUINT(*bits), 0)
422  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
423  CASE "property"
424  .FunNam = *FB_NAM.rep(find_value("name", AttNams, AttVals))
425  VAR r = find_value("readable", AttNams, AttVals) ' *< local variable
426  VAR w = find_value("writable", AttNams, AttVals) ' *< local variable
427  .PropRW = IIF(r ANDALSO *r = "0", 0, 1)
428  .PropRW += IIF(w ANDALSO *w = "0", 0, 2)
429  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
430  CASE "virtual-method"
431  .ParaCnt = 0 : .ParaStr = "(" : .FunTyp = ""
432  .FunNam = *FB_NAM.rep(find_value("name", AttNams, AttVals))
433  g_markup_parse_context_push(ctx, @Func_parser, UserData) '& func_parser();
434  CASE "implements"
435 
436 _END_PARSER(CLASS)
437 
438  SELECT CASE *element_name
439  CASE "constructor"
440  .BlockCnt += 1
441  _END_FUNC()
442  IF .type_flg <> TYPE_FUN THEN .Raus(.Level) &= NL "'' ??? CTOR w/o type"
443 
444  .Raus(.Level) &= NL " DECLARE CONSTRUCTOR " & .ParaStr
445  VAR dll = "__" & .BlockCnt ' *< local variable
446  .Raus(.Level) &= NL " " & dll & " AS FUNCTION" & .ParaStr & " AS " & .FunTyp _
447  & " = DYLIBSYMBOL(" & .OopDll & ", """ & .FunDll & """)"
448 
449  .Raus(0) &= NL "CONSTRUCTOR " & .Nams(.Level) & .ParaStr
450  IF .ParaCnt THEN .ParaStr = "P1" ELSE .ParaStr = ""
451  FOR i AS INTEGER = 2 TO .ParaCnt
452  .ParaStr &= ", P" & i
453  NEXT
454  .Raus(0) &= NL " __Obj = " & dll & "(" & .ParaStr & ")"
455  .Raus(0) &= NL "END CONSTRUCTOR"
456  .type_flg = 0
457  CASE "field"
458  .BlockCnt += 1
459  SELECT CASE AS CONST .type_flg
460  CASE TYPE_SUB
461  .Raus(.Level) &= NL " " & .FieldNam & " AS SUB CDECL" & .ParaStr
462  CASE TYPE_FUN
463  .Raus(.Level) &= NL " " & .FieldNam & " AS FUNCTION CDECL" & .ParaStr & " AS " & .FunTyp
464  CASE ELSE
465  .Raus(.Level) &= NL " AS " & fb_type(UserData) & " " & .FieldNam
466  IF .FieldBits THEN .Raus(.Level) &= " : " & .FieldBits
467  END SELECT : .type_flg = 0
468  g_markup_parse_context_pop(ctx)
469  CASE "virtual-method"
470  .BlockCnt += 1
471  _END_FUNC()
472  SELECT CASE AS CONST .type_flg
473  CASE TYPE_SUB : .Raus(.Level) &= NL " " & .FunNam & " AS SUB CDECL" & .ParaStr
474  CASE ELSE : .Raus(.Level) &= NL " " & .FunNam & " AS FUNCTION CDECL" & .ParaStr & " AS " & .FunTyp
475  END SELECT
476  CASE "method", "function"
477  .BlockCnt += 1
478  _END_FUNC()
479  VAR dll = "__" & .BlockCnt
480 
481  VAR p = INSTR(.ParaStr, ", ") ' *< local variable
482  VAR par = "(" ' *< local variable
483  IF p THEN par &= MID(.ParaStr, p + 2) ELSE par &= ")"
484 
485  VAR parcall = UCASE(.NamSpace & "_" & .Nams(.Level)) & "(@THIS)" ' *< local variable
486  FOR i AS INTEGER = 1 TO .ParaCnt - 1
487  parcall &= ", P" & i
488  NEXT
489 
490  SELECT CASE AS CONST .type_flg
491  CASE TYPE_SUB
492  .Raus(.Level) &= NL " DECLARE SUB " & .FunNam & par
493  .Raus(.Level) &= NL " " & dll & " AS SUB" & .ParaStr _
494  & " = DYLIBSYMBOL(" & .OopDll & ", """ & .FunDll & """)"
495  .Raus(0) &= NL "SUB " & .Nams(.Level) & "." & .FunNam & par
496  .Raus(0) &= NL " " & dll & "(" & parcall & ")"
497  .Raus(0) &= NL "END SUB"
498  CASE ELSE
499  .Raus(.Level) &= NL " DECLARE FUNCTION " & .FunNam & par & " AS " & .FunTyp
500  .Raus(.Level) &= NL " " & dll & " AS FUNCTION" & .ParaStr & " AS " & .FunTyp _
501  & " = DYLIBSYMBOL(" & .OopDll & ", """ & .FunDll & """)"
502  .Raus(0) &= NL "FUNCTION " & .Nams(.Level) & "." & .FunNam & par & " AS " & .FunTyp
503  .Raus(0) &= NL " RETURN " & dll & "(" & parcall & ")"
504  .Raus(0) &= NL "END FUNCTION"
505  END SELECT : .type_flg = 0
506  CASE "property" ' !!!
507  FOR i AS INTEGER = 0 TO LEN(.FunNam) - 1
508  IF .FunNam[i] = ASC("-") THEN .FunNam[i] = ASC("_")
509  NEXT
510  IF BIT(.PropRW, 0) THEN
511  .Raus(.Level) &= NL " DECLARE PROPERTY " & .FunNam & "() AS " & .Typ
512  .Raus(0) &= NL "PROPERTY " & .Nams(.Level) & "." & .FunNam & "() AS " & .Typ
513  .Raus(0) &= NL " DIM AS " & .Typ & " __r"
514  .Raus(0) &= NL " g_object_get(__Obj, """ & .FunNam & """, @__r, NULL)"
515  .Raus(0) &= NL " RETURN __r"
516  .Raus(0) &= NL "END PROPERTY"
517  END IF
518  IF BIT(.PropRW, 1) THEN
519  .Raus(.Level) &= NL " DECLARE PROPERTY " & .FunNam & "(BYVAL P1 AS" & .Typ & ")"
520  .Raus(0) &= NL "PROPERTY " & .Nams(.Level) & "." & .FunNam & "(BYVAL AS" & .Typ & ")"
521  .Raus(0) &= NL " g_object_set(__Obj, """ & .FunNam & """, P1, NULL)"
522  .Raus(0) &= NL "END PROPERTY"
523  END IF
524  g_markup_parse_context_pop(ctx)
525  CASE "implements"
526 
527 _NEW_PARSER(CLASS)
528 '& };
529 
530 
531 '& SUB_CDECL udt_parser(){
532 Udt_parser:
533 _START_PARSER(Udt)
534 
535  SELECT CASE *element_name
536  CASE "field"
537  VAR n = find_value("name", AttNams, AttVals)
538  VAR c = find_value("c:identifier", AttNams, AttVals)
539  .FieldNam = *FB_NAM.rep(IIF(c, c, n))
540  VAR bits = find_value("bits", AttNams, AttVals)
541  .FieldBits = IIF(bits, CUINT(*bits), 0)
542  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
543  CASE "virtual-method"
544  g_markup_parse_context_push(ctx, @Skip_parser, UserData) '& skip_parser();
545  CASE "constructor", "method", "function"
546  _START_FUNC()
547  CASE "property"
548 
549 _END_PARSER(Udt)
550 
551  SELECT CASE *element_name
552  CASE "field"
553  .BlockCnt += 1
554  SELECT CASE AS CONST .type_flg
555  CASE TYPE_SUB
556  .Raus(.Level) &= NL " " & .FieldNam & " AS SUB CDECL" & .ParaStr
557  CASE TYPE_FUN
558  .Raus(.Level) &= NL " " & .FieldNam & " AS FUNCTION CDECL" & .ParaStr & " AS " & .FunTyp
559  CASE ELSE
560  .Raus(.Level) &= NL " AS " & fb_type(UserData) & " " & .FieldNam
561  IF .type_flg = TYPE_ARRAY ANDALSO .ArrayLen > 0 _
562  THEN .Raus(.Level) &= "(" & .ArrayLen - 1 & ")"
563  IF .FieldBits THEN .Raus(.Level) &= " : " & .FieldBits
564  END SELECT : .type_flg = 0
565  g_markup_parse_context_pop(ctx)
566  CASE "virtual-method"
567  g_markup_parse_context_pop(ctx)
568  CASE "method", "function", "constructor"
569  _END_FUNC()
570  SELECT CASE AS CONST .type_flg
571  CASE TYPE_SUB
572  .Raus(0) &= NL "DECLARE SUB " & .FunNam & .ParaStr
573  CASE ELSE
574  .Raus(0) &= NL "DECLARE FUNCTION " & .FunNam & .ParaStr & " AS " & .FunTyp
575  END SELECT : .type_flg = 0
576  CASE "property" ' !!!
577 
578 _NEW_PARSER(Udt)
579 '& };
580 
581 
582 '& SUB_CDECL unio_parser(){
583 Unio_parser:
584 _START_PARSER(Unio)
585 
586  SELECT CASE *element_name
587  CASE "field"
588  VAR n = find_value("name", AttNams, AttVals) ' *< local variable
589  VAR c = find_value("c:identifier", AttNams, AttVals) ' *< local variable
590  .FieldNam = *FB_NAM.rep(IIF(OOP, n, IIF(c, c, n)))
591  VAR bits = find_value("bits", AttNams, AttVals) ' *< local variable
592  .FieldBits = IIF(bits, CUINT(*bits), 0)
593  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
594  CASE "record"
595  .Level += 1 : IF .Level > UBOUND(.Raus) THEN ?"Raus maximum exeded!"
596  IF .Level > .RausMax THEN .RausMax = .Level
597  VAR nam = *FB_NAM.rep(find_value("name", AttNams, AttVals)) ' *< local variable
598  .Nams(.Level) = "__G2B_" & .Nams(.Level - 1) & "_" & nam
599  .Raus(.Level - 1) &= NL " AS " & .Nams(.Level) & " " & nam
600  .Raus(.Level) &= NL "TYPE " & .Nams(.Level)
601  g_markup_parse_context_push(ctx, IIF(OOP, @Class_parser, @Udt_parser), UserData) '& class_parser(); Udt_parser();
602 
603 _END_PARSER(Unio)
604 
605  SELECT CASE *element_name
606  CASE "field"
607  .BlockCnt += 1
608  SELECT CASE AS CONST .type_flg
609  CASE TYPE_SUB
610  .Raus(.Level) &= NL " " & .FieldNam & " AS SUB CDECL" & .ParaStr
611  CASE TYPE_FUN
612  .Raus(.Level) &= NL " " & .FieldNam & " AS FUNCTION CDECL" & .ParaStr & " AS " & .FunTyp
613  CASE ELSE
614  .Raus(.Level) &= NL " AS " & fb_type(UserData) & " " & .FieldNam
615  IF .FieldBits THEN .Raus(.Level) &= " : " & .FieldBits
616  END SELECT : .type_flg = 0
617  g_markup_parse_context_pop(ctx)
618  CASE "record"
619  .BlockCnt += 1
620  .Raus(.Level) &= NL "END TYPE"
621  .Level -= 1
622  g_markup_parse_context_pop(ctx)
623 
624 _NEW_PARSER(Unio)
625 '& };
626 
627 
628 '& SUB_CDECL enum_parser(){
629 Enum_parser:
630 _START_PARSER(ENUM)
631 
632  SELECT CASE *element_name
633  CASE "member"
634  VAR nam = *FB_NAM.rep(find_value(*IIF(OOP, @"name", @"c:identifier"), AttNams, AttVals)) ' *< local variable
635  VAR value = find_value("value", AttNams, AttVals) ' *< local variable
636  PRINT #.FnrBi, NL " " & nam;
637  IF value THEN PRINT #.FnrBi, " = " & CINT(*value);
638 
639 _END_PARSER(ENUM)
640 
641  SELECT CASE *element_name
642  CASE "member"
643 
644 _NEW_PARSER(ENUM)
645 '& };
646 
647 
648 '& SUB_CDECL pass1_parser(){
649 Pass1_parser:
650 _START_PARSER(pass1)
651 
652  SELECT CASE *element_name
653  CASE "constant"
654  VAR n = find_value(IIF(OOP, @"name", @"c:type"), AttNams, AttVals) ' *< local variable
655  IF 0 = n THEN n = find_value("c:identifier", AttNams, AttVals)
656  .FieldNam = *FB_NAM.rep(n)
657  .FieldVal = *find_value("value", AttNams, AttVals)
658  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
659  CASE "enumeration", "bitfield"
660  VAR nam = *FB_NAM.rep(find_value(IIF(OOP, @"name", @"c:type"), AttNams, AttVals))
661 
662  IF LEN(nam) THEN PRINT #.FnrBi, NL "TYPE AS LONG " & nam;
663  PRINT #.FnrBi, NL "ENUM";
664  'PRINT #.FnrBi, NL "ENUM " & nam;
665 
666  IF OOP THEN PRINT #.FnrBi, " EXPLICIT";
667  g_markup_parse_context_push(ctx, @Enum_parser, UserData) '& enum_parser();
668  CASE "alias"
669  VAR n = find_value(IIF(OOP, @"name", @"c:type"), AttNams, AttVals) ' *< local variable
670  IF 0 = n THEN n = find_value("glib:type-name", AttNams, AttVals)
671  IF n THEN .FieldNam = *FB_NAM.rep(n) ELSE .FieldNam = ""
672  g_markup_parse_context_push(ctx, @Type_parser, UserData) '& type_parser();
673  CASE "class", "record", "interface"
674  VAR n = find_value(IIF(OOP, @"name", @"c:type"), AttNams, AttVals) ' *< local variable
675  IF 0 = n THEN n = find_value("glib:type-name", AttNams, AttVals)
676  VAR nam = *FB_NAM.rep(n) ' *< local variable
677  PRINT #.FnrBi, NL "TYPE AS _" & nam & " " & nam;
678  CASE "include"
679  PRINT #.FnrBi, NL "#INCLUDE ONCE """ & _
680  *find_value("name", AttNams, AttVals) & "-" & _
681  *find_value("version", AttNams, AttVals) & ".bi""";
682  CASE "repository"
683  PRINT #.FnrBi, NL "' Repository version " & *find_value("version", AttNams, AttVals);
684  CASE "namespace"
685  IF 0 = LEN(.NamSpace) THEN .NamSpace = *find_value("name", AttNams, AttVals)
686  'SELECT CASE .NamSpace
687  'CASE "GLib", "GObject", "GModule", "Gio" : .NamSpace = "G"
688  'END SELECT
689  VAR dll = find_value("shared-library", AttNams, AttVals) + 3 ' *< local variable
690  IF dll > 3 ANDALSO 0 = LEN(.NamDLL) THEN .NamDll = LEFT(*dll, INSTR(*dll, ".so") - 1)
691 
692  IF 0 = OOP THEN EXIT SELECT
693  IF dll > 3 THEN
694  .OopDll = "__G2B_" & *find_value("name", AttNams, AttVals)
695  PRINT #.FnrBi, NL "DIM SHARED AS ANY PTR " & .OopDll;
696  PRINT #.FnrBi, NL .OopDll & " = DYLIBLOAD(""" & .NamDll & """)";
697  END IF
698  PRINT #.FnrBi, NL "NAMESPACE " & .NamSpace
699 
700 _END_PARSER(pass1)
701 
702  SELECT CASE *element_name
703  CASE "constant"
704  PRINT #.FnrBi, NL "#DEFINE " & .FieldNam;
705  SELECT CASE .Typ
706  CASE "utf8", "filename"
707  PRINT #.FnrBi, " @!""" & .FieldVal & """";
708  CASE ELSE
709  PRINT #.FnrBi, " " & .FieldVal;
710  END SELECT
711  g_markup_parse_context_pop(ctx)
712  CASE "enumeration", "bitfield"
713  PRINT #.FnrBi, NL "END ENUM";
714  g_markup_parse_context_pop(ctx)
715  CASE "alias"
716  IF LEN(.FieldNam) _
717  THEN PRINT #.FnrBi, NL "TYPE AS " & fb_type(UserData) & " " & .FieldNam; _
718  ELSE PRINT #.FnrBi, NL "TYPE AS ANY " & fb_type(UserData);
719  g_markup_parse_context_pop(ctx)
720  CASE "class", "record", "interface"
721  CASE "include", "repository", "namespace"
722 
723 _NEW_PARSER(pass1)
724 '& };
725 
726 
727 '& SUB_CDECL passX_parser(){
728 PassX_parser:
729 _START_PARSER(passX)
730  SELECT CASE *element_name
731  CASE "repository", "namespace" : EXIT SUB
732  END SELECT
733 
734  VAR n = find_value(*IIF(OOP, @"name", @"c:type"), AttNams, AttVals)
735  IF 0 = n THEN
736  n = find_value("glib:type-name", AttNams, AttVals)
737  IF 0 = n THEN n = find_value("name", AttNams, AttVals)
738  END IF
739  IF FIRST.A = -1 THEN ' we're in P_3
740  IF FIRST.find(n) THEN ' element allready done?
741  .SkipElem = 1
742  g_markup_parse_context_push(ctx, @Skip_parser, UserData) '& skip_parser();
743  EXIT SUB
744  END IF
745  ELSE ' we're in P_X
746  IF *n <> .NextElm THEN ' not our element
747  .SkipElem = 1
748  g_markup_parse_context_push(ctx, @Skip_parser, UserData) '& skip_parser();
749  EXIT SUB
750  END IF
751  .NextElm = FIRST.nxt()
752  END IF
753 
754  SELECT CASE *element_name
755  CASE "interface", "class"
756  IF 0 = OOP THEN ' generate class macros
757  VAR g = find_value("glib:get-type", AttNams, AttVals) ' *< local variable
758  IF g ANDALSO *g <> "intern" THEN
759  VAR s = find_value("glib:type-struct", AttNams, AttVals) _' *< local variable
760  , t1 = UCASE(.NamSpace) & "_" _ ' *< local variable
761  , p = INSTR(*g, "_") _ ' *< local variable
762  , t2 = UCASE(MID(*g, p + 1, LEN(*g) - p - 9)) _ ' *< local variable
763  , t3 = t1 & "TYPE_" & t2 _ ' *< local variable
764  , t4 = t3 & ", " & *g _ ' *< local variable
765  , t5 = .NamSpace & *s ' *< local variable
766 
767  .Raus(0) &= NL "DECLARE FUNCTION " & *g & "() AS GType"
768  .Raus(0) &= NL "#DEFINE " & t3 & " (" & *g & "())"
769  .Raus(0) &= NL "#DEFINE " & t1 & t2 & "(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), " & t3 & ", " & *n & "))"
770  .Raus(0) &= NL "#DEFINE " & t1 & t2 & "_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST((obj), " & t3 & ", " & t5 & "))"
771  .Raus(0) &= NL "#DEFINE " & t1 & "IS_" & t2 & "(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), " & t3 & "))"
772  IF element_name[0] = ASC("i") THEN
773  .Raus(0) &= NL "#DEFINE " & t1 & t2 & "_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), " & t3 & ", " & t5 &"))"
774  ELSE
775  .Raus(0) &= NL "#DEFINE " & t1 & "IS_CLASS_" & t2 & "(obj) (G_TYPE_CHECK_CLASS_TYPE((obj), " & t3 & "))"
776  .Raus(0) &= NL "#DEFINE " & t1 & t2 & "_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), " & t3 & ", " & t5 &"))"
777  END IF
778  END IF
779  END IF
780  .BlockCnt = 0
781  .Nams(.Level) = *FB_NAM.rep(n)
782  .Raus(.Level) &= NL "TYPE _" & .Nams(.Level)
783  g_markup_parse_context_push(ctx, IIF(OOP, @Class_parser, @Udt_parser), UserData) '& class_parser(); Udt_parser();
784  CASE "record"
785  .BlockCnt = 0
786  .Nams(.Level) = *FB_NAM.rep(n)
787  .Raus(.Level) &= NL "TYPE _" & .Nams(.Level)
788  g_markup_parse_context_push(ctx, IIF(OOP, @Class_parser, @Udt_parser), UserData) '& class_parser(); Udt_parser();
789  CASE "union"
790  .Nams(.Level) = *FB_NAM.rep(n)
791  .Raus(.Level) = NL "UNION " & .Nams(.Level)
792  g_markup_parse_context_push(ctx, @Unio_parser, UserData) '& unio_parser();
793  CASE "callback"
794  .ParaCnt = 0 : .ParaStr = "(" : .FunTyp = ""
795  .FunNam = *FB_NAM.rep(find_value(*IIF(OOP, @"name", @"c:type"), AttNams, AttVals))
796  g_markup_parse_context_push(ctx, @Func_parser, UserData) '& func_parser();
797 
798 _END_PARSER(passX)
799 
800  IF .SkipElem THEN
801  .SkipElem = 0
802  g_markup_parse_context_pop(ctx)
803  EXIT SUB
804  END IF
805 
806  SELECT CASE *element_name
807  CASE "record", "interface", "class"
808  IF .Level <> 1 THEN ?"Raus level <> 1"
809  IF .BlockCnt _
810  THEN .Raus(1) &= NL "END TYPE" : .BlockCnt = 0 _
811  ELSE .Raus(1) = ""
812  FOR i AS INTEGER = .RausMax TO 0 STEP -1
813  PRINT #.FnrBi, .Raus(i);
814  .Raus(i) = ""
815  NEXT : .RausMax = 1
816  g_markup_parse_context_pop(ctx)
817  CASE "union"
818  IF .Level <> 1 THEN ?"Raus level <> 1"
819  IF .BlockCnt _
820  THEN .Raus(1) &= NL "END UNION" : .BlockCnt = 0 _
821  ELSE .Raus(1) = "TYPE AS _" & .Nams(.Level) & " " & .Nams(.Level)
822  FOR i AS INTEGER = .RausMax TO 0 STEP -1
823  PRINT #.FnrBi, .Raus(i);
824  .Raus(i) = ""
825  NEXT : .RausMax = 1
826  g_markup_parse_context_pop(ctx)
827  CASE "callback"
828  _END_FUNC()
829  SELECT CASE AS CONST .type_flg
830  CASE TYPE_SUB : PRINT #.FnrBi, NL "TYPE " & .FunNam & " AS SUB CDECL" & .ParaStr;
831  CASE ELSE : PRINT #.FnrBi, NL "TYPE " & .FunNam & " AS FUNCTION CDECL" & .ParaStr & " AS " & .FunTyp;
832  END SELECT
833  CASE "repository", "namespace"
834 
835 _NEW_PARSER(passX)
836 '& };
837 
838 
839 '& SUB_CDECL pass4_parser(){
840 Pass4_parser:
841 _START_PARSER(pass4)
842 
843  SELECT CASE *element_name
844  CASE "function"
845  .FuncSkip = find_value("moved-to", AttNams, AttVals) '& find_value();
846  IF .FuncSkip THEN EXIT SELECT
847  _START_FUNC() '& func_parser();
848  CASE "repository", "namespace"
849 
850 _END_PARSER(pass4)
851 
852  SELECT CASE *element_name
853  CASE "function"
854  IF .FuncSkip THEN EXIT SELECT
855  _END_FUNC()
856  SELECT CASE AS CONST .type_flg
857  CASE TYPE_SUB : PRINT #.FnrBi, NL "DECLARE SUB " & .FunNam & .ParaStr;
858  CASE ELSE : PRINT #.FnrBi, NL "DECLARE FUNCTION " & .FunNam & .ParaStr & " AS " & .FunTyp;
859  END SELECT : .type_flg = 0
860  CASE "repository"
861  CASE "namespace"
862  PRINT #.FnrBi, NL "END EXTERN"
863  IF OOP THEN PRINT #.FnrBi, NL "END NAMESPACE"
864 
865 _NEW_PARSER(pass4)
866 '& };
867 
868 
873 #MACRO PARSE(_N_)
874  SCOPE
875  VAR ctx = g_markup_parse_context_new(@pass##_N_##_parser, 0, @UDat, NULL)
876  IF g_markup_parse_context_parse(ctx, buffer, length, @errr) THEN _
877  IF 0 = g_markup_parse_context_end_parse(ctx, @errr) THEN _
878  g_print(!"Cannot parse %s (invalid content)\n", filename, NULL)
879  g_markup_parse_context_free(ctx)
880  END SCOPE
881 #ENDMACRO
882 
883 '& int main(){
884 
885 IF COMMAND(1) = "-v" orelse COMMAND(1) = "--version" then ?V_TEXT : END
886 'IF __FB_ARGC__ <= 1 THEN ?"Pass in filename as parameter!" : END
887 IF __FB_ARGC__ <> 2 orelse _
888  COMMAND(1) = "-h" orelse COMMAND(1) = "--help" then ?H_TEXT : END
889 
890 VAR filename = COMMAND(1) _ ' *< input file name
891  , basename = MID(filename, INSTRREV(filename, ANY "\/") + 1) ' *< name without path
892 
893 IF g_str_has_suffix(filename, ".gir") _
894  THEN basename = LEFT(basename, LEN(basename) - 4) _
895  ELSE filename &= ".gir"
896 
897 VAR ofile = basename & ".bi" _ ' *< name of output file
898  , ifile = basename & ".GirToBac" _ ' *< name of configuration file
899  , proto = "" ' *< protocol messages
900 
901 DIM AS GError PTR errr = NULL ' *< location for GLib errors
902 DIM AS Context UDat ' *< data to exchange between parsers
903 
904 DIM AS gchar PTR buffer ' *< buffer for input data
905 DIM AS gsize length ' *< length of input data
906 
907 IF 0 = g_file_get_contents(filename, @buffer, @length, @errr) THEN
908  ?"Cannot open " & filename;
909 ELSE
910  ?"loading " & filename;
911 
912 WITH UDat
913  .FnrBi = FREEFILE
914  'if open cons(for output as .FnrBi) then
915  '?NL "Cannot open console for output!";
916  IF OPEN(ofile FOR OUTPUT AS .FnrBi) THEN
917  ?NL "Cannot open file for output!";
918  ELSE
919  PRINT #.FnrBi, "' FreeBasic header file, auto-generated by"
920  PRINT #.FnrBi, "' ### GirToBac ###"
921  PRINT #.FnrBi, "' LGPLv2.1 (C) 2013-2015 by Thomas[ dot }Freiherr[ at ]gmx[ dot }net"
922  PRINT #.FnrBi, "' Auto-translated from file " & filename
923 
924  DIM AS gchar PTR buff2 ' *< buffer for control file
925  DIM AS gsize length2 ' *< length of control file
926  IF g_file_get_contents(ifile, @buff2, @length2, @errr) THEN
927  ?NL "loading " & ifile;
928  VAR ctx = g_markup_parse_context_new(@G2b_parser, 0, @UDat, NULL)
929  IF g_markup_parse_context_parse(ctx, buff2, length2, @errr) THEN _ '& g2b_parser();
930  IF 0 = g_markup_parse_context_end_parse(ctx, @errr) THEN _
931  g_print(!"Cannot parse %s (invalid content)\n", ifile, NULL)
932  g_markup_parse_context_free(ctx)
933  g_free(buff2)
934  END IF
935  ?NL "generating " & ofile & " ... ";
936  IF LEN(.Check) THEN PRINT #.FnrBi, "#IFNDEF " & .Check
937  PRINT #.FnrBi, "#INCLUDE ONCE ""_GirToBac-0.0.bi"""
938 
939  PARSE(1) '& pass1_parser(); // #DEFINE, ENUM, TYPE
940 
941  IF OOP ORELSE 0 = LEN(.NamDll) THEN
942  PRINT #.FnrBi, NL "EXTERN ""C""";
943  ELSE
944  PRINT #.FnrBi, NL "EXTERN ""C"" LIB """ & .NamDll & """";
945  END IF
946 
947  PRINT #.FnrBi, NL "' P_X" ' UNIONs, CALLBACKs and TYPEs (ordered)
948  .NextElm = FIRST.nxt()
949  WHILE FIRST.A
950  VAR xx = FIRST.A ' *< stack position
951  PARSE(X) '& passX_parser();
952  IF xx <> FIRST.A THEN CONTINUE WHILE
953  proto &= NL !"\t" & .NextElm & " <first>"
954  .NextElm = FIRST.nxt()
955  WEND
956  FIRST.A = -1
957 
958  PRINT #.FnrBi, NL "' P_3" ' UNIONs, CALLBACKs and TYPEs (rest)
959  PARSE(X) '& passX_parser();
960 
961  PRINT #.FnrBi, NL "' P_4" ' SUBs and FUNCTIONs
962  PARSE(4) '& pass4_parser();
963 
964  PRINT #.FnrBi,
965  IF LEN(.Check) THEN PRINT #.FnrBi, "#ENDIF ' " & .Check
966  CLOSE #.FnrBi
967  ?"done";
968  END IF
969 END WITH
970  g_free(buffer)
971 END IF
972 
973 FB_NAM.list(proto) '& RepData.list();
974 FB_TYP.list(proto) '& RepData.list();
975 IF LEN(proto) THEN ?NL "Symbols in " & ifile & ", but not in " & filename & !":\n" & proto;
976 ?
977 
978 '& };
979