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 )