Back to index

plt-scheme  4.2.1
generateh.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  * global 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 #include <libit/string.h>
00032 #include <libit/ctype.h>
00033 #include <wbuild.h>
00034 #include <wsym.h>
00035 
00036 #include <libintl.h>
00037 #define _(String) gettext(String)
00038 
00039 #include <libit/malloc.h>
00040 
00041 /* Public header file. The public header file contains the |#define|s
00042  * for the resources and other exported identifiers. It is protected by a
00043  * guard.
00044  *
00045  * The public header files generated by wbuild also include the public
00046  * header file of the superclass, although this is not de rigueur for
00047  * standard widgets. The reason is that the exported things from
00048  * superclasses often stay valied for subclasses. An application that
00049  * includes only the widget that it actually uses, would have no access
00050  * to anything defined in the superclasses.
00051  */
00052 
00053 
00054 /* The Intrinsics header files are alway found in |X11|, but other
00055  * files can either be in the same directory as where the headers for
00056  * this widget should go (|prefix| from |-p| option), or in an explicitly
00057  * named directory. E.g., if the widget was declared `@@class myclass
00058  * (Foo/mysuper),' then `Foo' will be used instead of |prefix|.
00059  */
00060 
00061 inline static void public_include(FILE *f, Class c, char *prefix, char *private)
00062 {
00063        char *s, *slash;
00064 
00065        if (c->super && c->super->filenamepart)
00066               s = get(c->super->filenamepart);
00067        else
00068               s = get(c->superclass);
00069 
00070        slash = strchr(s, '/');
00071        if (slash) {
00072               fprintf(f, "#include <%s%s.h>\n", s, private);
00073        } else {
00074               fprintf(f, "#include <%s/%s%s.h>\n", prefix, s, private);
00075        }
00076 }
00077 
00078 
00079 #if 0
00080 inline static void public_include(FILE *f, Class c)
00081 {
00082        if (c->superclass == CORE)
00083               fputs("#include <X11/Core.h>\n", f);
00084        else if (c->superclass == OBJECT)
00085               fputs("#include <X11/Object.h>\n", f);
00086        else if (c->superclass == RECTOBJ)
00087               fputs("#include <X11/RectObj.h>\n", f);
00088        else if (c->superclass == COMPOSITE)
00089               fputs("#include <X11/Composite.h>\n", f);
00090        else if (c->superclass == SHELL
00091                      || c->superclass == OVERRIDESHELL
00092                      || c->superclass == WMSHELL
00093                      || c->superclass == VENDORSHELL
00094                      || c->superclass == TRANSIENTSHELL
00095                      || c->superclass == TOPLEVELSHELL
00096                      || c->superclass == APPLICATIONSHELL)
00097               fputs("#include <X11/Shell.h>\n", f);
00098        else if (c->superclass == CONSTRAINT)
00099               fputs("#include <X11/Constraint.h>\n", f);
00100        else if (c->superclass == XMPRIMITIVE || c->superclass == PRIMITIVE)
00101               /* There is no such thing as Xm/Primitive.h */ ;
00102        else if (c->superclass == XMMANAGER || c->superclass == MANAGER)
00103               /* There is no such thing as Xm/Manager.h */ ;
00104        else if (c->super) {
00105               char *p, *q = get(c->superclass);
00106               if ((p = strrchr(q, '/'))) {
00107                      *p = '\0';
00108                      fprintf(f, "#include <%s>\n",
00109                             get(get_headername(q, c->super)));
00110                      *p = '/';
00111               } else {
00112                      fprintf(f, "#include <%s>\n",
00113                             get(get_headername(prefix, c->super)));
00114               }
00115        }
00116 }
00117 #endif
00118 
00119 /* Exported things come in two flavors: functions and other things.
00120  * Functions are printed with their parameter list protected by a macro.
00121  * The function |declare_function| is defined
00122  * in~\ref{declare-function}.
00123  */
00124 
00125 inline static void declare_export_type(FILE *f, Section s)
00126 {
00127        fputs("typedef ", f);
00128        fputS(s->decl->type, f);
00129        putc(' ', f);
00130        fputS(s->decl->name, f);
00131        fputs(";\n\n", f);
00132 }
00133 
00134 
00135 static void define_macro(FILE *f, Class c, Decl d)
00136 {
00137        Decl d1;
00138 
00139        fputs("#define ", f);
00140        fputS(d->name, f);
00141        if (d->params) {
00142               putc('(', f);
00143               for (d1 = d->params; d1; d1 = d1->next) {
00144                      fputS(d1->name, f);
00145                      if (d1->next)
00146                             fputs(", ", f);
00147               }
00148               putc(')', f);
00149        }
00150        putc(' ', f);
00151        print_body(f, d->body, c, d->name, d->lineno, 1);
00152        fputs("\n\n", f);
00153 }
00154 
00155 inline static void declare_export_var(FILE *f, Section s)
00156 {
00157        fputS(s->decl->type, f);
00158        putc(' ', f);
00159        fputS(s->decl->name, f);
00160        if (s->decl->suffix)
00161               fputS(s->decl->suffix, f);
00162        fputs(";\n\n", f);
00163 }
00164 
00165 /* For each resource there are two define's, one for the instance name
00166  * (starting with \.{XtN}, and one for the class name, starting with
00167  * \.{XtC}. However, if the resource is inherited, we don't have to declare
00168  * it here.
00169  */
00170 
00171 inline static void define_resource_symbols(FILE *f, Class c)
00172 {
00173        STRING hi, hc, ht;
00174        Section s;
00175 
00176        for (s = c->publicvars; s; s = s->next) {
00177               if (s->decl == NULL || s->decl->tp != Var)
00178                      continue;
00179               if (find_instvar_class(c, s->decl->name) != c)
00180                      continue;
00181               if (s->decl->typesym) {
00182                      ht = hdup(s->decl->typesym);
00183               } else if (!s->decl->type) {
00184                      fprintf(stderr, _("%s:%d: Missing type for `%s'\n"),
00185                             get(c->filename), s->decl->lineno,
00186                             get(s->decl->name));
00187                      nerrors++;
00188                      continue;      
00189               } else {
00190                      ht = get_word(get(get_classname(s->decl->type)));
00191               }
00192               if (s->decl->namesym) {
00193                      hi = get_instname(s->decl->namesym);
00194                      hc = get_classname(s->decl->namesym);
00195               } else {
00196                      hi = get_instname(s->decl->name);
00197                      hc = get_classname(s->decl->name);
00198               }
00199               fprintf(f, "#ifndef XtN%s\n", get(hi));
00200               fprintf(f, "#define XtN%s \"%s\"\n", get(hi), get(hi));
00201               fprintf(f, "#endif\n");
00202               fprintf(f, "#ifndef XtC%s\n", get(hc));
00203               fprintf(f, "#define XtC%s \"%s\"\n", get(hc), get(hc));
00204               fprintf(f, "#endif\n");
00205               fprintf(f, "#ifndef XtR%s\n", get(ht));
00206               fprintf(f, "#define XtR%s \"%s\"\n", get(ht), get(ht));
00207               fprintf(f, "#endif\n\n");
00208               delete(hi);
00209               delete(hc);
00210               delete(ht);
00211        }
00212 }
00213 
00214 /* Constraint resources are treated the same as public variables: for
00215  * each resource there are two define's, one for the instance name
00216  * (starting with \.{XtN}, and one for the class name, starting with
00217  * \.{XtC}. However, if the resource is inherited, we don't have to
00218  * declare it here.
00219  */
00220 
00221 inline static void define_constraint_resource_symbols(FILE *f, Class c)
00222 {
00223        STRING hi, hc, ht;
00224        Section s;
00225 
00226        for (s = c->constraints; s; s = s->next) {
00227               if (s->decl == NULL || s->decl->tp != Var)
00228                      continue;
00229               if (find_constr_class(c, s->decl->name) != c)
00230                      continue;
00231               if (s->decl->typesym)
00232                      ht = hdup(s->decl->typesym);
00233               else if (!s->decl->type) {
00234                      fprintf(stderr, _("%s:%d: Missing type for `%s'\n"),
00235                             get(c->filename), s->decl->lineno,
00236                             get(s->decl->name));
00237                      nerrors++;
00238                      continue;      
00239               } else {
00240                      ht = get_word(get(get_classname(s->decl->type)));
00241               }
00242               if (s->decl->namesym) {
00243                      hi = get_instname(s->decl->namesym);
00244                      hc = get_classname(s->decl->namesym);
00245               } else {
00246                      hi = get_instname(s->decl->name);
00247                      hc = get_classname(s->decl->name);
00248               }
00249               fprintf(f, "#ifndef XtN%s\n", get(hi));
00250               fprintf(f, "#define XtN%s \"%s\"\n", get(hi), get(hi));
00251               fprintf(f, "#endif\n");
00252               fprintf(f, "#ifndef XtC%s\n", get(hc));
00253               fprintf(f, "#define XtC%s \"%s\"\n", get(hc), get(hc));
00254               fprintf(f, "#endif\n");
00255               fprintf(f, "#ifndef XtR%s\n", get(ht));
00256               fprintf(f, "#define XtR%s \"%s\"\n", get(ht), get(ht));
00257               fprintf(f, "#endif\n\n");
00258               delete(hi);
00259               delete(hc);
00260               delete(ht);
00261        }
00262 }
00263 
00264 inline static void typedef_class_instance(FILE *f, Class c)
00265 {
00266        fprintf(f, "typedef struct _%sClassRec *%sWidgetClass;\n",
00267               get(c->name), get(c->name));
00268        fprintf(f, "typedef struct _%sRec *%sWidget;\n",
00269               get(c->name), get(c->name));
00270        fprintf(f, "externalref WidgetClass %sWidgetClass;\n",
00271               get(get_instname(c->name)));
00272 }
00273 
00274 inline static void declare_exports(FILE *f, Class c)
00275 {
00276        Section s;
00277 
00278        for (s = c->exports; s; s = s->next) {
00279               if (s->decl) {
00280                      switch (s->decl->tp) {
00281                             case Var: declare_export_var(f, s); break;
00282                             case Def: define_macro(f, c, s->decl); break;
00283                             case Proc: declare_function(1, s->decl->name,
00284                                    s->decl, f); break;
00285                             case Type: declare_export_type(f, s); break;
00286                             case Incl:
00287                                    fprintf(f, "#include %s\n",
00288                                           get(s->decl->name));
00289                                    break;
00290                             case Undefined: break;
00291                             case Trans: break;
00292                      }
00293               }
00294        }
00295 }
00296 
00297 void public_header(FILE *f, Class c, char *prefix, char *guard)
00298 {
00299        wbuild_comment(f);
00300        fprintf(f, "#ifndef %s\n", guard);
00301        fprintf(f, "#define %s\n", guard);
00302        public_include(f, c, prefix, "");
00303        fputs("_XFUNCPROTOBEGIN\n", f);
00304        declare_exports(f, c);
00305        define_resource_symbols(f, c);
00306        define_constraint_resource_symbols(f, c);
00307        typedef_class_instance(f, c);
00308        fputs("_XFUNCPROTOEND\n", f);
00309        fprintf(f, "#endif /* %s */\n", guard);
00310 }
00311 
00312 /* Private header file. The private header file has an even more strict
00313  * layout than the public header file. It contains an external declaration
00314  * for the class record and four typedefs: the class part, the complete
00315  * class record, the instance part and the complete instance record.
00316  */
00317 
00318 
00319 /* The private header file needs two includes, for the private header
00320  * of the superclass (if any) and for the public header of the class
00321  * itself.
00322  */
00323 
00324 #if 0
00325 inline static generate_private_includes(FILE *f, Class c)
00326 {
00327        if (c->superclass == CORE)
00328               fputs("#include <X11/CoreP.h>\n", f);
00329        else if (c->superclass == RECTOBJ)
00330               fputs("#include <X11/RectObjP.h>\n", f);
00331        else if (c->superclass == OBJECT)
00332               fputs("#include <X11/ObjectP.h>\n", f);
00333        else if (c->superclass == COMPOSITE)
00334               fputs("#include <X11/CompositeP.h>\n", f);
00335        else if (c->superclass == SHELL
00336               || c->superclass == OVERRIDESHELL
00337               || c->superclass == WMSHELL
00338               || c->superclass == VENDORSHELL
00339               || c->superclass == TRANSIENTSHELL
00340               || c->superclass == TOPLEVELSHELL
00341               || c->superclass == APPLICATIONSHELL)
00342               fputs("#include <X11/ShellP.h>\n", f);
00343        else if (c->superclass == CONSTRAINT)
00344               fputs("#include <X11/ConstrainP.h>\n", f);
00345        else if (c->superclass == XMPRIMITIVE || c->superclass == PRIMITIVE)
00346               fputs("#include <Xm/PrimitiveP.h>\n", f);
00347        else if (c->superclass == XMMANAGER || c->superclass == MANAGER)
00348               fputs("#include <Xm/ManagerP.h>\n", f);
00349        else if (c->super) {
00350               char *p, *q = get(c->superclass);
00351               if ((p = strrchr(q, '/'))) {
00352               *p = '\0';
00353               fprintf(f, "#include <%s>\n",
00354                      get(get_headerPname(q, c->super)));
00355               *p = '/';
00356        } else {
00357               fprintf(f, "#include <%s>\n",
00358                      get(get_headerPname(prefix, c->super)));
00359        }
00360   }
00361   fprintf(f, "#include <%s>\n", get(get_headername(prefix, c)));
00362 #endif
00363 
00364 /* There may be macro definitions in the public, private, constraint
00365  * and classvar sections. These macros are collected at the start if the
00366  * private include file, because they should be available to subclasses,
00367  * but not to others.
00368  *
00369  * The macro definitions are collected by scanning throught the public,
00370  * private and class variables sections.
00371  */
00372 
00373 inline static void generate_macro_loop(FILE *f, Class c, Section s)
00374 {
00375        while (s) {
00376               if ((s->decl) && (s->decl->tp == Def))
00377                      define_macro(f, c, s->decl);
00378               s = s->next;
00379        }
00380 }
00381 
00382 inline static void generate_macro(FILE *f, Class c)
00383 {
00384        generate_macro_loop(f, c, c->classvars);
00385        generate_macro_loop(f, c, c->privatevars);
00386        generate_macro_loop(f, c, c->publicvars);
00387        generate_macro_loop(f, c, c->constraints);
00388        generate_macro_loop(f, c, c->privconstr);
00389 }
00390 
00391 /* Similarly, the type definitions are collected. But in the public
00392  * section there can be no type definitions, so only the private and
00393  * class var sections are scanned.
00394  */
00395 
00396 static inline void generate_typedefs(FILE *f, Class c)
00397 {
00398        Section s;
00399 
00400        for (s = c->classvars; s; s = s->next)
00401               if ((s->decl) && (s->decl->tp == Type))
00402                      fprintf(f, "typedef %s %s;\n",
00403                             get(s->decl->type), get(s->decl->name));
00404        for (s = c->privatevars; s; s = s->next)
00405               if ((s->decl) && (s->decl->tp == Type))
00406                      fprintf(f, "typedef %s %s;\n",
00407                             get(s->decl->type), get(s->decl->name));
00408 }
00409 
00410 /* Methods that are new in this widget have to have a symbolic constant
00411  * |XtInherit*|. Subclasses will then be able to inherit the method (simply by
00412  * not redefining it). Resolving inheritance is done by a method
00413  * |class_part_initialize| in normal widgets, but in widgets generated
00414  * with wbuild the inheritance is done automatically. However, if there
00415  * is a |class_part_initialize| method defined in the specification file,
00416  * the automatic inheritance will not be used.
00417  * (See~\ref{resolve-inheritance})
00418  *
00419  * If the name of the method started with a \$ (|class_id = DOLLAR|), it
00420  * is considered a new method, whether or not it has the same name as a
00421  * method in a superclass. If the name of the method started with
00422  * |$(class)|, it is considered an inherited method.
00423  */
00424 
00425 inline static void generate_inherit_defines(FILE *f, Class c)
00426 {
00427        Section s;
00428        Decl d1;
00429 
00430        for (s = c->methods; s; s = s->next) {
00431               if (!s->decl || s->decl->tp != Proc)
00432                      /* No decl in this section */
00433                      continue;
00434               if (s->decl->class_id && s->decl->class_id != DOLLAR) 
00435                      /* Inherited method */
00436                      continue;
00437               if (!s->decl->class_id
00438                             && find_method_class(c, s->decl->name) != c)
00439                      /* Inherited method */
00440                      continue;
00441               fprintf(f, "typedef %s (*%s_Proc)(\n",
00442                      s->decl->type ? get(s->decl->type) : "void",
00443                      get(s->decl->name));
00444               fprintf(f, "#if NeedFunctionPrototypes\n");
00445               if (s->decl->params == NULL) {
00446                      fputs("void", f);
00447               } else {
00448                      for (d1 = s->decl->params; d1; d1 = d1->next) {
00449                             if (d1->name == DOLLAR)
00450                                    fputs("Widget", f);
00451                             else
00452                                    fputS(d1->type, f);
00453                             if (d1->suffix)
00454                                    /* An array? */
00455                                    fprintf(f, " %s%s", get(d1->name),
00456                                           get(d1->suffix));
00457                             if (d1->next)
00458                                    putc(',', f);
00459                      }
00460               }
00461               fprintf(f, "\n#endif\n);\n");
00462               fprintf(f, "#define XtInherit_%s ((%s_Proc) _XtInherit)\n",
00463               get(s->decl->name), get(s->decl->name));
00464        }
00465 }
00466 
00467 /* The constraint part contains the constraint resources of the
00468  * widget. This part is only gegerated if the widget is a subclass of
00469  * Constraint.
00470  *
00471  * The macros defined in this section are simply interleaved with the
00472  * variable declarations. The C preprocessor will know how to deal with
00473  * them.
00474  *
00475  * Only fields which are new in this class are declared. The names of the
00476  * variables are searched for in superclasses first. If the name starts
00477  * with a \$, it is considered a new variable, regardless of the
00478  * existence of variables with the same name in superclasses.
00479  *
00480  * When the section has no variables, a dummy variable will be added.
00481  *
00482  * For some strange reason we print comments.  I don't know why--wbuild
00483  * output is quite unreadable.
00484  */
00485 
00486 inline static void generate_constraint_part_record(FILE *f, Class c)
00487 {
00488        int n;
00489        Section s;
00490 
00491        fprintf(f, "typedef struct {\n");
00492        n = 0;
00493        fprintf(f, "/* Constraint resources */\n");
00494        for (s = c->constraints; s; s = s->next) {
00495               if (s->decl && s->decl->tp == Var) {
00496                      if (s->decl->class_id
00497                             && s->decl->class_id != DOLLAR)
00498                             /* Inherited */
00499                             continue;
00500                      if (!s->decl->class_id
00501                             && find_constr_class(c,s->decl->name) != c)
00502                             /* Inherited */
00503                             continue;
00504                      fprintf(f, "%s %s", get(s->decl->type),
00505                             get(s->decl->name));
00506                      if (s->decl->suffix)
00507                             fputS(s->decl->suffix, f);
00508                      fputs(";\n", f);
00509                      n++;
00510               }
00511        }
00512        fprintf(f, "/* Private constraint variables */\n");
00513        for (s = c->privconstr; s; s = s->next) {
00514               if (s->decl == NULL)
00515                      continue;
00516               if (s->decl->tp == Var) {
00517                      if (s->decl->class_id && (s->decl->class_id != DOLLAR))
00518                             /* Inherited */
00519                             continue;
00520                      if (!s->decl->class_id
00521                             && find_constr_class(c,s->decl->name) != c)
00522                             /* Inherited */
00523                             continue;
00524                      fprintf(f, "%s %s", get(s->decl->type), get(s->decl->name));
00525                      if (s->decl->suffix)
00526                             fputS(s->decl->suffix, f);
00527                      fputs(";\n", f);
00528                      n++;
00529               }
00530        }
00531        if (n == 0)
00532               fprintf(f, "int dummy;\n");
00533        fprintf(f, "} %sConstraintPart;\n\n", get(c->name));
00534 }
00535 
00536 inline static void declare_super_constraint_parts(FILE *f, Class c)
00537 {
00538        if (c != NULL) {
00539               if (c->super && c->superclass != CONSTRAINT)
00540                      declare_super_constraint_parts(f, c->super);
00541               fprintf(f, "%sConstraintPart %s;\n",
00542                      get(c->name), get(get_instname(c->name)));
00543        }
00544 }
00545 
00546 inline static void generate_constraint_rec(FILE *f, Class c)
00547 {
00548        fprintf(f, "typedef struct _%sConstraintRec {\n", get(c->name));
00549        declare_super_constraint_parts(f, c);
00550        fprintf(f, "} %sConstraintRec;\n\n", get(c->name));
00551 }
00552 
00553 /* The class part structure contains the class variables that are
00554  * introduced in this widget. It also contains the new methods. If there
00555  * are no class variables or methods (|n| = 0), a dummy variable is added.
00556  *
00557  * If the name of the variable starts with |$|, it is declared without
00558  * checking for variables of the same name in superclasses. The field
00559  * |class_id| has been set to |DOLLAR| by the parser to enforce this. If
00560  * the name starts with |$(class)|, it is an inherited variable and
00561  * should not be declared here.
00562  *
00563  * There may be macro and type definitions interleaved with the class
00564  * variables. They have already been generated, so they can be skipped
00565  * here.
00566  */
00567 
00568 inline static void generate_class_part_rec(FILE *f, Class c)
00569 {
00570        int n;
00571        Section s;
00572 
00573        n = 0;
00574        fprintf(f, "\ntypedef struct {\n/* methods */\n");
00575        for (s = c->methods; s; s = s->next) {
00576               if (s->decl && (s->decl->tp == Proc)) {
00577                      if (s->decl->class_id
00578                             && s->decl->class_id != DOLLAR)
00579                             /* Inherited */
00580                             continue;
00581                      if (!s->decl->class_id
00582                             && find_method_class(c, s->decl->name) != c)
00583                             /* Inherited */
00584                             continue;
00585                      fprintf(f, "%s_Proc %s;\n",
00586                             get(s->decl->name), get(s->decl->name));
00587                      n++;
00588               }
00589        }
00590        fprintf(f, "/* class variables */\n");
00591        for (s = c->classvars; s; s = s->next) {
00592               if (s->decl && (s->decl->tp)) {
00593                      if (s->decl->class_id
00594                             && s->decl->class_id != DOLLAR)
00595                             /* Inherited */
00596                             continue;
00597                      if (!s->decl->class_id
00598                             && find_classvar_class(c,s->decl->name)!=c)
00599                             /* Inherited */
00600                             continue;
00601                      fprintf(f, "%s %s", get(s->decl->type),
00602                             get(s->decl->name));
00603                      if (s->decl->suffix)
00604                             fputS(s->decl->suffix, f);
00605                      fputs(";\n", f);
00606                      n++;
00607               }
00608        }
00609        if (n == 0)
00610               fprintf(f, "int dummy;\n");
00611        fprintf(f, "} %sClassPart;\n", get(c->name));
00612 }
00613 
00614 /* The complete class record contains fields for all of the
00615  * superclasses. It is most easily created by a recursive procedure.
00616  *
00617  * The class parts for RectObj and Object are treated specially: (1) the
00618  * field will be called |object_class|, never |rectobj_class|; (2) Object
00619  * is not `really' a superclass of RectObj, so recursion stops at
00620  * RectObj.
00621  *
00622  * The configuration file makes sure that the RectObj class structure
00623  * defines nothing that is not already in Object, even if that means that
00624  * two methods that are defined in RectObj are now (incorrectly) added to
00625  * the Object class. This works as long as nobody tries to use those
00626  * methods in an Object.
00627  */
00628 
00629 inline static void declare_superclassparts(FILE *f, Class c)
00630 {
00631        if (!c)
00632               return;
00633        if (c->name == OBJECT || c->name == RECTOBJ) {
00634               fprintf(f, "%sClassPart object_class;\n", get(c->name));
00635        } else {
00636               declare_superclassparts(f, c->super);
00637               fprintf(f, "%sClassPart %s_class;\n", get(c->name),
00638               get(get_instname(c->name)));
00639        }
00640 }
00641 
00642 inline static void generate_class_rec(FILE *f, Class c)
00643 {
00644        fprintf(f, "\ntypedef struct _%sClassRec {\n", get(c->name));
00645        declare_superclassparts(f, c);
00646        fprintf(f, "} %sClassRec;\n\n", get(c->name));
00647 }
00648 
00649 /* The instance part contains the resources and private variables of the
00650  * widget. The resources come first, as is the convention.
00651  *
00652  * The macros defined in the public and private sections are simply
00653  * interleaved with the variable declarations. The C preprocessor will
00654  * know how to deal with them.
00655  *
00656  * Only fields which are new in this class are declared. The names of the
00657  * variables are searched for in superclasses first. If the name starts
00658  * with a \$, it is considered a new variable, regardless of the
00659  * existence of variables with the same name in superclasses.
00660  *
00661  * When neither the public division nor the private division holds any
00662  * variables, a dummy variable will be added.
00663  */
00664 
00665 inline static void generate_instance_part_rec(FILE *f, Class c)
00666 {
00667        int n;
00668        Section s;
00669 
00670        fprintf(f, "typedef struct {\n");
00671        n = 0;
00672        fprintf(f, "/* resources */\n");
00673        for (s = c->publicvars; s; s = s->next) {
00674               if (s->decl && (s->decl->tp == Var)) {
00675                      if (s->decl->class_id
00676                             && s->decl->class_id != DOLLAR)
00677                             /* Inherited */
00678                             continue;
00679                      if (!s->decl->class_id
00680                             && find_instvar_class(c, s->decl->name) != c)
00681                             /* Inherited */
00682                             continue;
00683                      fprintf(f, "%s %s", get(s->decl->type),
00684                             get(s->decl->name));
00685                      if (s->decl->suffix)
00686                             fputS(s->decl->suffix, f);
00687                      fputs(";\n", f);
00688                      n++;
00689               }
00690        }
00691        fprintf(f, "/* private state */\n");
00692        for (s = c->privatevars; s; s = s->next) {
00693               if (s->decl && (s->decl->tp == Var)) {
00694                      if (s->decl->class_id
00695                             && s->decl->class_id != DOLLAR)
00696                             /* Inherited */
00697                             continue;
00698                      if (!s->decl->class_id
00699                             && find_instvar_class(c,s->decl->name) != c)
00700                             /* Inherited */
00701                             continue;
00702                      if (!s->decl->type) {
00703                             nerrors++;
00704                             fprintf(stderr,
00705                                    _("%s:%d: Missing type for `%s'\n"),
00706                                    get(c->filename), s->decl->lineno,
00707                                    get(s->decl->name));
00708                             continue;
00709                      }
00710                      fprintf(f, "%s %s", get(s->decl->type),
00711                             get(s->decl->name));
00712                      if (s->decl->suffix)
00713                             fputS(s->decl->suffix, f);
00714                      fputs(";\n", f);
00715                      n++;
00716               }
00717        }
00718        if (n == 0)
00719               fprintf(f, "int dummy;\n");
00720        fprintf(f, "} %sPart;\n\n", get(c->name));
00721 }
00722 
00723 inline static void declare_superparts(FILE *f, Class c)
00724 {
00725        if (!c)
00726               return;
00727        if (c->super)
00728               declare_superparts(f, c->super);
00729        fprintf(f, "%sPart %s;\n",
00730        get(c->name), get(get_instname(c->name)));
00731 }
00732 
00733 inline static void generate_complete_instance_part_rec(FILE *f, Class c)
00734 {
00735        fprintf(f, "typedef struct _%sRec {\n", get(c->name));
00736        declare_superparts(f, c);
00737        fprintf(f, "} %sRec;\n\n", get(c->name));
00738 }
00739 
00740 inline static void generate_extern_decl_class_rec(FILE *f, Class c)
00741 {
00742        fprintf(f, "externalref %sClassRec %sClassRec;\n\n",
00743               get(c->name), get(get_instname(c->name)));
00744 }
00745 
00746 void generate_private_header(FILE *f, Class c, char *prefix, char *guard)
00747 {
00748        wbuild_comment(f);
00749        fprintf(f, "#ifndef %s\n", guard);
00750        fprintf(f, "#define %s\n", guard);
00751        public_include(f, c, prefix, "P");
00752        fprintf(f, "#include <%s/%s.h>\n", prefix,
00753               get(c->filenamepart ? c->filenamepart : c->name));
00754        fputs("_XFUNCPROTOBEGIN\n", f);
00755        generate_macro(f, c);
00756        generate_typedefs(f, c);
00757        generate_inherit_defines(f, c);
00758        if (find_superclass(c, CONSTRAINT) != NULL) {
00759               generate_constraint_part_record(f, c);
00760               generate_constraint_rec(f, c);
00761        }
00762        generate_class_part_rec(f, c);
00763        generate_class_rec(f, c);
00764        generate_instance_part_rec(f, c);
00765        generate_complete_instance_part_rec(f, c);
00766        generate_extern_decl_class_rec(f, c);
00767        fputs("_XFUNCPROTOEND\n", f);
00768        fprintf(f, "#endif /* %s */\n", guard);
00769 }