/* Emit #defines to stdout (this will be redirected to generate target-hook-def.h) which set target hooks initializer macros to their default values. These should only be emitted for hooks whose type is given by DOCNAME. */ static void emit_init_macros (const char *docname) { int i; const int MAX_NEST = 2; int print_nest, nest = 0; for (print_nest = 0; print_nest <= MAX_NEST; print_nest++) { for (i = 0; i < (int) (sizeof hook_array / sizeof hook_array[0]); i++) { char *name = upstrdup (hook_array[i].name); if (strcmp (hook_array[i].docname, docname) != 0) continue; if (!hook_array[i].type) { if (*name) { if (nest && nest == print_nest) printf (" %s, \\\n", name); nest++; if (nest > MAX_NEST) fatal ("Unexpected nesting of %s\n", name); if (nest == print_nest) printf ("\n#define %s \\\n { \\\n", name); } else { if (nest == print_nest) printf (" }\n"); nest--; } continue; } if (0 == print_nest) { /* Output default definitions of target hooks. */ printf ("#ifndef %s\n#define %s %s\n#endif\n", name, name, hook_array[i].init); } if (nest == print_nest) printf (" %s, \\\n", name); } } }
static int sfcb_add_class(FILE * f, hashentry * he, class_entry * ce, int endianMode) { /* SFCB related */ ClClass * sfcbClass; ClClass * sfcbClassRewritten; ClProperty * sfcbProp; ClMethod * sfcbMeth; ClParameter * sfcbParam; CMPIParameter param; CMPIData data; int prop_id; int meth_id; int meth_param_id; int size; /* Symtab related */ qual_chain * quals = ce -> class_quals; prop_chain * props = ce -> class_props; method_chain * meths = ce -> class_methods; param_chain * meth_params; /* postfix processing - recursive */ if ( ce -> class_parent) { sfcb_add_class( f, he, ce -> class_parent, endianMode ); } if ( htlookup(he, upstrdup(ce -> class_id, strlen(ce -> class_id)), strlen(ce -> class_id)) == NULL ) { if (sfcb_options & BACKEND_VERBOSE) { fprintf(stderr," adding class %s \n", ce -> class_id ); } /* remember we did this class already */ htinsert(he, upstrdup(ce -> class_id, strlen(ce -> class_id)), strlen(ce -> class_id), (void *)1); sfcbClass = ClClassNew( ce -> class_id, ce -> class_parent ? ce -> class_parent -> class_id : NULL ); if (sfcbClass == NULL) { fprintf(stderr,"Error: could not create SFCB class for %s\n",ce -> class_id); return 1; } while (quals) { if (sfcb_options & BACKEND_VERBOSE) { fprintf(stderr," adding qualifier %s for class %s \n", quals -> qual_id, ce -> class_id ); } if (!skipQuals(quals)) { ClClassAddQualifier(&sfcbClass->hdr, &sfcbClass->qualifiers, quals->qual_id, make_cmpi_data(quals->qual_qual->qual_type, quals->qual_qual->qual_array, quals->qual_vals)); } quals = quals -> qual_next; } while (props) { if (sfcb_options & BACKEND_VERBOSE) { if (props->prop_attr & PROPERTY_KEY) fprintf(stderr," adding key property %s for class %s \n", props -> prop_id, ce -> class_id ); else fprintf(stderr," adding property %s for class %s \n", props -> prop_id, ce -> class_id ); } data = make_cmpi_data(props->prop_type, props->prop_array, props->prop_value); prop_id = ClClassAddProperty(sfcbClass, props->prop_id, data, data.type == CMPI_ref ? props->prop_type.type_ref->class_id : NULL); if (prop_id == 0) { fprintf(stderr,"Error: could not add SFCB class property %s for %s\n", props -> prop_id, ce -> class_id); return 1; } quals = props -> prop_quals; sfcbProp=((ClProperty*)ClObjectGetClSection(&sfcbClass->hdr,&sfcbClass->properties))+prop_id-1; while (quals) { if (!skipQuals(quals)) { if (sfcb_options & BACKEND_VERBOSE) { fprintf(stderr," adding qualifier %s for property %s in class %s\n", quals -> qual_id, props -> prop_id, ce -> class_id ); } ClClassAddPropertyQualifier(&sfcbClass->hdr, sfcbProp, quals->qual_id, make_cmpi_data(quals->qual_qual->qual_type, quals->qual_qual->qual_array, quals->qual_vals)); } quals = quals -> qual_next; } props = props -> prop_next; } while (meths) { meth_id = ClClassAddMethod(sfcbClass, meths->method_id, make_cmpi_type(meths->method_type, meths->method_array)); quals = meths->method_quals; sfcbMeth=((ClMethod*)ClObjectGetClSection(&sfcbClass->hdr,&sfcbClass->methods))+meth_id-1; while(quals) { if (!skipQuals(quals)) { ClClassAddMethodQualifier(&sfcbClass->hdr, sfcbMeth, quals->qual_id, make_cmpi_data(quals->qual_qual->qual_type, quals->qual_qual->qual_array, quals->qual_vals)); } quals = quals->qual_next; } meth_params = meths->method_params; while(meth_params && meth_params->param_id) { param.type = make_cmpi_type(meth_params->param_type, meth_params->param_array); param.arraySize = meth_params->param_array; if((param.type == CMPI_ref || param.type == CMPI_refA) && meth_params->param_type.type_ref) { param.refName = meth_params->param_type.type_ref->class_id; } else { param.refName = NULL; } meth_param_id = ClClassAddMethParameter(&sfcbClass->hdr, sfcbMeth, meth_params->param_id, param); quals = meth_params->param_quals; sfcbParam=((ClParameter*)ClObjectGetClSection(&sfcbClass->hdr,&sfcbMeth->parameters))+meth_param_id-1; while(quals) { if (!skipQuals(quals)) { ClClassAddMethParamQualifier(&sfcbClass->hdr, sfcbParam, quals->qual_id, make_cmpi_data(quals->qual_qual->qual_type, quals->qual_qual->qual_array, quals->qual_vals)); } quals = quals->qual_next; } meth_params = meth_params->param_next; } meths = meths->method_next; } sfcbClassRewritten = ClClassRebuildClass(sfcbClass,NULL); if (opt_reduced) { sfcbClassRewritten->hdr.type = HDR_IncompleteClass; } size=sfcbClassRewritten->hdr.size; if (swapMode) { void *tmp=sfcbClassRewritten; sfcbClassRewritten = swapEntryClass(sfcbClassRewritten,&size); free(tmp); } fwrite(sfcbClassRewritten,size,1,f); free(sfcbClassRewritten); } return 0; }
/* Read the documentation file with name IN_FNAME, perform substitutions to incorporate informtion from hook_array, and emit the result on stdout. Hooks defined with DEFHOOK / DEFHOOKPOD are emitted at the place of a matching @hook in the input file; if there is no matching @hook, the hook is emitted after the hook that precedes it in target.def . Usually, the emitted hook documentation starts with the hook signature, followed by the string from the doc field. The documentation is bracketed in @deftypefn / @deftypevr and a matching @end. While emitting the doc field, @Fcode is translated to @code, and an @findex entry is added to the affected paragraph. If the doc field starts with '*', the leading '*' is stripped, and the doc field is otherwise emitted unaltered; no function signature/ @deftypefn/deftypevr/@end is emitted. In particular, a doc field of "*" means not to emit any ocumentation for this target.def / hook_array entry at all (there might be documentation for this hook in the file named IN_FNAME, though). A doc field of 0 is used to append the hook signature after the previous hook's signture, so that one description can be used for a group of hooks. When the doc field is "", @deftypefn/@deftypevr and the hook signature is emitted, but not the matching @end. This allows all the free-form documentation to be placed in IN_FNAME, to work around GPL/GFDL licensing incompatibility issues. */ static void emit_documentation (const char *in_fname) { int i, j; char buf[1000]; htab_t start_hooks = htab_create (99, s_hook_hash, s_hook_eq_p, (htab_del) 0); FILE *f; bool found_start = false; /* Enter all the start hooks in start_hooks. */ f = fopen (in_fname, "r"); if (!f) { perror (""); fatal ("Couldn't open input file"); } while (fscanf (f, "%*[^@]"), buf[0] = '\0', fscanf (f, "@%5[^ \n]", buf) != EOF) { void **p; struct s_hook *shp; if (strcmp (buf, "hook") != 0) continue; buf[0] = '\0'; fscanf (f, "%999s", buf); shp = XNEW (struct s_hook); shp->name = upstrdup (buf); shp->pos = -1; p = htab_find_slot (start_hooks, shp, INSERT); if (*p != HTAB_EMPTY_ENTRY) fatal ("Duplicate placement for hook %s\n", shp->name); *(struct s_hook **) p = shp; } fclose (f); /* For each hook in hook_array, if it is a start hook, store its position. */ for (i = 0; i < (int) (sizeof hook_array / sizeof hook_array[0]); i++) { struct s_hook sh, *shp; void *p; if (!hook_array[i].doc || strcmp (hook_array[i].doc, "*") == 0) continue; sh.name = upstrdup (hook_array[i].name); p = htab_find (start_hooks, &sh); if (p) { shp = (struct s_hook *) p; if (shp->pos >= 0) fatal ("Duplicate hook %s\n", sh.name); shp->pos = i; found_start = true; } else if (!found_start) fatal ("No place specified to document hook %s\n", sh.name); free (sh.name); } /* Copy input file to stdout, substituting @hook directives with the corresponding hook documentation sequences. */ f = fopen (in_fname, "r"); if (!f) { perror (""); fatal ("Couldn't open input file"); } for (;;) { struct s_hook sh, *shp; int c = getc (f); char *name; if (c == EOF) break; if (c != '@') { putchar (c); continue; } buf[0] = '\0'; fscanf (f, "%5[^ \n]", buf); if (strcmp (buf, "hook") != 0) { printf ("@%s", buf); continue; } fscanf (f, "%999s", buf); sh.name = name = upstrdup (buf); shp = (struct s_hook *) htab_find (start_hooks, &sh); if (!shp || shp->pos < 0) fatal ("No documentation for hook %s\n", sh.name); i = shp->pos; do { const char *q, *e; const char *deftype; const char *doc, *fcode, *p_end; /* A leading '*' means to output the documentation string without further processing. */ if (*hook_array[i].doc == '*') printf ("%s", hook_array[i].doc + 1); else { if (i != shp->pos) printf ("\n\n"); emit_findices (hook_array[i].doc, name); /* Print header. Function-valued hooks have a parameter list, unlike POD-valued ones. */ deftype = hook_array[i].param ? "deftypefn" : "deftypevr"; printf ("@%s {%s} ", deftype, hook_array[i].docname); if (strchr (hook_array[i].type, ' ')) printf ("{%s}", hook_array[i].type); else printf ("%s", hook_array[i].type); printf (" %s", name); if (hook_array[i].param) { /* Print the parameter list, with the parameter names enclosed in @var{}. */ printf (" "); for (q = hook_array[i].param; (e = strpbrk (q, " *,)")); q = e + 1) /* Type names like 'int' are followed by a space, sometimes also by '*'. 'void' should appear only in "(void)". */ if (*e == ' ' || *e == '*' || *q == '(') printf ("%.*s", (int) (e - q + 1), q); else printf ("@var{%.*s}%c", (int) (e - q), q, *e); } /* POD-valued hooks sometimes come in groups with common documentation.*/ for (j = i + 1; j < (int) (sizeof hook_array / sizeof hook_array[0]) && hook_array[j].doc == 0 && hook_array[j].type; j++) { char *namex = upstrdup (hook_array[j].name); printf ("\n@%sx {%s} {%s} %s", deftype, hook_array[j].docname, hook_array[j].type, namex); } if (hook_array[i].doc[0]) { printf ("\n"); /* Print each documentation paragraph in turn. */ for (doc = hook_array[i].doc; *doc; doc = p_end) { /* Find paragraph end. */ p_end = strstr (doc, "\n\n"); p_end = (p_end ? p_end + 2 : doc + strlen (doc)); /* Print paragraph, emitting @Fcode as @code. */ for (; (fcode = strstr (doc, "@Fcode{")) && fcode < p_end; doc = fcode + 2) printf ("%.*s@", (int) (fcode - doc), doc); printf ("%.*s", (int) (p_end - doc), doc); /* Emit function indices for next paragraph. */ emit_findices (p_end, name); } printf ("\n@end %s", deftype); } } if (++i >= (int) (sizeof hook_array / sizeof hook_array[0]) || !hook_array[i].doc) break; free (name); sh.name = name = upstrdup (hook_array[i].name); } while (!htab_find (start_hooks, &sh)); free (name); } }