Alien-Judy
view release on metacpan or search on metacpan
src/judy-1.0.5/tool/jhton.c view on Meta::CPAN
} // CheckNesting()
// ****************************************************************************
// E M I T N R O F F H E A D E R
//
// Given the input filename, a pointer to a page name string to return, and the
// docnode tree under g_Pdnhead, extract header info and emit nroff header
// lines.
FUNCTION void EmitNroffHeader(
char * Filename, // input file.
char ** PPageName) // such as "Judy1", to return.
{
char * filerev = PCNULL; // from first comment in input.
char * pagesection; // such as "3X".
char lcletter; // manual tab section, such as "j".
char * revision; // from centered table datum.
time_t currtime; // for ctime().
// Extract "weird" header values:
//
// These must be found in the docnodes tree and prepared for emitting nroff.
ExtractHeader(g_Pdnhead, &filerev,
PPageName, &pagesection, &lcletter, &revision);
if (filerev == PCNULL)
{
Error(ERREXIT, NOERRNO, "HTML file lacks comment lines; it must "
"contain at least one comment line, and the first one must "
"contain revision information");
}
// Emit file header; note, ctime() output already contains a newline:
(void) time(&currtime);
(void) printf(".\\\" Auto-translated to nroff -man from %s by %s at %s",
Filename, gc_myname, ctime(&currtime));
(void) printf(".\\\" %s\n", filerev);
(void) printf(".TA %c\n", lcletter);
(void) printf(".TH %s %s\n", *PPageName, pagesection);
(void) puts( ".ds )H Hewlett-Packard Company");
(void) printf(".ds ]W %s\n", revision);
} // EmitNroffHeader()
// ****************************************************************************
// E M I T N R O F F B O D Y
//
// Given a current node in the docnodes tree, the current <DL> level, a flag
// whether below a <PRE> node, the manual entry page name, and in
// g_prevlinenum, the previous input line number that resulted in output,
// recursively emit nroff body text. Translate the HTML docnodes as described
// in the comments prior to EmitNroffHeader(), and also translate certain HTML
// escaped chars back to literal form. Hope the results are legal nroff
// without spurious unintended nroff commands embedded.
//
// Note: This function recurses two ways; first, to the child subtree, and
// second, to the next sibling at the current level.
FUNCTION void EmitNroffBody(
Pdn_t Pdn, // current top of subtree.
int DLLevel, // <DL> level, top = 0.
int InPRE, // bit flags for <PRE> handling.
char * PageName) // such as "Judy1".
{
int DLcount = 0; // set to 1 if hit <DL> here.
char * suffix = PCNULL; // to print after children, before siblings.
// When about to emit text, if the previous output came from a lower input line
// number, start with a newline; otherwise do not, and let the text
// concatenate:
//
// Use CHECKPREV except when the text to be emitted is forced to a new line.
#ifdef CPPRINT // for special debugging:
#define CHECKPREVPRINT printf("\ncp %d %d\n", g_prevlinenum, Pdn->dn_linenum)
#else
#define CHECKPREVPRINT // null
#endif
#define CHECKPREV \
CHECKPREVPRINT; \
{ if (g_prevlinenum && (g_prevlinenum < (Pdn->dn_linenum))) PUTC('\n');}
// To support CHECKPREV, call SETPREV() after emitting text that might need a
// line break to a new line, or SETPREVNONL to ensure NO newline, that is, the
// next text concatenates on the same line:
//
// Note: For a correct line number, SETPREV() must account for any newlines in
// the text just emitted.
#define SETPREV(Text) g_prevlinenum = (Pdn->dn_linenum) + CountNewlines(Text)
#define SETPREVNONL g_prevlinenum = g_linenumlim // no newline.
// Check if under a lower-level <DL>, for continuing an indented paragraph:
#define UNDER_DL ((DLLevel > 1) \
&& ((Pdn->dn_Pparent) != PDNNULL) \
&& ((Pdn->dn_Pparent->dn_type) == DN_TYPE_DL))
// SWITCH ON DOCNODE TYPE:
if (Pdn->dn_noemit) // upstream node said to skip this one.
goto NextNode;
switch (Pdn->dn_type)
{
// DOCUMENT TEXT:
//
// Just emit it with HTML escaped chars modified, with backslashes doubled,
// with no trailing newline, and if not within <PRE> text, with any leading
// whitespace deleted, so that, for example, something like "\fI text\fP" does
// not result.
case DN_TYPE_TEXT:
assert((Pdn->dn_text) != PCNULL);
CHECKPREV;
EmitText(Pdn->dn_text, InPRE, Pdn->dn_linenum);
SETPREV(Pdn->dn_text);
break;
// IGNORE THESE TYPES:
//
// See EmitNroffHeader() for nroff equivalents already emitted in some cases.
// In some cases, mark all child nodes no-emit to ignore them.
case DN_TYPE_HTML:
case DN_TYPE_HEAD:
case DN_TYPE_BODY:
case DN_TYPE_COMM: break;
case DN_TYPE_TITLE:
case DN_TYPE_TABLE:
case DN_TYPE_TR:
case DN_TYPE_TD:
MarkNoEmit(Pdn->dn_Pchild, /* Font = */ FALSE);
break;
// DESCRIPTIVE LIST:
//
// At the top level these represent manual entry sections, and any bold markers
// around the text are ignored. Below the top level these translate to tagged
// paragraphs. Here, just note the increment and continue the walk.
case DN_TYPE_DL:
DLcount = 1;
break;
// DESCRIPTIVE LIST TAG:
case DN_TYPE_DT:
assert(NEST(DN_TYPE_DT)); // tag text must be child.
if ((Pdn->dn_Pchild) == PDNNULL) // no child exists.
{
Error(ERREXIT, NOERRNO, "HTML tag \"%s\" found at input line "
"%d lacks text, which is required by this translator",
TAG(DN_TYPE_DT), Pdn->dn_linenum);
}
// Further handling depends on DLLevel as explained above:
if (DLLevel <= 1) // major manual section.
src/judy-1.0.5/tool/jhton.c view on Meta::CPAN
// ****************************************************************************
// P A R E N T P R E
//
// Given a docnode (can be null) and a flag whether only bold <PRE> is of
// interest, return TRUE if any of its parents is a <PRE> (marked for bold
// text), that is, DN_TYPE_PRE (with dn_bold set); otherwise return FALSE.
FUNCTION bool_t ParentPre(
Pdn_t Pdn, // starting node.
bool_t BoldOnly) // flag: only care about bold <PRE>.
{
if (Pdn == PDNNULL) return (FALSE); // no parent.
for (Pdn = Pdn->dn_Pparent; Pdn != PDNNULL; Pdn = Pdn->dn_Pparent)
{
if (((Pdn->dn_type) == DN_TYPE_PRE)
&& ((! BoldOnly) || (Pdn->dn_bold)))
{
return(TRUE);
}
}
return(FALSE);
} // ParentPre()
// ****************************************************************************
// M A R K N O E M I T
//
// Given a docnode (can be null), and a flag, recursively mark the node and all
// children and siblings as do-not-emit, unless the flag is set, only mark font
// docnodes.
FUNCTION void MarkNoEmit(
Pdn_t Pdn, // top node to mark.
bool_t Font) // flag: only mark font docnodes.
{
if (Pdn == PDNNULL) return;
if ((! Font)
|| ((Pdn->dn_type) == DN_TYPE_B)
|| ((Pdn->dn_type) == DN_TYPE_I))
{
(Pdn->dn_noemit) = TRUE;
}
if ((Pdn->dn_Pchild) != PDNNULL) MarkNoEmit(Pdn->dn_Pchild, Font);
if ((Pdn->dn_Pnext) != PDNNULL) MarkNoEmit(Pdn->dn_Pnext, Font);
} // MarkNoEmit()
// ****************************************************************************
// E M I T T E X T
//
// Given a text string, a bitflag for <PRE> status, and an input line number
// for error reporting, copy the text string to stdout with no added newlines,
// but translating selected HTML escape codes to simple characters, doubling
// any backslashes, and if InPRE, inserting .IP (if INPRE_INDENT) or .PP at
// blank lines (between successive newlines), and if INPRE_BOLD, putting back
// bold font since .IP/.PP seems to reset the font. Warn about unrecognized
// escape codes.
struct et_list {
char * et_escape; // expected text.
size_t et_len; // of expected text.
char et_emit; // equivalent char.
} et_list[] = {
{ "amp;", 4, '&', },
{ "gt;", 3, '>', },
{ "lt;", 3, '<', },
{ PCNULL, 0, ' ', }, // end of list.
};
FUNCTION void EmitText(
char * Pch, // text to emit.
int InPRE, // bitflag for <PRE> status.
int Linenum) // for error reporting.
{
char * Pch2; // place in text.
struct et_list * Pet; // place in et_list[].
while ((Pch2 = strchr(Pch, '&')) != PCNULL) // another escape code.
{
*Pch2 = CHNULL; // briefly terminate.
EmitTextPRE(Pch, InPRE); // emit preceding part.
*Pch2 = '&';
Pch = Pch2 + 1; // past '&'.
for (Pet = et_list; Pet->et_escape != PCNULL; ++Pet)
{
if (strncmp(Pch, Pet->et_escape, Pet->et_len) == 0)
{
PUTC(Pet->et_emit); // translate.
Pch += Pet->et_len; // skip escapecode.
break;
}
}
if (Pet->et_escape == PCNULL) // no match found.
{
Error(NOEXIT, NOERRNO, "Unrecognized HTML escape code in "
"line %d (or text beginning on that line): \"%.4s...\", "
"passed through unaltered", Linenum, Pch2);
PUTC('&'); // emit start of escape code.
// continue with Pch is just after the '&'.
}
}
EmitTextPRE(Pch, InPRE); // emit remaining part.
} // EmitText()
// ****************************************************************************
// E M I T T E X T P R E
//
// Given a text string with no HTML escape codes in it and a bitflag for <PRE>
// status (see EmitText()), emit the string with <PRE> handling, and with any
// backslashes doubled.
FUNCTION void EmitTextPRE(
char * Pch, // string to emit.
int InPRE) // bitflag for <PRE> status.
{
char * Pch2; // place in string.
if (! InPRE) { EmitTextBS(Pch); return; }
while ((Pch2 = strchr(Pch, '\n')) != PCNULL) // another newline.
{
*Pch2 = CHNULL; // briefly terminate.
EmitTextBS(Pch); // emit preceding part.
*Pch2 = '\n';
PUTC('\n'); // emit current newline.
if (*(Pch = Pch2 + 1) == '\n') // successive newline.
{
// emit before next newline:
PUTS((InPRE & INPRE_INDENT) ? ".IP" : ".PP");
// also reset font:
if (InPRE & INPRE_BOLD) PUTS("\n.ft B");
}
}
EmitTextBS(Pch); // emit trailing part.
} // EmitTextPRE()
// ****************************************************************************
// E M I T T E X T B S
//
// Given a text string with no HTML escape codes in it, emit the string with
// any backslashes doubled.
FUNCTION void EmitTextBS(
char * Pch) // string to emit.
{
while (*Pch != CHNULL)
{
PUTC(*Pch); if (*Pch == '\\') PUTC('\\');
++Pch;
}
} // EmitTextBS()
// ****************************************************************************
// N O W H I T E S P A C E
//
// Given a string, return TRUE if it contains no whitespace, otherwise FALSE.
FUNCTION bool_t NoWhiteSpace(
char * Pch) // string to check.
{
assert(Pch != PCNULL);
while (*Pch != CHNULL) { if (ISSPACE(*Pch)) return(FALSE); ++Pch; }
return(TRUE);
} // NoWhiteSpace()
// ****************************************************************************
// C O U N T N E W L I N E S
//
// Return the number of newline chars in a string.
FUNCTION int CountNewlines(
char * Pch) // in which to count newlines.
{
int count = 0;
assert(Pch != PCNULL);
while (*Pch != CHNULL) count += ((*Pch++) == '\n');
return(count);
} // CountNewlines()
// ****************************************************************************
// S T R S A V E
//
// Given a string, copy the string into malloc'd space and return a pointer to
// the new copy. Error out if malloc() fails.
FUNCTION char * StrSave(
char * string)
{
return(strcpy((char *) Malloc((size_t) (strlen(string) + 1)), string));
} // StrSave()
( run in 1.406 second using v1.01-cache-2.11-cpan-354807fb38d )