/*----------------------------------------------------------------------*\ | Code to write HTML version of formal metadata. | | | | Peter N. Schweitzer (U.S. Geological Survey, Reston, VA 20192) | \*----------------------------------------------------------------------*/ #include #include #include #include #include #include "keyword.h" #include "item.h" #include "config.h" #include "revision.h" #include "stricmp.h" extern char *iso8859_1[]; extern void unescape_string (char *s); extern char *related_file (char *type); extern char *read_text (char *input_file); extern int valid_utf8 (unsigned char *s); /* in encoding.c */ extern int unicode_of_utf8 (char **s); /* in encoding.c */ extern unsigned char *utf8_of (unsigned char *dst, int c); /* in encoding.c */ extern char *get_character_encoding (void); /* in xml.c */ /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static struct item *parse_html (char *name) { return (NULL); } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static char html_doctype[] = ""; static char preformat_indicator = '>'; static int do_preformatting = 1; static int do_meta = 1; static int utf8_in = 0; static int utf8_out = 0; static char *empty = ""; static char *begin_tag = ""; static char *end_tag = ""; static void set_keyword_formatting (char *prefix, char *suffix) { if (prefix) begin_tag = prefix; if (suffix) end_tag = suffix; } /*----------------------------------------------------------------------*/ struct format { struct format *next; enum fgdc_keyword key; struct { char *begin_tag; char *end_tag; int obeylines; } keyword, value; int omit; }; static struct format *format = NULL; static struct format *format_of (enum fgdc_keyword key) { struct format *g; if (format == NULL) return (NULL); else for (g=format; g; g=g->next) if (g->key == key) break; return (g); } static void add_format (enum fgdc_keyword key, char *key_prefix, char *key_suffix, char *value_prefix, char *value_suffix, int obeylines, int omit) { struct format *g; if (key == Wnull) return; if (!key_prefix) key_prefix = begin_tag; if (!key_suffix) key_suffix = end_tag; if (!value_prefix) value_prefix = empty; if (!value_suffix) value_suffix = empty; if (format == NULL) if (format = (struct format *) malloc (sizeof (struct format))) { format->next = NULL; format->key = key; format->keyword.begin_tag = key_prefix; format->keyword.end_tag = key_suffix; format->value.begin_tag = value_prefix; format->value.end_tag = value_suffix; format->value.obeylines = obeylines; format->omit = omit; } else { fprintf (stderr,"Error: could not allocate space for HTML format info\n"); exit (1); } else if (g = format_of (key)) { g->keyword.begin_tag = key_prefix; g->keyword.end_tag = key_suffix; g->value.begin_tag = value_prefix; g->value.end_tag = value_suffix; g->value.obeylines = obeylines; g->omit = omit; } else { for (g=format; g->next; g=g->next); if (g->next = (struct format *) malloc (sizeof (struct format))) { g = g->next; g->next = NULL; g->key = key; g->keyword.begin_tag = key_prefix; g->keyword.end_tag = key_suffix; g->value.begin_tag = value_prefix; g->value.end_tag = value_suffix; g->value.obeylines = obeylines; g->omit = omit; } else { fprintf (stderr,"Error: could not allocate space for HTML child format\n"); exit (1); } } } static void dump_formats (void) { struct format *g; printf ("Formats:\n"); for (g=format; g; g=g->next) { printf (" Element: %s\n",text_of(g->key)); printf (" Name\n"); printf (" begin_tag (0x%08lX): %s\n",g->keyword.begin_tag,g->keyword.begin_tag); printf (" end_tag (0x%08lX): %s\n",g->keyword.end_tag,g->keyword.end_tag); printf (" Value\n"); printf (" begin_tag (0x%08lX): %s\n",g->value.begin_tag,g->value.begin_tag); printf (" end_tag (0x%08lX): %s\n",g->value.end_tag,g->value.end_tag); printf (" obeylines : %d\n",g->value.obeylines); } } static char *key_prefix_of (enum fgdc_keyword key) { struct format *g; if (g = format_of (key)) return (g->keyword.begin_tag); else return (begin_tag); } static char *key_suffix_of (enum fgdc_keyword key) { struct format *g; if (g = format_of (key)) return (g->keyword.end_tag); else return (end_tag); } static char *value_prefix_of (enum fgdc_keyword key) { struct format *g; if (g = format_of (key)) return (g->value.begin_tag); else return (empty); } static char *value_suffix_of (enum fgdc_keyword key) { struct format *g; if (g = format_of (key)) return (g->value.end_tag); else return (empty); } static int obeylines (enum fgdc_keyword key) { struct format *g; if (g = format_of (key)) return (g->value.obeylines); else return (0); } static int omit (enum fgdc_keyword key) { struct format *g; if (g = format_of (key)) return (g->omit); else return (0); } /*----------------------------------------------------------------------*/ static int do_text_translation = 1; static char *(*munge)(char *string); static char *buffer = NULL; static int buffer_length = 0; static char *as_is (char *string) { return (string); } static void clear_buffer (void) { if (buffer) *buffer = 0; else if (buffer = (char *) malloc (4096)) { memset (buffer,0,4096); buffer_length = 4096; } else { fprintf (stderr,"Error: failed to allocate 4096 bytes for html translation buffer\n"); exit (1); } } static char *add_to_buffer (char *string, int j) { int k,n; char *t; if (!string || j == 0) { t = buffer + strlen (buffer); return (t); } if (!buffer) if (buffer = (char *) malloc (4096)) { memset (buffer,0,4096); buffer_length = 4096; } else { fprintf (stderr,"Error: failed to allocate 4096 bytes for html translation buffer\n"); exit (1); } k = strlen (buffer); n = ((j < 4096) ? 4096 : j+1); if (k + j + 1 >= buffer_length) if (buffer = (char *) realloc (buffer,buffer_length+n)) { buffer_length += n; } else { fprintf (stderr,"Error: failed to reallocate %d bytes for html translation buffer\n",buffer_length + n); exit (1); } t = buffer + k; memcpy (t,string,j); t += j; *t = 0; return (t); } static void add_character (char **s) { int n; char *t = *s; char entity [16]; /* for entity references */ char bytes[8]; /* for UTF-8 encoded characters */ if (utf8_in) { n = unicode_of_utf8 (s); if (n < 128) add_to_buffer (t,1); else if (n < 256 && iso8859_1[n] != NULL) { sprintf (entity,"&%s;",iso8859_1[n]); add_to_buffer (entity,strlen (entity)); } else if (utf8_out) { utf8_of (bytes,n); add_to_buffer (bytes,strlen(bytes)); } else {} /* if no encoding, write no output */ } else { if (utf8_out) { n = *t; if (n < 256 && iso8859_1[n] != NULL) { sprintf (entity,"&%s;",iso8859_1[n]); add_to_buffer (entity,strlen (entity)); } else { utf8_of (bytes,n); add_to_buffer (bytes,strlen(bytes)); } } else { add_to_buffer (t,1); } t++; /* one byte per character, so increment the pointer */ *s = t; /* store t in address pointed to by s */ } } static char *htmlentities (char *string) { char *s,*t; clear_buffer(); if (!string) return (buffer); s = string; while (*s) { switch (*s) { case '<': add_to_buffer ("<",4); s++; break; case '>': add_to_buffer (">",4); s++; break; case '&': add_to_buffer ("&",5); s++; break; case '"': add_to_buffer (""",6); s++; break; default: add_character (&s); break; } } return (buffer); } static char *translated (char *string) { int n; char *b,*e,*s,*t; char entity [16]; char bytes[8]; /* for UTF-8 encodings */ clear_buffer(); if (!string) return (buffer); s = string; while (*s) { switch (*s) { case '<': if (e = strchr (s,'>')) { if ((b = strrchr (s,'<')) == s) { char *d = b+1; while (*d && isspace (*d)) d++; if (memicmp (d,"URL",3) == 0) { /* Start A tag with HREF attribute */ add_to_buffer (" b && isspace (*(d-1))) d--; /* Copy the URL into the tag */ add_to_buffer (b,d-b); /* Close the A tag, add an entity lt*/ /* add_to_buffer ("\"><URL:",10); */ add_to_buffer ("\">",2); /* Copy the URL into the text */ add_to_buffer (b,d-b); /* Close the URL and the anchor */ /* add_to_buffer (">",8); */ add_to_buffer ("",4); /* Point s to the end of the URL */ s = e + 1; break; } } } add_to_buffer ("<",4); s++; break; case '>': add_to_buffer (">",4); s++; break; case '&': add_to_buffer ("&",5); s++; break; case '"': add_to_buffer (""",6); s++; break; /* Intercept ftp://url and make it a live link */ case 'f': if (memcmp (s,"ftp://",6) == 0) { b = s; e = b; while (*e && !isspace(*e) && *e != '>' && *e != ')') e++; /*--------------------------------------------------*\ | If the last character is punctuation, assume | | that the punctuation is part of the context, not | | part of the URL. This works for most, but not | | all punctuation. For example, / is a reasonable | | character with which to end a URL, as is ?. | \*--------------------------------------------------*/ if (ispunct (*(e-1))) if (*(e-1) != '/' && *(e-1) != '?') e--; /* Start A tag with HREF attribute */ add_to_buffer ("",2); /* Add entity < if one is not already present */ /* if (s > string) { if (*(s-1) != '<') add_to_buffer ("<",4); } else add_to_buffer ("<",4); */ /* Copy the URL into the text */ add_to_buffer (b,e-b); /* Add entity > if one is not already present */ /* if (*e != '>') add_to_buffer (">",4); */ /* Close the URL and the anchor */ add_to_buffer ("",4); /* Point s to the end of the URL */ s = e; } else add_character (&s); break; /* Intercept http://url and make it a live link. Do likewise for https:// */ case 'h': if ((memcmp (s,"http://",7) == 0) || (memcmp (s,"https://",8) == 0)) { b = s; e = b; while (*e && !isspace(*e) && *e != '>' && *e != ')') e++; /*--------------------------------------------------*\ | If the last character is punctuation, assume | | that the punctuation is part of the context, not | | part of the URL. This works for most, but not | | all punctuation. For example, / is a reasonable | | character with which to end a URL, as is ?. | \*--------------------------------------------------*/ if (ispunct (*(e-1))) if (*(e-1) != '/' && *(e-1) != '?') e--; /* Start A tag with HREF attribute */ add_to_buffer ("",2); /* Add entity < if one is not already present */ /* if (s > string) { if (*(s-1) != '<') add_to_buffer ("<",4); } else add_to_buffer ("<",4); */ /* Copy the URL into the text */ add_to_buffer (b,e-b); /* Add entity > if one is not already present */ /* if (*e != '>') add_to_buffer (">",4); */ /* Close the URL and the anchor */ add_to_buffer ("",4); /* Point s to the end of the URL */ s = e; } else add_character (&s); break; /* Intercept mailto:address and make it a live link */ case 'm': if (memcmp (s,"mailto:",7) == 0) { b = s; e = b; while (*e && !isspace(*e) && *e != '>' && *e != ')') e++; /*--------------------------------------------------*\ | If the last character is punctuation, assume | | that the punctuation is part of the context, not | | part of the URL. This works for most, but not | | all punctuation. For example, / is a reasonable | | character with which to end a URL, as is ?. | \*--------------------------------------------------*/ if (ispunct (*(e-1))) if (*(e-1) != '/' && *(e-1) != '?') e--; /* Start A tag with HREF attribute */ add_to_buffer ("",2); /* Add entity < if one is not already present */ /* if (s > string) { if (*(s-1) != '<') add_to_buffer ("<",4); } else add_to_buffer ("<",4); */ /* Copy the URL into the text */ add_to_buffer (b,e-b); /* Add entity > if one is not already present */ /* if (*e != '>') add_to_buffer (">",4); */ /* Close the URL and the anchor */ add_to_buffer ("",4); /* Point s to the end of the URL */ s = e; } else add_character (&s); break; default: add_character (&s); break; } } return (buffer); } static char *what_to_print_for_Wblank = "
\n"; static FILE *fp = NULL; static void write_html_value (struct item *p) { struct item *q; char *s; int preformatting = 0; if (!p) return; for (q=p->child; q; q=q->next) if (q->key == Wblank) { if (do_preformatting) if (preformatting) {/* do nothing */} else fprintf (fp,"%s",what_to_print_for_Wblank); else fprintf (fp,"%s",what_to_print_for_Wblank); } else { if (s = q->d) { if (do_preformatting) if (preformatting) if (*q->d == preformat_indicator) s++; else { fprintf (fp,"\n"); preformatting = 0; } else if (*q->d == preformat_indicator) { fprintf (fp,"
\n");
							preformatting = 1;
							s++;
							}
				fprintf (fp,"%s",munge(s));
				}
			if (!preformatting)
				if (obeylines(p->key)) fprintf (fp,"
"); fprintf (fp,"\n"); } if (preformatting) fprintf (fp,"
\n"); } static void write_html_item (struct item *p) { char *s; struct item *q; if (!p) return; if (omit (p->key)) return; if (p->key != Wblank && p->key != Wunknown) fprintf (fp,"
%s%s:%s ",key_prefix_of(p->key),munge(text_of(p->key)),key_suffix_of(p->key)); if (q = p->child) { while (q) if (q->key != Wblank) break; else q = q->next; if (!q) return; if (q->key == Wunknown) { /*----------------------------------------------------------*\ | If the first child of p is Wunknown, assume that all | | other children are as well. | \*----------------------------------------------------------*/ if (p->child->next == NULL && strlen (p->child->d) < 64) { if (s = value_prefix_of(p->key)) fprintf (fp,"%s",s); fprintf (fp,"%s",munge(p->child->d)); if (s = value_suffix_of(p->key)) fprintf (fp,"%s",s); fprintf (fp,"
\n"); } else { fprintf (fp,"\n
\n"); if (s = value_prefix_of(p->key)) fprintf (fp,"%s\n",s); write_html_value (p); if (s = value_suffix_of(p->key)) fprintf (fp,"%s\n",s); fprintf (fp,"
\n"); } } else { /*----------------------------------------------------------*\ | The first child of p is a known element. Assume that | | all other children are as well. | \*----------------------------------------------------------*/ fprintf (fp,"\n
\n"); fprintf (fp,"
\n"); for (q=p->child; q; q=q->next) if (q->key == Wblank) fprintf (fp,"%s",what_to_print_for_Wblank); else if (q->key == Wunknown) { if (q->d) fprintf (fp,"%s
\n",q->d); } else write_html_item (q); fprintf (fp,"
\n"); fprintf (fp,"
\n"); } } else { /* There are no children of p */ fprintf (fp,"\n"); } } static void write_links (char *which); static void do_meta_tags (struct item *first); void write_html (char *output_file, struct item *first) { int i; struct item *p,*q; char *b,*s,*t,*title; int title_allocated = 0; void *opt,*v,*vv; time_t T; unsigned char bytes[8]; /* for UTF-8 translation */ if (first == NULL) return; /* If encoding is UTF-8, remember this for later */ if (stricmp (get_character_encoding(),"UTF-8") == 0) { utf8_in = 1; utf8_out = 1; } /*------------------------------------------------------------------*\ | Get options from config tree | \*------------------------------------------------------------------*/ if (opt = find_option (NULL,"output")) if (opt = find_option (opt,"html")) { /*----------------------------------------------------------*\ | "translate off" activates html code in text values. By | | Default such html code is rendered literally. | \*----------------------------------------------------------*/ if (v = find_option (opt,"translate")) { do_text_translation = 1; if (s = text_of_option (v)) if (stricmp (s,"off") == 0) do_text_translation = 0; } /*----------------------------------------------------------*\ | "preformat" encloses groups of lines that begin with > | | in
 tags.  Optional value is the character	|
			 | used to indicate sections that should be preformatted.	|
			 | Default is >.  Turn off with preformat off.				|
			\*----------------------------------------------------------*/

			if (v = find_option (opt,"preformat")) {
				do_preformatting = 1;
				if (s = text_of_option (v))
					if (stricmp (s,"off") == 0) do_preformatting = 0;
					else
						if (*s) preformat_indicator = *s;
				}

			/*----------------------------------------------------------*\
			 | "meta off" disables dublin-core meta elements generation |
			\*----------------------------------------------------------*/

			if (v = find_option (opt,"meta")) {
				do_meta = 1;
				if (s = text_of_option (v))
					if (stricmp (s,"off") == 0) do_meta = 0;
				}

			/*----------------------------------------------------------*\
			 | "encoding" specifies output encoding, typically used for	|
			 | UTF-8.  If not specified and UTF-8 is input, make UTF-8	|
			 | also the output encoding.								|
			\*----------------------------------------------------------*/

			if (v = find_option (opt,"encoding")) {
				if (s = text_of_option (v))
					if (stricmp (s,"utf-8") == 0) utf8_out = 1;
					else utf8_out = 0;
				}
			}

	/* Generally you want to translate characters */

	if (do_text_translation) munge = translated;
	else munge = as_is;

	if (!format) {
		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html")) {

				if (v = find_option (opt,"keyword")) {
					char *prefix = NULL;
					char *suffix = NULL;

					if (vv = find_option (v,"prefix"))
						if (s = text_of_option (vv)) prefix = s; else prefix = empty;
					if (vv = find_option (v,"suffix"))
						if (s = text_of_option (vv)) suffix = s; else suffix = empty;
					set_keyword_formatting (prefix,suffix);
					}

				if (v = find_option (opt,"blanks")) {
					char *s = text_of_option (v);
					if (*s) unescape_string (s);
					what_to_print_for_Wblank = s;
					}

				if (opt = find_option (opt,"element"))
					do {
						if (v = find_option (opt,"key")) {
							char *name = NULL;
							if (name = text_of_option (v)) {
								char *key_prefix   = NULL;
								char *key_suffix   = NULL;
								char *value_prefix = NULL;
								char *value_suffix = NULL;
								int obeylines      = 0;
								int omit           = 0;
								enum fgdc_keyword key;
								key = key_of (name);

								if (v = find_option (opt,"name")) {
									if (vv = find_option (v,"prefix"))
										if (!(key_prefix = text_of_option (vv)))
											key_prefix = empty;
									if (vv = find_option (v,"suffix"))
										if (!(key_suffix = text_of_option (vv)))
											key_suffix = empty;
									}

								if (v = find_option (opt,"value")) {
									if (vv = find_option (v,"prefix"))
										if (!(value_prefix = text_of_option (vv)))
											value_prefix = empty;
									if (vv = find_option (v,"suffix"))
										if (!(value_suffix = text_of_option (vv)))
											value_prefix = empty;
									if (vv = find_option (v,"obeylines")) obeylines = 1;
									}

								if (v = find_option (opt,"omit")) omit = 1;

								add_format (key,key_prefix,key_suffix,value_prefix,value_suffix,obeylines,omit);
								}
							}
						} while (opt = find_next_option (opt,"element"));
				}
		}

	title = output_file;
	if (p = find_key (first,WCitation))
		if (p = find_key (p,WTitle))
			if (p->child)
				if (p->child->key == Wunknown) {
					int n = 0;
					for (q=p->child; q; q=q->next)
						if (q->d) n += 1 + strlen (q->d);
					if (title = (char *) malloc (1 + n)) {
						char *s = title;
						for (q=p->child; q; q=q->next) {
							if (q->d) {
								strcpy (s,q->d);
								s += strlen (q->d);
								}
							if (q->next) *s++ = ' ';
							*s = 0;
							}
						title_allocated = 1;
						}
					else
						title = p->child->d;
					}

	if (fp = fopen (output_file,"w")) {
		fprintf (fp,"%s\n",html_doctype);
		fprintf (fp,"\n");
		fprintf (fp,"\n");

		if (utf8_out)
			fprintf (fp,"  \n");
		else
			fprintf (fp,"  \n");

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"base"))
					if (s = text_of_option (opt)) {
						fprintf (fp,"  \n",output_file);
						}

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"style_file"))
					if (s = text_of_option (opt)) {
						if (t = read_text (s)) {
							char *tt = t + strlen (t) - 1;
							fprintf (fp,"\n",s);
							for (b=t; *b; b++)
								if (*b == 0x0D) *b = ' ';
							fprintf (fp,"%s",t);
							if (*tt != '\n') fprintf (fp,"\n");
							fprintf (fp,"\n",s);
							free (t);
							}
						}

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"stylesheet"))
					do {
						char *style_type = "text/css";
						if (v = find_option (opt,"type"))
							if (s = text_of_option (v)) style_type = s;
						if (v = find_option (opt,"href"))
							if (s = text_of_option (v))
								fprintf (fp,"  \n",style_type,s);
						} while (opt = find_next_option (opt,"stylesheet"));

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"script_file"))
					if (s = text_of_option (opt)) {
						if (t = read_text (s)) {
							char *tt = t + strlen (t) - 1;
							fprintf (fp,"\n",s);
							for (b=t; *b; b++)
								if (*b == 0x0D) *b = ' ';
							fprintf (fp,"%s",t);
							if (*tt != '\n') fprintf (fp,"\n");
							fprintf (fp,"\n",s);
							free (t);
							}
						}

		/* Print the title */

		fprintf (fp,"  ");
		fprintf (fp,htmlentities(title));
		fprintf (fp,"\n");

		if (do_meta) do_meta_tags (first);

		if (s = related_file ("original"))
			fprintf (fp,"  \n",s);

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"head"))
					if (s = text_of_option (opt))
						fprintf (fp,"%s\n",s);

		fprintf (fp,"\n");
		fprintf (fp,"\n");

		/*--------------------------------------------------------------*\
		 | Output user-specified header if there is one.				|
		\*--------------------------------------------------------------*/

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (v = find_option (opt,"header")) {
					if (s = text_of_option (v))
						fprintf (fp,"%s\n",s);
					}
				else
					if (v = find_option (opt,"header_file")) {
						if (s = text_of_option (v)) {
							if (t = read_text (s)) {
								fprintf (fp,"\n",s);
								for (b=t; *b; b++)
									if (*b == 0x0D) *b = ' ';
								fprintf (fp,"%s",t);
								b = t + strlen (t) - 1;
								if (*b != '\n') fprintf (fp,"\n");
								fprintf (fp,"\n",s);
								free (t);
								}
							}
						}

		/*--------------------------------------------------------------*\
		\*--------------------------------------------------------------*/

		fprintf (fp,"

"); fprintf (fp,htmlentities(title)); fprintf (fp,"

\n"); if (title_allocated) { free (title); title = NULL; title_allocated = 0; } /*--------------------------------------------------------------*\ | Links to other formats of this metadata record? | \*--------------------------------------------------------------*/ write_links ("html"); /*--------------------------------------------------------------*\ | Build a simple table of contents, using the major sections | | of the standard. Start with HREF anchors. | \*--------------------------------------------------------------*/ p = first; if (p->key == WMetadata) if (p->next) p = p->next; else if (p->child) p = p->child; else p = NULL; fprintf (fp,"

%s:

\n",htmlentities(text_of(WMetadata))); fprintf (fp,"
    \n"); i = 1; while (p) { char *s = text_of(p->key); if (!omit(p->key)) { if (p->key != Wunknown && p->key != Wblank) fprintf (fp,"
  • %s
  • \n",i,htmlentities(s)); } p = p->next; i++; } fprintf (fp,"
\n"); /*--------------------------------------------------------------*\ | Output the metadata, emplacing NAME anchors at the tops of | | major sections to which the HREF anchors have referred. | \*--------------------------------------------------------------*/ p = first; if (p->key == WMetadata) if (p->next) p = p->next; else if (p->child) p = p->child; else p = NULL; i = 1; while (p) { if (p->key != Wblank && !omit(p->key)) { fprintf (fp,"\n",i); fprintf (fp,"\n"); fprintf (fp,"
\n"); fprintf (fp,"
\n"); write_html_item (p); fprintf (fp,"
\n"); fprintf (fp,"\n"); } p = p->next; i++; } /*--------------------------------------------------------------*\ | Bottom of page. If BASE was specified, write the page URL. | \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); if (opt = find_option (NULL,"output")) if (opt = find_option (opt,"html")) if (!find_option (opt,"omit_url")) if (opt = find_option (opt,"base")) if (s = text_of_option (opt)) { fprintf (fp,"This page is <%s",s); if (*(s + strlen(s) - 1) != '/') fprintf (fp,"/"); fprintf (fp,"%s>
\n",output_file); } /*--------------------------------------------------------------*\ | Output user-specified footer if there is one. | \*--------------------------------------------------------------*/ if (opt = find_option (NULL,"output")) if (opt = find_option (opt,"html")) if (v = find_option (opt,"footer")) { if (s = text_of_option (v)) fprintf (fp,"%s\n",s); } else if (v = find_option (opt,"footer_file")) { if (s = text_of_option (v)) { if (t = read_text (s)) { fprintf (fp,"\n",s); for (b=t; *b; b++) if (*b == 0x0D) *b = ' '; fprintf (fp,"%s",t); b = t + strlen (t) - 1; if (*b != '\n') fprintf (fp,"\n"); fprintf (fp,"\n",s); free (t); } } } /*--------------------------------------------------------------*\ | Put a link and a time-stamp into the output file. | \*--------------------------------------------------------------*/ T = time (&T); t = ctime (&T); s = t + strlen (t) - 1; if (*s == '\n') *s-- = 0; if (*s == '\r') *s-- = 0; fprintf (fp,"Generated by mp version %s on %s
\n",revision.mp,t); /*--------------------------------------------------------------*\ \*--------------------------------------------------------------*/ fprintf (fp,"\n"); fprintf (fp,"\n"); fprintf (fp,"\n"); fclose (fp); } else { fprintf (stderr,"Error: could not create output file %s\n",output_file); return; } } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static void do_meta_tags (struct item *first) { struct item *p, *q, *r, *s; char *t; void *opt; char *language; int WLanguage; /*------------------------------------------------------------------*\ | Dublin Core SCHEMA link \*------------------------------------------------------------------*/ fprintf (fp," \n"); /*------------------------------------------------------------------*\ | Dublin Core TITLE element \*------------------------------------------------------------------*/ if (p = find_key (first,WCitation)) if (p = find_key (p,WTitle)) if (p = p->child) if (p->key == Wunknown) { fprintf (fp," d) fprintf (fp,"%s ",htmlentities(p->d)); p = p->next; } fprintf (fp,"\"/>\n"); } /*------------------------------------------------------------------*\ | Dublin Core CREATOR element \*------------------------------------------------------------------*/ if (p = find_key (first,WCitation)) if (p = find_key (p,WOriginator)) { fprintf (fp," key == WOriginator) if (q = p->child) if (q->d) fprintf (fp,"%s ",htmlentities(q->d)); p = p->next; } fprintf (fp,"\"/>\n"); } /*------------------------------------------------------------------*\ | Dublin Core SUBJECT element \*------------------------------------------------------------------*/ if (p = find_key (first,WTheme)) if (p = p->child) { fprintf (fp," key == WTheme_Keyword) if (q = p->child) if (q->d) fprintf (fp,"%s ",htmlentities(q->d)); p = p->next; } fprintf (fp,"\"/>\n"); } /*------------------------------------------------------------------*\ | Dublin Core DESCRIPTION element \*------------------------------------------------------------------*/ if (p = find_key (first,WDescription)) if (p = find_key (p,WAbstract)) if (p = p->child) if (p->key == Wunknown) { fprintf (fp," d) fprintf (fp,"%s ",htmlentities(p->d)); p = p->next; } fprintf (fp,"\"/>\n"); } /*------------------------------------------------------------------*\ | Dublin Core PUBLISHER element \*------------------------------------------------------------------*/ if (p = find_key (first,WMetadata_Contact)) { int found = 0; if (q = find_key (p,WContact_Organization)) if (r = q->child) if (r->d) { fprintf (fp," \n",htmlentities(r->d)); found = 1; } if (!found) if (q = find_key (p,WContact_Person)) if (r = q->child) if (r->d) { fprintf (fp," \n",htmlentities(r->d)); found = 1; } } /*------------------------------------------------------------------*\ | Dublin Core CONTRIBUTOR element \*------------------------------------------------------------------*/ if (p = find_key (first,WIdentification_Information)) if (p = find_key (p,WData_Set_Credit)) if (p = p->child) if (p->key == Wunknown) { fprintf (fp," d) fprintf (fp,"%s ",htmlentities(p->d)); p = p->next; } fprintf (fp,"\"/>\n"); } /*------------------------------------------------------------------*\ | Dublin Core DATE element \*------------------------------------------------------------------*/ if (p = find_key (first,WCitation)) if (p = find_key (p,WPublication_Date)) if (q = p->child) if (q->d) fprintf (fp," \n",htmlentities(q->d)); /*------------------------------------------------------------------*\ | Dublin Core TYPE element \*------------------------------------------------------------------*/ if (p = find_key (first,WCitation)) { int found = 0; if (p = find_key (p,WGeospatial_Data_Presentation_Form)) if (q = p->child) if (q->d) { fprintf (fp," \n",htmlentities(q->d)); found = 1; } if (!found) fprintf (fp," \n"); } /*------------------------------------------------------------------*\ | Dublin Core FORMAT element | Search each Standard_Order_Process, and for each, search each Digital_Form for Format_Name \*------------------------------------------------------------------*/ if (p = find_key (first,WDistribution_Information)) if (p = find_key (p,WStandard_Order_Process)) do { if (q = find_key (p,WDigital_Form)) do { if (r = find_key (q,WFormat_Name)) if (s = r->child) if (s->d) fprintf (fp," \n",htmlentities(s->d)); } while (q = find_next_key (q,WDigital_Form)); } while (p = find_next_key (p,WStandard_Order_Process)); /*------------------------------------------------------------------*\ | Dublin Core IDENTIFIER element | Hmmm. I don't think this will be reliably unique. \*------------------------------------------------------------------*/ if (p = find_key (first,WCitation)) if (p = find_key (p,WOnline_Linkage)) if (q = p->child) if (q->d) fprintf (fp," \n",htmlentities(q->d)); /*------------------------------------------------------------------*\ | Dublin Core SOURCE element | This also will not be reliably unique; depends on Distributor. \*------------------------------------------------------------------*/ if (p = find_key (first,WDistribution_Information)) if (p = find_key (p,WResource_Description)) if (q = p->child) if (q->d) fprintf (fp," \n",htmlentities(q->d)); /*------------------------------------------------------------------*\ | Dublin Core LANGUAGE element | | This isn't a standard element, but we could use clues. First, | if there's an extended element with this content, and it has a | value, we should use that. Second, if the language of the | metadata was specified in the config file, use that. Otherwise | assume that the language is English. \*------------------------------------------------------------------*/ language = NULL; WLanguage = key_of ("Language"); if (p = find_key (first,WLanguage)) if (q = p->child) if (q->d) language = q->d; if (!language) if (p = find_key (first,WMetadata_Language)) if (q = p->child) if (q->d) language = q->d; if (!language) if (opt = find_option (NULL,"input")) if (opt = find_option (opt,"language")) if (t = text_of_option (opt)) language = t; if (!language) language = "en"; fprintf (fp," \n",language); /*------------------------------------------------------------------*\ | Dublin Core RELATION element | Use if there is a Larger_Work_Citation \*------------------------------------------------------------------*/ if (p = find_key (first,WCitation)) if (p = find_key (p,WLarger_Work_Citation)) if (p = find_key (p,WTitle)) if (q = p->child) if (q->d) fprintf (fp," \n",htmlentities(q->d)); /*------------------------------------------------------------------*\ | Dublin Core COVERAGE element \*------------------------------------------------------------------*/ if (p = find_key (first,WWest_Bounding_Coordinate)) if (q = p->child) if (q->d) fprintf (fp," \n",htmlentities(q->d)); if (p = find_key (first,WEast_Bounding_Coordinate)) if (q = p->child) if (q->d) fprintf (fp," \n",htmlentities(q->d)); if (p = find_key (first,WSouth_Bounding_Coordinate)) if (q = p->child) if (q->d) fprintf (fp," \n",htmlentities(q->d)); if (p = find_key (first,WNorth_Bounding_Coordinate)) if (q = p->child) if (q->d) fprintf (fp," \n",htmlentities(q->d)); if (p = find_key (first,WPlace)) if (q = find_key (p,WPlace_Keyword)) do { if (r = q->child) if (r->d) fprintf (fp," \n",htmlentities(r->d)); } while (q = find_next_key (q,WPlace_Keyword)); if (p = find_key (first,WTime_Period_of_Content)) if (p = find_key (p,WRange_of_Dates_Times)) { fprintf (fp," child) if (r->d) fprintf (fp,"%s",htmlentities(r->d)); if (q = find_key (p,WBeginning_Time)) if (r = q->child) if (r->d) fprintf (fp,"T%s",htmlentities(r->d)); fprintf (fp,"\"/>\n"); fprintf (fp," child) if (r->d) fprintf (fp,"%s",htmlentities(r->d)); if (q = find_key (p,WEnding_Time)) if (r = q->child) if (r->d) fprintf (fp,"T%s",htmlentities(r->d)); fprintf (fp,"\"/>\n"); } if (p = find_key (first,WTemporal)) if (q = find_key (p,WTemporal_Keyword)) do { if (r = q->child) if (r->d) fprintf (fp," \n",htmlentities(r->d)); } while (q = find_next_key (q,WTemporal_Keyword)); /*------------------------------------------------------------------*\ | Dublin Core RIGHTS element | Combine Access_Constraints and Use_Constraints \*------------------------------------------------------------------*/ fprintf (fp," child) if (q->d) fprintf (fp,"Access constraints: %s; ",htmlentities(q->d)); if (p = find_key (first,WUse_Constraints)) if (q = p->child) if (q->d) fprintf (fp,"Use constraints: %s",htmlentities(q->d)); fprintf (fp,"\"/>\n"); } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static char *child_text (struct item *p) { struct item *q; if (p) for (q=p->child; q; q=q->next) if (q->key == Wunknown) return (q->d); return (NULL); } static char *full_text_buffer = NULL; static int full_text_buffer_length = 0; static char *full_text (struct item *p) { char *s; struct item *q; if (!p ) return (NULL); if (!p->child) return (NULL); /* Find the first non-blank child of p */ for (q=p->child; q; q=q->next) if (q->key != Wblank) break; /* If the first nonblank child is Wunknown, you can get a value */ if (q->key == Wunknown) { int n = 0; for (q=p->child; q; q=q->next) if (q->d) n += 1 + strlen (q->d); if (1+n > full_text_buffer_length) { int k = 1 + (1+n)/4096; if (full_text_buffer = (char *) realloc (full_text_buffer,k*4096)) full_text_buffer_length = k*4096; else return (NULL); } s = full_text_buffer; for (q=p->child; q; q=q->next) if (q->d) { strcpy (s,q->d); s += strlen (q->d); if (q->next) *s++ = ' '; } *s = 0; return (full_text_buffer); } else return (NULL); } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ #define MAX_NAME 128 static void parse_name (char *name, char *first, char *middle, char *last) { char *b,*e,*s; int i,n; if (*name == 0 || *name == '<') { *first = *middle = *last = 0; return; } /*------------------------------------------------------------------*\ | How many names are there? If we see more than one comma, or if | | we see the word "and", then we might safely assume that there | | are multiple names in this element, and we should leave it alone.| \*------------------------------------------------------------------*/ n = 0; for (b=name; *b; b++) if (*b == ',') n++; if (n > 1 || strstr (name," and ")) { *first = *middle = *last = 0; return; } /* One or zero commas, no occurrence of the word "and" */ b = name; if (e = strchr (name,',')) { /* Last, First Middle */ if (e - b < MAX_NAME) { memcpy (last,b,e-b); last[e-b] = 0; } else { memcpy (last,b,MAX_NAME-1); last[MAX_NAME-1] = 0; } e++; b = e; while (*b && isspace(*b)) b++; e = b; while (*e && !isspace(*e)) e++; if (e - b < MAX_NAME) { memcpy (first,b,e-b); first[e-b] = 0; } else { memcpy (first,b,MAX_NAME-1); first[MAX_NAME-1] = 0; } b = e; while (*b && isspace(*b)) b++; if (strlen (b) < MAX_NAME) { strcpy (middle,b); } else { memcpy (middle,b,MAX_NAME-1); middle[MAX_NAME-1] = 0; // Strip trailing space from middle s = middle + strlen(middle) - 1; while (isspace(*s)) *s-- = 0; } } else { /* First Middle Last */ e = b; while (*e && !isspace(*e)) e++; if (e - b < MAX_NAME) { memcpy (first,b,e-b); first[e-b] = 0; } else { memcpy (first,b,MAX_NAME-1); first[MAX_NAME-1] = 0; } b = e; while (*b && isspace(*b)) b++; e = b; while (*e && !isspace(*e)) e++; if (e - b < MAX_NAME) { memcpy (middle,b,e-b); middle[e-b] = 0; } else { memcpy (middle,b,MAX_NAME-1); middle[MAX_NAME-1] = 0; } b = e; while (*b && isspace(*b)) b++; e = b; while (*e && !isspace(*e)) e++; /*--------------------------------------------------------------*\ | If no more words, what we put in middle is really the last | | name, otherwise store in the last name what remains. | | This won't properly parse names like "John Smith Jr." | \*--------------------------------------------------------------*/ if (e - b == 0) { strcpy (last,middle); *middle = 0; } else { if (e - b < MAX_NAME) { memcpy (last,b,e-b); last[e-b] = 0; } else { memcpy (last,b,MAX_NAME-1); last[MAX_NAME-1] = 0; } /*----------------------------------------------------------*\ | If what's left is too large for an ancestral suffix like | | Sr., Jr., or III, cancel the whole parse operation. | | Otherwise, append what's left to the middle name. | \*----------------------------------------------------------*/ b = e; while (*b && isspace(*b)) b++; if (strlen (b) > 4) *first = *middle = *last = 0; else if (strlen (middle) < 28) { strcat (middle," "); strcat (middle,b); } // Strip trailing space from middle s = middle + strlen(middle) - 1; while (isspace(*s)) *s-- = 0; /*----------------------------------------------------------*\ | Check the first name; if it's U.S., then cancel parse. | \*----------------------------------------------------------*/ if (strcmp (first,"U.S.") == 0) *first = *middle = *last = 0; } } } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static void write_date (char *string) { int y,m,d; char *s; struct tm tm; char date_string [64]; if (!fp) return; if (! string) return; for (s=string; *s && isspace(*s); s++); if (!*s) return; if (!isdigit (*s)) { fprintf (fp,"%s",munge(string)); return; } y = m = d = 0; if (*s && isdigit(*s)) y = 10 * y + (*s++ - '0'); if (*s && isdigit(*s)) y = 10 * y + (*s++ - '0'); if (*s && isdigit(*s)) y = 10 * y + (*s++ - '0'); if (*s && isdigit(*s)) y = 10 * y + (*s++ - '0'); if (y < 100) y += 1900; if (y > 1900) tm.tm_year = y - 1900; else return; /*------------------------------------------------------------------*\ | If only a year was specified, just output the year. | \*------------------------------------------------------------------*/ while (*s && isspace(*s)) s++; if (!isdigit(*s)) { fprintf (fp,"%d",y); return; } /*------------------------------------------------------------------*\ | If YYYYMM or YYYYMMDD, decode the whole date. | \*------------------------------------------------------------------*/ if (*s && isdigit(*s)) m = 10 * m + (*s++ - '0'); if (*s && isdigit(*s)) m = 10 * m + (*s++ - '0'); tm.tm_mon = m - 1; if (*s && isdigit(*s)) d = 10 * d + (*s++ - '0'); if (*s && isdigit(*s)) d = 10 * d + (*s++ - '0'); if (d > 0) tm.tm_mday = d; else tm.tm_mday = 1; tm.tm_hour = tm.tm_min = tm.tm_sec = 0; tm.tm_isdst = 0; if (mktime (&tm) == (time_t) -1) { fprintf (fp,"%s",munge(string)); return; } *date_string = 0; if (d > 0) strftime (date_string,64,"%d-%b-%Y",&tm); else if (m > 0) strftime (date_string,64,"%b-%Y",&tm); else if (y > 0) strftime (date_string,64,"%Y",&tm); fprintf (fp,"%s",date_string); if (*s) fprintf (fp,"%s",munge(s)); } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static void write_citation (struct item *p) { char *s; struct item *q,*r; int wrote_series_information = 0; if (!fp || !p) return; if (p->key != WCitation_Information) return; fprintf (fp,"
\n"); /* Authors and other originators */ if (q = find_key (p,WOriginator)) if (q->parent == p) { if (s = full_text (q)) { char FirstName[MAX_NAME],MiddleName[MAX_NAME],LastName[MAX_NAME]; parse_name (s,FirstName,MiddleName,LastName); if (*LastName) { fprintf (fp,"%s",munge(LastName)); if (*FirstName) fprintf (fp,", %s",munge(FirstName)); if (*MiddleName) fprintf (fp," %s",munge(MiddleName)); } else fprintf (fp,"%s",munge(s)); } while (q = find_next_key (q,WOriginator)) if (s = full_text (q)) { char FirstName[64],MiddleName[64],LastName[64]; if (r = find_next_key (q,WOriginator)) fprintf (fp,", "); else fprintf (fp,", and "); parse_name (s,FirstName,MiddleName,LastName); if (*LastName) { fprintf (fp,"%s",munge(LastName)); if (*FirstName) fprintf (fp,", %s",munge(FirstName)); if (*MiddleName) fprintf (fp," %s",munge(MiddleName)); } else fprintf (fp,"%s",munge(s)); } } /* Publication date */ if (q = find_key (p,WPublication_Date)) if (s = full_text (q)) fprintf (fp,", %s",munge(s)); /* Title */ if (q = find_key (p,WTitle)) if (q->parent == p) if (s = full_text (q)) { fprintf (fp,", %s",munge(s)); if (find_key (p,WSeries_Information) || find_key (p,WPublication_Information)) fprintf (fp,":"); } /* Series Information */ if (q = find_key (p,WSeries_Information)) if (q->parent == p) { if (r = find_key (q,WSeries_Name)) if (s = full_text (r)) fprintf (fp," %s",munge(s)); if (r = find_key (q,WIssue_Identification)) if (s = full_text (r)) fprintf (fp," %s",munge(s)); wrote_series_information = 1; } /* Publication Information */ if (q = find_key (p,WPublication_Information)) if (q->parent == p) { if (wrote_series_information) fprintf (fp,","); if (r = find_key (q,WPublisher)) if (s = full_text (r)) fprintf (fp," %s",munge(s)); if (r = find_key (q,WPublication_Place)) if (s = full_text (r)) fprintf (fp,", %s",munge(s)); } fprintf (fp,".

\n"); /* Online Linkage */ if (q = find_key (p,WOnline_Linkage)) if (q->parent == p) { fprintf (fp,"Online Links:\n"); fprintf (fp,"

    \n"); do { if (s = full_text (q)) fprintf (fp,"
  • %s\n",munge(s)); } while (q = find_next_key (q,WOnline_Linkage)); fprintf (fp,"
\n"); fprintf (fp,"

\n"); } fprintf (fp,"

\n"); /* Other Citation Details */ if (q = find_key (p,WOther_Citation_Details)) if (q->parent == p) { fprintf (fp,"
\n"); write_html_item (q); fprintf (fp,"
\n"); } if (q = find_key (p,WLarger_Work_Citation)) { if (q->child) if (q->child->key == WCitation_Information) { fprintf (fp,"This is part of the following larger work.

\n"); write_citation (q->child); } } } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static void write_contact (struct item *p) { struct item *q,*r,*u; char *s; if (!fp || !p) return; fprintf (fp,"

\n"); /*-- Contact_Person, Contact_Organization --*/ if (q = find_key (p,WContact_Person_Primary)) { if (r = find_key (q,WContact_Person)) if (s = full_text(r)) fprintf (fp,"
%s
\n",munge(s)); if (r = find_key (q,WContact_Organization)) if (s = full_text(r)) fprintf (fp,"
%s
\n",munge(s)); } else if (q = find_key (p,WContact_Organization_Primary)) { if (r = find_key (q,WContact_Organization)) if (s = full_text(r)) fprintf (fp,"
%s
\n",munge(s)); if (r = find_key (q,WContact_Person)) if (s = full_text(r)) fprintf (fp,"
Attn: %s
\n",munge(s)); } /*-- Contact_Position --*/ if (q = find_key (p,WContact_Position)) if (s = full_text (q)) fprintf (fp,"
%s
\n",munge(s)); /*-- Contact_Address --*/ if (q = find_key (p,WContact_Address)) { if (r = find_key (q,WAddress)) for (u=r->child; u; u=u->next) if (u->d) fprintf (fp,"
%s
\n",munge(u->d)); if (r = find_key (q,WCity)) if (s = full_text(r)) fprintf (fp,"%s, ",munge(s)); if (r = find_key (q,WState_or_Province)) if (s = full_text(r)) fprintf (fp,"%s ",munge(s)); if (r = find_key (q,WPostal_Code)) if (s = full_text(r)) fprintf (fp,"
\n",munge(s)); if (r = find_key (q,WCountry)) if (s = full_text(r)) fprintf (fp,"
%s
\n",munge(s)); } fprintf (fp,"

\n"); /*-- phone, FAX, email --*/ if (q = find_key (p,WContact_Voice_Telephone)) if (s = full_text(q)) fprintf (fp,"

%s (voice)
\n",munge(s)); if (q = find_key (p,WContact_Facsimile_Telephone)) if (s = full_text(q)) fprintf (fp,"
%s (FAX)
\n",munge(s)); if (q = find_key (p,WContact_Electronic_Mail_Address)) if (s = full_text(q)) fprintf (fp,"
%s
\n",munge(s)); /*-- hours and instructions --*/ if (find_key (p,WHours_of_Service) || find_key (p,WContact_Instructions)) { fprintf (fp,"
\n"); if (q = find_key (p,WHours_of_Service)) write_html_item (q); if (q = find_key (p,WContact_Instructions)) write_html_item (q); fprintf (fp,"
\n"); } fprintf (fp,"
\n"); } /*----------------------------------------------------------------------*\ | Link to related files in HTML output. | \*----------------------------------------------------------------------*/ static void write_link_for (char *kind, char *label, char *which, int base_href) { char *f,*g,*t; if (f = related_file (kind)) { if (base_href) if (g = related_file (which)) while (t = strchr (f,'/')) if (memcmp (f,g,t-f+1) == 0) { g += t - f + 1; f += t - f + 1; } else break; fprintf (fp," - [%s]",f,label); } } static void write_links (char *which) { int done = 0; void *opt,*v; char *s,*t,*f,*g,*b; int base_href = 0; char *lead_text = NULL; /*------------------------------------------------------------------*\ | If there is a "link" element in the config file, create links | | based on the directives given there. | \*------------------------------------------------------------------*/ if (opt = find_option (NULL,"output")) if (opt = find_option (opt,"html")) { if (v = find_option (opt,"base")) if (text_of_option (v)) base_href = 1; if (opt = find_option (opt,"link")) { if (find_option (opt,"link_faq" ) || find_option (opt,"link_html") || find_option (opt,"link_text") || find_option (opt,"link_sgml") || find_option (opt,"link_xml" ) || find_option (opt,"link_dif" )) { if (!(b = related_file ("input"))) b = "error_no_input_file"; if (v = find_option (opt,"label")) if (s = text_of_option (v)) lead_text = s; if (lead_text) fprintf (fp,"%s",lead_text); else fprintf (fp,"Metadata also available as"); /*--------------------------------------------------*\ | Link to FAQ-style HTML \*--------------------------------------------------*/ if (strcmp (which,"faq") != 0) if (v = find_option (opt,"link_faq")) if (s = text_of_option (v)) { fprintf (fp," [Questions & Answers]"); } else write_link_for ("faq","Questions & Answers",which,base_href); /*--------------------------------------------------*\ | Link to outline-style HTML \*--------------------------------------------------*/ if (strcmp (which,"html") != 0) if (v = find_option (opt,"link_html")) if (s = text_of_option (v)) { fprintf (fp," - [Outline]"); } else write_link_for ("html","Outline",which,base_href); /*--------------------------------------------------*\ | Link to parseable text \*--------------------------------------------------*/ if (v = find_option (opt,"link_text")) if (s = text_of_option (v)) { fprintf (fp," - [Parseable text]"); } else write_link_for ("text","Parseable text",which,base_href); /*--------------------------------------------------*\ | Link to SGML \*--------------------------------------------------*/ if (v = find_option (opt,"link_sgml")) if (s = text_of_option (v)) { fprintf (fp," - [SGML]"); } else write_link_for ("sgml","SGML",which,base_href); /*--------------------------------------------------*\ | Link to XML \*--------------------------------------------------*/ if (v = find_option (opt,"link_xml")) if (s = text_of_option (v)) { fprintf (fp," - [XML]"); } else write_link_for ("xml","XML",which,base_href); /*--------------------------------------------------*\ | Link to DIF \*--------------------------------------------------*/ if (v = find_option (opt,"link_dif")) if (s = text_of_option (v)) { fprintf (fp," - [DIF]"); } else write_link_for ("dif","DIF",which,base_href); fprintf (fp,"

\n"); } done = 1; } } /*------------------------------------------------------------------*\ | If there was no "link" element in the config file, create links | | based on the expected names of the output files. | \*------------------------------------------------------------------*/ if (!done) { if (opt = find_option (NULL,"output")) if (opt = find_option (opt,"html")) if (opt = find_option (opt,"link")) if (v = find_option (opt,"label")) if (s = text_of_option (v)) lead_text = s; if (lead_text) fprintf (fp,"%s",lead_text); else fprintf (fp,"Metadata also available as"); if (strcmp (which,"faq") != 0) write_link_for ("faq","Questions & Answers",which,base_href); if (strcmp (which,"html") != 0) write_link_for ("html","Outline",which,base_href); write_link_for ("text","Parseable text",which,base_href); write_link_for ("sgml","SGML",which,base_href); write_link_for ("xml","XML",which,base_href); write_link_for ("dif","DIF",which,base_href); fprintf (fp,"

\n"); } } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static void write_data_set_part (struct item *q) { struct item *r; char *s; int WData_Set_Part = key_of ("Data_Set_Part"); int WPart_Name = key_of ("Part_Name"); int WPart_Type = key_of ("Part_Type"); int WPart_Description = key_of ("Part_Description"); if (q->key == WData_Set_Part) { fprintf (fp,"

"); if (r = find_key (q,WPart_Name)) if (r->parent == q) if (s = full_text (r)) fprintf (fp,"%s\n",munge(s)); if (r = find_key (q,WPart_Type)) if (r->parent == q) if (s = full_text (r)) fprintf (fp," (%s)",munge(s)); fprintf (fp,"\n"); fprintf (fp,"
\n"); if (r = find_key (q,WPart_Description)) if (r->parent == q) write_html_value (r); for (r=q->child; r; r=r->next) if (r->key == WData_Set_Part) break; if (r) { fprintf (fp,"

\n"); fprintf (fp,"

\n"); while (r) { if (r->key == WData_Set_Part) write_data_set_part (r); r = r->next; } fprintf (fp,"
\n"); fprintf (fp,"

\n"); } } } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/ static int projection[] = { WAlbers_Conical_Equal_Area, WAzimuthal_Equidistant, WEquidistant_Conic, WEquirectangular, WGeneral_Vertical_Near_sided_Perspective, WGnomonic, WLambert_Azimuthal_Equal_Area, WLambert_Conformal_Conic, WMercator, WModified_Stereographic_for_Alaska, WMiller_Cylindrical, WOblique_Mercator, WOrthographic, WPolar_Stereographic, WPolyconic, WRobinson, WSinusoidal, WSpace_Oblique_Mercator_Landsat, WStereographic, WTransverse_Mercator, Wvan_der_Grinten, Wnull }; void write_html_faq (char *output_file, struct item *first) { struct item *p,*q,*r,*u,*w,*h,*hh; char *b,*s,*t,*title; int title_allocated = 0; void *opt,*v; time_t T; unsigned char bytes[8]; /* for UTF-8 translation */ int WDescription_of_Geographic_Extent; int WData_Set_Structure; int WTaxonomy; int WAnalytical_Tool; int WASCII_File_Structure; int WMethodology; int distributor,distributor_count,counter; if (first == NULL) return; /* If encoding is UTF-8, remember this for later */ if (stricmp (get_character_encoding(),"UTF-8") == 0) { utf8_in = 1; utf8_out = 1; } /*------------------------------------------------------------------*\ | Get options from config tree | \*------------------------------------------------------------------*/ if (opt = find_option (NULL,"output")) if (opt = find_option (opt,"html")) { /*----------------------------------------------------------*\ | "translate off" activates html code in text values. By | | Default such html code is rendered literally. | \*----------------------------------------------------------*/ if (v = find_option (opt,"translate")) { do_text_translation = 1; if (s = text_of_option (v)) if (stricmp (s,"off") == 0) do_text_translation = 0; } /*----------------------------------------------------------*\ | "preformat" encloses groups of lines that begin with > | | in
 tags.  Optional value is the character	|
			 | used to indicate sections that should be preformatted.	|
			 | Default is >.  Turn off with preformat off.				|
			\*----------------------------------------------------------*/

			if (v = find_option (opt,"preformat")) {
				do_preformatting = 1;
				if (s = text_of_option (v))
					if (stricmp (s,"off") == 0) do_preformatting = 0;
					else
						if (*s) preformat_indicator = *s;
				}

			/*----------------------------------------------------------*\
			 | "meta off" disables dublin-core meta elements generation |
			\*----------------------------------------------------------*/

			if (v = find_option (opt,"meta")) {
				do_meta = 1;
				if (s = text_of_option (v))
					if (stricmp (s,"off") == 0) do_meta = 0;
				}

			/*----------------------------------------------------------*\
			 | "encoding" specifies output encoding, typically used for	|
			 | UTF-8.  If not specified and UTF-8 is input, make UTF-8	|
			 | also the output encoding.								|
			\*----------------------------------------------------------*/

			if (v = find_option (opt,"encoding")) {
				if (s = text_of_option (v))
					if (stricmp (s,"utf-8") == 0) utf8_out = 1;
					else utf8_out = 0;
				}
			}

	/* Generally you want to translate characters */

	if (do_text_translation) munge = translated;
	else munge = as_is;

	title = output_file;
	if (p = find_key (first,WCitation))
		if (p = find_key (p,WTitle))
			if (p->child)
				if (p->child->key == Wunknown) {
					int n = 0;
					for (q=p->child; q; q=q->next)
						if (q->d) n += 1 + strlen (q->d);
					if (title = (char *) malloc (1 + n)) {
						char *s = title;
						for (q=p->child; q; q=q->next) {
							if (q->d) {
								strcpy (s,q->d);
								s += strlen (q->d);
								}
							if (q->next) *s++ = ' ';
							*s = 0;
							}
						title_allocated = 1;
						}
					else
						if (p->child->d) title = p->child->d;
						else title = "(untitled)";
					}

	if (fp = fopen (output_file,"w")) {
		fprintf (fp,"%s\n",html_doctype);
		fprintf (fp,"\n");
		fprintf (fp,"\n");

		if (utf8_out)
			fprintf (fp,"  \n");
		else
			fprintf (fp,"  \n");

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"base"))
					if (s = text_of_option (opt)) {
						fprintf (fp,"  \n",output_file);
						}

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"style_file"))
					if (s = text_of_option (opt)) {
						if (t = read_text (s)) {
							char *tt = t + strlen (t) - 1;
							fprintf (fp,"\n",s);
							for (b=t; *b; b++)
								if (*b == 0x0D) *b = ' ';
							fprintf (fp,"%s",t);
							if (*tt != '\n') fprintf (fp,"\n");
							fprintf (fp,"\n",s);
							free (t);
							}
						}

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"stylesheet"))
					do {
						char *style_type = "text/css";
						if (v = find_option (opt,"type"))
							if (s = text_of_option (v)) style_type = s;
						if (v = find_option (opt,"href"))
							if (s = text_of_option (v))
								fprintf (fp,"  \n",style_type,s);
						} while (opt = find_next_option (opt,"stylesheet"));

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"script_file"))
					if (s = text_of_option (opt)) {
						if (t = read_text (s)) {
							char *tt = t + strlen (t) - 1;
							fprintf (fp,"\n",s);
							for (b=t; *b; b++)
								if (*b == 0x0D) *b = ' ';
							fprintf (fp,"%s",t);
							if (*tt != '\n') fprintf (fp,"\n");
							fprintf (fp,"\n",s);
							free (t);
							}
						}

		fprintf (fp,"  ");
		fprintf (fp,htmlentities(title));
		fprintf (fp,"\n");
		if (do_meta) do_meta_tags (first);

		if (s = related_file ("original"))
			fprintf (fp,"  \n",s);

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (opt = find_option (opt,"head"))
					if (s = text_of_option (opt))
						fprintf (fp,"%s\n",s);

		fprintf (fp,"\n");

		fprintf (fp,"\n");
		fprintf (fp,"\n");

		/*--------------------------------------------------------------*\
		 | Output user-specified header if there is one.				|
		\*--------------------------------------------------------------*/

		if (opt = find_option (NULL,"output"))
			if (opt = find_option (opt,"html"))
				if (v = find_option (opt,"header")) {
					if (s = text_of_option (v))
						fprintf (fp,"%s\n",s);
					}
				else
					if (v = find_option (opt,"header_file")) {
						if (s = text_of_option (v)) {
							if (t = read_text (s)) {
								char *tt = t + strlen (t) - 1;
								fprintf (fp,"\n",s);
								for (b=t; *b; b++)
									if (*b == 0x0D) *b = ' ';
								fprintf (fp,"%s",t);
								if (*tt != '\n') fprintf (fp,"\n");
								fprintf (fp,"\n",s);
								free (t);
								}
							}
						}

		/*--------------------------------------------------------------*\
		\*--------------------------------------------------------------*/

		fprintf (fp,"

"); fprintf (fp,htmlentities(title)); fprintf (fp,"

\n"); if (title_allocated) { free (title); title = NULL; title_allocated = 0; } /*--------------------------------------------------------------*\ | Links to other formats of this metadata record? | \*--------------------------------------------------------------*/ write_links ("faq"); /*--------------------------------------------------------------*\ | See whether some common extensions are in use \*--------------------------------------------------------------*/ WDescription_of_Geographic_Extent = key_of ("Description_of_Geographic_Extent"); WData_Set_Structure = key_of ("Data_Set_Structure"); WTaxonomy = key_of ("Taxonomy"); WAnalytical_Tool = key_of ("Analytical_Tool"); WASCII_File_Structure = key_of ("ASCII_File_Structure"); WMethodology = key_of ("Methodology"); /*--------------------------------------------------------------*\ | Build a simple table of contents, using the major questions | | of the plain-language document. Start with HREF anchors. | \*--------------------------------------------------------------*/ fprintf (fp,"

Frequently anticipated questions:

\n"); fprintf (fp,"\n"); /*--------------------------------------------------------------*\ | Output the metadata, emplacing NAME anchors at the tops of | | major sections to which the HREF anchors have referred. | \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); fprintf (fp,"

What does this data set describe?

\n"); fprintf (fp,"
\n"); fprintf (fp,"
\n"); if (p = find_key (first,WCitation)) if (p = find_key (p,WTitle)) write_html_item (p); if (p = find_key (first,WDescription)) { if (q = find_key (p,WAbstract)) write_html_item (q); if (q = find_key (p,WSupplemental_Information)) write_html_item (q); } fprintf (fp,"
\n"); fprintf (fp,"
\n"); fprintf (fp,"
    \n"); /*--------------------------------------------------------------*/ fprintf (fp,"
  1. How might this data set be cited?\n"); if (p = find_key (first,WCitation)) if (p = find_key (p,WCitation_Information)) write_citation (p); fprintf (fp,"
  2. \n"); /* what.1 */ /*--------------------------------------------------------------*/ fprintf (fp,"
  3. What geographic area does the data set cover?\n"); if (p = find_key (first,WSpatial_Domain)) { fprintf (fp,"
    \n"); if (q = find_key (p,WBounding_Coordinates)) for (r=q->child; r; r=r->next) write_html_item (r); /* Nice extension from NBII; use if present */ if (WDescription_of_Geographic_Extent != Wunknown) if (q = find_key (p,WDescription_of_Geographic_Extent)) write_html_item (q); fprintf (fp,"
    \n"); } fprintf (fp,"
  4. \n"); /* what.2 */ /*--------------------------------------------------------------*/ fprintf (fp,"
  5. What does it look like?\n"); if (p = find_key (first,WIdentification_Information)) { if (q = find_key (p,WBrowse_Graphic)) { fprintf (fp,"
    \n"); do { fprintf (fp,"
    "); if (r = find_key (q,WBrowse_Graphic_File_Name)) if (s = full_text (r)) fprintf (fp,"%s",munge(s)); if (r = find_key (q,WBrowse_Graphic_File_Type)) if (s = full_text (r)) fprintf (fp," (%s)",munge(s)); fprintf (fp,"\n
    \n"); if (r = find_key (q,WBrowse_Graphic_File_Description)) if (s = full_text (r)) write_html_value (r); } while (q = find_next_key (q,WBrowse_Graphic)); fprintf (fp,"
    \n"); } } fprintf (fp,"
  6. \n"); /* what.3 */ /*--------------------------------------------------------------*/ fprintf (fp,"
  7. Does the data set describe conditions during a particular time period?\n"); fprintf (fp,"
    \n"); if (p = find_key (first,WTime_Period_of_Content)) { if (q = find_key (p,WSingle_Date_Time)) { if (r = find_key (q,WCalendar_Date)) if (s = full_text (r)) { fprintf (fp,"
    Calendar_Date: "); write_date (s); } if (r = find_key (q,WTime_of_Day)) write_html_item (r); } else if (q = find_key (p,WMultiple_Dates_Times)) { for (q=q->child; q; q=q->next) if (s = full_text (q)) { fprintf (fp,"
    Calendar_Date: "); write_date (s); } } else if (q = find_key (p,WRange_of_Dates_Times)) for (r=q->child; r; r=r->next) if (r->key == WBeginning_Date) { if (s = full_text (r)) { fprintf (fp,"
    Beginning_Date: "); write_date (s); } } else if (r->key == WEnding_Date) { if (s = full_text (r)) { fprintf (fp,"
    Ending_Date: "); write_date (s); } } else write_html_item (r); if (q = find_key (p,WCurrentness_Reference)) write_html_item (q); } fprintf (fp,"
    \n"); fprintf (fp,"
  8. \n"); /* what.4 */ /*--------------------------------------------------------------*/ fprintf (fp,"
  9. What is the general form of this data set?\n"); fprintf (fp,"
    \n"); if (p = find_key (first,WCitation)) if (p = find_key (p,WGeospatial_Data_Presentation_Form)) write_html_item (p); fprintf (fp,"
    \n"); fprintf (fp,"
  10. \n"); /* what.5 */ /*--------------------------------------------------------------*/ fprintf (fp,"
  11. How does the data set represent geographic features?\n"); fprintf (fp,"
      \n"); fprintf (fp,"
    1. How are geographic features stored in the data set?
      \n"); if (p = find_key (first,WSpatial_Data_Organization_Information)) { /*----------------------------------------------------------*\ | If there is an Indirect_Spatial_Reference, output it. | \*----------------------------------------------------------*/ if (q = find_key (p,WIndirect_Spatial_Reference)) { fprintf (fp,"
      \n"); write_html_item (q); fprintf (fp,"
      \n"); } /*----------------------------------------------------------*\ | If there is a Direct_Spatial_Reference_Method, show it. | \*----------------------------------------------------------*/ if (q = find_key (p,WDirect_Spatial_Reference_Method)) if (s = full_text (q)) fprintf (fp,"This is a %s data set.\n",munge(s)); /*----------------------------------------------------------*\ | Point_and_Vector_Object_Information | \*----------------------------------------------------------*/ /*----------------------------------------------------------*\ | For each SDTS_Terms_Description, list the types, and if | | a count follows the type, show the count in parentheses | | after the type. Put the types in an unordered list. | \*----------------------------------------------------------*/ if (q = find_key (p,WPoint_and_Vector_Object_Information)) if (q = find_key (q,WSDTS_Terms_Description)) { fprintf (fp,"It contains the following vector data types (SDTS terminology):\n"); fprintf (fp,"
        \n"); do { for (r=q->child; r; r=r->next) if (r->key == WSDTS_Point_and_Vector_Object_Type) { if (r->child) fprintf (fp,"
      • %s",munge(full_text(r))); if (r->next) if (r->next->key == WPoint_and_Vector_Object_Count) if (s = full_text (r->next)) fprintf (fp," (%s)",munge(s)); fprintf (fp,"\n"); } } while (q = find_next_key (q,WSDTS_Terms_Description)); fprintf (fp,"
      \n"); } /*----------------------------------------------------------*\ | For each VPF_Point_and_Vector_Object_Information list | | the types, and if a count follows the type, show the | | count in parentheses after the type. Put the types in | | an unordered list. | \*----------------------------------------------------------*/ if (q = find_key (p,WPoint_and_Vector_Object_Information)) if (q = find_key (q,WVPF_Terms_Description)) { if (r = find_key (q,WVPF_Topology_Level)) if (s = full_text(r)) fprintf (fp,"VPF Topology level %s
      \n",munge(s)); fprintf (fp,"It contains the following vector data types (VPF terminology):\n"); fprintf (fp,"
        \n"); for (r=q->child; r; r=r->next) if (r->key == WVPF_Point_and_Vector_Object_Information) { if (u = find_key (r,WVPF_Point_and_Vector_Object_Type)) if (s = full_text(u)) fprintf (fp,"
      • %s",munge(s)); if (u = find_key (r,WPoint_and_Vector_Object_Count)) if (s = full_text(u)) fprintf (fp," (%s)",munge(s)); fprintf (fp,"\n"); } fprintf (fp,"
      \n"); } /*----------------------------------------------------------*\ | Raster_Object_Information | \*----------------------------------------------------------*/ if (q = find_key (p,WRaster_Object_Information)) { fprintf (fp,"It contains the following raster data types:\n"); fprintf (fp,"
        \n"); do { fprintf (fp,"
      • Dimensions"); if (r = find_key (q,WRow_Count)) if (s = full_text(r)) fprintf (fp," %s",munge(s)); if (r = find_key (q,WColumn_Count)) if (s = full_text(r)) fprintf (fp," x %s",munge(s)); if (r = find_key (q,WVertical_Count)) if (s = full_text(r)) fprintf (fp," x %s",munge(s)); if (r = find_key (q,WRaster_Object_Type)) if (s = full_text(r)) fprintf (fp,", type %s",munge(s)); fprintf (fp,"\n"); } while (q = find_next_key (q,WRaster_Object_Information)); fprintf (fp,"
      \n"); } } fprintf (fp,"
    2. \n"); /* what.6a */ /*--------------------------------------------------------------*/ fprintf (fp,"
    3. What coordinate system is used to represent geographic features?
      \n"); if (p = find_key (first,WSpatial_Reference_Information)) { /*----------------------------------------------------------*\ | Horizontal \*----------------------------------------------------------*/ if (q = find_key (p,WHorizontal_Coordinate_System_Definition)) { if (r = find_key (q,WGeographic)) { fprintf (fp,"Horizontal positions are specified in geographic coordinates, that is, latitude and longitude.\n"); if (u = find_key (r,WLatitude_Resolution)) if (s = full_text (u)) fprintf (fp,"Latitudes are given to the nearest %s.\n",munge(s)); if (u = find_key (r,WLongitude_Resolution)) if (s = full_text (u)) fprintf (fp,"Longitudes are given to the nearest %s.\n",munge(s)); if (u = find_key (r,WGeographic_Coordinate_Units)) if (s = full_text (u)) fprintf (fp,"Latitude and longitude values are specified in %s.\n",munge(s)); } else if (r = find_key (q,WPlanar)) { /*----------------------------------------------*\ | Map_Projection \*----------------------------------------------*/ if (u = find_key (r,WMap_Projection)) { if (w = find_key (r,WMap_Projection_Name)) { if (s = full_text (w)) fprintf (fp,"The map projection used is %s.
      \n",munge(s)); if (w->next) w=w->next; else if (w->prev) w=w->prev; } else { int i; s = NULL; for (i=0; projection[i] != Wnull; i++) if (w = find_key (u,projection[i])) { s = text_of (w->key); break; } if (s) fprintf (fp,"The map projection used is %s.
      \n",munge(s)); } if (!w) w = find_key (r,WMap_Projection_Parameters); if (w) { fprintf (fp,"
      \n"); fprintf (fp,"
      Projection parameters:\n"); fprintf (fp,"
      \n"); fprintf (fp,"
      \n"); for (h=w->child; h; h=h->next) write_html_item (h); fprintf (fp,"
      \n"); fprintf (fp,"
      \n"); } } /*----------------------------------------------*\ | Grid_Coordinate_System \*----------------------------------------------*/ if (u = find_key (r,WGrid_Coordinate_System)) { fprintf (fp,"
      \n"); for (w=u->child; w; w=w->next) write_html_item (w); fprintf (fp,"
      \n"); } /*----------------------------------------------*\ | Local_Planar \*----------------------------------------------*/ if (u = find_key (r,WLocal_Planar)) { fprintf (fp,"Horizontal coordinates are specified using a local planar system.
      \n"); if (w = find_key (u,WLocal_Planar_Description)) if (s = full_text (w)) fprintf (fp,"%s
      \n",munge(s)); if (w = find_key (u,WLocal_Planar_Georeference_Information)) if (s = full_text (w)) fprintf (fp,"%s
      \n",munge(s)); } /*----------------------------------------------*\ | Planar_Coordinate_Information \*----------------------------------------------*/ if (u = find_key (r,WPlanar_Coordinate_Information)) { if (v = find_key (u,WPlanar_Coordinate_Encoding_Method)) if (s = full_text (v)) fprintf (fp,"Planar coordinates are encoded using %s
      \n",munge(s)); if (v = find_key (u,WCoordinate_Representation)) { if (w = find_key (v,WAbscissa_Resolution)) if (s = full_text (w)) fprintf (fp,"Abscissae (x-coordinates) are specified to the nearest %s
      \n",munge(s)); if (w = find_key (v,WOrdinate_Resolution)) if (s = full_text (w)) fprintf (fp,"Ordinates (y-coordinates) are specified to the nearest %s
      \n",munge(s)); } else if (v = find_key (u,WDistance_and_Bearing_Representation)) { fprintf (fp,"Planar coordinates are specified using distance and bearing values.\n"); if (w = find_key (v,WDistance_Resolution)) if (s = full_text (w)) fprintf (fp,"Resolution of distance values: %s
      \n",munge(s)); if (w = find_key (v,WBearing_Resolution)) if (s = full_text (w)) fprintf (fp,"Resolution of bearing values: %s
      \n",munge(s)); if (w = find_key (v,WBearing_Units)) if (s = full_text (w)) fprintf (fp,"Bearing is specified in units of %s
      \n",munge(s)); if (w = find_key (v,WBearing_Reference_Direction)) if (s = full_text (w)) fprintf (fp,"Bearing is measured %s
      \n",munge(s)); if (w = find_key (v,WBearing_Reference_Meridian)) if (s = full_text (w)) fprintf (fp,"Bearing is measured from the %s meridian
      \n",munge(s)); } if (v = find_key (u,WPlanar_Distance_Units)) if (s = full_text (v)) fprintf (fp,"Planar coordinates are specified in %s
      \n",munge(s)); } } else if (r = find_key (q,WLocal)) { if (u = find_key (r,WLocal_Description)) if (s = full_text (u)) fprintf (fp,"This local coordinate system was used: %s
      \n",munge(s)); if (u = find_key (r,WLocal_Georeference_Information)) if (s = full_text (u)) fprintf (fp,"%s",munge(s)); } else { } if (r = find_key (q,WGeodetic_Model)) { if (u = find_key (r,WHorizontal_Datum_Name)) if (s = full_text (u)) fprintf (fp,"The horizontal datum used is %s.
      \n",munge(s)); if (u = find_key (r,WEllipsoid_Name)) if (s = full_text (u)) fprintf (fp,"The ellipsoid used is %s.
      \n",munge(s)); if (u = find_key (r,WSemi_major_Axis)) if (s = full_text (u)) fprintf (fp,"The semi-major axis of the ellipsoid used is %s.
      \n",munge(s)); if (u = find_key (r,WDenominator_of_Flattening_Ratio)) if (s = full_text (u)) fprintf (fp,"The flattening of the ellipsoid used is 1/%s.
      \n",munge(s)); } } /*----------------------------------------------------------*\ | Vertical \*----------------------------------------------------------*/ if (q = find_key (p,WVertical_Coordinate_System_Definition)) { fprintf (fp,"
      \n"); write_html_item (q); fprintf (fp,"
      \n"); } } fprintf (fp,"
    4. \n"); /* what.6b */ fprintf (fp,"
    \n"); fprintf (fp,"
  12. \n"); /* what.6 */ /*--------------------------------------------------------------*/ fprintf (fp,"
  13. How does the data set describe geographic features?\n"); if (p = find_key (first,WEntity_and_Attribute_Information)) { fprintf (fp,"
    \n"); for (q=p->child; q; q=q->next) switch (q->key) { case WDetailed_Description: if (r = find_key (q,WEntity_Type)) { fprintf (fp,"
    "); if (u = find_key (r,WEntity_Type_Label)) if (s = full_text (u)) fprintf (fp,"%s",munge(s)); fprintf (fp,"
    "); fprintf (fp,"
    "); if (u = find_key (r,WEntity_Type_Definition)) write_html_value (u); if (u = find_key (r,WEntity_Type_Definition_Source)) if (s = full_text (u)) fprintf (fp," (Source: %s)\n",munge(s)); fprintf (fp,"
    \n"); for (u=q->child; u; u=u->next) if (u->key == WAttribute) { fprintf (fp,"
    "); if (w = find_key (u,WAttribute_Label)) if (s = full_text (w)) fprintf (fp,"%s",munge(s)); fprintf (fp,"
    "); fprintf (fp,"
    "); if (w = find_key (u,WAttribute_Definition)) write_html_value (w); if (w = find_key (u,WAttribute_Definition_Source)) if (s = full_text (w)) fprintf (fp," (Source: %s)",munge(s)); if (w = find_key (u,WAttribute_Measurement_Frequency)) if (s = full_text (w)) fprintf (fp,"Frequency of measurement: %s\n",munge(s)); /*----------------------------------*\ | Tricky issues ahead! Find all | | the Enumerated_Domain elements | | and put them in a single table. | \*----------------------------------*/ if (w = find_key (u,WAttribute_Domain_Values)) { int count = 0; do { if (h = find_key (w,WEnumerated_Domain)) do { count++; } while (h = find_next_key (h,WEnumerated_Domain)); } while (w = find_next_key (w,WAttribute_Domain_Values)); if (count > 0) { fprintf (fp,"\n"); fprintf (fp,"\n"); w = find_key (u,WAttribute_Domain_Values); do { if (h = find_key (w,WEnumerated_Domain)) do { fprintf (fp,""); fprintf (fp,""); fprintf (fp,""); fprintf (fp,"\n"); } while (h = find_next_key (h,WEnumerated_Domain)); } while (w = find_next_key (w,WAttribute_Domain_Values)); fprintf (fp,"
    ValueDefinition
    "); if (hh = find_key (h,WEnumerated_Domain_Value)) if (s = full_text (hh)) fprintf (fp,"%s",munge(s)); fprintf (fp,""); if (hh = find_key (h,WEnumerated_Domain_Value_Definition)) if (s = full_text (hh)) if (*s) write_html_value (hh); else fprintf (fp," "); else fprintf (fp," "); else fprintf (fp," "); fprintf (fp,"
    \n"); } } /*----------------------------------*\ | Now find and show in tables all | | of the Range_, Codeset_, and | | Unrepresentable_ Domains. | \*----------------------------------*/ if (w = find_key (u,WAttribute_Domain_Values)) { do { if (h = find_key (w,WRange_Domain)) { fprintf (fp,"\n"); fprintf (fp,"\n"); if (hh = find_key (h,WRange_Domain_Minimum)) if (s = full_text (hh)) fprintf (fp,"\n",munge(s)); if (hh = find_key (h,WRange_Domain_Maximum)) if (s = full_text (hh)) fprintf (fp,"\n",munge(s)); if (hh = find_key (h,WAttribute_Units_of_Measure)) if (s = full_text (hh)) fprintf (fp,"\n",munge(s)); if (hh = find_key (h,WAttribute_Measurement_Resolution)) if (s = full_text (hh)) fprintf (fp,"\n",munge(s)); fprintf (fp,"
    Range of values
    Minimum:%s
    Maximum:%s
    Units:%s
    Resolution:%s
    \n"); } if (h = find_key (w,WCodeset_Domain)) { fprintf (fp,"\n"); fprintf (fp,"\n"); if (hh = find_key (h,WCodeset_Name)) if (s = full_text (hh)) fprintf (fp,"\n",munge(s)); if (hh = find_key (h,WCodeset_Source)) if (s = full_text (hh)) fprintf (fp,"\n",munge(s)); fprintf (fp,"
    Formal codeset
    Codeset Name:%s
    Codeset Source:%s
    \n"); } if (h = find_key (w,WUnrepresentable_Domain)) { if (s = full_text (h)) if (*s) { fprintf (fp,"\n"); write_html_value (h); fprintf (fp,"\n"); } } } while (w = find_next_key (w,WAttribute_Domain_Values)); } } fprintf (fp,"
    \n"); } break; case WOverview_Description: for (r=q->child; r; r=r->next) write_html_item (r); break; default: break; } fprintf (fp,"
    \n"); } fprintf (fp,"
  14. \n"); /* what.7 */ /*--------------------------------------------------------------*/ if (WData_Set_Structure != Wunknown) if (p = find_key (first,WData_Set_Structure)) { int WData_Set_Part = key_of ("Data_Set_Part"); fprintf (fp,"
  15. What are the components of this data set?\n"); fprintf (fp,"
    \n"); for (q=p->child; q; q=q->next) if (q->key == WData_Set_Part) write_data_set_part (q); fprintf (fp,"
    \n"); fprintf (fp,"
  16. \n"); /* what.8 */ } /*--------------------------------------------------------------*/ if (WTaxonomy != Wunknown) if (p = find_key (first,WTaxonomy)) { fprintf (fp,"
  17. What biological taxa does this data set concern?\n"); fprintf (fp,"
    \n"); write_html_item (p); fprintf (fp,"
    \n"); fprintf (fp,"
  18. \n"); /* what.9 */ } /*--------------------------------------------------------------*/ if (WAnalytical_Tool != Wunknown) if (p = find_key (first,WAnalytical_Tool)) { int WAnalytical_Tool_Description = key_of ("Analytical_Tool_Description"); int WTool_Access_Information = key_of ("Tool_Access_Information"); int WTool_Network_Resource_Name = key_of ("Tool_Network_Resource_Name"); int WTool_Access_Instructions = key_of ("Tool_Access_Instructions"); int WTool_Computer_and_Operating_System = key_of ("Tool_Computer_and_Operating_System"); int WTool_Contact = key_of ("Tool_Contact"); int WTool_Citation = key_of ("Tool_Citation"); int i,count,j; fprintf (fp,"
  19. What special analytical tools are available to help me understand this data set?\n"); /* How many Analytical_Tool elements are here? */ count = 0; for (q=p; q; q = find_next_key (q,WAnalytical_Tool)) count++; /* Write about each one in turn */ i = 0; fprintf (fp,"
    \n"); do { fprintf (fp,"
    Tool %d of %d\n",i,count); fprintf (fp,"
    \n"); if (q = find_key (p,WAnalytical_Tool_Description)) write_html_value (q); if (q = find_key (p,WTool_Access_Information)) { fprintf (fp,"How to obtain this tool:\n"); if (r = find_key (q,WTool_Network_Resource_Name)) { j = 0; fprintf (fp,"
      \n>"); do { if (s = full_text (r)) { fprintf (fp,"
    • %s\n",munge(s)); j++; } } while (r = find_next_key (r,WTool_Network_Resource_Name)); fprintf (fp,"
    \n>"); if (j > 0) fprintf (fp,"

    \n"); } if (r = find_key (q,WTool_Access_Instructions)) { fprintf (fp,"
    \n"); fprintf (fp,"
    How to access the tool:
    \n"); fprintf (fp,"
    \n"); write_html_item (r); fprintf (fp,"
    \n"); } if (r = find_key (q,WTool_Computer_and_Operating_System)) { fprintf (fp,"
    \n"); fprintf (fp,"
    Computer and operating system needed:
    \n"); fprintf (fp,"
    \n"); write_html_item (r); fprintf (fp,"
    \n"); } } if (q = find_key (p,WTool_Contact)) { fprintf (fp,"Whom to contact for more information:\n"); write_contact (q); } if (q = find_key (p,WTool_Citation)) { fprintf (fp,"References:\n"); write_citation (q); } } while (p = find_next_key (p,WAnalytical_Tool)); fprintf (fp,"
    \n"); fprintf (fp,"
  20. \n"); /* what.10 */ } fprintf (fp,"
\n"); /*--------------------------------------------------------------*\ \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); fprintf (fp,"

Who produced the data set?

\n"); fprintf (fp,"
    \n"); /* who */ /*--------------------------------------------------------------*/ fprintf (fp,"
  1. Who are the originators of the data set? (may include formal authors, digital compilers, and editors)\n"); if (p = find_key (first,WCitation)) if (q = find_key (p,WOriginator)) { fprintf (fp,"
      \n"); do { if (s = full_text (q)) fprintf (fp,"
    • %s\n",munge(s)); } while (q = find_next_key (q,WOriginator)); fprintf (fp,"
    \n"); } fprintf (fp,"
  2. \n"); /* who.1 */ /*--------------------------------------------------------------*/ fprintf (fp,"
  3. Who also contributed to the data set?\n"); if (p = find_key (first,WData_Set_Credit)) { fprintf (fp,"
    \n"); write_html_value (p); fprintf (fp,"
    \n"); } fprintf (fp,"
  4. \n"); /* who.2 */ /*--------------------------------------------------------------*/ fprintf (fp,"
  5. To whom should users address questions about the data?\n"); if (p = find_key (first,WPoint_of_Contact)) write_contact (p); fprintf (fp,"
  6. \n"); /* who.3 */ /*--------------------------------------------------------------*/ fprintf (fp,"
\n"); /* who */ /*--------------------------------------------------------------*\ \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); fprintf (fp,"

Why was the data set created?

\n"); if (p = find_key (first,WPurpose)) { fprintf (fp,"
\n"); write_html_value (p); fprintf (fp,"
\n"); } /*--------------------------------------------------------------*\ \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); fprintf (fp,"

How was the data set created?

\n"); fprintf (fp,"
    \n"); /* how */ if ((WMethodology != Wunknown) && find_key (first,WMethodology)) { int WMethodology_Type = key_of ("Methodology_Type"); int WMethodology_Identifier = key_of ("Methodology_Identifier"); int WMethodology_Description = key_of ("Methodology_Description"); int WMethodology_Citation = key_of ("Methodology_Citation"); int WMethodology_Keyword = key_of ("Methodology_Keyword"); int WMethodology_Keyword_Thesaurus = key_of ("Methodology_Keyword_Thesaurus"); int i,count; fprintf (fp,"
  1. What methods were used to collect the data?\n"); if (p = find_key (first,WData_Quality_Information)) if (p = find_key (p,WLineage)) if (p = find_key (p,WMethodology)) { count = 0; for (q=p; q; q = find_next_key (q,WMethodology)) count++; i = 0; fprintf (fp,"
    \n"); do { fprintf (fp,"
    Method %d of %d\n",i,count); fprintf (fp,"
    \n"); if (q = find_key (p,WMethodology_Type)) if (s = full_text (q)) fprintf (fp,"Type: %s
    \n",munge(s)); if (q = find_key (p,WMethodology_Description)) { write_html_value (q); } if (q = find_key (p,WMethodology_Citation)) { fprintf (fp,"Reference:
    \n"); write_citation (q); } } while (p = find_next_key (p,WMethodology)); } } fprintf (fp,"
  2. From what previous works were the data drawn?\n"); if (p = find_key (first,WLineage)) { int count = 0; if (q = find_key (p,WSource_Information)) { count++; while (q = find_next_key (q,WSource_Information)) count++; } if (q = find_key (p,WSource_Information)) { int k = 0; fprintf (fp,"
    \n"); do { k++; fprintf (fp,"
    "); if (r = find_key (q,WSource_Citation_Abbreviation)) if (s = full_text (r)) fprintf (fp,"%s",munge(s)); fprintf (fp," (source %d of %d)\n",k,count); fprintf (fp,"
    \n"); if (r = find_key (q,WSource_Citation)) if (r = find_key (r,WCitation_Information)) write_citation (r); fprintf (fp,"
    \n"); if (r = find_key (q,WType_of_Source_Media)) write_html_item (r); if (r = find_key (q,WSource_Scale_Denominator)) write_html_item (r); if (r = find_key (q,WSource_Contribution)) write_html_item (r); fprintf (fp,"
    \n"); } while (q = find_next_key (q,WSource_Information)); fprintf (fp,"
    \n"); } } fprintf (fp,"
  3. \n"); /* how.1 */ fprintf (fp,"
  4. How were the data generated, processed, and modified?\n"); if (p = find_key (first,WLineage)) { int count = 0; if (q = find_key (p,WProcess_Step)) { count++; while (q = find_next_key (q,WProcess_Step)) count++; } if (q = find_key (p,WProcess_Step)) { int k = 0; fprintf (fp,"
    \n"); do { k++; fprintf (fp,"
    "); if (r = find_key (q,WProcess_Date)) if (s = full_text (r)) { fprintf (fp,"Date: "); write_date (s); } fprintf (fp," (process %d of %d)\n",k,count); fprintf (fp,"
    \n"); if (r = find_key (q,WProcess_Description)) write_html_value (r); if (r = find_key (q,WProcess_Contact)) { fprintf (fp,"Person who carried out this activity:
    \n"); write_contact (r); } if (r = find_key (q,WSource_Used_Citation_Abbreviation)) { fprintf (fp,"Data sources used in this process:\n"); fprintf (fp,"
      \n"); do { if (s = full_text (r)) fprintf (fp,"
    • %s\n",munge(s)); } while (r = find_next_key (r,WSource_Used_Citation_Abbreviation)); fprintf (fp,"
    \n"); } if (r = find_key (q,WSource_Produced_Citation_Abbreviation)) { fprintf (fp,"Data sources produced in this process:\n"); fprintf (fp,"
      \n"); do { if (s = full_text (r)) fprintf (fp,"
    • %s\n",munge(s)); } while (r = find_next_key (r,WSource_Produced_Citation_Abbreviation)); fprintf (fp,"
    \n"); } } while (q = find_next_key (q,WProcess_Step)); fprintf (fp,"
    \n"); } } fprintf (fp,"
  5. \n"); /* how.2 */ fprintf (fp,"
  6. What similar or related data should the user be aware of?\n"); if (p = find_key (first,WIdentification_Information)) if (p = find_key (p,WCross_Reference)) do { if (q = find_key (p,WCitation_Information)) write_citation (q); } while (p = find_next_key (p,WCross_Reference)); fprintf (fp,"
  7. \n"); /* how.3 */ fprintf (fp,"
\n"); /* how */ /*--------------------------------------------------------------*\ \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); fprintf (fp,"

How reliable are the data; what problems remain in the data set?

\n"); if (p = find_key (first,WData_Quality_Information)) { fprintf (fp,"
    \n"); /* quality */ fprintf (fp,"
  1. How well have the observations been checked?
    \n"); if (q = find_key (p,WAttribute_Accuracy_Report)) write_html_value (q); fprintf (fp,"
  2. \n"); /* quality.1 */ fprintf (fp,"
  3. How accurate are the geographic locations?
    \n"); if (q = find_key (p,WHorizontal_Positional_Accuracy_Report)) write_html_value (q); fprintf (fp,"
  4. \n"); /* quality.2 */ fprintf (fp,"
  5. How accurate are the heights or depths?
    \n"); if (q = find_key (p,WVertical_Positional_Accuracy_Report)) write_html_value (q); fprintf (fp,"
  6. \n"); /* quality.3 */ fprintf (fp,"
  7. Where are the gaps in the data? What is missing?
    \n"); if (q = find_key (p,WCompleteness_Report)) write_html_value (q); fprintf (fp,"
  8. \n"); /* quality.4 */ fprintf (fp,"
  9. How consistent are the relationships among the observations, including topology?
    \n"); if (q = find_key (p,WLogical_Consistency_Report)) write_html_value (q); fprintf (fp,"
  10. \n"); /* quality.5 */ fprintf (fp,"
\n"); /* quality */ } /*--------------------------------------------------------------*\ \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); fprintf (fp,"

How can someone get a copy of the data set?

\n"); fprintf (fp,"
\n"); fprintf (fp,"Are there legal restrictions on access or use of the data?\n"); fprintf (fp,"
\n"); if (p = find_key (first,WIdentification_Information)) { fprintf (fp,"
\n"); if (q = find_key (p,WAccess_Constraints)) write_html_item (q); if (q = find_key (p,WUse_Constraints)) write_html_item (q); fprintf (fp,"
\n"); } fprintf (fp,"
\n"); fprintf (fp,"
\n"); /* How many distributors are there? */ distributor = 0; distributor_count = 0; if (p = find_key (first,WDistribution_Information)) do { if (q = find_key (p,WDistributor)) distributor_count++; } while (p = find_next_key (p,WDistribution_Information)); counter = 0; if (p = find_key (first,WDistribution_Information)) do { fprintf (fp,"
    \n"); /* getacopy */ if (counter == 0) fprintf (fp,"
  1. Who distributes the data set?"); else fprintf (fp,"
  2. Who distributes the data set?",counter); if (q = find_key (p,WDistributor)) { distributor++; fprintf (fp," (Distributor %d of %d)
    \n",distributor,distributor_count); write_contact (q); } else fprintf (fp,"[Distributor contact information not provided.]\n"); fprintf (fp,"
  3. \n"); /* getacopy.1 */ if (counter == 0) fprintf (fp,"
  4. What's the catalog number I need to order this data set?\n"); else fprintf (fp,"
  5. What's the catalog number I need to order this data set?\n",counter); if (q = find_key (p,WResource_Description)) if (s = full_text (q)) { fprintf (fp,"%s\n",munge(s)); } fprintf (fp,"
  6. \n"); /* getacopy.2 */ if (counter == 0) fprintf (fp,"
  7. What legal disclaimers am I supposed to read?\n"); else fprintf (fp,"
  8. What legal disclaimers am I supposed to read?\n",counter); if (q = find_key (p,WDistribution_Liability)) { fprintf (fp,"
    \n"); write_html_value (q); fprintf (fp,"
    \n"); } fprintf (fp,"
  9. \n"); /* getacopy.3 */ if (counter == 0) fprintf (fp,"
  10. How can I download or order the data?\n"); else fprintf (fp,"
  11. How can I download or order the data?\n",counter); /*------------------------------------------------------*\ | for each Standard_Order_Process | for each Digital_Form | Format_Information_Content | Format_Name | Format_Version or Format_Date | Format_Specification | Transfer_Size | for each Digital_Transfer_Option | if Online_Option | label "Online access" | for each Online_Option | for each Computer_Contact_Information | find Network_Address | for each Network_Resource_Name | list the value | if Offline_Option | label "Offline ordering" | for each Offline_Option | Offline_Media | Recording_Density | Recording_Density_Units | Recording_Format | Compatibility_Information \*------------------------------------------------------*/ if (q = find_key (p,WStandard_Order_Process)) { do { fprintf (fp,"
      \n"); if (r = find_key (q,WDigital_Form)) { fprintf (fp,"
    • Availability in digital form:\n"); do { fprintf (fp,"\n"); fprintf (fp,"\n"); fprintf (fp,"\n"); fprintf (fp,"\n"); if (u = find_key (r,WDigital_Transfer_Option)) { if (w = find_key (u,WOnline_Option)) { fprintf (fp,"\n"); fprintf (fp,"\n"); fprintf (fp,"\n"); } if (w = find_key (u,WOffline_Option)) { fprintf (fp,"\n"); fprintf (fp,"\n"); fprintf (fp,"\n"); } } fprintf (fp,"
      Data format:\n"); if (u = find_key (r,WFormat_Information_Content)) { write_html_value (u); if (u = find_key (r,WFormat_Name)) if (s = full_text (u)) fprintf (fp," in format %s",munge(s)); } else if (u = find_key (r,WFormat_Name)) if (s = full_text (u)) fprintf (fp,"%s",munge(s)); fprintf (fp,"\n"); if (u = find_key (r,WFormat_Version_Number)) if (s = full_text (u)) fprintf (fp," (version %s)",munge(s)); else if (u = find_key (r,WFormat_Version_Date)) if (s = full_text (u)) { fprintf (fp," (version of "); write_date (s); fprintf (fp,")"); } fprintf (fp,"\n"); if (u = find_key (r,WFormat_Specification)) write_html_value (u); /* NBII extension describing ASCII file structure */ if (WASCII_File_Structure != Wunknown) if (u = find_key (r,WASCII_File_Structure)) { fprintf (fp,"
      \n"); write_html_item (u); fprintf (fp,"
      \n"); } if (u = find_key (r,WTransfer_Size)) if (s = full_text (u)) fprintf (fp,"Size: %s\n",munge(s)); fprintf (fp,"
      Network links:\n"); do { struct item *w1,*w2,*w3; if (w1 = find_key (w,WComputer_Contact_Information)) do { if (w2 = find_key (w1,WNetwork_Address)) if (w3 = find_key (w2,WNetwork_Resource_Name)) do { if (s = full_text (w3)) fprintf (fp,"%s
      \n",munge(s)); } while (w3 = find_next_key (w3,WNetwork_Resource_Name)); } while (w1 = find_next_key (w1,WComputer_Contact_Information)); } while (w = find_next_key (w,WOnline_Option)); fprintf (fp,"
      Media you can order:\n"); do { if (h = find_key (w,WOffline_Media)) if (s = full_text (h)) fprintf (fp,"%s\n",munge(s)); if (h = find_key (w,WRecording_Density)) if (s = full_text (h)) fprintf (fp,"(Density %s\n",munge(s)); if (h = find_key (w,WRecording_Density_Units)) if (s = full_text (h)) fprintf (fp,"%s)\n",munge(s)); if (h = find_key (w,WRecording_Format)) if (s = full_text (h)) fprintf (fp,"(format %s)\n",munge(s)); if (h = find_key (w,WCompatibility_Information)) if (s = full_text (h)) fprintf (fp,"
      Note: %s\n",munge(s)); } while (w = find_next_key (w,WOffline_Option)); fprintf (fp,"
      \n"); } while (r = find_next_key (r,WDigital_Form)); } if (r = find_key (q,WNon_digital_Form)) { fprintf (fp,"
    • Availability in non-digital form:
      \n"); write_html_value (r); } fprintf (fp,"
    • Cost to order the data: "); if (r = find_key (q,WFees)) { if (s = full_text (r)) { if (strlen (s) > 64) fprintf (fp,"

      \n"); fprintf (fp,"%s

      \n",munge(s)); } } if (r = find_key (q,WOrdering_Instructions)) { fprintf (fp,"
    • Special instructions:\n"); fprintf (fp,"
      \n"); write_html_value (r); fprintf (fp,"
      \n"); } if (r = find_key (q,WTurnaround)) { fprintf (fp,"
    • How long will it take to get the data?\n"); fprintf (fp,"
      \n"); write_html_value (r); fprintf (fp,"
      \n"); } fprintf (fp,"
    \n"); } while (q = find_next_key (q,WStandard_Order_Process)); } fprintf (fp,"
  12. \n"); /* getacopy.4 */ if (q = find_key (p,WCustom_Order_Process)) { if (counter == 0) fprintf (fp,"
  13. Is there some other way to get the data?\n"); else fprintf (fp,"
  14. Is there some other way to get the data?\n",counter); fprintf (fp,"
    \n"); write_html_value (q); fprintf (fp,"
    \n"); fprintf (fp,"
  15. \n"); /* getacopy.5 */ } if (q = find_key (p,WTechnical_Prerequisites)) { if (counter == 0) fprintf (fp,"
  16. What hardware or software do I need in order to use the data set?\n"); else fprintf (fp,"
  17. What hardware or software do I need in order to use the data set?\n",counter); fprintf (fp,"
    \n"); write_html_value (q); fprintf (fp,"
    \n"); fprintf (fp,"
  18. \n"); /* getacopy.6 */ } if (find_next_key (p,WDistribution_Information)) fprintf (fp,"
    \n"); fprintf (fp,"
\n"); /* getacopy */ counter++; } while (p = find_next_key (p,WDistribution_Information)); /*--------------------------------------------------------------*\ \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); fprintf (fp,"

Who wrote the metadata?

\n"); if (p = find_key (first,WMetadata_Reference_Information)) { fprintf (fp,"
\n"); /* Metadata_Date and friends */ fprintf (fp,"
Dates:\n"); fprintf (fp,"
"); if (q = find_key (p,WMetadata_Date)) if (s = full_text (q)) { fprintf (fp,"Last modified: "); write_date (s); fprintf (fp,"
\n"); } if (q = find_key (p,WMetadata_Review_Date)) if (s = full_text (q)) { fprintf (fp,"Last Reviewed: "); write_date (s); fprintf (fp,"
\n"); } if (q = find_key (p,WMetadata_Future_Review_Date)) if (s = full_text (q)) { fprintf (fp,"To be reviewed: "); write_date (s); fprintf (fp,"
\n"); } fprintf (fp,"
\n"); /* Metadata_Contact */ fprintf (fp,"
Metadata author:\n"); fprintf (fp,"
\n"); if (q = find_key (p,WMetadata_Contact)) write_contact (q); fprintf (fp,"
\n"); /* Standard name and version */ if (q = find_key (p,WMetadata_Standard_Name)) if (s = full_text (q)) fprintf (fp,"
Metadata standard:
%s",munge(s)); if (q = find_key (p,WMetadata_Standard_Version)) if (s = full_text (q)) fprintf (fp," (%s)",munge(s)); if (q = find_key (p,WMetadata_Extensions)) { fprintf (fp,"
Metadata extensions used:\n"); fprintf (fp,"
\n"); fprintf (fp,"
    \n"); do { if (r = find_key (q,WProfile_Name)) if (s = full_text (q)) fprintf (fp,"
  • %s
  • \n",munge(s)); if (r = find_key (q,WOnline_Linkage)) do { if (s = full_text (r)) fprintf (fp,"
  • %s
  • \n",munge(s)); } while (r = find_next_key (r,WOnline_Linkage)); } while (q = find_next_key (q,WMetadata_Extensions)); fprintf (fp,"
\n"); fprintf (fp,"
\n"); } fprintf (fp,"
\n"); } /*--------------------------------------------------------------*\ | Bottom of page. If BASE was specified, write the page URL. | \*--------------------------------------------------------------*/ fprintf (fp,"
\n"); if (opt = find_option (NULL,"output")) if (opt = find_option (opt,"html")) if (!find_option (opt,"omit_url")) if (opt = find_option (opt,"base")) if (s = text_of_option (opt)) { fprintf (fp,"This page is <%s",s); if (*(s + strlen(s) - 1) != '/') fprintf (fp,"/"); fprintf (fp,"%s>
\n",output_file); } /*--------------------------------------------------------------*\ | Output user-specified footer if there is one. | \*--------------------------------------------------------------*/ if (opt = find_option (NULL,"output")) if (opt = find_option (opt,"html")) if (v = find_option (opt,"footer")) { if (s = text_of_option (v)) fprintf (fp,"%s\n",s); } else if (v = find_option (opt,"footer_file")) { if (s = text_of_option (v)) { if (t = read_text (s)) { char *tt = t + strlen (t) - 1; fprintf (fp,"\n",s); fprintf (fp,"%s",t); if (*tt != '\n') fprintf (fp,"\n"); fprintf (fp,"\n",s); free (t); } } } /*--------------------------------------------------------------*\ | Put a link and a time-stamp into the output file. | \*--------------------------------------------------------------*/ T = time (&T); t = ctime (&T); s = t + strlen (t) - 1; if (*s == '\n') *s-- = 0; if (*s == '\r') *s-- = 0; fprintf (fp,"Generated by mp version %s on %s
\n",revision.mp,t); /*--------------------------------------------------------------*\ \*--------------------------------------------------------------*/ fprintf (fp,"\n"); fprintf (fp,"\n"); fprintf (fp,"\n"); fclose (fp); } else { fprintf (stderr,"Error: could not create output file %s\n",output_file); return; } } /*----------------------------------------------------------------------*\ \*----------------------------------------------------------------------*/