patch allowing to add GCC attributes to methods
Jean-Yves Lefort <[email protected]> Mon, 28 Jan 2008 18:10:20 +0100
| Newsgroups | gmane.comp.gnome.devtools.gob.general |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format. [email protected] Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="PGP-SHA1"; boundary="Signature=_Mon__28_Jan_2008_18_10_20_+0100_PkcS9RSUBmpBbUWJ" --Signature=_Mon__28_Jan_2008_18_10_20_+0100_PkcS9RSUBmpBbUWJ Content-Type: multipart/mixed; boundary="Multipart=_Mon__28_Jan_2008_18_10_20_+0100_i.aKsy.QZL7asG1/" --Multipart=_Mon__28_Jan_2008_18_10_20_+0100_i.aKsy.QZL7asG1/ Content-Type: text/plain; charset=US-ASCII Content-Disposition: inline Content-Transfer-Encoding: quoted-printable The attached patch allows to add GCC attributes to methods, using a syntax borrowed from C#. For instance: [G_GNUC_PRINTF(1, 2)] private void say_something (const char *format, ...) { } The text enclosed in brackets is not parsed (the lexer returns a CCODE token). It is inserted verbatim in the function declaration, before the trailing semicolon. With this patch, gob no longer unconditionally adds G_GNUC_UNUSED to methods, which is a bad idea since it might hide programming errors. Users should now specify it manually when needed. Attributes are not supported for overriden methods since these methods are not meant to be called directly. For signals and virtual methods, the attributes are added to the declaration of the invocation wrapper, but not to the "__real" default implementation method that gob emits. Two patches are provided: gob2-2.0.15-attr.diff The attributes feature alone. gob2-2.0.15-gobject-overrides-and-attr.diff The attributes feature and another feature I've implemented previously (see the message with subject "patch adding first-class support of constructor/dispose/finalize methods"). This unified patch is provided because the two individual patches conflict with each other and require merging. --=20 Jean-Yves Lefort <[email protected]> --Multipart=_Mon__28_Jan_2008_18_10_20_+0100_i.aKsy.QZL7asG1/ Content-Type: text/x-diff; name="gob2-2.0.15-attr.diff" Content-Disposition: attachment; filename="gob2-2.0.15-attr.diff" Content-Transfer-Encoding: quoted-printable --- src/lexer.l.orig 2007-09-28 06:26:49.000000000 +0200 +++ src/lexer.l 2008-01-28 16:04:28.000000000 +0100 @@ -31,6 +31,7 @@ #include "main.h" #include "util.h" =20 +static int bracket_depth =3D 0; static int parenth_depth =3D 0; static int before_comment /* New flex is on drugs */ @@ -102,6 +103,7 @@ =20 %x COMMENT %x C_CODE +%x ATTR_CODE %x CODE_STRING %x CLASS_CODE %x CLASS_STRING @@ -267,7 +269,7 @@ add_to_cbuf(yytext); } =20 -<C_CODE>\/\/.*$ { add_to_cbuf(yytext); /*comment, ignore*/ } +<C_CODE,ATTR_CODE>\/\/.*$ { add_to_cbuf(yytext); /*comment, ignore*/ } <CLASS_CODE>\/\/.*$ { ; /*comment, ignore*/ } <CLASS_CODE_I>\/\/.*$ { ; /*comment, ignore*/ } <PROPERTY_CODE_I>\/\/.*$ { ; /*comment, ignore*/ } @@ -277,20 +279,25 @@ BEGIN(COMMENT); before_comment =3D C_CODE; } +<ATTR_CODE>\/\* { + add_to_cbuf(yytext); + BEGIN(COMMENT); + before_comment =3D ATTR_CODE; +} <CLASS_CODE>\/\* {BEGIN(COMMENT); before_comment =3D CLASS_CODE; } <CLASS_CODE_I>\/\* {BEGIN(COMMENT); before_comment =3D CLASS_CODE_I; } <PROPERTY_CODE_I>\/\* {BEGIN(COMMENT); before_comment =3D PROPERTY_CODE_I;= } <COMMENT>\*\/ { - if(before_comment =3D=3D C_CODE) add_to_cbuf(yytext); + if(before_comment =3D=3D C_CODE || before_comment =3D=3D ATTR_CODE) add_t= o_cbuf(yytext); BEGIN(before_comment); } <COMMENT>. { /* comment, ignore */ - if(before_comment =3D=3D C_CODE) add_to_cbuf(yytext); + if(before_comment =3D=3D C_CODE || before_comment =3D=3D ATTR_CODE) add_t= o_cbuf(yytext); } <COMMENT>\n { /* comment, ignore */ - if(before_comment =3D=3D C_CODE) add_to_cbuf(yytext); + if(before_comment =3D=3D C_CODE || before_comment =3D=3D ATTR_CODE) add_t= o_cbuf(yytext); } =20 ^\%(a|all)\{ { @@ -353,14 +360,14 @@ return code_type; } =20 -<C_CODE>\'\{\' { add_to_cbuf(yytext); } -<C_CODE>\'\\\{\' { add_to_cbuf(yytext); } -<C_CODE>\'\}\' { add_to_cbuf(yytext); } -<C_CODE>\'\\\}\' { add_to_cbuf(yytext); } -<C_CODE>\'\"\' { add_to_cbuf(yytext); } -<C_CODE>\'\\\"\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\{\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\\\{\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\}\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\\\}\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\"\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\\\"\' { add_to_cbuf(yytext); } =09 -<C_CODE>\\. { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\\. { add_to_cbuf(yytext); } =20 =20 <C_CODE>\" { @@ -368,6 +375,11 @@ before_string =3D C_CODE; add_to_cbuf(yytext); } +<ATTR_CODE>\" { + BEGIN(CODE_STRING); + before_string =3D ATTR_CODE; + add_to_cbuf(yytext); + } <PROPERTY_CODE_I>\" { BEGIN(CODE_STRING); before_string =3D PROPERTY_CODE_I; @@ -391,6 +403,10 @@ parenth_depth++; add_to_cbuf(yytext); } +<ATTR_CODE>\[ { + bracket_depth++; + add_to_cbuf(yytext); + } <C_CODE>\} { parenth_depth--; if(parenth_depth<0) { @@ -403,9 +419,21 @@ } add_to_cbuf(yytext); } +<ATTR_CODE>\] { + bracket_depth--; + if(bracket_depth<0) { + REJECT; + } else if(bracket_depth=3D=3D0) { + BEGIN(CLASS_CODE_I); + yylval.cbuf =3D cbuf; + cbuf =3D NULL; + return CCODE; + } + add_to_cbuf(yytext); + } =20 -<C_CODE>. { add_to_cbuf(yytext); } -<C_CODE>\n { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>. { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\n { add_to_cbuf(yytext); } =20 class { static int found_classes =3D 0; @@ -612,6 +640,13 @@ BEGIN(INITIAL); return '}'; } +<CLASS_CODE_I>\[ { + BEGIN(ATTR_CODE); + bracket_depth=3D1; + yylval.line =3D line_no; + clear_cbuf(); + return '['; + } =20 <CLASS_CODE,CLASS_CODE_I,INITIAL,PROPERTY_CODE,PROPERTY_CODE_I>[\f\t ] ; = /*ignore*/ =20 --- src/main.c.orig 2007-10-17 16:49:04.000000000 +0200 +++ src/main.c 2008-01-28 17:01:49.000000000 +0100 @@ -189,21 +189,25 @@ g_free(s); } =20 - -static void -print_method (FILE *fp, - const char *typeprefix, - const char *nameprefix, - const char *subnameprefix, - const char *namepostfix, - const char *afterargs, - const char *postfix, - const Method *m, - gboolean one_arg_per_line, - gboolean no_funcbase, - gboolean kill_underscore, - gboolean first_unused, - gboolean fake_names) +typedef enum +{ + PRINT_METHOD_ONE_ARG_PER_LINE =3D 1 << 0, + PRINT_METHOD_NO_FUNCBASE =3D 1 << 1, + PRINT_METHOD_FIRST_UNUSED =3D 1 << 2, + PRINT_METHOD_FAKE_NAMES =3D 1 << 3, + PRINT_METHOD_NO_ATTR =3D 1 << 4 +} PrintMethodFlags; + +static void +print_method2 (FILE *fp, + const char *typeprefix, + const char *nameprefix, + const char *subnameprefix, + const char *namepostfix, + const char *afterargs, + const char *postfix, + const Method *m, + PrintMethodFlags flags) { GList *li; const char *id; @@ -213,7 +217,7 @@ =20 id =3D m->id; =20 - if(no_funcbase) + if ((flags & PRINT_METHOD_NO_FUNCBASE) !=3D 0) out_printf(fp, "%s%s%s%s(", nameprefix, subnameprefix, id, namepostfix);=20 else @@ -229,19 +233,19 @@ if ( ! no_gnu && ! for_cpp && /* g++ has a cow with this */ li =3D=3D m->args && - first_unused) { + (flags & PRINT_METHOD_FIRST_UNUSED) !=3D 0) { unused =3D " G_GNUC_UNUSED"; } =20 print_type(fp, arg->atype, FALSE); - if (fake_names) + if ((flags & PRINT_METHOD_FAKE_NAMES) !=3D 0) out_printf (fp, "___fake___"); if(li->next) out_printf(fp, "%s%s%s,%s", arg->name, arg->atype->postfix ? arg->atype->postfix : "", unused, - one_arg_per_line ? "\n\t\t\t\t\t" : " "); + (flags & PRINT_METHOD_ONE_ARG_PER_LINE) !=3D 0 ? "\n\t\t\t\t\t" : = " "); else out_printf(fp, "%s%s%s", arg->name, arg->atype->postfix ? @@ -250,11 +254,54 @@ } if(m->vararg) out_printf(fp, ",%s...", - one_arg_per_line ? "\n\t\t\t\t\t" : " ");=20 + (flags & PRINT_METHOD_ONE_ARG_PER_LINE) !=3D 0 ? "\n\t\t\t\t\t" : "= ");=20 } else { out_printf(fp, "void");=20 } - out_printf(fp, "%s)%s", afterargs, postfix);=20 + + out_printf(fp, "%s)", afterargs); + + if (m->attr && (flags & PRINT_METHOD_NO_ATTR) =3D=3D 0) + out_printf(fp, " %s", m->attr); + + out_printf(fp, "%s", postfix); +} + +static void +print_method (FILE *fp, + const char *typeprefix, + const char *nameprefix, + const char *subnameprefix, + const char *namepostfix, + const char *afterargs, + const char *postfix, + const Method *m, + gboolean one_arg_per_line, + gboolean no_funcbase, + gboolean kill_underscore, + gboolean first_unused, + gboolean fake_names) +{ + PrintMethodFlags flags =3D 0; + + if (one_arg_per_line) + flags |=3D PRINT_METHOD_ONE_ARG_PER_LINE; + if (no_funcbase) + flags |=3D PRINT_METHOD_NO_FUNCBASE; + if (first_unused) + flags |=3D PRINT_METHOD_FIRST_UNUSED; + if (fake_names) + flags |=3D PRINT_METHOD_FAKE_NAMES; + + print_method2(fp, + typeprefix, + nameprefix, + subnameprefix, + namepostfix, + afterargs, + postfix, + m, + flags); } =20 static gboolean @@ -371,11 +418,13 @@ =20 /* if a signal mark it as such */ if(m->method !=3D VIRTUAL_METHOD) - print_method(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n", - m, FALSE, TRUE, TRUE, FALSE, FALSE); + print_method2(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n", + m, PRINT_METHOD_NO_FUNCBASE | + PRINT_METHOD_NO_ATTR); else - print_method(outh, "\t", "(* ", "", ") ", "", ";\n", - m, FALSE, TRUE, TRUE, FALSE, FALSE); + print_method2(outh, "\t", "(* ", "", ") ", "", ";\n", + m, PRINT_METHOD_NO_FUNCBASE | + PRINT_METHOD_NO_ATTR); } =20 static void @@ -422,8 +471,11 @@ "\"%s\"," "(GCallback) __extension__ ({", funcbase, m->id, macrobase, typebase, m->id); - print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ", - " =3D (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE); + print_method2 (outh, "", "(* ___", "", ") ", ", gpointer ___data ", + " =3D (func); ", m, + PRINT_METHOD_NO_FUNCBASE + | PRINT_METHOD_FAKE_NAMES + | PRINT_METHOD_NO_ATTR); out_printf (outh, "___%s; }), (data))\n", m->id); =20 /* connect_after */ @@ -433,8 +485,11 @@ "\"%s\"," "(GCallback) __extension__ ({", funcbase, m->id, macrobase, typebase, m->id); - print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ", - " =3D (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE); + print_method2 (outh, "", "(* ___", "", ") ", ", gpointer ___data ", + " =3D (func); ", m, + PRINT_METHOD_NO_FUNCBASE + | PRINT_METHOD_FAKE_NAMES + | PRINT_METHOD_NO_ATTR); out_printf (outh, "___%s; }), (data))\n", m->id); =20 /* connect_data */ @@ -445,8 +500,11 @@ "\"%s\"," "(GCallback) __extension__ ({", funcbase, m->id, macrobase, typebase, m->id); - print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ", - " =3D (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE); + print_method2 (outh, "", "(* ___", "", ") ", ", gpointer ___data ", + " =3D (func); ", m, + PRINT_METHOD_NO_FUNCBASE + | PRINT_METHOD_FAKE_NAMES + | PRINT_METHOD_NO_ATTR); out_printf (outh, "___%s; }), (data), (destroy_data), (GConnectFlags)(fl= ags))\n", m->id); } } @@ -526,9 +584,9 @@ m->method =3D=3D SIGNAL_FIRST_METHOD || m->method =3D=3D VIRTUAL_METHOD) { if(m->cbuf) - print_method(out, - "static ", "___real_", "", " ", "", ";\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, + "static ", "___real_", "", " ", "", ";\n", + m, PRINT_METHOD_NO_ATTR); } /* no else, here, it might still have a private prototype, it's not * exclusive */ @@ -537,15 +595,13 @@ m->cbuf)) { /* add unique ID */ char *s =3D g_strdup_printf("___%x_", (guint)m->unique_id); - print_method(out, "static ", s, "", " ", "", - no_gnu?";\n":" G_GNUC_UNUSED;\n", + print_method(out, "static ", s, "", " ", "", ";\n", m, FALSE, FALSE, FALSE, FALSE, FALSE); g_free(s); } else if(m->scope =3D=3D PRIVATE_SCOPE || m->method =3D=3D INIT_METHOD || m->method =3D=3D CLASS_INIT_METHOD) { - print_method(out, "static ", "", "", " ", "", - no_gnu?";\n":" G_GNUC_UNUSED;\n", + print_method(out, "static ", "", "", " ", "", ";\n", m, FALSE, FALSE, TRUE, FALSE, FALSE); } } @@ -2831,11 +2887,11 @@ if(m->line_no > 0) out_addline_infile(out, m->line_no); if(m->scope =3D=3D PRIVATE_SCOPE) - print_method(out, "static ", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "static ", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); else /* PUBLIC, PROTECTED */ - print_method(out, "", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); print_method_body(m, TRUE, TRUE); /* the outfile line was added above */ break; @@ -2844,11 +2900,11 @@ if(m->line_no > 0) out_addline_infile(out, m->line_no); if(m->scope =3D=3D PRIVATE_SCOPE) - print_method(out, "static ", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "static ", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); else /* PUBLIC, PROTECTED */ - print_method(out, "", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); out_addline_outfile (out); =20 out_printf (out, "{\n"); @@ -2966,8 +3022,8 @@ break; if(m->line_no > 0) out_addline_infile(out, m->line_no); - print_method(out, "static ", "\n___real_", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, TRUE, FALSE); + print_method2(out, "static ", "\n___real_", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); print_method_body(m, FALSE, TRUE); /* the outfile line was added above */ break; @@ -2975,11 +3031,11 @@ if(m->line_no > 0) out_addline_infile(out, m->line_no); if(m->scope=3D=3DPRIVATE_SCOPE) - print_method(out, "static ", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "static ", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); else /* PUBLIC, PROTECTED */ - print_method(out, "", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); out_addline_outfile(out); out_printf(out, "{\n" "\t%sClass *klass;\n", typebase); @@ -3024,8 +3080,9 @@ break; if(m->line_no > 0) out_addline_infile(out, m->line_no); - print_method(out, "static ", "\n___real_", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, TRUE, FALSE); + print_method2(out, "static ", "\n___real_", "", " ", "", "\n", + m, PRINT_METHOD_FIRST_UNUSED + | PRINT_METHOD_NO_ATTR); print_method_body(m, FALSE, TRUE); /* the outfile line was added above */ break; --- src/parse.y.orig 2007-03-09 18:46:14.000000000 +0100 +++ src/parse.y 2008-01-28 16:58:25.000000000 +0100 @@ -146,7 +146,7 @@ =20 static void push_function (int scope, int method, char *oid, char *id, - GString *cbuf, int line_no, int ccode_line, + GString *attr, GString *cbuf, int line_no, int ccode_line, gboolean vararg, GList *flags) { Node *node; @@ -207,6 +207,7 @@ "args:steal", funcargs, "onerror:steal", onerror, "defreturn:steal", defreturn, + "attr:steal", attr ? attr->str : NULL, "cbuf:steal", c_cbuf, "line_no", line_no, "ccode_line", ccode_line, @@ -216,6 +217,8 @@ =20 last_added_method =3D (Method *)node; =20 + if(attr) + g_string_free(attr, FALSE); if(cbuf) g_string_free(cbuf, /*only free segment if we haven't passed it @@ -405,7 +408,7 @@ push_funcarg ("self", FALSE); =09 push_function (PUBLIC_SCOPE, REGULAR_METHOD, NULL, - get_id, get_cbuf, get_lineno, + get_id, NULL, get_cbuf, get_lineno, lineno, FALSE, NULL); } =09 @@ -439,7 +442,7 @@ =09 typestack =3D g_list_prepend (typestack, node2); push_function (PUBLIC_SCOPE, REGULAR_METHOD, NULL, - set_id, set_cbuf, set_lineno, + set_id, NULL, set_cbuf, set_lineno, lineno, FALSE, NULL); } =20 @@ -1678,9 +1681,25 @@ YYERROR; } push_function(the_scope, $<sigtype>3,NULL, - $<id>5, $<cbuf>10,$<line>1, + $<id>5, NULL, $<cbuf>10,$<line>1, ccode_line, vararg, $<list>2); } + | '[' CCODE SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnva= ls codenocode { + if(!has_self) { + yyerror(_("signal without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, $<sigtype>5,NULL, + $<id>7, $<cbuf>2, $<cbuf>12,$<line>3, + ccode_line, vararg, $<list>4); + } | scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' returnvals= codenocode { if(!has_self) { yyerror(_("signal without 'self' as " @@ -1694,9 +1713,25 @@ YYERROR; } push_function(the_scope, $<sigtype>4, NULL, - $<id>6, $<cbuf>11, $<line>2, + $<id>6, NULL, $<cbuf>11, $<line>2, ccode_line, vararg, $<list>3); } + | '[' CCODE scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' = returnvals codenocode { + if(!has_self) { + yyerror(_("signal without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, $<sigtype>6, NULL, + $<id>8, $<cbuf>2, $<cbuf>13, $<line>4, + ccode_line, vararg, $<list>5); + } | VIRTUAL scope type TOKEN '(' funcargs ')' returnvals codenocode { if(!has_self) { yyerror(_("virtual method without 'self' as " @@ -1710,7 +1745,23 @@ YYERROR; } push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>4, - $<cbuf>9, $<line>1, + NULL, $<cbuf>9, $<line>1, + ccode_line, vararg, NULL); + } + | '[' CCODE VIRTUAL scope type TOKEN '(' funcargs ')' returnvals codenoco= de { + if(!has_self) { + yyerror(_("virtual method without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>6, + $<cbuf>2, $<cbuf>11, $<line>3, ccode_line, vararg, NULL); } | scope VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { @@ -1726,7 +1777,23 @@ YYERROR; } push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>4, - $<cbuf>9, $<line>2, + NULL, $<cbuf>9, $<line>2, + ccode_line, vararg, NULL); + } + | '[' CCODE scope VIRTUAL type TOKEN '(' funcargs ')' returnvals codenoco= de { + if(!has_self) { + yyerror(_("virtual method without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>6, + $<cbuf>2, $<cbuf>11, $<line>4, ccode_line, vararg, NULL); } | VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { @@ -1737,12 +1804,23 @@ YYERROR; } push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL, - $<id>3, $<cbuf>8, $<line>1, + $<id>3, NULL, $<cbuf>8, $<line>1, + ccode_line, vararg, NULL); + } + | '[' CCODE VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { + if(!has_self) { + yyerror(_("virtual method without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL, + $<id>5, $<cbuf>2, $<cbuf>10, $<line>3, ccode_line, vararg, NULL); } | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' returnvals coden= ocode { push_function(NO_SCOPE, OVERRIDE_METHOD, $<id>3, - $<id>6, $<cbuf>11, + $<id>6, NULL, $<cbuf>11, $<line>1, ccode_line, vararg, NULL); } @@ -1753,19 +1831,29 @@ YYERROR; } push_function(the_scope, REGULAR_METHOD, NULL, $<id>3, - $<cbuf>8, $<line>1, ccode_line, + NULL, $<cbuf>8, $<line>1, ccode_line, + vararg, NULL); + } + | '[' CCODE scope type TOKEN '(' funcargs ')' returnvals codenocode { + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, REGULAR_METHOD, NULL, $<id>5, + $<cbuf>2, $<cbuf>10, $<line>3, ccode_line, vararg, NULL); } | TOKEN '(' TOKEN ')' codenocode { if(strcmp($<id>1, "init")=3D=3D0) { push_init_arg($<id>3,FALSE); push_function(NO_SCOPE, INIT_METHOD, NULL, - $<id>1, $<cbuf>5, $<line>2, + $<id>1, NULL, $<cbuf>5, $<line>2, ccode_line, FALSE, NULL); } else if(strcmp($<id>1, "class_init")=3D=3D0) { push_init_arg($<id>3,TRUE); push_function(NO_SCOPE, CLASS_INIT_METHOD, NULL, - $<id>1, $<cbuf>5, $<line>2, + $<id>1, NULL, $<cbuf>5, $<line>2, ccode_line, FALSE, NULL); } else { g_free($<id>1); --- src/treefuncs.def.orig 2007-03-09 18:46:14.000000000 +0100 +++ src/treefuncs.def 2008-01-28 16:16:21.000000000 +0100 @@ -126,6 +126,7 @@ NODELIST args STRING onerror STRING defreturn + STRING attr STRING cbuf INT line_no INT ccode_line --Multipart=_Mon__28_Jan_2008_18_10_20_+0100_i.aKsy.QZL7asG1/ Content-Type: text/x-diff; name="gob2-2.0.15-gobject-overrides-and-attr.diff" Content-Disposition: attachment; filename="gob2-2.0.15-gobject-overrides-and-attr.diff" Content-Transfer-Encoding: quoted-printable --- src/lexer.l.orig 2007-09-28 06:26:49.000000000 +0200 +++ src/lexer.l 2008-01-28 17:15:53.000000000 +0100 @@ -31,6 +31,7 @@ #include "main.h" #include "util.h" =20 +static int bracket_depth =3D 0; static int parenth_depth =3D 0; static int before_comment /* New flex is on drugs */ @@ -102,6 +103,7 @@ =20 %x COMMENT %x C_CODE +%x ATTR_CODE %x CODE_STRING %x CLASS_CODE %x CLASS_STRING @@ -267,7 +269,7 @@ add_to_cbuf(yytext); } =20 -<C_CODE>\/\/.*$ { add_to_cbuf(yytext); /*comment, ignore*/ } +<C_CODE,ATTR_CODE>\/\/.*$ { add_to_cbuf(yytext); /*comment, ignore*/ } <CLASS_CODE>\/\/.*$ { ; /*comment, ignore*/ } <CLASS_CODE_I>\/\/.*$ { ; /*comment, ignore*/ } <PROPERTY_CODE_I>\/\/.*$ { ; /*comment, ignore*/ } @@ -277,20 +279,25 @@ BEGIN(COMMENT); before_comment =3D C_CODE; } +<ATTR_CODE>\/\* { + add_to_cbuf(yytext); + BEGIN(COMMENT); + before_comment =3D ATTR_CODE; +} <CLASS_CODE>\/\* {BEGIN(COMMENT); before_comment =3D CLASS_CODE; } <CLASS_CODE_I>\/\* {BEGIN(COMMENT); before_comment =3D CLASS_CODE_I; } <PROPERTY_CODE_I>\/\* {BEGIN(COMMENT); before_comment =3D PROPERTY_CODE_I;= } <COMMENT>\*\/ { - if(before_comment =3D=3D C_CODE) add_to_cbuf(yytext); + if(before_comment =3D=3D C_CODE || before_comment =3D=3D ATTR_CODE) add_t= o_cbuf(yytext); BEGIN(before_comment); } <COMMENT>. { /* comment, ignore */ - if(before_comment =3D=3D C_CODE) add_to_cbuf(yytext); + if(before_comment =3D=3D C_CODE || before_comment =3D=3D ATTR_CODE) add_t= o_cbuf(yytext); } <COMMENT>\n { /* comment, ignore */ - if(before_comment =3D=3D C_CODE) add_to_cbuf(yytext); + if(before_comment =3D=3D C_CODE || before_comment =3D=3D ATTR_CODE) add_t= o_cbuf(yytext); } =20 ^\%(a|all)\{ { @@ -353,14 +360,14 @@ return code_type; } =20 -<C_CODE>\'\{\' { add_to_cbuf(yytext); } -<C_CODE>\'\\\{\' { add_to_cbuf(yytext); } -<C_CODE>\'\}\' { add_to_cbuf(yytext); } -<C_CODE>\'\\\}\' { add_to_cbuf(yytext); } -<C_CODE>\'\"\' { add_to_cbuf(yytext); } -<C_CODE>\'\\\"\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\{\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\\\{\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\}\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\\\}\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\"\' { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\'\\\"\' { add_to_cbuf(yytext); } =09 -<C_CODE>\\. { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\\. { add_to_cbuf(yytext); } =20 =20 <C_CODE>\" { @@ -368,6 +375,11 @@ before_string =3D C_CODE; add_to_cbuf(yytext); } +<ATTR_CODE>\" { + BEGIN(CODE_STRING); + before_string =3D ATTR_CODE; + add_to_cbuf(yytext); + } <PROPERTY_CODE_I>\" { BEGIN(CODE_STRING); before_string =3D PROPERTY_CODE_I; @@ -391,6 +403,10 @@ parenth_depth++; add_to_cbuf(yytext); } +<ATTR_CODE>\[ { + bracket_depth++; + add_to_cbuf(yytext); + } <C_CODE>\} { parenth_depth--; if(parenth_depth<0) { @@ -403,9 +419,21 @@ } add_to_cbuf(yytext); } +<ATTR_CODE>\] { + bracket_depth--; + if(bracket_depth<0) { + REJECT; + } else if(bracket_depth=3D=3D0) { + BEGIN(CLASS_CODE_I); + yylval.cbuf =3D cbuf; + cbuf =3D NULL; + return CCODE; + } + add_to_cbuf(yytext); + } =20 -<C_CODE>. { add_to_cbuf(yytext); } -<C_CODE>\n { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>. { add_to_cbuf(yytext); } +<C_CODE,ATTR_CODE>\n { add_to_cbuf(yytext); } =20 class { static int found_classes =3D 0; @@ -612,6 +640,13 @@ BEGIN(INITIAL); return '}'; } +<CLASS_CODE_I>\[ { + BEGIN(ATTR_CODE); + bracket_depth=3D1; + yylval.line =3D line_no; + clear_cbuf(); + return '['; + } =20 <CLASS_CODE,CLASS_CODE_I,INITIAL,PROPERTY_CODE,PROPERTY_CODE_I>[\f\t ] ; = /*ignore*/ =20 --- src/main.c.orig 2007-10-17 16:49:04.000000000 +0200 +++ src/main.c 2008-01-28 17:15:53.000000000 +0100 @@ -92,11 +92,16 @@ static gboolean special_array[SPECIAL_LAST] =3D {0}; static gboolean any_special =3D FALSE; =20 +static gboolean need_constructor =3D FALSE; +static Method * user_constructor =3D NULL; + static gboolean need_dispose =3D FALSE; static Method * dispose_handler =3D NULL; +static Method * user_dispose_method =3D NULL; =20 static gboolean need_finalize =3D FALSE; static Method * finalize_handler =3D NULL; +static Method * user_finalize_method =3D NULL; =20 FILE *out =3D NULL; FILE *outh =3D NULL; @@ -189,21 +194,25 @@ g_free(s); } =20 - -static void -print_method (FILE *fp, - const char *typeprefix, - const char *nameprefix, - const char *subnameprefix, - const char *namepostfix, - const char *afterargs, - const char *postfix, - const Method *m, - gboolean one_arg_per_line, - gboolean no_funcbase, - gboolean kill_underscore, - gboolean first_unused, - gboolean fake_names) +typedef enum +{ + PRINT_METHOD_ONE_ARG_PER_LINE =3D 1 << 0, + PRINT_METHOD_NO_FUNCBASE =3D 1 << 1, + PRINT_METHOD_FIRST_UNUSED =3D 1 << 2, + PRINT_METHOD_FAKE_NAMES =3D 1 << 3, + PRINT_METHOD_NO_ATTR =3D 1 << 4 +} PrintMethodFlags; + +static void +print_method2 (FILE *fp, + const char *typeprefix, + const char *nameprefix, + const char *subnameprefix, + const char *namepostfix, + const char *afterargs, + const char *postfix, + const Method *m, + PrintMethodFlags flags) { GList *li; const char *id; @@ -213,7 +222,7 @@ =20 id =3D m->id; =20 - if(no_funcbase) + if ((flags & PRINT_METHOD_NO_FUNCBASE) !=3D 0) out_printf(fp, "%s%s%s%s(", nameprefix, subnameprefix, id, namepostfix);=20 else @@ -229,19 +238,19 @@ if ( ! no_gnu && ! for_cpp && /* g++ has a cow with this */ li =3D=3D m->args && - first_unused) { + (flags & PRINT_METHOD_FIRST_UNUSED) !=3D 0) { unused =3D " G_GNUC_UNUSED"; } =20 print_type(fp, arg->atype, FALSE); - if (fake_names) + if ((flags & PRINT_METHOD_FAKE_NAMES) !=3D 0) out_printf (fp, "___fake___"); if(li->next) out_printf(fp, "%s%s%s,%s", arg->name, arg->atype->postfix ? arg->atype->postfix : "", unused, - one_arg_per_line ? "\n\t\t\t\t\t" : " "); + (flags & PRINT_METHOD_ONE_ARG_PER_LINE) !=3D 0 ? "\n\t\t\t\t\t" : = " "); else out_printf(fp, "%s%s%s", arg->name, arg->atype->postfix ? @@ -250,11 +259,54 @@ } if(m->vararg) out_printf(fp, ",%s...", - one_arg_per_line ? "\n\t\t\t\t\t" : " ");=20 + (flags & PRINT_METHOD_ONE_ARG_PER_LINE) !=3D 0 ? "\n\t\t\t\t\t" : "= ");=20 } else { out_printf(fp, "void");=20 } - out_printf(fp, "%s)%s", afterargs, postfix);=20 + + out_printf(fp, "%s)", afterargs); + + if (m->attr && (flags & PRINT_METHOD_NO_ATTR) =3D=3D 0) + out_printf(fp, " %s", m->attr); + + out_printf(fp, "%s", postfix); +} + +static void +print_method (FILE *fp, + const char *typeprefix, + const char *nameprefix, + const char *subnameprefix, + const char *namepostfix, + const char *afterargs, + const char *postfix, + const Method *m, + gboolean one_arg_per_line, + gboolean no_funcbase, + gboolean kill_underscore, + gboolean first_unused, + gboolean fake_names) +{ + PrintMethodFlags flags =3D 0; + + if (one_arg_per_line) + flags |=3D PRINT_METHOD_ONE_ARG_PER_LINE; + if (no_funcbase) + flags |=3D PRINT_METHOD_NO_FUNCBASE; + if (first_unused) + flags |=3D PRINT_METHOD_FIRST_UNUSED; + if (fake_names) + flags |=3D PRINT_METHOD_FAKE_NAMES; + + print_method2(fp, + typeprefix, + nameprefix, + subnameprefix, + namepostfix, + afterargs, + postfix, + m, + flags); } =20 static gboolean @@ -269,6 +321,9 @@ =09 if(m->method =3D=3D INIT_METHOD || m->method =3D=3D CLASS_INIT_METHOD || + m->method =3D=3D CONSTRUCTOR_METHOD || + m->method =3D=3D DISPOSE_METHOD || + m->method =3D=3D FINALIZE_METHOD || m->method =3D=3D OVERRIDE_METHOD) continue; =20 @@ -291,6 +346,9 @@ =09 if(m->method =3D=3D INIT_METHOD || m->method =3D=3D CLASS_INIT_METHOD || + m->method =3D=3D CONSTRUCTOR_METHOD || + m->method =3D=3D DISPOSE_METHOD || + m->method =3D=3D FINALIZE_METHOD || m->method =3D=3D OVERRIDE_METHOD) continue; =20 @@ -330,6 +388,9 @@ =09 if(m->method =3D=3D INIT_METHOD || m->method =3D=3D CLASS_INIT_METHOD || + m->method =3D=3D CONSTRUCTOR_METHOD || + m->method =3D=3D DISPOSE_METHOD || + m->method =3D=3D FINALIZE_METHOD || m->method =3D=3D OVERRIDE_METHOD) continue; =20 @@ -371,11 +432,13 @@ =20 /* if a signal mark it as such */ if(m->method !=3D VIRTUAL_METHOD) - print_method(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n", - m, FALSE, TRUE, TRUE, FALSE, FALSE); + print_method2(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n", + m, PRINT_METHOD_NO_FUNCBASE | + PRINT_METHOD_NO_ATTR); else - print_method(outh, "\t", "(* ", "", ") ", "", ";\n", - m, FALSE, TRUE, TRUE, FALSE, FALSE); + print_method2(outh, "\t", "(* ", "", ") ", "", ";\n", + m, PRINT_METHOD_NO_FUNCBASE | + PRINT_METHOD_NO_ATTR); } =20 static void @@ -422,8 +485,11 @@ "\"%s\"," "(GCallback) __extension__ ({", funcbase, m->id, macrobase, typebase, m->id); - print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ", - " =3D (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE); + print_method2 (outh, "", "(* ___", "", ") ", ", gpointer ___data ", + " =3D (func); ", m, + PRINT_METHOD_NO_FUNCBASE + | PRINT_METHOD_FAKE_NAMES + | PRINT_METHOD_NO_ATTR); out_printf (outh, "___%s; }), (data))\n", m->id); =20 /* connect_after */ @@ -433,8 +499,11 @@ "\"%s\"," "(GCallback) __extension__ ({", funcbase, m->id, macrobase, typebase, m->id); - print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ", - " =3D (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE); + print_method2 (outh, "", "(* ___", "", ") ", ", gpointer ___data ", + " =3D (func); ", m, + PRINT_METHOD_NO_FUNCBASE + | PRINT_METHOD_FAKE_NAMES + | PRINT_METHOD_NO_ATTR); out_printf (outh, "___%s; }), (data))\n", m->id); =20 /* connect_data */ @@ -445,8 +514,11 @@ "\"%s\"," "(GCallback) __extension__ ({", funcbase, m->id, macrobase, typebase, m->id); - print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ", - " =3D (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE); + print_method2 (outh, "", "(* ___", "", ") ", ", gpointer ___data ", + " =3D (func); ", m, + PRINT_METHOD_NO_FUNCBASE + | PRINT_METHOD_FAKE_NAMES + | PRINT_METHOD_NO_ATTR); out_printf (outh, "___%s; }), (data), (destroy_data), (GConnectFlags)(fl= ags))\n", m->id); } } @@ -526,9 +598,9 @@ m->method =3D=3D SIGNAL_FIRST_METHOD || m->method =3D=3D VIRTUAL_METHOD) { if(m->cbuf) - print_method(out, - "static ", "___real_", "", " ", "", ";\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, + "static ", "___real_", "", " ", "", ";\n", + m, PRINT_METHOD_NO_ATTR); } /* no else, here, it might still have a private prototype, it's not * exclusive */ @@ -537,15 +609,16 @@ m->cbuf)) { /* add unique ID */ char *s =3D g_strdup_printf("___%x_", (guint)m->unique_id); - print_method(out, "static ", s, "", " ", "", - no_gnu?";\n":" G_GNUC_UNUSED;\n", + print_method(out, "static ", s, "", " ", "", ";\n", m, FALSE, FALSE, FALSE, FALSE, FALSE); g_free(s); } else if(m->scope =3D=3D PRIVATE_SCOPE || m->method =3D=3D INIT_METHOD || - m->method =3D=3D CLASS_INIT_METHOD) { - print_method(out, "static ", "", "", " ", "", - no_gnu?";\n":" G_GNUC_UNUSED;\n", + m->method =3D=3D CLASS_INIT_METHOD || + m->method =3D=3D CONSTRUCTOR_METHOD || + m->method =3D=3D DISPOSE_METHOD || + m->method =3D=3D FINALIZE_METHOD) { + print_method(out, "static ", "", "", " ", "", ";\n", m, FALSE, FALSE, TRUE, FALSE, FALSE); } } @@ -629,66 +702,68 @@ } } =20 -static void -find_dispose(const Class *cl) +static Method * +find_method(const Class *cl, int method, const char *id) { GList *li; =20 - dispose_handler =3D NULL; for(li=3Dcl->nodes;li;li=3Dg_list_next(li)) { Node *n =3D li->data; if(n->type =3D=3D METHOD_NODE) { Method *m =3D (Method *)n; - if(m->method =3D=3D OVERRIDE_METHOD && - strcmp(m->id, "dispose")=3D=3D0) { - if(strcmp(m->otype, "G:Object") !=3D 0) { - error_print(GOB_ERROR, m->line_no, - "dispose method override " - "of class other then " - "G:Object"); - } - if(g_list_length(m->args) !=3D 1) { - error_print(GOB_ERROR, m->line_no, - "dispose method override " - "with more then one " - "parameter"); - } - dispose_handler =3D m; - break; - } + if (m->method =3D=3D method + && (id =3D=3D NULL || strcmp(m->id, id)=3D=3D0)) + return m; } } + + return NULL; } =20 static void -find_finalize(const Class *cl) +find_constructor(const Class *cl) { - GList *li; + user_constructor =3D find_method(cl, CONSTRUCTOR_METHOD, NULL); +} =20 - finalize_handler =3D NULL; - for(li=3Dcl->nodes;li;li=3Dg_list_next(li)) { - Node *n =3D li->data; - if(n->type =3D=3D METHOD_NODE) { - Method *m =3D (Method *)n; - if(m->method =3D=3D OVERRIDE_METHOD && - strcmp(m->id, "finalize")=3D=3D0) { - if(strcmp(m->otype, "G:Object") !=3D 0) { - error_print(GOB_ERROR, m->line_no, - "finalize method override " - "of class other then " - "G:Object"); - } - if(g_list_length(m->args) !=3D 1) { - error_print(GOB_ERROR, m->line_no, - "finalize method override " - "with more then one " - "parameter"); - } - finalize_handler =3D m; - break; - } - } +static void +find_dispose(const Class *cl) +{ + dispose_handler =3D find_method(cl, OVERRIDE_METHOD, "dispose"); + if (dispose_handler !=3D NULL) { + if(strcmp(dispose_handler->otype, "G:Object") !=3D 0) + error_print(GOB_ERROR, dispose_handler->line_no, + "dispose method override " + "of class other then " + "G:Object"); + if(g_list_length(dispose_handler->args) !=3D 1) + error_print(GOB_ERROR, dispose_handler->line_no, + "dispose method override " + "with more then one " + "parameter"); + } + + user_dispose_method =3D find_method(cl, DISPOSE_METHOD, NULL); +} + +static void +find_finalize(const Class *cl) +{ + finalize_handler =3D find_method(cl, OVERRIDE_METHOD, "finalize"); + if (finalize_handler !=3D NULL) { + if(strcmp(finalize_handler->otype, "G:Object") !=3D 0) + error_print(GOB_ERROR, finalize_handler->line_no, + "finalize method override " + "of class other then " + "G:Object"); + if(g_list_length(finalize_handler->args) !=3D 1) + error_print(GOB_ERROR, finalize_handler->line_no, + "finalize method override " + "with more then one " + "parameter"); } + + user_finalize_method =3D find_method(cl, FINALIZE_METHOD, NULL); } =20 =20 @@ -2118,6 +2193,33 @@ } =20 static void +add_constructor (Class *c) +{ + out_printf(out, "\nstatic GObject *\n" + "___constructor (GType type, guint n_construct_properties, GObjectCon= structParam *construct_properties)\n" + "{\n"); + out_printf(out, + "#define __GOB_FUNCTION__ \"%s::constructor\"\n", + c->otype); + + out_printf(out, "\tGObject *obj_self;\n"); + out_printf(out, "\t%s *self;\n", typebase); + + out_printf(out, "\tobj_self =3D G_OBJECT_CLASS (parent_class)->constructo= r (type, n_construct_properties, construct_properties);\n"); + out_printf(out, "\tself =3D %s (obj_self);\n", macrobase); + + if (user_constructor->line_no > 0) + out_addline_infile (out, user_constructor->line_no); + out_printf (out, "\t%s_constructor (self);\n", funcbase); + if (user_constructor->line_no > 0) + out_addline_outfile (out); + + out_printf(out, "\treturn obj_self;\n"); + out_printf(out, "}\n" + "#undef __GOB_FUNCTION__\n\n"); +} + +static void add_dispose (Class *c) { out_printf(out, "\nstatic void\n" @@ -2127,7 +2229,7 @@ "#define __GOB_FUNCTION__ \"%s::dispose\"\n", c->otype); =20 - if (unreftors > 0) { + if (unreftors > 0 || user_dispose_method !=3D NULL) { out_printf (out, "\t%s *self%s =3D %s (obj_self);\n", typebase, ! no_gnu ? " G_GNUC_UNUSED" : "", @@ -2143,6 +2245,14 @@ if (dispose_handler->line_no > 0) out_addline_outfile (out); } else { + if (user_dispose_method !=3D NULL) { + if (user_dispose_method->line_no > 0) + out_addline_infile (out, user_dispose_method->line_no); + out_printf (out, "\t%s_dispose (self);\n", funcbase); + if (user_dispose_method->line_no > 0) + out_addline_outfile (out); + } + out_printf (out, "\tif (G_OBJECT_CLASS (parent_class)->dispose) \\\n" "\t\t(* G_OBJECT_CLASS (parent_class)->dispose) (obj_self);\n"); @@ -2178,7 +2288,8 @@ c->otype); =20 if (privates > 0 || - destructors > 0) { + destructors > 0 || + user_finalize_method !=3D NULL) { const char *unused =3D ""; if ( ! no_gnu) unused =3D " G_GNUC_UNUSED"; @@ -2202,6 +2313,14 @@ if(finalize_handler->line_no > 0) out_addline_outfile(out); } else { + if (user_finalize_method !=3D NULL) { + if (user_finalize_method->line_no > 0) + out_addline_infile (out, user_finalize_method->line_no); + out_printf (out, "\t%s_finalize (self);\n", funcbase); + if (user_finalize_method->line_no > 0) + out_addline_outfile (out); + } + out_printf(out, "\tif(G_OBJECT_CLASS(parent_class)->finalize) \\\n" "\t\t(* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n"); @@ -2381,6 +2500,9 @@ =20 /* if there are no handlers for these things, we * need to set them up here */ + if(need_constructor) + out_printf(out, "\tg_object_class->constructor " + "=3D ___constructor;\n"); if(need_dispose && !dispose_handler) out_printf(out, "\tg_object_class->dispose " "=3D ___dispose;\n"); @@ -2831,11 +2953,11 @@ if(m->line_no > 0) out_addline_infile(out, m->line_no); if(m->scope =3D=3D PRIVATE_SCOPE) - print_method(out, "static ", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "static ", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); else /* PUBLIC, PROTECTED */ - print_method(out, "", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); print_method_body(m, TRUE, TRUE); /* the outfile line was added above */ break; @@ -2844,11 +2966,11 @@ if(m->line_no > 0) out_addline_infile(out, m->line_no); if(m->scope =3D=3D PRIVATE_SCOPE) - print_method(out, "static ", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "static ", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); else /* PUBLIC, PROTECTED */ - print_method(out, "", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); out_addline_outfile (out); =20 out_printf (out, "{\n"); @@ -2966,8 +3088,8 @@ break; if(m->line_no > 0) out_addline_infile(out, m->line_no); - print_method(out, "static ", "\n___real_", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, TRUE, FALSE); + print_method2(out, "static ", "\n___real_", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); print_method_body(m, FALSE, TRUE); /* the outfile line was added above */ break; @@ -2975,11 +3097,11 @@ if(m->line_no > 0) out_addline_infile(out, m->line_no); if(m->scope=3D=3DPRIVATE_SCOPE) - print_method(out, "static ", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "static ", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); else /* PUBLIC, PROTECTED */ - print_method(out, "", "\n", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method2(out, "", "\n", "", " ", "", "\n", + m, PRINT_METHOD_NO_ATTR); out_addline_outfile(out); out_printf(out, "{\n" "\t%sClass *klass;\n", typebase); @@ -3024,8 +3146,9 @@ break; if(m->line_no > 0) out_addline_infile(out, m->line_no); - print_method(out, "static ", "\n___real_", "", " ", "", "\n", - m, FALSE, FALSE, TRUE, TRUE, FALSE); + print_method2(out, "static ", "\n___real_", "", " ", "", "\n", + m, PRINT_METHOD_FIRST_UNUSED + | PRINT_METHOD_NO_ATTR); print_method_body(m, FALSE, TRUE); /* the outfile line was added above */ break; @@ -3064,6 +3187,15 @@ /* the outfile line was added above */ out_printf(out, "#undef PARENT_HANDLER\n"); break; + case CONSTRUCTOR_METHOD: + case DISPOSE_METHOD: + case FINALIZE_METHOD: + if(m->line_no > 0) + out_addline_infile(out, m->line_no); + print_method(out, "static ", "\n", "", " ", "", "\n", + m, FALSE, FALSE, TRUE, FALSE, FALSE); + print_method_body(m, TRUE, TRUE); + /* the outfile line was added above */ default: break; } @@ -3633,6 +3765,9 @@ funcbase); } =20 + if (need_constructor) + add_constructor (c); + if (need_dispose) add_dispose (c); =20 @@ -4441,15 +4576,24 @@ =20 make_bases (); make_inits ((Class *)class); - if(unreftors > 0) { + + find_constructor ((Class *)class); + if (user_constructor !=3D NULL) + need_constructor =3D TRUE; + + find_dispose ((Class *)class); + if (unreftors > 0 || + dispose_handler !=3D NULL || + user_dispose_method !=3D NULL) need_dispose =3D TRUE; - find_dispose ((Class *)class); - } + + find_finalize ((Class *)class); if (destructors > 0 || - privates > 0) { + privates > 0 || + user_finalize_method !=3D NULL) { need_finalize =3D TRUE; - find_finalize ((Class *)class); } + check_bad_symbols ((Class *)class); check_duplicate_symbols ((Class *)class); check_duplicate_overrides ((Class *)class); --- src/parse.y.orig 2007-03-09 18:46:14.000000000 +0100 +++ src/parse.y 2008-01-28 17:16:24.000000000 +0100 @@ -146,7 +146,7 @@ =20 static void push_function (int scope, int method, char *oid, char *id, - GString *cbuf, int line_no, int ccode_line, + GString *attr, GString *cbuf, int line_no, int ccode_line, gboolean vararg, GList *flags) { Node *node; @@ -155,7 +155,11 @@ =20 g_assert(scope !=3D CLASS_SCOPE); =20 - if(method =3D=3D INIT_METHOD || method =3D=3D CLASS_INIT_METHOD) { + if(method =3D=3D INIT_METHOD + || method =3D=3D CLASS_INIT_METHOD + || method =3D=3D CONSTRUCTOR_METHOD + || method =3D=3D DISPOSE_METHOD + || method =3D=3D FINALIZE_METHOD) { type =3D (Type *)node_new (TYPE_NODE, "name", "void", NULL); @@ -207,6 +211,7 @@ "args:steal", funcargs, "onerror:steal", onerror, "defreturn:steal", defreturn, + "attr:steal", attr ? attr->str : NULL, "cbuf:steal", c_cbuf, "line_no", line_no, "ccode_line", ccode_line, @@ -216,6 +221,8 @@ =20 last_added_method =3D (Method *)node; =20 + if(attr) + g_string_free(attr, FALSE); if(cbuf) g_string_free(cbuf, /*only free segment if we haven't passed it @@ -405,7 +412,7 @@ push_funcarg ("self", FALSE); =09 push_function (PUBLIC_SCOPE, REGULAR_METHOD, NULL, - get_id, get_cbuf, get_lineno, + get_id, NULL, get_cbuf, get_lineno, lineno, FALSE, NULL); } =09 @@ -439,7 +446,7 @@ =09 typestack =3D g_list_prepend (typestack, node2); push_function (PUBLIC_SCOPE, REGULAR_METHOD, NULL, - set_id, set_cbuf, set_lineno, + set_id, NULL, set_cbuf, set_lineno, lineno, FALSE, NULL); } =20 @@ -1678,9 +1685,25 @@ YYERROR; } push_function(the_scope, $<sigtype>3,NULL, - $<id>5, $<cbuf>10,$<line>1, + $<id>5, NULL, $<cbuf>10,$<line>1, ccode_line, vararg, $<list>2); } + | '[' CCODE SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnva= ls codenocode { + if(!has_self) { + yyerror(_("signal without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, $<sigtype>5,NULL, + $<id>7, $<cbuf>2, $<cbuf>12,$<line>3, + ccode_line, vararg, $<list>4); + } | scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' returnvals= codenocode { if(!has_self) { yyerror(_("signal without 'self' as " @@ -1694,9 +1717,25 @@ YYERROR; } push_function(the_scope, $<sigtype>4, NULL, - $<id>6, $<cbuf>11, $<line>2, + $<id>6, NULL, $<cbuf>11, $<line>2, ccode_line, vararg, $<list>3); } + | '[' CCODE scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' = returnvals codenocode { + if(!has_self) { + yyerror(_("signal without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, $<sigtype>6, NULL, + $<id>8, $<cbuf>2, $<cbuf>13, $<line>4, + ccode_line, vararg, $<list>5); + } | VIRTUAL scope type TOKEN '(' funcargs ')' returnvals codenocode { if(!has_self) { yyerror(_("virtual method without 'self' as " @@ -1710,7 +1749,23 @@ YYERROR; } push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>4, - $<cbuf>9, $<line>1, + NULL, $<cbuf>9, $<line>1, + ccode_line, vararg, NULL); + } + | '[' CCODE VIRTUAL scope type TOKEN '(' funcargs ')' returnvals codenoco= de { + if(!has_self) { + yyerror(_("virtual method without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>6, + $<cbuf>2, $<cbuf>11, $<line>3, ccode_line, vararg, NULL); } | scope VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { @@ -1726,7 +1781,23 @@ YYERROR; } push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>4, - $<cbuf>9, $<line>2, + NULL, $<cbuf>9, $<line>2, + ccode_line, vararg, NULL); + } + | '[' CCODE scope VIRTUAL type TOKEN '(' funcargs ')' returnvals codenoco= de { + if(!has_self) { + yyerror(_("virtual method without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>6, + $<cbuf>2, $<cbuf>11, $<line>4, ccode_line, vararg, NULL); } | VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { @@ -1737,12 +1808,23 @@ YYERROR; } push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL, - $<id>3, $<cbuf>8, $<line>1, + $<id>3, NULL, $<cbuf>8, $<line>1, + ccode_line, vararg, NULL); + } + | '[' CCODE VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { + if(!has_self) { + yyerror(_("virtual method without 'self' as " + "first parameter")); + free_all_global_state(); + YYERROR; + } + push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL, + $<id>5, $<cbuf>2, $<cbuf>10, $<line>3, ccode_line, vararg, NULL); } | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' returnvals coden= ocode { push_function(NO_SCOPE, OVERRIDE_METHOD, $<id>3, - $<id>6, $<cbuf>11, + $<id>6, NULL, $<cbuf>11, $<line>1, ccode_line, vararg, NULL); } @@ -1753,27 +1835,53 @@ YYERROR; } push_function(the_scope, REGULAR_METHOD, NULL, $<id>3, - $<cbuf>8, $<line>1, ccode_line, + NULL, $<cbuf>8, $<line>1, ccode_line, + vararg, NULL); + } + | '[' CCODE scope type TOKEN '(' funcargs ')' returnvals codenocode { + if(the_scope =3D=3D CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } + push_function(the_scope, REGULAR_METHOD, NULL, $<id>5, + $<cbuf>2, $<cbuf>10, $<line>3, ccode_line, vararg, NULL); } | TOKEN '(' TOKEN ')' codenocode { if(strcmp($<id>1, "init")=3D=3D0) { push_init_arg($<id>3,FALSE); push_function(NO_SCOPE, INIT_METHOD, NULL, - $<id>1, $<cbuf>5, $<line>2, + $<id>1, NULL, $<cbuf>5, $<line>2, ccode_line, FALSE, NULL); } else if(strcmp($<id>1, "class_init")=3D=3D0) { push_init_arg($<id>3,TRUE); push_function(NO_SCOPE, CLASS_INIT_METHOD, NULL, - $<id>1, $<cbuf>5, $<line>2, + $<id>1, NULL, $<cbuf>5, $<line>2, + ccode_line, FALSE, NULL); + } else if(strcmp($<id>1, "constructor")=3D=3D0) { + push_init_arg($<id>3, FALSE); + push_function(NO_SCOPE, CONSTRUCTOR_METHOD, NULL, + $<id>1, NULL, $<cbuf>5, $<line>2, + ccode_line, FALSE, NULL); + } else if(strcmp($<id>1, "dispose")=3D=3D0) { + push_init_arg($<id>3, FALSE); + push_function(NO_SCOPE, DISPOSE_METHOD, NULL, + $<id>1, NULL, $<cbuf>5, $<line>2, + ccode_line, FALSE, NULL); + } else if(strcmp($<id>1, "finalize")=3D=3D0) { + push_init_arg($<id>3, FALSE); + push_function(NO_SCOPE, FINALIZE_METHOD, NULL, + $<id>1, NULL, $<cbuf>5, $<line>2, ccode_line, FALSE, NULL); } else { g_free($<id>1); g_free($<id>3); g_string_free($<cbuf>5,TRUE); yyerror(_("parse error " - "(untyped blocks must be init or " - "class_init)")); + "(untyped blocks must be init, " + "class_init, constructor, dispose " + "or finalize)")); YYERROR; } } --- src/treefuncs.def.orig 2007-03-09 18:46:14.000000000 +0100 +++ src/treefuncs.def 2008-01-28 17:15:53.000000000 +0100 @@ -40,6 +40,9 @@ REGULAR_METHOD, INIT_METHOD, CLASS_INIT_METHOD, + CONSTRUCTOR_METHOD, + DISPOSE_METHOD, + FINALIZE_METHOD, VIRTUAL_METHOD, SIGNAL_LAST_METHOD, SIGNAL_FIRST_METHOD, @@ -126,6 +129,7 @@ NODELIST args STRING onerror STRING defreturn + STRING attr STRING cbuf INT line_no INT ccode_line --Multipart=_Mon__28_Jan_2008_18_10_20_+0100_i.aKsy.QZL7asG1/-- --Signature=_Mon__28_Jan_2008_18_10_20_+0100_PkcS9RSUBmpBbUWJ Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFHngyDyzD7UaO4AGoRAs8BAJ4pkh+YEYaDQiQz4n136QV2V7wBuACfZ5dY Uhhew2dno0TvZDP9TTWi69I= =rzxK -----END PGP SIGNATURE----- --Signature=_Mon__28_Jan_2008_18_10_20_+0100_PkcS9RSUBmpBbUWJ-- [email protected] Content-Type: text/plain; charset=us-ascii; name="footer.txt" Content-Disposition: inline Content-Transfer-Encoding: 8bit -- to unsubscribe: send mail to [email protected] with "unsubscribe gob-list" in the subject [email protected]