Back to index

plt-scheme  4.2.1
generatec.c
Go to the documentation of this file.
00001 /*   wbuild
00002      Copyright (C) 1996  Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
00003      
00004      This program is free software; you can redistribute it and/or
00005      modify it under the terms of the GNU General Public License
00006      as published by the Free Software Foundation; either version 2
00007      of the License, or (at your option) any later version.
00008      
00009      This program is distributed in the hope that it will be useful,
00010      but WITHOUT ANY WARRANTY; without even the implied warranty of
00011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012      GNU General Public License for more details.
00013      
00014      You should have received a copy of the GNU General Public License
00015      along with this program; if not, write to the Free Software
00016      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 /* This module contains the code that generates C and
00020  * documentation files from the specification of the widgets in a |Class|
00021  * datastructure. The only exported function is |generate|, which uses the
00022  * list of class specifications.
00023  */
00024 
00025 #define fputS(s, f) fputs(get(s), f)
00026 
00027 #include <config.h>
00028 #include <stdio.h>
00029 
00030 #include <libit/unistd.h>
00031 
00032 #include <libit/string.h>
00033 
00034 #include <libit/ctype.h>
00035 #include <wbuild.h>
00036 #include <wsym.h>
00037 
00038 #include <libintl.h>
00039 #define _(String) gettext(String)
00040 
00041 #include <libit/malloc.h>
00042 
00043 /* Implementation file. The implementation file contains the
00044  * definitions of all methods, actions and utility functions. It
00045  * initializes the class record and the translations.
00046  */
00047 
00048 /* inlining philosophy: nautilus has fast processor, slow disks.  Don't
00049  * significantly increase size of executable.
00050  *
00051  * Actually, I'm probably wasting too much effort on this...
00052  */
00053 
00054 /* |define_function| creates the function's header (taking care of
00055  * substituting `self' for `\$') and the function's body (again
00056  * substituting `self' where appropriate).
00057  *
00058  * The function header is defined twice, separated with |#if
00059  * NeedFunctionPrototypes|, echoing the forward declaration that was
00060  * created earlier.
00061  */
00062 
00063 static void define_header(int export, Decl d, FILE *f, int lines, int lineno,
00064        STRING sourcefile)
00065 {
00066        Decl d1;
00067 
00068        fputs("/*ARGSUSED*/\n", f);
00069        fprintf(f, "#if NeedFunctionPrototypes\n");
00070        lined(lineno, sourcefile);
00071        if (!export)
00072               fputs("static ", f);
00073        if (d->type)
00074               fputS(d->type, f);
00075        else
00076               fputs("void", f);
00077        fprintf(f, " %s(", get(d->name));
00078        if (d->params == NULL) {
00079               fputs("void", f);
00080        } else {
00081               for (d1 = d->params; d1; d1 = d1->next) {
00082                      if (d1->name == DOLLAR)
00083                             fprintf(f, "Widget self");
00084                      else if (d1->name == DOTDOTDOT)
00085                             fprintf(f, "...");
00086                      else
00087                             fprintf(f, "%s %s", get(d1->type),
00088                                    get(d1->name));
00089                      if (d1->suffix)
00090                             /* An array? */
00091                             fputS(d1->suffix, f);
00092                      if (d1->next)
00093                             putc(',', f);
00094               }
00095        }
00096        fprintf(f, ")\n#else\n");
00097        lined(lineno, sourcefile);
00098        if (! export)
00099               fputs("static ", f);
00100        if (d->type)
00101               fputS(d->type, f);
00102        else
00103               fputs("void", f);
00104        fprintf(f, " %s(", get(d->name));
00105        for (d1 = d->params; d1; d1 = d1->next) {
00106               if (d1->name == DOLLAR)
00107                      fputs("self", f);
00108               else if (d1->name == DOTDOTDOT)
00109                      fputs("va_alist", f);
00110               else
00111                      fputS(d1->name, f);
00112               if (d1->next)
00113                      putc(',', f);
00114        }
00115        putc(')', f);
00116        for (d1 = d->params; d1; d1 = d1->next) {
00117               if (d1->name == DOLLAR)
00118                      fprintf(f, "Widget self");
00119               else if (d1->name == DOTDOTDOT)
00120                      fprintf(f, "va_dcl");
00121               else
00122                      fprintf(f, "%s %s", get(d1->type), get(d1->name));
00123               if (d1->suffix)
00124                      /* An array? */
00125                      fputS(d1->suffix, f);
00126               if (d1->name != DOTDOTDOT)
00127                      putc(';', f);
00128        }
00129        fprintf(f, "\n#endif\n");
00130 }
00131 
00132 
00133 /* The number of declarations in a list of sections is counted,
00134  * omitting the macro definitions, since they are not declarations in the
00135  * C sense.
00136  */
00137 
00138 static int number_of_decls(Section sect)
00139 {
00140        Section s;
00141        int n;
00142 
00143        n = 0;
00144        for (s = sect; s; s = s->next) {
00145               if (s->decl && (s->decl->tp != Def)) n++;
00146        }
00147        return n;
00148 }
00149 
00150 static void define_function(int export, int lines, Decl d, STRING body, Class c,
00151        FILE *f, int lineno)
00152 {
00153        define_header(export, d, f, lines, lineno, c->filename);
00154        lined(lineno + 1, c->filename);
00155        print_body(f, body, c, d->name, lineno, 0);
00156 }
00157 
00158 static void define_macro(FILE *f, Decl d, Class c)
00159 {
00160        Decl d1;
00161 
00162        fputs("#define ", f);
00163        fputS(d->name, f);
00164        if (d->params) {
00165               putc('(', f);
00166               for (d1 = d->params; d1; d1 = d1->next) {
00167                      fputS(d1->name, f);
00168                      if (d1->next)
00169                             fputs(", ", f);
00170               }
00171               putc(')', f);
00172        }
00173        putc(' ', f);
00174        print_body(f, d->body, c, d->name, d->lineno, 1);
00175        fputs("\n\n", f);
00176 }
00177 
00178 #if 0
00179 /* |declare_function| creates a prototype for a function |d|. If
00180  * |export| is |False|, the prototype will be preceded by
00181  * |"static"|.\mkref{declare-function}
00182  */
00183 
00184 static void declare_function(int export, STRING name, Decl d, FILE *f)
00185 {
00186        Decl d1;
00187 
00188        if (!export)
00189               fputs("static ", f);
00190 
00191        if (d->type)
00192               fputS(d->type, f);
00193        else
00194               fputs("void", f);
00195 
00196        putc(' ', f);
00197        fputS(name, f);
00198        fputs("(\n#if NeedFunctionPrototypes\n", f);
00199        if (!d->params) {
00200               fputs("void", f);
00201        } else {
00202               for (d1 = d->params; d1; d1 = d1->next) {
00203                      if (d1->name == DOLLAR)
00204                             fputs("Widget", f);
00205                      else
00206                             fputS(d1->type, f);
00207                      if (d1->suffix)
00208                             fprintf(f, " %s%s", get(d1->name),
00209                                    get(d1->suffix));
00210                      if (d1->next) (void) putc(',', f);
00211               }
00212        }
00213        fputs("\n#endif\n);\n", f);
00214 }
00215 #endif
00216 
00217 /* The are two type of included files: system header files and local
00218  * header files. System header files are files whose names are bracketed
00219  * by $<$ and $>$.  Local header files have quotes.
00220  */
00221 
00222 inline static void generate_import_file(FILE *f, Section s)
00223 {
00224        fprintf(f, "#include %s\n", get(s->decl->name));
00225 }
00226 
00227 inline static void generate_import_var(FILE *f, Section s)
00228 {
00229        fprintf(f, "extern %s %s", get(s->decl->type), get(s->decl->name));
00230        if (s->decl->suffix)
00231               fputS(s->decl->suffix, f);
00232        fputs(";\n", f);
00233 }
00234 
00235 inline static void generate_import_func(FILE *f, Section s)
00236 {
00237        declare_function(1, s->decl->name, s->decl, f);
00238 }
00239 
00240 /* The implementation file starts with a set of included files. The
00241  * intrinsics and string definitions are always included. Next is the
00242  * private header file of the widget itself. After that there may be
00243  * additional inclusions.
00244  */
00245 
00246 inline static void generate_imports(FILE *f, Class c, char *prefix, int lines)
00247 {
00248        Section s;
00249 
00250        fprintf(f, "#include <X11/IntrinsicP.h>\n");
00251        fprintf(f, "#include <X11/StringDefs.h>\n");
00252        for (s = c->imports; s; s = s->next) {
00253               if (s->decl) {
00254                      lined(s->decl->lineno, c->filename);
00255                      switch (s->decl->tp) {
00256                             case Proc: generate_import_func(f, s); break;
00257                             case Var: generate_import_var(f, s); break;
00258                             case Incl: generate_import_file(f, s); break;
00259                             /* RMS, you don't see the following:
00260                              * to placate -Wall
00261                              * (it should be optomized away)
00262                              */
00263                             case Undefined: break;
00264                             case Type: break;
00265                             case Def: break;
00266                             case Trans: break;
00267                      }
00268               }
00269        }
00270        fprintf(f, "#include <%s>\n", get(get_headerPname(prefix, c)));
00271 }
00272 
00273 /* The resource list might also initialize resources from superclasses.
00274  * The offset has to be calculated carefully. |s1| is the declaration, it is
00275  * different from |s|, if the variable is inherited.
00276  *
00277  * Macros are skipped, since they have already been defined in the
00278  * private header file.
00279  */
00280 
00281 inline static void res_name_class(FILE *f, Section s1)
00282 {
00283        fprintf(f, "{XtN%s,XtC%s,",
00284               s1->decl->namesym
00285                      ? get(s1->decl->namesym) : get(s1->decl->name),
00286               s1->decl->namesym
00287                      ? get(get_classname(s1->decl->namesym))
00288                      : get(get_classname(s1->decl->name)));
00289 }
00290 
00291 
00292 inline static void res_type(FILE *f, Section s1)
00293 {
00294        fprintf(f, "XtR%s,", s1->decl->typesym ? get(s1->decl->typesym)
00295               : get(get_classname(get_word(get(s1->decl->type)))));
00296 }
00297 
00298 inline static void res_size_offset(FILE *f, Class c, Section s1)
00299 {
00300        fprintf(f, "sizeof(((%sRec*)NULL)->%s.%s),", get(c->name),
00301               get(get_instname(find_instvar_class(c, s1->decl->name)->name)),
00302               get(s1->decl->name));
00303        fprintf(f, "XtOffsetOf(%sRec,%s.%s),", get(c->name),
00304               get(get_instname(find_instvar_class(c, s1->decl->name)->name)),
00305               get(s1->decl->name));
00306 }
00307 
00308 inline static void res_initial_type(FILE *f, Section s)
00309 {
00310        if (s->decl->valuesym)
00311               fprintf(f, "XtR%s,", get(s->decl->valuesym));
00312        else
00313               fprintf(f, "XtRImmediate,");
00314 }
00315 
00316 inline static void res_initial_value(FILE *f, Section s)
00317 {
00318        fprintf(f, "(XtPointer)%s},\n", get(s->decl->value));
00319 }
00320 
00321 inline static void res_list(FILE *f, Class c, int lines)
00322 {
00323        Section s, s1;
00324 
00325        if (number_of_decls(c->publicvars) != 0) {
00326               fprintf(f, "\nstatic XtResource resources[] = {\n");
00327               for (s = c->publicvars; s; s = s->next) {
00328                      if (s->decl && (s->decl->tp == Var)) {
00329                             s1 = find_pubvar(c, s->decl->name);
00330                             lined(s->decl->lineno, c->filename);
00331                             res_name_class(f, s1);
00332                             res_type(f, s1);
00333                             res_size_offset(f, c, s1);
00334                             res_initial_type(f, s1);
00335                             s1 = find_pubvar_back(c, s->decl->name);
00336                             res_initial_value(f, s1);
00337                      }
00338               }
00339               fprintf(f, "};\n");
00340        }
00341 }
00342 
00343 /* The constraint resource list is similar to the resource list.
00344  */
00345 inline static void res_constraint_size_offset(FILE *f, Class c, Section s1)
00346 {
00347        fprintf(f, "sizeof(((%sConstraintRec*)NULL)->%s.%s),", get(c->name),
00348               get(get_instname(find_constr_class(c, s1->decl->name)->name)),
00349               get(s1->decl->name));
00350        fprintf(f, "XtOffsetOf(%sConstraintRec,%s.%s),", get(c->name),
00351               get(get_instname(find_constr_class(c, s1->decl->name)->name)),
00352               get(s1->decl->name));
00353 }
00354 
00355 inline static void generate_constraint_res_list(FILE *f, Class c, int lines)
00356 {
00357        Section s, s1;
00358        if (number_of_decls(c->constraints) != 0) {
00359               fprintf(f, "\nstatic XtResource constraint_resources[] = {\n");
00360               for (s = c->constraints; s; s = s->next) {
00361                      if (s->decl && (s->decl->tp == Var)) {
00362                             s1 = find_constraint(c, s->decl->name);
00363                             lined(s->decl->lineno, c->filename);
00364                             res_name_class(f, s1);
00365                             res_type(f, s1);
00366                             res_constraint_size_offset(f, c, s1);
00367                             res_initial_type(f, s1);
00368                             res_initial_value(f, s1);
00369                      }
00370               }
00371               fprintf(f, "};\n");
00372        }
00373 }
00374 
00375 
00376 /* All action functions have the same parameters; they should be
00377  * omitted in the spec files. The variable |action_proto| holds a
00378  * declaration of a prototypical action function. The parameters are
00379  * taken from that variable.
00380  */
00381 
00382 inline static void action_func_decl(FILE *f, Class c, int lines)
00383 {
00384        Section s;
00385 
00386        for (s = c->actions; s; s = s->next) {
00387               if (s->decl && (s->decl->tp == Proc)) {
00388                      warn_if_params(s->decl->params, c->filename,
00389                             s->decl->lineno, s->decl->name);
00390                      lined(s->decl->lineno, c->filename);
00391                      declare_function(0, s->decl->name,
00392                             action_proto.decl, f);
00393               } else if (s->decl && (s->decl->tp == Def)) {
00394                      define_macro(f, s->decl, c);
00395               }
00396        }
00397 }
00398 
00399 /* The action table will be called |actionsList| and the translation
00400  * table |defaultTranslations|. Both may be empty.
00401  */
00402 
00403 inline static void action_table_trans(FILE *f, Class c)
00404 {
00405        Section s;
00406 
00407        if (number_of_decls(c->actions) != 0) {
00408               fprintf(f, "\nstatic XtActionsRec actionsList[] = {\n");
00409               for (s = c->actions; s; s = s->next) {
00410                      if (s->decl && s->decl->tp == Proc) {
00411                             fprintf(f, "{\"%s\", %s},\n",
00412                                    get(s->decl->name), get(s->decl->name));
00413                      }
00414               }
00415               fprintf(f, "};\n");
00416        }
00417        if (number_of_decls(c->translations) != 0) {
00418               fprintf(f, "\nstatic char defaultTranslations[] = \"\\\n");
00419               for (s = c->translations; s; s = s->next) {
00420                      if (s->decl) {
00421                             fprintf(f, "%s: %s\\n\\\n",
00422                                    get(s->decl->type),
00423                                    get(s->decl->value));
00424                      }
00425               }
00426               fprintf(f, "\";\n");
00427        }
00428 }
00429 
00430 /* The methods all have forward declarations. The code here includes
00431  * ANSI style prototypes, protected with a macro. The method definitions
00432  * further on have old style K\&R headers.
00433  *
00434  * Wbuild generates a function called |"_resolve_inheritance"| that takes
00435  * care of replacing `XtInherit' by to appropriate methods in the final
00436  * widget. This function will be used as the |class_part_initialize|
00437  * method, unless the specificationfile already has such a method; in
00438  * that case the function will still be generated, but not installed in
00439  * the class record.
00440  */
00441 
00442 
00443 /* All methods have forward declaration. If the method is inherited,
00444  * there should be no parameter list, as the inherited parameter list
00445  * will be used. If |class_id| is |DOLLAR|, it is forced to be a new
00446  * method, if |class_id| is anything else (except |NIL|), it must be an
00447  * inherited method, from the given class.
00448  */
00449 
00450 inline static void declare_method(FILE *f, Class c, Section s)
00451 {
00452        Section s2;
00453 
00454        if (s->decl->class_id == DOLLAR)
00455               /* Force a new method */
00456               s2 = s;
00457        else if (!s->decl->class_id)
00458               /* Search for it */
00459               s2 = find_method(c, s->decl->name);
00460        else
00461               /* Search from given class */
00462               s2 = find_method(find_superclass(c, s->decl->class_id),
00463                      s->decl->name);
00464        if (s2 == NULL) {
00465               fprintf(stderr,
00466                      _("%s:%d: method \"%s\" or class \"%s\" not found\n"),
00467                      get(c->filename), s->decl->lineno, get(s->decl->name),
00468                      get(s->decl->class_id));
00469                      nerrors++;
00470        } else {
00471               if (s2 != s)
00472                      warn_if_params(s->decl->params, c->filename,
00473                             s->decl->lineno, s->decl->name);
00474               declare_function(0, s->decl->name, s2->decl, f);
00475        }
00476 }
00477 
00478 inline static void method_func_decl(FILE *f, Class c, int lines)
00479 {
00480        Section s;
00481 
00482        fprintf(f, "static void _resolve_inheritance(\n");
00483        fprintf(f, "#if NeedFunctionPrototypes\n");
00484        fprintf(f, "WidgetClass\n");
00485        fprintf(f, "#endif\n");
00486        fprintf(f, ");\n");
00487        for (s = c->methods; s; s = s->next) {
00488               if (s->decl && s->decl->tp == Proc) {
00489                      lined(s->decl->lineno, c->filename);
00490                      declare_method(f, c, s);
00491               }
00492        }
00493 }
00494 
00495 /* The work of initializing the class record is done by a recursive
00496  * procedure. The WidgetClass identifier is defined at the end of the
00497  * structure.
00498  */
00499 
00500 static void init_class_parts(FILE *f, Class self, Class part);
00501 
00502 inline static void class_record_instantation(FILE *f, Class c)
00503 {
00504        STRING instname;
00505 
00506        instname = get_instname(c->name);
00507        fprintf(f, "\n%sClassRec %sClassRec = {\n",
00508               get(c->name), get(instname));
00509        init_class_parts(f, c, c);
00510        fprintf(f, "};\n");
00511        fprintf(f,
00512               "WidgetClass %sWidgetClass = (WidgetClass) &%sClassRec;\n",
00513               get(instname), get(instname));
00514 }
00515 
00516 
00517 static void initialize_core_class_part(FILE *f, Class self, Class part)
00518 {
00519        char *p, *q;
00520        int nd;
00521 
00522        fprintf(f, "{ /* core_class part */\n");
00523        q = get(self->superclass);
00524        p = strrchr(q, '/');
00525        if (p)
00526               fprintf(f,
00527                      "/* superclass   \t*/  (WidgetClass) &%sClassRec,\n",
00528                      get(get_instname(hash(p + 1))));
00529        else
00530               fprintf(f,
00531                      "/* superclass   \t*/  (WidgetClass) &%sClassRec,\n",
00532                      get(get_instname(self->superclass)));
00533        fprintf(f, "/* class_name   \t*/  \"%s\",\n", get(self->name));
00534        fprintf(f, "/* widget_size  \t*/  sizeof(%sRec),\n", get(self->name));
00535        fprintf(f, "/* class_initialize \t*/  %s,\n",
00536               has_method(self, CLASS_INITIALIZE)
00537               ? "class_initialize" : "NULL");
00538        fprintf(f, "/* class_part_initialize*/  %s,\n",
00539               has_method(self, CLASS_PART_INITIALIZE)
00540               ? "class_part_initialize" : "_resolve_inheritance");
00541        fprintf(f, "/* class_inited \t*/  FALSE,\n");
00542        fprintf(f, "/* initialize   \t*/  %s,\n",
00543               has_method(self, INITIALIZE) ? "initialize" : "NULL");
00544        fprintf(f, "/* initialize_hook \t*/  %s,\n",
00545               has_method(self, INITIALIZE_HOOK) ? "initialize_hook" : "NULL");
00546        fprintf(f, "/* realize      \t*/  %s,\n",
00547               has_method(self, REALIZE) ? "realize" : "XtInheritRealize");
00548 
00549        nd = number_of_decls(self->actions);
00550        if (nd)
00551               fprintf(f, "/* actions      \t*/  actionsList,\n");
00552        else
00553                fprintf(f, "/* actions      \t*/  NULL,\n");
00554        fprintf(f, "/* num_actions  \t*/  %d,\n", nd);
00555 
00556        nd = number_of_decls(self->publicvars);
00557        if (nd)
00558               fprintf(f, "/* resources    \t*/  resources,\n");
00559        else
00560               fprintf(f, "/* resources    \t*/  NULL,\n");
00561        fprintf(f, "/* num_resources \t*/  %d,\n", nd);
00562 
00563        fprintf(f, "/* xrm_class    \t*/  NULLQUARK,\n");
00564        fprintf(f, "/* compres_motion \t*/  %s,\n",
00565               get(find_classvar_value(self, COMPRESS_MOTION)));
00566        fprintf(f, "/* compress_exposure \t*/  %s,\n",
00567               get(find_classvar_value(self, COMPRESS_EXPOSURE)));
00568        fprintf(f, "/* compress_enterleave \t*/  %s,\n",
00569               get(find_classvar_value(self, COMPRESS_ENTERLEAVE)));
00570        fprintf(f, "/* visible_interest \t*/  %s,\n",
00571               get(find_classvar_value(self, VISIBLE_INTEREST)));
00572        fprintf(f, "/* destroy      \t*/  %s,\n",
00573               has_method(self, DESTROY) ? "destroy" : "NULL");
00574        fprintf(f, "/* resize       \t*/  %s,\n",
00575               has_method(self, RESIZE) ? "resize" : "XtInheritResize");
00576        fprintf(f, "/* expose       \t*/  %s,\n",
00577               has_method(self, EXPOSE) ? "expose" : "XtInheritExpose");
00578        fprintf(f, "/* set_values   \t*/  %s,\n",
00579               has_method(self, SET_VALUES) ? "set_values" : "NULL");
00580        fprintf(f, "/* set_values_hook \t*/  %s,\n",
00581               has_method(self, SET_VALUES_HOOK) ? "set_values_hook" : "NULL");
00582        fprintf(f, "/* set_values_almost \t*/  %s,\n",
00583               has_method(self, SET_VALUES_ALMOST) ?
00584               "set_values_almost" : "XtInheritSetValuesAlmost");
00585        fprintf(f, "/* get_values+hook \t*/  %s,\n",
00586               has_method(self, GET_VALUES_HOOK) ? "get_values_hook" : "NULL");
00587        fprintf(f, "/* accept_focus \t*/  %s,\n",
00588               has_method(self, ACCEPT_FOCUS)
00589               ? "accept_focus" : "XtInheritAcceptFocus");
00590        fprintf(f, "/* version      \t*/  XtVersion,\n");
00591        fprintf(f, "/* callback_private \t*/  NULL,\n");
00592 
00593        if (number_of_decls(self->translations))
00594               fprintf(f, "/* tm_table      \t*/  defaultTranslations,\n");
00595        else
00596               fputs("/* tm_table      \t*/  NULL,\n", f);
00597 
00598        fprintf(f, "/* query_geometry \t*/  %s,\n",
00599               has_method(self, QUERY_GEOMETRY) ?
00600               "query_geometry" : "XtInheritQueryGeometry");
00601        fprintf(f, "/* display_acceleator \t*/  %s,\n",
00602               has_method(self, DISPLAY_ACCELERATOR) ?
00603               "display_accelerator" : "XtInheritDisplayAccelerator");
00604        fprintf(f, "/* extension    \t*/  %s\n",
00605               get(find_classvar_value(self, EXTENSION)));
00606        fprintf(f, "},\n");
00607 }
00608 
00609 inline static void initialize_object_class_part(FILE *f, Class self, Class part)
00610 {
00611        int nd;
00612 
00613        fprintf(f, "{ /* object class part */\n");
00614        fprintf(f, "(WidgetClass) &%sClassRec,\n",
00615               get(get_instname(self->superclass)));
00616        fprintf(f, "\"%s\",\n", get(self->name));
00617        fprintf(f, "sizeof(%sRec),\n", get(self->name));
00618        fprintf(f, "%s,\n", has_method(self, CLASS_INITIALIZE) ?
00619               "class_initialize" : "NULL");
00620        fprintf(f, "%s,\n", has_method(self, CLASS_PART_INITIALIZE) ?
00621               "class_part_initialize" : "_resolve_inheritance");
00622        fprintf(f, "FALSE,\n");
00623        fprintf(f, "%s,\n", has_method(self, INITIALIZE) ?
00624               "initialize" : "NULL");
00625        fprintf(f, "%s,\n", has_method(self, INITIALIZE_HOOK) ?
00626               "initialize_hook" : "NULL");
00627        fprintf(f, "NULL,\n"); /* obj1 <- `realize' */
00628        fprintf(f, "NULL,\n"); /* obj2 <- `actions' */
00629        fprintf(f, "0,\n"); /* obj3 <- `num_actions' */
00630 
00631        nd = number_of_decls(self->publicvars);
00632        if (nd == 0)
00633               fprintf(f, "NULL,\n");
00634        else
00635               fprintf(f, "resources,\n");
00636        fprintf(f, "%d,\n", nd);
00637 
00638        fprintf(f, "NULLQUARK,\n");
00639        fprintf(f, "False,\n"); /* obj4 <- `compress_motion' */
00640        fprintf(f, "False,\n"); /* obj5 <- `compress_exposure' */
00641        fprintf(f, "False,\n"); /* obj6 <- `compress_enterleave' */
00642        fprintf(f, "False,\n"); /* obj7 <- `visible_interest' */
00643        fprintf(f, "%s,\n", has_method(self, DESTROY) ? "destroy" : "NULL");
00644        fprintf(f, "NULL,\n"); /* obj8 <- `resize' */
00645        fprintf(f, "NULL,\n"); /* obj9 <- `expose' */
00646        fprintf(f, "%s,\n",
00647               has_method(self, SET_VALUES) ? "set_values" : "NULL");
00648        fprintf(f, "%s,\n",
00649               has_method(self, SET_VALUES_HOOK) ? "set_values_hook" : "NULL");
00650        fprintf(f, "NULL,\n"); /* obj10 <- `set_values_almost' */
00651        fprintf(f, "%s,\n",
00652               has_method(self, GET_VALUES_HOOK) ? "get_values_hook" : "NULL");
00653        fprintf(f, "NULL,\n"); /* obj11 <- `accept_focus' */
00654        fprintf(f, "XtVersion,\n");
00655        fprintf(f, "NULL,\n");
00656        fprintf(f, "NULL,\n"); /* obj12 <- `tm_table' */
00657        fprintf(f, "NULL,\n"); /* obj13 <- `query_geometry' */
00658        fprintf(f, "NULL,\n"); /* obj14 <- `display_accelerator' */
00659        fprintf(f, "%s\n", get(find_classvar_value(self, EXTENSION)));
00660        fprintf(f, "},\n");
00661 }
00662 
00663 inline static void initialize_rectobj_class_part(FILE *f, Class self,
00664        Class part)
00665 {
00666        int nd;
00667 
00668        fprintf(f, "{ /* rectobj class part */\n");
00669        fprintf(f, "(WidgetClass) &%sClassRec,\n",
00670               get(get_instname(self->superclass)));
00671        fprintf(f, "\"%s\",\n", get(self->name));
00672        fprintf(f, "sizeof(%sRec),\n", get(self->name));
00673        fprintf(f, "%s,\n", has_method(self, CLASS_INITIALIZE) ?
00674               "class_initialize" : "NULL");
00675        fprintf(f, "%s,\n", has_method(self, CLASS_PART_INITIALIZE) ?
00676               "class_part_initialize" : "_resolve_inheritance");
00677        fprintf(f, "FALSE,\n");
00678        fprintf(f, "%s,\n", has_method(self, INITIALIZE) ?
00679               "initialize" : "NULL");
00680        fprintf(f, "%s,\n", has_method(self, INITIALIZE_HOOK) ?
00681               "initialize_hook" : "NULL");
00682        fprintf(f, "NULL,\n"); /* rect1 <- `realize' */
00683        fprintf(f, "NULL,\n"); /* rect2 <- `actions' */
00684        fprintf(f, "0,\n"); /* rect3 <- `num_actions' */
00685 
00686        nd = number_of_decls(self->publicvars);
00687        if (nd)
00688               fprintf(f, "resources,\n");
00689        else
00690               fprintf(f, "NULL,\n");
00691        fprintf(f, "%d,\n", nd);
00692 
00693        fprintf(f, "NULLQUARK,\n");
00694        fprintf(f, "False,\n"); /* rect4 <- `compress_motion' */
00695        fprintf(f, "False,\n"); /* rect5 <- `compress_exposure' */
00696        fprintf(f, "False,\n"); /* rect6 <- `compress_enterleave' */
00697        fprintf(f, "False,\n"); /* rect7 <- `visible_interest' */
00698        fprintf(f, "%s,\n",
00699        has_method(self, DESTROY) ? "destroy" : "NULL");
00700        fprintf(f, "%s,\n",
00701        has_method(self, RESIZE) ? "resize" : "XtInheritResize");
00702        fprintf(f, "%s,\n",
00703               has_method(self, EXPOSE) ? "expose" : "XtInheritExpose");
00704        fprintf(f, "%s,\n",
00705               has_method(self, SET_VALUES) ? "set_values" : "NULL");
00706        fprintf(f, "%s,\n",
00707               has_method(self, SET_VALUES_HOOK) ? "set_values_hook" : "NULL");
00708        fprintf(f, "%s,\n", has_method(self, SET_VALUES_ALMOST) ?
00709               "set_values_almost" : "XtInheritSetValuesAlmost");
00710        fprintf(f, "%s,\n",
00711               has_method(self, GET_VALUES_HOOK) ? "get_values_hook" : "NULL");
00712        fprintf(f, "NULL,\n"); /* rect9 <- `accept_focus' */
00713        fprintf(f, "XtVersion,\n");
00714        fprintf(f, "NULL,\n");
00715        fprintf(f, "NULL,\n"); /* rect10 <- `tm_table' */
00716        fprintf(f, "%s,\n", has_method(self, QUERY_GEOMETRY) ?
00717               "query_geometry" : "XtInheritQueryGeometry");
00718        fprintf(f, "NULL,\n"); /* rect11 <- `display_accelerator' */
00719        fprintf(f, "%s\n", get(find_classvar_value(self, EXTENSION)));
00720        fprintf(f, "},\n");
00721 }
00722 
00723 static void initialize_composite_class_part(FILE *f, Class self, Class part)
00724 {
00725        initialize_core_class_part(f, self, part);
00726 
00727        fprintf(f, "{ /* composite_class part */\n");
00728        fprintf(f, "%s,\n", has_method(self, GEOMETRY_MANAGER) ?
00729               "geometry_manager" : "XtInheritGeometryManager");
00730        fprintf(f, "%s,\n", has_method(self, CHANGE_MANAGED) ?
00731               "change_managed" : "XtInheritChangeManaged");
00732        fprintf(f, "%s,\n", has_method(self, INSERT_CHILD) ?
00733               "insert_child" : "XtInheritInsertChild");
00734        fprintf(f, "%s,\n", has_method(self, DELETE_CHILD) ?
00735               "delete_child" : "XtInheritDeleteChild");
00736        fprintf(f, "NULL\n");
00737        fprintf(f, "},\n");
00738 }
00739 
00740 static void initialize_constraint_class_part(FILE *f, Class self, Class part)
00741 {
00742        int nd;
00743 
00744        initialize_composite_class_part(f, self, part);
00745 
00746        fprintf(f, "{ /* constraint_class part */\n");
00747 
00748        nd = number_of_decls(self->constraints);
00749        fprintf(f, "/* constraint_resources     */  %s,\n",
00750               nd == 0 ? "NULL" : "constraint_resources");
00751        fprintf(f, "/* num_constraint_resources */  %d,\n", nd);
00752 
00753        fprintf(f,"/* constraint_size          */  sizeof(%sConstraintRec),\n",
00754               get(self->name));
00755        fprintf(f, "/* constraint_initialize    */  %s,\n",
00756               has_method(self, CONSTRAINT_INITIALIZE) ?
00757               "constraint_initialize" : "NULL");
00758        fprintf(f, "/* constraint_destroy       */  %s,\n",
00759               has_method(self, CONSTRAINT_DESTROY) ?
00760               "constraint_destroy" : "NULL");
00761        fprintf(f, "/* constraint_set_values    */  %s,\n",
00762               has_method(self, CONSTRAINT_SET_VALUES) ?
00763               "constraint_set_values" : "NULL");
00764        fprintf(f, "/* constraint_extension     */  %s\n",
00765               get(find_classvar_value(self, CONSTRAINT_EXTENSION)));
00766        fprintf(f, "},\n");
00767 }
00768 
00769 inline static void initialize_xmprimitive_class_part(FILE *f, Class self,
00770        Class part)
00771 {
00772        initialize_core_class_part(f, self, part);
00773 
00774        fprintf(f, "{ /* XmPrimitive class part */\n");
00775        fprintf(f, "%s,\t/* border_highlight */\n",
00776               has_method(self, BORDER_HIGHLIGHT) ?
00777               "border_highlight" : "XmInheritBorderHighlight");
00778        fprintf(f, "%s,\t/* border_unhighlight */\n",
00779               has_method(self, BORDER_UNHIGHLIGHT) ?
00780               "border_unhighlight" : "XmInheritBorderUnhighlight");
00781        fprintf(f, "%s,\t/* translations */\n",
00782               get(find_classvar_value(self, TRANSLATIONS)));
00783        fprintf(f, "%s,\t/* arm_and_activate */\n",
00784               has_method(self, ARM_AND_ACTIVATE) ?
00785               "arm_and_activate" : "XmInheritArmAndActivate");
00786        fprintf(f, "%s,\t/* syn_resources */\n",
00787               get(find_classvar_value(self, SYN_RESOURCES)));
00788        fprintf(f, "%s,\t/* num_syn_resources */\n",
00789               get(find_classvar_value(self, NUM_SYN_RESOURCES)));
00790        fprintf(f, "#define primitive_extension extension\n");
00791        fprintf(f, "%s,\t/* primitive_extension */\n",
00792               get(find_classvar_value(self, PRIMITIVE_EXTENSION)));
00793        fprintf(f, "},\n");
00794 }
00795 
00796 inline static void initialize_xmmanager_class_part(FILE *f, Class self,
00797        Class part)
00798 {
00799        initialize_constraint_class_part(f, self, part);
00800 
00801        fprintf(f, "{ /* XmManager class part */\n");
00802        fprintf(f, "#define manager_extension extension\n");
00803        fprintf(f, "/* translations                 */  %s,\n",
00804               get(find_classvar_value(self, TRANSLATIONS)));
00805        fprintf(f, "/* syn_resources                */  %s,\n",
00806               get(find_classvar_value(self, SYN_RESOURCES)));
00807        fprintf(f, "/* num_syn_resources            */  %s,\n",
00808               get(find_classvar_value(self, NUM_SYN_RESOURCES)));
00809        fprintf(f, "/* syn_constraint_resources     */  %s,\n",
00810               get(find_classvar_value(self, SYN_CONSTRAINT_RESOURCES)));
00811        fprintf(f, "/* num_syn_constraint_resources */  %s,\n",
00812               get(find_classvar_value(self, NUM_SYN_CONSTRAINT_RESOURCES)));
00813        fprintf(f, "/* parent_process               */  %s,\n",
00814               has_method(self, PARENT_PROCESS) ?
00815               "parent_process" : "XmInheritParentProcess");
00816        fprintf(f, "/* manager_extension            */  %s,\n",
00817               get(find_classvar_value(self, MANAGER_EXTENSION)));
00818        fprintf(f, "},\n");
00819 }
00820 
00821 
00822 /* Since the intrinsic classes do not conform to the layout as used by
00823  * this widget builder (i.e., methods first, then class variables) they
00824  * are treated separately. The intrinsic classes handled here are Core,
00825  * RectObj, Composite and Shell.
00826  */
00827 
00828 static void init_class_parts(FILE *f, Class self, Class part)
00829 {
00830        int n;
00831        Section s;
00832        STRING h;
00833 
00834        if (part->superclass == CORE) {
00835               initialize_core_class_part(f, self, part);
00836        } else if (part->superclass == OBJECT) {
00837               initialize_object_class_part(f, self, part);
00838        } else if (part->superclass == RECTOBJ) {
00839               initialize_rectobj_class_part(f, self, part);
00840        } else if (part->superclass == COMPOSITE) {
00841               initialize_composite_class_part(f, self, part);
00842        } else if (part->superclass == CONSTRAINT) {
00843               initialize_constraint_class_part(f, self, part);
00844        } else if (part->superclass == PRIMITIVE
00845                      || part->superclass==XMPRIMITIVE) {
00846               initialize_xmprimitive_class_part(f, self, part);
00847        } else if (part->superclass == MANAGER
00848                      || part->superclass == XMMANAGER) {
00849               initialize_xmmanager_class_part(f, self, part);
00850        } else if (! part->super) {
00851               fprintf(stderr, _("superclass %s not found\n"),
00852                      get(part->superclass));
00853               nerrors++;
00854        } else {
00855               init_class_parts(f, self, part->super); /* Recursively */
00856        }
00857        fprintf(f, "{ /* %s_class part */\n", get(part->name));
00858        n = 0;
00859        for (s = part->methods; s; s = s->next) {
00860               if (s->decl && s->decl->tp == Proc
00861                      && find_method_class(part, s->decl->name) == part) {
00862                      if (has_method(self, s->decl->name))
00863                             fprintf(f, "%s,\n", get(s->decl->name));
00864                      else
00865                             fprintf(f, "XtInherit_%s,\n",
00866                                    get(s->decl->name));
00867                      n++;
00868               }
00869        }
00870        for (s = part->classvars; s; s = s->next) {
00871               if (s->decl && s->decl->tp == Var
00872                      && find_classvar_class(part, s->decl->name) == part) {
00873                      h = find_classvar_value(self, s->decl->name);
00874                      fprintf(f, "/* %s */  %s,\n", get(s->decl->name),
00875                             get(h));
00876                      n++;
00877               }
00878        }
00879        if (n == 0)
00880               fprintf(f, " /* dummy */  0\n");
00881        fprintf(f, "},\n");
00882 }
00883 
00884 /* The local functions are also declared with a function prototype
00885  * before they are defined, because they may be mutually recursive.
00886  */
00887 inline static void define_utility_type(FILE *f, Section s)
00888 {
00889        fprintf(f, "typedef %s %s;\n", get(s->decl->type), get(s->decl->name));
00890 }
00891 
00892 
00893 inline static void define_utility_var(FILE *f, Section s)
00894 {
00895        fprintf(f, "static %s %s", get(s->decl->type), get(s->decl->name));
00896        if (s->decl->suffix)
00897               /* An array? */
00898               fputS(s->decl->suffix, f);
00899        if (s->decl->value)
00900               fprintf(f, " = %s", get(s->decl->value));
00901        fputs(";\n", f);
00902 }
00903 
00904 inline static void generate_local_functions(FILE *f, Class c, int lines)
00905 {
00906        Section s;
00907 
00908        for (s = c->utilities; s; s = s->next) {
00909               if (s->decl) {
00910                      lined(s->decl->lineno, c->filename);
00911                      switch (s->decl->tp) {
00912                             case Proc:
00913                                    declare_function(0, s->decl->name,
00914                                           s->decl, f);
00915                                    break;
00916                             case Var:
00917                                    define_utility_var(f, s);
00918                                    break;
00919                             case Type:
00920                                    define_utility_type(f, s);
00921                                    break;
00922                             case Def:
00923                                    define_macro(f, s->decl, c);
00924                                    break;
00925                             /* In the continuing fight to make
00926                              * gcc -Wall be quiet, we have the following:
00927                              */
00928                             case Undefined: break;
00929                             case Incl: break;
00930                             case Trans: break;
00931                      }
00932               }
00933        }
00934        for (s = c->utilities; s; s = s->next) {
00935               if (s->decl && s->decl->tp == Proc) {
00936                      lined(s->decl->lineno, c->filename);
00937                      define_function(0, lines, s->decl, s->decl->body,
00938                      c, f, s->decl->lineno);
00939               }
00940        }
00941 }
00942 
00943 
00944 
00945 
00946 static void generate_action_function_defs(FILE *f, Class c, int lines)
00947 {
00948        Section s;
00949 
00950        for (s = c->actions; s; s = s->next) {
00951               if (s->decl && s->decl->tp == Proc) {
00952                      fputs("/*ARGSUSED*/\n", f);
00953                      lined(s->decl->lineno, c->filename);
00954                      fprintf(f,
00955                             "static void %s(self,event,params,num_params)",
00956                             get(s->decl->name));
00957                      fprintf(f,
00958                             "Widget self;XEvent*event;String*params;"
00959                             "Cardinal*num_params;\n");
00960                      print_body(f, s->decl->body, c, s->decl->name,
00961                             s->decl->lineno, 0);
00962                      putc('\n', f);
00963               }
00964        }
00965 }
00966 
00967 /* The |_resolve_inheritance| method contains two lines for each method
00968  * that is new in this class. The lines contain code that check for the
00969  * constant |XtInherit|-something and put the method from the superclass
00970  * in its place. The routine returns immediately when the |class| is
00971  * |c| itself, since a class doesn't inherit from itself.
00972  *
00973  * When the class is a subclass of Composite, the extension record that
00974  * tells Composite to accept gadgets as children is automatically added.
00975  * This means that the X Toolkit will not be able to issue a warning when
00976  * gadgets are added as children to a composite widget that can't handle
00977  * them. But on the other hand, having to specify explicitly whether a
00978  * widget accepts gadgets is a nuisance, and it doesn't even guarantee
00979  * that the widget will accept a particular type of gadget.
00980  */
00981 
00982 
00983 inline static void generate_resolve_inheritance_defs(FILE *f, Class c)
00984 {
00985        STRING instname;
00986        Section s;
00987 
00988        instname = get_instname(c->name);
00989 
00990        fprintf(f, "static void _resolve_inheritance(class)\n");
00991        fprintf(f, "WidgetClass class;\n");
00992        fprintf(f, "{\n");
00993        fprintf(f, "  %sWidgetClass c = (%sWidgetClass) class;\n",
00994               get(c->name), get(c->name));
00995        fprintf(f, "  %sWidgetClass super;\n", get(c->name));
00996        if (find_superclass(c, COMPOSITE)) {
00997               fprintf(f, "  static CompositeClassExtensionRec "
00998               "extension_rec = {\n");
00999               fprintf(f,
01000                      "    NULL, NULLQUARK, XtCompositeExtensionVersion,\n");
01001               fprintf(f, "    sizeof(CompositeClassExtensionRec), True};\n");
01002               fprintf(f, "  CompositeClassExtensionRec *ext;\n");
01003               fprintf(f, "  ext = (XtPointer)XtMalloc(sizeof(*ext));\n");
01004               fprintf(f, "  *ext = extension_rec;\n");
01005               fprintf(f, "  ext->next_extension = "
01006                      "c->composite_class.extension;\n");
01007               fprintf(f, "  c->composite_class.extension = ext;\n");
01008        }
01009        fprintf(f, "  if (class == %sWidgetClass) return;\n", get(instname));
01010        fprintf(f, "  super = (%sWidgetClass)class->core_class.superclass;\n",
01011               get(c->name));
01012        for (s = c->methods; s; s = s->next) {
01013               if (s->decl && s->decl->tp == Proc
01014                      && find_method_class(c, s->decl->name) == c) {
01015                      fprintf(f, "  if (c->%s_class.%s == XtInherit_%s)\n",
01016                             get(instname), get(s->decl->name),
01017                             get(s->decl->name));
01018                      fprintf(f,
01019                             "    c->%s_class.%s = super->%s_class.%s;\n",
01020                             get(instname), get(s->decl->name),
01021                             get(instname), get(s->decl->name));
01022               }
01023        }
01024        fprintf(f, "}\n");
01025 }
01026 
01027 
01028 /* The |insert_child|, |delete_child| and |geometry_manager| methods
01029  * are treated specially, because we want to ensure that there is a
01030  * `self' declared in them, even though their only parameter is |child|.
01031  * Directly after the opening brace we insert the line |Widget self =
01032  * XtParent(child);|.
01033  */
01034 
01035 inline static void generate_method_synthetic_self(FILE *f, Class c,
01036        Section s, Section s2, int lines)
01037 {
01038        define_header(0, s2->decl, f, lines, s2->decl->lineno, c->filename);
01039        fprintf(f, "{ Widget self = XtParent(%s); ",
01040               get(s2->decl->params->name));
01041        print_body(f, s->decl->body, c, s2->decl->name, s->decl->lineno, 0);
01042        fputs("}\n", f);
01043 }
01044 
01045 inline static void generate_method_def(FILE *f, Class c, Section s, int lines)
01046 {
01047        Section s2;
01048 
01049        s2 = find_method(c, s->decl->name);
01050        if (find_superclass(c, COMPOSITE) && s->decl->name == INSERT_CHILD) {
01051               generate_method_synthetic_self(f, c, s, s2, lines);
01052        } else if (find_superclass(c, COMPOSITE)
01053                      && s->decl->name == DELETE_CHILD) {
01054               generate_method_synthetic_self(f, c, s, s2, lines);
01055        } else if (find_superclass(c, COMPOSITE)
01056                      && s->decl->name == GEOMETRY_MANAGER) {
01057               generate_method_synthetic_self(f, c, s, s2, lines);
01058        } else {
01059               define_function(0, lines, s2->decl, s->decl->body, c, f,
01060                      s->decl->lineno);
01061        }
01062 }
01063 
01064 inline static void generate_method_function_defs(FILE *f, Class c, int lines)
01065 {
01066        Section s;
01067 
01068        generate_resolve_inheritance_defs(f, c);
01069        for (s = c->methods; s; s = s->next) {
01070               if (s->decl && s->decl->tp == Proc) {
01071                      lined(s->decl->lineno, c->filename);
01072                      generate_method_def(f, c, s, lines);
01073               } else if (s->decl && s->decl->tp == Def) {
01074                      define_macro(f, s->decl, c);
01075               }
01076        }
01077 }
01078 
01079 /* If the exported variable is not initialized, there is no need to
01080  * define it again, since the declaration is already put in the public
01081  * header file.
01082  */
01083 
01084 inline static void define_exported_variable(FILE *f, Class c,
01085        Section s, int lines)
01086 {
01087        if (s->decl->value) {
01088               lined(s->decl->lineno, c->filename);
01089               fprintf(f, "%s %s%s = %s;\n",
01090                      get(s->decl->type), get(s->decl->name),
01091                      get(s->decl->suffix), get(s->decl->value));
01092        }
01093 }
01094 
01095 inline static void generate_exported_function_defs(FILE *f, Class c, int lines)
01096 {
01097        Section s;
01098 
01099        for (s = c->exports; s; s = s->next) {
01100               if (s->decl) {
01101                      lined(s->decl->lineno, c->filename);
01102                      switch (s->decl->tp) {
01103                             case Proc:
01104                                    define_function(1, lines, s->decl,
01105                                           s->decl->body, c, f,
01106                                           s->decl->lineno);
01107                                    break;
01108                             case Var:
01109                                    define_exported_variable(f, c, s,
01110                                           lines);
01111                                    break;
01112                             case Undefined: break;
01113                             case Trans: break;
01114                             case Type: break;
01115                             case Def: break;
01116                             case Incl: break;
01117                      }
01118               }
01119        }
01120 }
01121 
01122 void generatec(FILE *f, Class c, char *prefix, int lines)
01123 {
01124        wbuild_comment(f);
01125        generate_imports(f, c, prefix, lines);
01126        action_func_decl(f, c, lines);
01127        action_table_trans(f, c);
01128        method_func_decl(f, c, lines);
01129        generate_local_functions(f, c, lines);
01130        res_list(f, c, lines);
01131        generate_constraint_res_list(f, c, lines);
01132        class_record_instantation(f, c);
01133        generate_action_function_defs(f, c, lines);
01134        generate_method_function_defs(f, c, lines);
01135        generate_exported_function_defs(f, c, lines);
01136 }