/*****************************************************************************/ /* sdm2htm.c The SDM2HTM utility converts SDML (VAX DOCUMENT source) into HTML (Hyper-Text Markup Language). Not bullet-proof! No apologies; this is a quick throw- together to get our SDML documentation available to the hypertext environment. (NOTE at 23-JAN-1995; even with HyperReader working reasonably well and providing access to native Bookreader documents this utility still has a valuable function in providing HTML-formatted versions, which look and work better under Web browsers) This program cannot be understood without a knowledge of VAX DOCUMENT and HTML, and without reference to descriptions of DOCUMENT markup tags. Uses recursive function calls extensively ... The need for recursion is illustrated by the following SDML fragment: "(The (Need For (Recursion\BOLD)))\symbol) Uses fixed size buffers for all processing. This means that there is fixed capacity for such constructs as a tag's parameter parentheses ( e.g. (...)) The size of these buffers is generous, but still finite. Checks for buffer overflow are included. This utility could be improved by making these buffers dynamically allocated, and expand as string sizes demanded. Sigh! Many common GLOBAL tags are handled elegantly. This utility does not pretend to provide a complete SDML conversion. It is easily extensible. It does not do any sort of syntax checking. It relies on the prior use of DOCUMENT to ensure that all all syntax problems are detected and corrected. It assumes that the source is syntax-problem-free. The file names generated comprise three components. First the source file name, separated from the other two by an underscore. Second the number as two digits, 01 to 99. Third, the sub-chapter () files as two digits, 00 to 99. Hence file names look like ... NAME_0100.HTML DOCUMENT tags occur in files with digits 0000 to 0099. A "Table Of Contents" file is created (NAME_0000). A tag becomes a "Title Page" HTML file (usually NAME_0001). A tag becomes a "Copyright Page" HTML file (usually NAME_0002). A tag becomes a "Preface" HTML file (usually NAME_0003). Each becomes a separate HTML file (NAME_nn00). tags become separate HTML files (NAME_nnnn). tags become separate HTML files (NAME_nnnn). s have the leading spaces absorbed according to the number of them on the first line of multi-line examples. If this is atypical of the following line "mark" where the leading spaces should be absorbed to using a backspace characters (^H, i.e. in TPU use ^V^H). Both SDMTHM (i.e. browsers) and DOCUMENT render this correctly. HTML/DOCUMENT SPECIFIC OUTPUT ----------------------------- HTML control is enabled from within (...) tags. As this is embedded in comment tags DOCUMENT nevers sees it, allowing HTML directives to be passed to this utility. These directives are: (HTML/OFF) turns off HTML generation, allowing printed/Bookreader specific text to be generated. (HTML/ON) turns HTML generation back on. (URL/ON) turns URL-looking text into a link. (URL/OFF) turns URL-looking link generation off. (HREF=...) allows a link to a symbol in an external document to be added in much the same way as a (..) does for the current document. The syntax of the (HREF=..) must be the absolute or relative file specification for the document containing the symbol, a '!' character, the relative path to that document used in the generated link, a '#' character, then the symbols string. This construct expects to be followed by an (..) file containing a reference to the external document for DOCUMENT to use. The next is suppressed in the HTML document! An example usage: (see (HREF=[-.CONFIG]CONFIG.SDML!../config/#example_symbol) (config.sdml)). Bit clunky I'll admit but does add a certain usability between HTML documents. (HTML=...) allows HTML specific markup text to be provided for Hyper- Text documents, but is off course hidden from VAX DOCUMENT and is not included in printed/online text. (HTML/POPUP=...) ... (HTML/ENDPOPUP) creates a separate HTML file that is linked to using the text following the /POPUP=. QUALIFIERS ---------- /[NO]COMMENTS SDML s are included (default: NO) /COMPATIBILITY=integer provide some level of backward compatible behaviour /BODY=string string for tag attributes /[NO]COLOUR default is document colour, specify fo no colour /DBUG turns on all "if (Debug)" statements /DIRECTORY=string directory into which to place the generated HTML files /[NO]FLAG_UNKNOWN_TAGS report all unknown tags (default: NO) /[NO]FRAMED create an HTML framed document (default: NO) /HREF=string generate a HREF cross-reference for another document /[NO]HTML output HTML (default), /NOHTML allows checking /INDEX=[file-name] create a "home page" also with the name_0000.HTML /[NO]ODS5 control extended file specification (basically testing) /[NO]QUIET display no messages except errors /[NO]SENTENCE_SPACING add a   after sentence-terminating periods /STYLE[=url] use a CSS style sheet, or use this style sheet /[NO]UNKNOWN_TAGS include commented-out unknown flags (default: NO) /[NO]VERBOSE display progress messages (default) /VERSION display software version BUILD DETAILS ------------- See BUILD_SDM2HTM.COM COPYRIGHT --------- Copyright (C) 1996-2016 Mark G.Daniel This program, comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it the under the conditions of the GNU GENERAL PUBLIC LICENSE, version 3 or any later version. http://www.gnu.org/licenses/gpl.txt VERSION HISTORY (update SoftwareID as well!) --------------- 30-JAN-2016 MGD v1.11.7, 21st century buttons (sorta) 26-MAR-2015 AMc v1.11.6, support , and 07-FEB-2015 MGD v1.11.5, bugfix; (again!) ProcessTag() IncludeFile[] 10-DEC-2014 MGD v1.11.4, bugfix; ProcessTag() (HREF=..) 04-FEB-2014 MGD v1.11.3, INDEX.HTML to index.html 13-JUL-2013 MGD v1.11.2, 09-APR-2012 MGD v1.11.1, MSIE 26-JUL-2009 MGD v1.11.0, XHTML compliance, CSS formatting and /STYLE external cross-reference and /HREF obsolete /[NO]SENTENCE_SPACING 02-MAR-2008 MGD v1.10.9, fragment references a hash rather than symbolic (eryup, never content) 16-SEP-2006 MGD v1.10.8, fragment references symbolic rather than numeric 23-DEC-2003 MGD v1.10.7, minor conditional mods to support IA64 add a bit of space around table borders 31-MAR-2003 MGD v1.10.6, in line with general WASD doco changes LINK and VLINK colours from 0000ff to 0000cc, table row colour to #eeeeee 17-NOV-2002 MGD v1.10.5, remove '\n' in HTML, add

before

  • in lists 29-DEC-2001 MGD v1.10.4, make /NOSENTENCE_SPACING the default 17-MAY-2001 MGD v1.10.3, provide for (SIMPLE) using
    , add /VERSION for easily identification 04-FEB-2001 MGD v1.10.2, bugfix; no trailing '\n' on some 25-JAN-2001 MGD v1.10.1, bugfix; += associated with s 20-DEC-2000 MGD v1.10.0, add ChapterReferences(), modify table-of-contents generation, provide /COMPATIBILITY, (after looking at this again after some period of time I'm a little embarressed) 20-AUG-2000 MGD v1.9.1, add colour to 09-APR-2000 MGD v1.9.0, support extended file specifications (ODS-5), add a   after sentence-terminating periods, integrated MCJ modifications noted below 11-Feb-2000 MCJ V1.8.2gw, Change
  • ", -1); } else htptr = StringCopy (&ErrorInfo, htptr, &Capacity, " align=\"left\" valign=\"top\"> ", -1); Buffer[0] = '\0'; ErrorInfo.SourceLineNumber = __LINE__; while (*sdptr == '\\') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } else htptr = StringCopy (&ErrorInfo, htptr, &Capacity, " align=\"left\" valign=\"top\"> ", -1); Buffer[0] = '\0'; } if (*sdptr == ')') sdptr++; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { TableRowCount++; if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); if (Buffer[0]) htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); else htptr = StringCopy (&ErrorInfo, htptr, &Capacity, " ", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); Buffer[0] = '\0'; ErrorInfo.SourceLineNumber = __LINE__; while (*sdptr == '\\') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); if (Buffer[0]) htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); else htptr = StringCopy (&ErrorInfo, htptr, &Capacity, " ", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); Buffer[0] = '\0'; } if (*sdptr == ')') sdptr++; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* note: <title>() tags can have up to 3 '\'-separated lines in them */ if (*sdptr == '(') { cptr = DocumentTitle; sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); for (sptr = Buffer; *sptr; *cptr++ = *sptr++); while (*sdptr == '\\') { *cptr++ = ' '; sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); for (sptr = Buffer; *sptr; *cptr++ = *sptr++); } *cptr = '\0'; if (*sdptr == ')') sdptr++; } sprintf (Scratch, "<title>%s\n

    %s

    \n", UnmarkupTitle(DocumentTitle), DocumentTitle); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { EndHtmlFile (SdmlFilePtr, HtmlFilePtr); TitlePageCount = ++FrontMatterCount; GenerateHtmlFileName (HtmlFilePtr, 0, TitlePageCount); CreateHtmlFile (HtmlFilePtr, SdmlFilePtr); /* in this case 'Symbol' will be generated by NoteReference() */ NoteReference (HtmlFilePtr, Symbol, "", "Title Page", 0); WriteContentsItem (HtmlFilePtr, 0, Symbol); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, HTML_DOCTYPE, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n\n", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, MetaInformation(SdmlFilePtr), -1); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n", -1); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, HtmlBodyTag, -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n\n", -1); EndHtmlFile (SdmlFilePtr, HtmlFilePtr); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "|", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1) || strsame (TagName, "", -1) || strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; } } else /*------------------------------------------------------------------------*/ /* Begin M.C.Jordan extensions */ if (strsame (TagName, "", -1)) { time_t time_now; /* Mcj */ struct tm *p; /* Mcj */ if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; } ErrorInfo.SourceLineNumber = __LINE__; time_now = time(NULL); p = localtime (&time_now); if (strsame (Buffer, "FULL", -1)) strftime (Buffer, sizeof(Buffer), "%d-%b-%Y %T", p); if (!Buffer[0]) strftime (Buffer, sizeof(Buffer), "%b %d, %Y", p); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n\n", -1); EndHtmlFile (SdmlFilePtr, HtmlFilePtr); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); while (*sdptr == '\\') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); } if (*sdptr == ')') sdptr++; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Symbol, sizeof(Symbol)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Scratch, sizeof(Scratch)); if (*sdptr == ')') sdptr++; } NoteReference (HtmlFilePtr, Symbol, "", Scratch, 1); } else /* End M.C.Jordan extensions */ /*------------------------------------------------------------------------*/ { /*************************/ /* unrecognised SDML tag */ /*************************/ if (PassNumber == 2) { UnknownTagCount++; if (FlagUnknownTags) { fprintf (stdout, "%%%s-W-TAG, unknown %s in line %d\n", Utility, TagName, SdmlFilePtr->LineNumber); } } if (!InsideComment++) { if (IncludeUnknownTags) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } } RecursionLevel--; return (sdptr); } /*****************************************************************************/ /* */ EndHtmlFile ( struct SdmlFileData *SdmlFilePtr, struct HtmlFileData *HtmlFilePtr ) { char *sptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "EndHtmlFile() |%s|\n", HtmlFilePtr->FileName); if (HtmlFilePtr->FileName[0]) { FlushOutputLine (HtmlFilePtr); if (ParagraphCount[ParagraphIndex=0]) { fputs ("

    \n", HtmlFilePtr); ParagraphCount[ParagraphIndex] = 0; } if (SectionNumber[0]) { /* there has been a previous chapter being output, finalize */ sptr = NavigationButtons (true); fputs (sptr, HtmlFilePtr->FilePtr); fputs ("\n\n", HtmlFilePtr->FilePtr); } CloseHtmlFile (HtmlFilePtr); HtmlFilePtr->FileName[0] = '\0'; } } /*****************************************************************************/ /* Raw HTML can be introduced into output text from the SDML source text by using the construct "(HTML=...)". */ char* RawHtml ( struct SdmlFileData *SdmlFilePtr, struct HtmlFileData *HtmlFilePtr, struct ErrorData *ErrorInfoPtr, char *sdptr, char *htptr, int Capacity ) { int status, ParenthesisCount = 0; char *cptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "RawHtml()\n"); /* allow for the terminating null */ if (Capacity) Capacity--; for (;;) { while (!*sdptr) { *htptr++ = '\n'; if (!Capacity--) BufferOverflow (ErrorInfoPtr); if (ReadSdmlLine (SdmlFilePtr) == NULL) { *htptr = '\0'; return (sdptr); } sdptr = SdmlFilePtr->InLine; } if (*sdptr == ')') { if (!ParenthesisCount) { *htptr = '\0'; return (sdptr); } ParenthesisCount--; if (Debug) fprintf (stdout, "Par..Count %d\n", ParenthesisCount); *htptr++ = *sdptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); continue; } if (*sdptr == '(') { ParenthesisCount++; if (Debug) fprintf (stdout, "Par..Count %d\n", ParenthesisCount); *htptr++ = *sdptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); continue; } if (*sdptr == '<') { *htptr++ = *sdptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); if (toupper(*sdptr) == 'A') { *htptr++ = *sdptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); while (*sdptr && isspace(*sdptr)) { *htptr++ = *sdptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); } if (strsame (sdptr, "HREF=\"", 6)) { cptr = FrameTargetTop; while (*cptr) { *htptr++ = *cptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); } } } continue; } *htptr++ = *sdptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); } } /*****************************************************************************/ /* Recursively called function. Skip all text between the parentheses of a "(...)" construct. */ char* AbsorbTagParameter ( struct SdmlFileData *SdmlFilePtr, char *sdptr ) { int status, ParenthesisCount = 0; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "AbsorbTagParameter()\n"); for (;;) { if (!*sdptr) { if (ReadSdmlLine (SdmlFilePtr) == NULL) return (sdptr); sdptr = SdmlFilePtr->InLine; } if (*sdptr == ')') { if (!ParenthesisCount) return (sdptr+1); ParenthesisCount--; if (Debug) fprintf (stdout, "Par..Count %d\n", ParenthesisCount); } if (*sdptr == '(') { ParenthesisCount++; if (Debug) fprintf (stdout, "Par..Count %d\n", ParenthesisCount); } sdptr++; } } /*****************************************************************************/ /* Recursively called function. Get all text between the parentheses of a "(...)" construct. */ char* SkipUnknownTag ( struct SdmlFileData *SdmlFilePtr, struct ErrorData *ErrorInfoPtr, char *sdptr, char *htptr, int Capacity ) { int status, ParenthesisCount = 0; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "SkipUnknownTag()\n"); for (;;) { if (!*sdptr) { if (ReadSdmlLine (SdmlFilePtr) == NULL) return (sdptr); sdptr = SdmlFilePtr->InLine; } if (*sdptr == ')') { if (!ParenthesisCount) return (sdptr+1); ParenthesisCount--; if (Debug) fprintf (stdout, "Par..Count %d\n", ParenthesisCount); } if (*sdptr == '(') { ParenthesisCount++; if (Debug) fprintf (stdout, "Par..Count %d\n", ParenthesisCount); } ErrorInfoPtr->SourceLineNumber = __LINE__; htptr = HtmlCopy (ErrorInfoPtr, htptr, &Capacity, sdptr++, 1); } } /*****************************************************************************/ /* Put HTML anchors "[contents]", "[next]", "[previous]", etc., at the start or end of a chapter. Writes directly into the 'OutputLine'. */ char* NavigationButtons (boolean AtEnd) { static char Scratch [1024]; char *sptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "NavigationButtons()\n"); sptr = Scratch; if (AtEnd) { strcpy (sptr, "\n


    \n"); while (*sptr) sptr++; } if (SectionNumber[0] < TotalChapters) { sprintf (sptr, "next", HtmlName, SectionNumber[0]+1, 0, FrameTargetSelf); while (*sptr) sptr++; } else { strcpy (sptr, "next"); while (*sptr) sptr++; } if (SectionNumber[0] > 1) { sprintf (sptr, " previous", HtmlName, SectionNumber[0]-1, 0, FrameTargetSelf); while (*sptr) sptr++; } else { strcpy (sptr, " previous"); while (*sptr) sptr++; } sprintf (sptr, " contents", HtmlName, 0, TableOfContentsCount, FrameTargetTop); while (*sptr) sptr++; if (DoFramed) { sprintf (sptr, " full-page", HtmlName, SectionNumber[0], 0, FrameTargetTop); while (*sptr) sptr++; } if (AtEnd) { *sptr++ = '\n'; *sptr = '\0'; } else { strcpy (sptr, "\n
    \n"); while (*sptr) sptr++; } return (Scratch); } /*****************************************************************************/ /* Create an entry in the linked-list of cross-reference data. 'Symbol' (usually from SDML tag parameter information but will create a unique symbol if required) is used as an index into the list (i.e. can be searched on). 'Number' is the chapter/heading number (e.g. "1.2.3 - Section Numbering"). If supplied the above style of reference text heading is generated in the anchor, if not then the anchor would be unnumbered (e.g. "Section Numbering"). 'Title' is the text appearing in the HTML document anchor (e.g. "Section Numbering"). */ void NoteReference ( struct HtmlFileData *HtmlFilePtr, char *Symbol, char *NumberString, char *Title, char Type ) { int status; char *cptr, *sptr, *zptr; struct ReferenceData *rptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "NoteReference() |%s|%s|\n", Symbol, Title); if ((rptr = malloc (sizeof (struct ReferenceData))) == NULL) { status = vaxc$errno; fprintf (stdout, "%%%s-E-MALLOC, allocating reference memory\n-%s\n", Utility, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } if (RefHeadPtr == NULL) RefHeadPtr = RefTailPtr = rptr; else { RefTailPtr->NextPtr = rptr; RefTailPtr = rptr; } rptr->ReferenceNumber = ReferenceNumber; if (!Symbol[0]) sprintf (Symbol, "%08.08x", ReferenceNumber); zptr = (sptr = rptr->Symbol) + sizeof(rptr->Symbol)-1; for (cptr = Symbol; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; zptr = (sptr = rptr->NumberString) + sizeof(rptr->NumberString)-1; for (cptr = NumberString; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; zptr = (sptr = rptr->Title) + sizeof(rptr->Title)-1; for (cptr = Title; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; zptr = (sptr = rptr->NameOfFile) + sizeof(rptr->NameOfFile)-1; for (cptr = HtmlFilePtr->NameOfFile; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; rptr->Type = Type; rptr->NextPtr = NULL; } /*****************************************************************************/ /* Return an eight hex character string hash value of the supplied string. Hashing function based on code by Arash Partow. */ char* StringHash (char *str) { static char HashString [16]; unsigned int x, i, len, hash; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "StringHash() |%s|\n", str); hash = 0; len = strlen(str); for (i = 0; i < len; str++, i++) { hash = (hash << 4) + tolower(*str); if ((x = hash & 0xF0000000L) != 0) { hash ^= (x >> 24); hash &= ~x; } } sprintf (HashString, "%08.08x", hash & 0x7FFFFFFF); return (HashString); } /*****************************************************************************/ /* Look for an entry ('Symbol') in the linked-list of cross-reference data. If found return a pointer to it, if not return NULL. */ struct ReferenceData* FindReference (char *Symbol) { struct ReferenceData *rptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "FindReference() |%s|\n", Symbol); for (rptr = RefHeadPtr; rptr != NULL; rptr = rptr->NextPtr) if (toupper(Symbol[0]) == toupper(rptr->Symbol[0])) if (strsame (Symbol, rptr->Symbol, -1)) break; return (rptr); } /*****************************************************************************/ /* Return the index either the supplied symbol orreference point was found or -1. */ int DebugReference ( char *Symbol, struct ReferenceData *RefPtr ) { int cnt = 0; struct ReferenceData *rptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "FindReference() |%s|\n", Symbol); for (rptr = RefHeadPtr; rptr != NULL; rptr = rptr->NextPtr) { if (RefPtr != NULL && rptr == RefPtr) break; else if (Symbol != NULL && strsame (Symbol, rptr->Symbol, -1)) break; cnt++; } if (rptr == NULL) cnt = -1; return (cnt); } /*****************************************************************************/ /* Look for all references beginning with this chapter number. Create a list of them on the page. */ char* ChapterReferences ( struct ErrorData *ErrorInfoPtr, char *htptr, int *CapacityPtr, char* ChapterNumberString ) { int Capacity, ChapterNumber, Count = 0, PeriodCount, ThisNumber; char *cptr, *sptr; char Scratch [BUFFER_SIZE]; struct ReferenceData *rptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ChapterReferences() |%s|n", ChapterNumberString); ChapterNumber = atol(ChapterNumberString); sptr = Scratch; sptr += sprintf (sptr, "\n"); for (rptr = RefHeadPtr; rptr != NULL; rptr = rptr->NextPtr) { /* only interested in the major, numbered headings */ if (!rptr->NumberString[0]) continue; PeriodCount = 0; for (cptr = rptr->NumberString; *cptr; cptr++) if (*cptr == '.') PeriodCount++; if (!PeriodCount || atol(rptr->NumberString) != ChapterNumber) continue; Count++; sptr += sprintf (sptr, "%s - \ %s\n", PeriodCount+1, rptr->NumberString, rptr->ReferenceNumber, rptr->NameOfFile, StringHash(rptr->Symbol), FrameTargetSelf, rptr->Title); } strcpy (sptr, "\n
    \n"); Capacity = *CapacityPtr; for (sptr = Scratch; *sptr && Capacity-- > 0; *htptr++ = *sptr++); *htptr = '\0'; *CapacityPtr = Capacity; if (!Capacity) BufferOverflow (ErrorInfoPtr); return (htptr); } /*****************************************************************************/ /* Create an anchor in the HTML text. Locate 'Symbol' in the linked-list of reference data and use the file name, reference number and title for the reference. */ char* MakeReference ( struct HtmlFileData *HtmlFilePtr, struct ErrorData *ErrorInfoPtr, char *htptr, int *CapacityPtr, char *Symbol ) { char Scratch [BUFFER_SIZE]; struct ReferenceData *rptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "MakeReference() |%s|\n", Symbol); if ((rptr = FindReference (Symbol)) == NULL) sprintf (Scratch, "#BADREF(%s)", Symbol); else if (rptr->Type == 0) { if (rptr->NumberString[0]) sprintf (Scratch, "%s - %s", rptr->ReferenceNumber, rptr->NameOfFile, StringHash(rptr->Symbol), FrameTargetSelf, rptr->NumberString, rptr->Title); else sprintf (Scratch, "%s", rptr->ReferenceNumber, rptr->NameOfFile, StringHash(rptr->Symbol), FrameTargetSelf, rptr->Title); } else if (rptr->Type == 1) sprintf (Scratch, "%s", rptr->Title); ErrorInfoPtr->SourceLineNumber = __LINE__; htptr = StringCopy (ErrorInfoPtr, htptr, CapacityPtr, Scratch, -1); return (htptr); } /*****************************************************************************/ /* Provide a link (..) to a reference symbol in the job-table logical name SDM2HTM_HREF that can then be used as a(n external) link in an SDM2HTM document! Used by the (HREF=..) pseudo tag. */ int ExternalHref (int delnm) { static $DESCRIPTOR (LogTableDsc, "LNM$JOB"); static $DESCRIPTOR (LogNameDsc, ""); int idx, status; char RelPath [256], Scratch [BUFFER_SIZE]; char *cptr, *sptr, *zptr; struct ReferenceData *rptr; struct { short int buf_len; short int item; unsigned char *buf_addr; unsigned short *ret_len; } CreLnmItem [2]; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ExternalHref() |%s|\n", ExternalHrefPtr); LogNameDsc.dsc$a_pointer = "SDM2HTM_HREF"; LogNameDsc.dsc$w_length = strlen(LogNameDsc.dsc$a_pointer); if (delnm) { status = sys$dellnm (&LogTableDsc, &LogNameDsc, 0); return (status); } CreLnmItem[0].item = LNM$_STRING; memset (&CreLnmItem[1], 0, sizeof(CreLnmItem[1])); CreLnmItem[0].buf_addr = "#BADREF(ExternalHref())"; CreLnmItem[0].buf_len = 23; status = sys$crelnm (0, &LogTableDsc, &LogNameDsc, 0, &CreLnmItem); if (VMSnok(status)) return (status); zptr = (sptr = RelPath) + sizeof(RelPath)-1; for (cptr = ExternalHrefPtr; *cptr && *cptr != '#' && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; if (*cptr) cptr++; if ((rptr = FindReference (cptr)) == NULL) sprintf (Scratch, "#BADREF(%s)", cptr); else if (rptr->Type == 0) { if (rptr->NumberString[0]) sprintf (Scratch, ""%s"; %s - %s", DocumentTitle, RelPath, rptr->NameOfFile, StringHash(rptr->Symbol), rptr->NumberString, rptr->Title); else sprintf (Scratch, ""%s"; %s", DocumentTitle, RelPath, rptr->NameOfFile, StringHash(rptr->Symbol), rptr->Title); } else if (rptr->Type == 1) sprintf (Scratch, ""%s"; %s", DocumentTitle, rptr->Title); CreLnmItem[0].buf_addr = Scratch; CreLnmItem[0].buf_len = strlen(Scratch); status = sys$crelnm (0, &LogTableDsc, &LogNameDsc, 0, &CreLnmItem); return (status); } /*****************************************************************************/ /* Begin the "table of contents" HTML file. */ int BeginContents (struct SdmlFileData *SdmlFilePtr) { int status, retval; /*********/ /* begin */ /*********/ strcpy (ChapterTitle, "Table of Contents"); OpenContentsFile (SdmlFilePtr); if (!DoGenerateHtml || PassNumber == 1) return (SS$_NORMAL); if (DoFramed) { retval = fprintf (ContentsFilePtr, "%s\ \n\ \n\ %s\ %s\n\ \n\ %s\

    %s

    \n\ \n", HTML_DOCTYPE, MetaInformation(SdmlFilePtr), UnmarkupTitle(ChapterTitle), HtmlBodyTag, ChapterTitle); } else { retval = fprintf (ContentsFilePtr, "%s\ \n\ \n\ %s\ %s\n\ \n\ %s\

    %s

    \n\

    %s

    \n\ \n", HTML_DOCTYPE, MetaInformation(SdmlFilePtr), UnmarkupTitle(ChapterTitle), HtmlBodyTag, DocumentTitle, ChapterTitle); } if (retval < 0) return (vaxc$errno); else return (SS$_NORMAL); } /*****************************************************************************/ /* Add an item to the "table of contents" HTML file. The 'Level' parameter indicates whether this is a level 1, level 2, etc., heading. The item becomes an anchor pointing to a chapter HTML file, or into a heading within a chapter section. All "" HTML tags increase this count by one. */ WriteContentsItem ( struct HtmlFileData *HtmlFilePtr, int Level, char *Symbol ) { static int ItemCount = 0; int Count; char *sptr; char Fragment [32], String [BUFFER_SIZE]; struct ReferenceData *rptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "WriteContentsItem() |%d|%s|\n", Level, Symbol); if (PassNumber == 1) return; Level++; sptr = String; ItemCount++; if ((rptr = FindReference (Symbol)) == NULL) fprintf (ContentsFilePtr, "ERROR: REFERENCE NOT FOUND"); else { if (Level > 1) sprintf (Fragment, "#%s", StringHash(rptr->Symbol)); else Fragment[0] = '\0'; if (rptr->NumberString[0]) fprintf (ContentsFilePtr, "\ %s - %s\ \n", Level, rptr->NumberString, HtmlFilePtr->NameOfFile, Fragment, FrameTargetPage, rptr->Title); else fprintf (ContentsFilePtr, "\ %s\ \n", HtmlFilePtr->NameOfFile, Fragment, FrameTargetPage, rptr->Title); } } /*****************************************************************************/ /* End the "table of contents" HTML file. */ EndContents () { int Count; char *sptr; /*********/ /* begin */ /*********/ fputs ("\n", ContentsFilePtr); fprintf (ContentsFilePtr, "

    This HTML document was produced from SDML \ (DEC DOCUMENT source) by the %s utility (%s)

    \n\ \n\ \n", Utility, SoftwareID); fclose (ContentsFilePtr); } /*****************************************************************************/ /* Open the "table of contents" HTML file. */ int OpenContentsFile (struct SdmlFileData *SdmlFilePtr) { int status; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "OpenContentsFile()"); status = SS$_NORMAL; if (!DoGenerateHtml || PassNumber == 1) return (status); if (DoFramed) TableOfContentsCount = ++FrontMatterCount; else TableOfContentsCount = FrontMatterCount; sprintf (ContentsFileName, "%s%s_00%02.02d.html", HtmlDirectoryPtr, HtmlName, TableOfContentsCount); if (DoVerbose) fprintf (stdout, "[Created %s]\n", ContentsFileName); ContentsFilePtr = fopen (ContentsFileName, "w"); if (ContentsFilePtr == NULL) { status = vaxc$errno; if (Debug) fprintf (stdout, "fopen() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-TOCFILE, opening %s\n-%s\n", Utility, SdmlFilePtr->FileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } return (status); } /*****************************************************************************/ /* */ int WriteFrameFile (struct SdmlFileData *SdmlFilePtr) { int status, retval; char FrameFileName [ODS_MAX_FILE_NAME_LENGTH]; FILE *FrameFilePtr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "WriteFrameFile()"); status = SS$_NORMAL; if (!DoGenerateHtml || PassNumber == 1) return (status); sprintf (FrameFileName, "%s%s_0000.html", HtmlDirectoryPtr, HtmlName); if (DoVerbose) fprintf (stdout, "[Created %s]\n", FrameFileName); FrameFilePtr = fopen (FrameFileName, "w"); if (FrameFilePtr == NULL) { status = vaxc$errno; if (Debug) fprintf (stdout, "fopen() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-FRAMEDFILE, creating %s\n-%s\n", Utility, SdmlFilePtr->FileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } retval = fprintf (FrameFilePtr, "%s\ \n\ \n\ %s\ %s\n\ \n\ \n\ \n\ \n\ \n\ \n", HTML_DOCTYPE, MetaInformation(SdmlFilePtr), UnmarkupTitle(DocumentTitle), HtmlName, TableOfContentsCount, HtmlName, TitlePageCount); if (retval < 0) { status = vaxc$errno; if (Debug) fprintf (stdout, "fprintf() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-FRAMEDFILE, writing %s\n-%s\n", Utility, SdmlFilePtr->FileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } fclose (FrameFilePtr); return (status); } /*****************************************************************************/ /* */ int WriteIndexPage (struct SdmlFileData *SdmlFilePtr) { int status, retvale; char Buffer [2048], IndexFileName [ODS_MAX_FILE_NAME_LENGTH], ZeroInLine [ODS_MAX_FILE_NAME_LENGTH], ZeroFileName [ODS_MAX_FILE_NAME_LENGTH]; FILE *IndexFilePtr, *ZeroFilePtr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "WriteIndexPage()"); status = SS$_NORMAL; if (!DoGenerateHtml || PassNumber == 1) return (status); sprintf (ZeroFileName, "%s%s_0000.html", HtmlDirectoryPtr, HtmlName); sprintf (IndexFileName, "%s%s", HtmlDirectoryPtr, IndexPageName); IndexFilePtr = fopen (IndexFileName, "w"); if (IndexFilePtr == NULL) { status = vaxc$errno; if (Debug) fprintf (stdout, "fopen() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-FRAMEDFILE, creating %s\n-%s\n", Utility, IndexFileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } if (DoVerbose) fprintf (stdout, "[Created %s]\n", IndexFileName); ZeroFilePtr = fopen (ZeroFileName, "r"); if (ZeroFilePtr == NULL) { status = vaxc$errno; if (Debug) fprintf (stdout, "fopen() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-FRAMEDFILE, creating %s\n-%s\n", Utility, ZeroFileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } while (fgets (Buffer, sizeof(Buffer), ZeroFilePtr) != NULL) { if (fputs (Buffer, IndexFilePtr) == EOF) { status = vaxc$errno; if (Debug) fprintf (stdout, "fputs() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-INDEXPAGE, writing %s\n-%s\n", Utility, ZeroFileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } } fclose (ZeroFilePtr); fclose (IndexFilePtr); return (status); } /*****************************************************************************/ /* The file name comprises the RMS file 'name' component plus a two digit section number (the 'chapter' or "

    " number), plus a two digit subsection number. */ GenerateHtmlFileName ( struct HtmlFileData *HtmlFilePtr, int SectionCount, int SubSectionCount ) { char *cptr; sprintf (HtmlFilePtr->NameOfFile, "%s_%02.02d%02.02d.html", HtmlName, SectionCount, SubSectionCount); sprintf (HtmlFilePtr->FileName, "%s%s", HtmlDirectoryPtr, HtmlFilePtr->NameOfFile); for (cptr = HtmlFilePtr->NameOfFile; *cptr; *cptr++) *cptr = tolower(*cptr); if (Debug) fprintf (stdout, "GenerateHtmlFileName |%s|%s|\n", HtmlFilePtr->NameOfFile, HtmlFilePtr->FileName); } /*****************************************************************************/ /* Meta tags providing utility name, source files and date. */ char *MetaInformation (struct SdmlFileData *SdmlFilePtr) { static $DESCRIPTOR (MetaFaoDsc, "\n\ \n\ \n\ \n\ \n\ !AZ!AZ!AZ"); static char String [BUFFER_SIZE]; int status; short Length; unsigned long UnixTime; char *cptr; char UnixDateTime [32]; struct tm *UnixTmPtr; $DESCRIPTOR (StringDsc, String); /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "MetaInformation() |%s|\n", SdmlFilePtr->ExpFileName); time (&UnixTime); UnixTmPtr = localtime (&UnixTime); if (!strftime (UnixDateTime, sizeof(UnixDateTime), "%a, %d %b %Y %T", UnixTmPtr)) strcpy (UnixDateTime, "[error]"); if (Debug) fprintf (stdout, "UnixDateTime |%s|\n", UnixDateTime); if (VMSnok (status = sys$fao (&MetaFaoDsc, &Length, &StringDsc, SoftwareID, SdmlFilePtr->ExpFileName, UnixDateTime, SOFTWARECR, CopyrightInfo, StyleSheetPtr ? "\n" : ""))) { fprintf (stdout, "%%%s-E-METAINFO, generating META information\n-%s\n", Utility, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } String[Length] = '\0'; return (String); } /*****************************************************************************/ /* Open an HTML output file. */ int CreateHtmlFile ( struct HtmlFileData *HtmlFilePtr, struct SdmlFileData *SdmlFilePtr ) { int status; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "CreateHtmlFile()\n"); status = SS$_NORMAL; if (!DoGenerateHtml || PassNumber == 1) return (status); HtmlFilePtr->FilePtr = fopen (HtmlFilePtr->FileName, "w"); if (HtmlFilePtr->FilePtr == NULL) { if (Debug) fprintf (stdout, "fopen() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-HTMLFILE, creating %s\n-%s\n", Utility, HtmlFilePtr->FileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } if (DoVerbose) fprintf (stdout, "[Created %s]\n", HtmlFilePtr->FileName); return (status); } /*****************************************************************************/ /* */ CloseHtmlFile (struct HtmlFileData *HtmlFilePtr) { if (Debug) fprintf (stdout, "CloseHtmlFile()\n"); if (HtmlFilePtr->FilePtr == NULL) return; FlushOutputLine (HtmlFilePtr); fclose (HtmlFilePtr->FilePtr); HtmlFilePtr->FilePtr = NULL; HtmlFilePtr->FileName[0] = '\0'; } /*****************************************************************************/ /* */ FlushOutputLine (struct HtmlFileData *HtmlFilePtr) { if (Debug) fprintf (stdout, "FlushOutputLine()\n"); if (OutputLine[0]) { fputs (OutputLine, HtmlFilePtr->FilePtr); fputc ('\n', HtmlFilePtr->FilePtr); } *(OutputLinePtr = OutputLine) = '\0'; } /*****************************************************************************/ /* Read a record (line) from the source SDML file. Returns pointer to buffer if not end-of-file, NULL if end-of-file (a'la fgets()). */ char* ReadSdmlLine (struct SdmlFileData *SdmlFilePtr) { int status; char *cptr; SdmlFilePtr->InLine[0] = '\0'; if (fgets (SdmlFilePtr->InLine, sizeof(SdmlFilePtr->InLine), SdmlFilePtr->FilePtr) == NULL) return (NULL); SdmlFilePtr->LineNumber++; for (cptr = SdmlFilePtr->InLine; *cptr && *cptr != '\n'; cptr++); *cptr = '\0'; if (Debug) fprintf (stdout, "ReadSdmlLine()\n|%s|\n", SdmlFilePtr->InLine); return (SdmlFilePtr->InLine); } /*****************************************************************************/ /* Uses static storage ... careful! Assume all document '<' and '>' are entity- escaped and any here only represent markup! */ char* UnmarkupTitle (char *String) { static char OutString [256]; char *cptr, *sptr; sptr = OutString; cptr = String; while (*cptr) { if (*cptr == '<') { while (*cptr && *cptr != '>') cptr++; if (*cptr) cptr++; } else *sptr++ = *cptr++; } *sptr = '\0'; return (OutString); } /*****************************************************************************/ /* Copy one string to another, with capacity checking. If parameter 'ccnt' is less than 0 then all characters are copied, if 1 then one character copied, etc. */ char* StringCopy ( struct ErrorData *ErrorInfoPtr, char *sptr, int *CapacityPtr, char *tptr, int ccnt ) { int Capacity; Capacity = *CapacityPtr; while (ccnt-- && *tptr) { if (isprint(*tptr) || *tptr == '\n') { *sptr++ = *tptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); } else tptr++; } *sptr = '\0'; *CapacityPtr = Capacity; return (sptr); } /*****************************************************************************/ /* Copy text from one string to another, with capacity checking, converting characters forbidden to appear as plain-text in HTML. For example the '<', '&', etc. Convert these to the corresponding HTML character entities. If parameter 'ccnt' is less than 0 then all characters are copied, if 1 then one character copied, etc. */ char* HtmlCopy ( struct ErrorData *ErrorInfoPtr, char *sptr, int *CapacityPtr, char *tptr, int ccnt ) { int Capacity; Capacity = *CapacityPtr; while (ccnt-- && *tptr) { switch (*tptr) { case '<' : if ((Capacity -= 4) < 0) BufferOverflow (ErrorInfoPtr); strcpy (sptr, "<"); sptr += 4; tptr++; break; case '>' : if ((Capacity -= 4) < 0) BufferOverflow (ErrorInfoPtr); strcpy (sptr, ">"); sptr += 4; tptr++; break; case '&' : if ((Capacity -= 5) < 0) BufferOverflow (ErrorInfoPtr); strcpy (sptr, "&"); sptr += 5; tptr++; break; default : if (isprint(*tptr) || *tptr == '\t' || *tptr == '\n') { *sptr++ = *tptr++; if (!Capacity--) BufferOverflow (ErrorInfoPtr); } else tptr++; } } *sptr = '\0'; *CapacityPtr = Capacity; return (sptr); } /*****************************************************************************/ /* Count the number of leading spaces. */ CountPreLeadSpace ( char *cptr, int SourceCodeLine ) { if (Debug) fprintf (stdout, "CountPreLeadSpace() %d |%s|\n", SourceCodeLine, cptr); for (PreLeadSpaceCount = 0; *cptr && *cptr == ' '; cptr++) PreLeadSpaceCount++; } /*****************************************************************************/ /* Report buffer overflow error. */ BufferOverflow (struct ErrorData *ErrorInfoPtr) { if (ErrorInfoPtr == NULL) fprintf (stdout, "%%%s-E-BUFOVF, buffer overflow\n", Utility); else { if (IncludeSourceLineNumber) { fprintf (stdout, "%%%s-E-BUFOVF, buffer overflow (%s line %d)\n", Utility, SoftwareID, ErrorInfoPtr->SourceLineNumber); } else fprintf (stdout, "%%%s-E-BUFOVF, buffer overflow\n", Utility); fprintf (stdout, "-%s-I-TAG, \"%s\"\n-%s-I-LOCN, line %d of %s\n", Utility, ErrorInfoPtr->TagNamePtr, Utility, ErrorInfoPtr->TagLineNumber, ErrorInfoPtr->SdmlFileNamePtr); } exit (STS$K_ERROR | STS$M_INHIB_MSG); } /****************************************************************************/ /* Return an integer reflecting the major and minor version of VMS (e.g. 60, 61, 62, 70, 71, 72, etc.) */ #ifdef ODS_EXTENDED int GetVmsVersion () { static char SyiVersion [16]; static struct { short int buf_len; short int item; unsigned char *buf_addr; unsigned short *ret_len; } SyiItems [] = { { 8, SYI$_VERSION, &SyiVersion, 0 }, { 0,0,0,0 } }; int status, version; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "GetVmsVersion()\n"); if (VMSnok (status = sys$getsyiw (0, 0, 0, &SyiItems, 0, 0, 0))) exit (status); SyiVersion[8] = '\0'; version = ((SyiVersion[1]-48) * 10) + (SyiVersion[3]-48); if (Debug) fprintf (stdout, "|%s| %d\n", SyiVersion, version); return (version); } #endif /* ODS_EXTENDED */ /*****************************************************************************/ /* */ char* SysGetMsg (int StatusValue) { static char Message [256]; short int Length; $DESCRIPTOR (MessageDsc, Message); sys$getmsg (StatusValue, &Length, &MessageDsc, 0, 0); Message[Length] = '\0'; if (Debug) fprintf (stdout, "SysGetMsg() |%s|\n", Message); return (Message); } /****************************************************************************/ /* Does a case-insensitive, character-by-character string compare and returns true if two strings are the same, or false if not. If a maximum number of characters are specified only those will be compared, if the entire strings should be compared then specify the number of characters as 0. */ boolean strsame ( char *sptr1, char *sptr2, int count ) { while (*sptr1 && *sptr2) { if (toupper (*sptr1++) != toupper (*sptr2++)) return (false); if (count) if (!--count) return (true); } if (*sptr1 || *sptr2) return (false); else return (true); } /****************************************************************************/

    to use WIDTH=50% to align second column. Add processing of using existing NoteReference functionality. One small change to NoteReference to distinguish between symbols generated by headings and those by explicit symbol definitions. The ReferenceData structure now has a type field to accommodate this. Modify MakeReference to add active links for heading symbol references but to do simple text replacement for the others. Change processing to not generate an unmatched . 04-Feb-2000 MCJ V1.8.1gw, Add handling for , , and . Appendix only handled like a chapter at the moment. Add using HTML . Change to use HTML to better mirror SDML. 26-SEP-1999 MGD v1.8.1, ReadSdmlLine() read check 16-JAN-1999 MGD v1.8.0, add space before , only use

    ,

    ,

    for headings, default document colours, make generated tables HTML 3.2 compliant, force all HTML file specifications to lower case 23-JAN-1998 MGD v1.7.0, "home page" copy of document name_0000.HTML, "unmarkup" text for 28-AUG-1997 MGD v1.6.1, minor fiddle to [contents] link in framed documents 03-AUG-1997 MGD v1.6.0, frames capability, bugfix; "[next]" link truncated all links following 29-JUL-1997 MGD v1.5.0, /BODY qualifier 27-MAY-1997 MGD v1.4.0, added HTML DOCTYPE and META information 08-JUL-1996 MGD v1.3.0, output file record format changed from VAR to STMLF; bugfix in concluding a popup-file; changes to table formatting for better compliance 24-MAY-1995 MGD v1.2.0, minor changes for AXP compatibility 20-APR-1995 MGD v1.1.2, added

    book-title

    to each chapter 23-JAN-1995 MGD v1.1.1, remove "[" and "]" anchor descriptions 20-OCT-1994 MGD v1.1.0, ignore tags outside , , , context ... shouldn't be there! 08-AUG-1994 MGD v1.0.0, initial development */ /*****************************************************************************/ #define SOFTWAREVN "1.11.7" #define SOFTWARECR "Copyright (C) 1996-2016 Mark G.Daniel" #define SOFTWARENM "SDM2HTM" #ifdef __ALPHA char SoftwareID [] = SOFTWARENM " AXP-" SOFTWAREVN; #endif #ifdef __ia64 char SoftwareID [] = SOFTWARENM " IA64-" SOFTWAREVN; #endif #ifdef __VAX char SoftwareID [] = SOFTWARENM " VAX-" SOFTWAREVN; #endif #define SOFTWAREGPL \ "This software comes with ABSOLUTELY NO WARRANTY.\n\ This is free software, and you are welcome to redistribute it the under the\n\ conditions of the GNU GENERAL PUBLIC LICENSE, version 3 or any later version.\n\ http://www.gnu.org/licenses/gpl.txt"; /* standard C header files */ #include #include #include #include /* VMS related header files */ #include #include #include #include #include #include #include #include #include #include /* application header files */ #include "enamel.h" #ifndef __VAX # pragma nomember_alignment #endif #ifndef __VAX # ifndef NO_ODS_EXTENDED # define ODS_EXTENDED 1 /* this is smaller than the technical maximum, but still quite large! */ # define ODS_MAX_FILE_NAME_LENGTH 511 # define ODS_MAX_FILESYS_NAME_LENGTH 264 # endif #endif #define ODS2_MAX_FILE_NAME_LENGTH 255 #ifndef ODS_MAX_FILE_NAME_LENGTH # define ODS_MAX_FILE_NAME_LENGTH ODS2_MAX_FILE_NAME_LENGTH #endif #if ODS_MAX_FILE_NAME_LENGTH < ODS2_MAX_FILE_NAME_LENGTH # define ODS_MAX_FILE_NAME_LENGTH ODS2_MAX_FILE_NAME_LENGTH #endif #define boolean int #define true 1 #define false 0 #define VMSok(x) ((x) & STS$M_SUCCESS) #define VMSnok(x) !(((x) & STS$M_SUCCESS)) #define OUTPUT_LINE_SIZE 65536 #define BUFFER_SIZE 65536 #define INPUT_LINE_SIZE 2048 #define SYMBOL_SIZE 32 #define TAG_NAME_SIZE 32 #define MAX_HEAD_TAG 6 #define DEFAULT_INDEX_PAGE_NAME "index.html" #define HTML_DOCTYPE "\n" #define INTERNAL_STYLE_SHEET \ "\n" /**************************/ /* data type declarations */ /**************************/ struct SdmlFileData { FILE *FilePtr; char FileName [ODS_MAX_FILE_NAME_LENGTH]; char ExpFileName [ODS_MAX_FILE_NAME_LENGTH]; char InLine [INPUT_LINE_SIZE]; boolean CommentHref; int LineNumber; char *sdptr; }; struct HtmlFileData { FILE *FilePtr; char FileName [ODS_MAX_FILE_NAME_LENGTH]; char NameOfFile [ODS_MAX_FILE_NAME_LENGTH]; }; struct ReferenceData { struct ReferenceData *NextPtr; int ReferenceNumber; char NameOfFile [ODS_MAX_FILE_NAME_LENGTH]; char Symbol [SYMBOL_SIZE]; char NumberString [32]; char Title [256]; char Type; }; struct ErrorData { char *TagNamePtr; int TagLineNumber; char *SdmlFileNamePtr; int SourceLineNumber; }; /******************/ /* global storage */ /******************/ char CopyrightInfo [] = SOFTWARECR "\n" SOFTWAREGPL; char Utility[] = "SDM2HTM"; boolean Debug, DoFramed, DoGenerateHtml, NoDocumentColour, DoQuiet, DoVerbose, IncludeComments, IncludeSourceLineNumber, IncludeUnknownTags, FlagUnknownTags, HtmlOn, OdsExtended, SentenceSpacing, UrlLinkOn; int CompatibilityLevel, FrontMatterCount, InsideComment, InsideFormalExample, InsideFormalTable, InsideLiteral, InsidePreformattedText, InsideTagCount, PassNumber, PopUpNumber, PreLeadSpaceCount, ReferenceNumber, TableOfContentsLevel, TableOfContentsCount, TitlePageCount, TotalChapters, UnknownTagCount; /* section numbers range from 0 (chapter) to 6 (head6) */ int SectionNumber[MAX_HEAD_TAG+1]; char CommandLine [256], ChapterTitle [256], ContentsFileName [ODS_MAX_FILE_NAME_LENGTH], DefaultStyleSheet [256], DocumentTitle [256], HtmlBodyTag [256], HtmlName [ODS_MAX_FILE_NAME_LENGTH], IndexPageName [ODS_MAX_FILE_NAME_LENGTH], OutputLine [OUTPUT_LINE_SIZE]; char *ExternalHrefPtr, *FrameTargetPage, *FrameTargetSelf, *FrameTargetToc, *FrameTargetTop, *HtmlDirectoryPtr, *OutputLinePtr, *SdmlFileSpecPtr, *StyleSheetPtr; int ParagraphCount [64]; int ParagraphIndex; int ListItemCount [64]; char EndListTag [64][8]; int EndListTagIndex = 0; FILE *ContentsFilePtr; struct HtmlFileData HtmlFile; struct SdmlFileData SdmlFile; struct ReferenceData *RefHeadPtr = NULL, *RefTailPtr = NULL; /***********************/ /* required prototypes */ /***********************/ char* AbsorbTagParameter (struct SdmlFileData*, char*); char* ChapterReferences (struct ErrorData*, char*, int*, char*); int DebugReference (char*, struct ReferenceData*); char* HtmlCopy (struct ErrorData*, char*, int*, char*, int); char* MakeReference (struct HtmlFileData*, struct ErrorData*, char*, int*, char*); char *MetaInformation (struct SdmlFileData *SdmlFilePtr); char* NavigationButtons (boolean); void NoteReference (struct HtmlFileData*, char*, char*, char*, char); char* ProcessSdmlLines (struct SdmlFileData*, struct HtmlFileData*, char*); char* ProcessTag (struct SdmlFileData*, struct HtmlFileData*, struct ErrorData*, char*, char*, int); char* ProcessTagParameter (struct SdmlFileData*, struct HtmlFileData*, struct ErrorData*, char*, char*, int); char* RawHtml (struct SdmlFileData*, struct HtmlFileData*, struct ErrorData*, char*, char*, int); char* ReadSdmlLine (struct SdmlFileData*); struct ReferenceData* FindReference (char*); char* SkipUnknownTag (struct SdmlFileData*, struct ErrorData*, char*, char*, int); char* StringCopy (struct ErrorData*, char*, int*, char*, int); char* StringHash (char*); char* SysGetMsg (int); char* UnmarkupTitle (char*); /*****************************************************************************/ /* */ int main () { /*********/ /* begin */ /*********/ #ifdef ODS_EXTENDED OdsExtended = (GetVmsVersion() >= 72); ENAMEL_NAML_SANITY_CHECK #endif /* ODS_EXTENDED */ DoVerbose = DoGenerateHtml = true; DoQuiet = SentenceSpacing = false; HtmlDirectoryPtr = SdmlFileSpecPtr = ""; GetParameters (); if (DoQuiet) DoVerbose = false; if (ExternalHrefPtr) { char CWDir [256]; char *cptr, *sptr, *zptr; zptr = (sptr = CWDir) + sizeof(CWDir)-1; for (cptr = SdmlFileSpecPtr; *cptr && *cptr != ']' && sptr < zptr; *sptr++ = *cptr++); if (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; SdmlFileSpecPtr = cptr; if (chdir (CWDir) == -1) exit (vaxc$errno); } /* each two digits is major, then minor, then bugfix number */ if (CompatibilityLevel <= 0) CompatibilityLevel = 999999; else fprintf (stdout, "%%%s-W-COMPATABILITY, level is %d\n", Utility, CompatibilityLevel); exit (SourceFile (SdmlFileSpecPtr)); } /*****************************************************************************/ /* Get "command-line" parameters, whether from the command-line or from a configuration symbol or logical containing the equivalent. */ GetParameters () { static char CommandLine [256]; static unsigned long Flags = 0; int status; unsigned short Length; char *aptr, *cptr, *clptr, *sptr; char ch; $DESCRIPTOR (CommandLineDsc, CommandLine); /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "GetParameters()\n"); if ((clptr = getenv ("SDM2HTM$PARAM")) == NULL) { /* get the entire command line following the verb */ if (VMSnok (status = lib$get_foreign (&CommandLineDsc, 0, &Length, &Flags))) exit (status); (clptr = CommandLine)[Length] = '\0'; } aptr = NULL; ch = *clptr; for (;;) { if (aptr != NULL && *aptr == '/') *aptr = '\0'; if (!ch) break; *clptr = ch; if (Debug) fprintf (stdout, "clptr |%s|\n", clptr); while (*clptr && isspace(*clptr)) *clptr++ = '\0'; aptr = clptr; if (*clptr == '/') clptr++; while (*clptr && !isspace (*clptr) && *clptr != '/') { if (*clptr != '\"') { clptr++; continue; } cptr = clptr; clptr++; while (*clptr) { if (*clptr == '\"') if (*(clptr+1) == '\"') clptr++; else break; *cptr++ = *clptr++; } *cptr = '\0'; if (*clptr) clptr++; } ch = *clptr; if (*clptr) *clptr = '\0'; if (Debug) fprintf (stdout, "aptr |%s|\n", aptr); if (!*aptr) continue; /**************/ /* parameters */ /**************/ if (strsame (aptr, "/COMMENTS", 5)) { IncludeComments = true; continue; } if (strsame (aptr, "/NOCOMMENTS", 7)) { IncludeComments = false; continue; } if (strsame (aptr, "/COMPATIBILITY=", 5)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; CompatibilityLevel = atoi(cptr); continue; } if (strsame (aptr, "/BODY=", 4)) { strcpy (sptr = HtmlBodyTag, "\n"); continue; } if (strsame (aptr, "/COLOUR", 4)) { NoDocumentColour = false; continue; } if (strsame (aptr, "/NOCOLOUR", 6)) { NoDocumentColour = true; continue; } if (strsame (aptr, "/DBUG", -1)) { Debug = true; continue; } if (strsame (aptr, "/DIRECTORY=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; HtmlDirectoryPtr = aptr; continue; } if (strsame (aptr, "/FLAG_UNKNOWN_TAGS", 4)) { FlagUnknownTags = true; continue; } if (strsame (aptr, "/NOFLAG_UNKNOWN_TAGS", 6)) { FlagUnknownTags = false; continue; } if (strsame (aptr, "/FRAMED", 4)) { DoFramed = true; continue; } if (strsame (aptr, "/NOFRAMED", 6)) { DoFramed = false; continue; } if (strsame (aptr, "/HTML", 4)) { DoGenerateHtml = true; continue; } if (strsame (aptr, "/NOHTML", 6)) { DoGenerateHtml = false; continue; } if (strsame (aptr, "/HREF=", 6)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; ExternalHrefPtr = cptr; continue; } if (strsame (aptr, "/INDEX=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; *(sptr = IndexPageName) = '\0'; while (*cptr) *sptr++ = *cptr++; *sptr = '\0'; if (!IndexPageName[0]) strcpy (IndexPageName, DEFAULT_INDEX_PAGE_NAME); continue; } if (strsame (aptr, "/ODS5", 5)) { OdsExtended = true; continue; } if (strsame (aptr, "/NOODS5", 7)) { OdsExtended = false; continue; } if (strsame (aptr, "/QUIET", 5)) { DoQuiet = true; continue; } if (strsame (aptr, "/NOQUIET", 6)) { DoQuiet = false; continue; } if (strsame (aptr, "/SOURCE", 4)) { IncludeSourceLineNumber = true; continue; } if (strsame (aptr, "/STYLE=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; StyleSheetPtr = aptr; continue; } if (strsame (aptr, "/UNKNOWN_TAGS", 4)) { IncludeUnknownTags = true; continue; } if (strsame (aptr, "/NOUNKNOWN_TAGS", 6)) { IncludeUnknownTags = false; continue; } if (strsame (aptr, "/VERBOSE", 5)) { DoVerbose = true; continue; } if (strsame (aptr, "/NOVERBOSE", 6)) { DoVerbose = false; continue; } if (strsame (aptr, "/VERSION", 5)) { fprintf (stdout, "%%%s-I-SOFTWAREID, %s\n%s\n", Utility, SoftwareID, CopyrightInfo); exit (SS$_NORMAL); } if (*aptr == '/') { fprintf (stdout, "%%%s-E-IVQUAL, unrecognized qualifier\n \\%s\\\n", Utility, aptr+1); exit (STS$K_ERROR | STS$M_INHIB_MSG); } if (!SdmlFileSpecPtr[0]) { SdmlFileSpecPtr = aptr; continue; } fprintf (stdout, "%%%s-E-MAXPARM, too many parameters\n \\%s\\\n", Utility, aptr); exit (STS$K_ERROR | STS$M_INHIB_MSG); } } /*****************************************************************************/ /* Using 'SdmlFileSpecPtr' find matching file(s), process SDML text into HTML text. */ SourceFile (char *FileSpec) { int status, FileCount = 0; unsigned short Length; char c; char *cptr, *NamDevicePtr, *NamNamePtr, *NamTypePtr, *NamVersionPtr; char ExpFileName [ODS_MAX_FILE_NAME_LENGTH]; struct FAB ParseFab; struct NAM ParseNam; #ifdef ODS_EXTENDED struct NAML ParseNaml; #endif /* ODS_EXTENDED */ /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "SourceFile() |%s|\n", FileSpec); ParseFab = cc$rms_fab; #ifdef ODS_EXTENDED if (OdsExtended) { ParseFab.fab$l_dna = ParseFab.fab$l_fna = -1; ParseFab.fab$b_dns = ParseFab.fab$b_fns = 0; ParseFab.fab$l_nam = &ParseNaml; ENAMEL_RMS_NAML(ParseNaml) ParseNaml.naml$l_long_defname = "*.SDML"; ParseNaml.naml$l_long_defname_size = 6; ParseNaml.naml$l_long_filename = FileSpec; ParseNaml.naml$l_long_filename_size = strlen(FileSpec); ParseNaml.naml$l_long_expand = ExpFileName; ParseNaml.naml$l_long_expand_alloc = sizeof(ExpFileName)-1; } else #endif /* ODS_EXTENDED */ { ParseFab.fab$l_dna = "*.SDML"; ParseFab.fab$b_dns = 6; ParseFab.fab$l_fna = FileSpec; ParseFab.fab$b_fns = strlen(FileSpec); ParseFab.fab$l_nam = &ParseNam; ParseNam = cc$rms_nam; ParseNam.nam$l_esa = ExpFileName; ParseNam.nam$b_ess = ODS2_MAX_FILE_NAME_LENGTH; } if (VMSnok (status = sys$parse (&ParseFab, 0, 0))) return (status); #ifdef ODS_EXTENDED if (OdsExtended) { NamDevicePtr = ParseNaml.naml$l_long_dev; NamNamePtr = ParseNaml.naml$l_long_name; NamTypePtr = ParseNaml.naml$l_long_type; NamVersionPtr = ParseNaml.naml$l_long_ver; } else #endif /* ODS_EXTENDED */ { NamDevicePtr = ParseNam.nam$l_dev; NamNamePtr = ParseNam.nam$l_name; NamTypePtr = ParseNam.nam$l_type; NamVersionPtr = ParseNam.nam$l_ver; } #ifdef ODS_EXTENDED if (OdsExtended) { if (ParseNaml.naml$l_fnb & NAM$M_WILDCARD) { fprintf (stdout, "%%%s-E-WLD, wildcards not allowed for input specification\n", Utility); return (STS$K_ERROR | STS$M_INHIB_MSG); } } else #endif /* ODS_EXTENDED */ if (ParseNam.nam$l_fnb & NAM$M_WILDCARD) { fprintf (stdout, "%%%s-E-WLD, wildcards not allowed for input specification\n", Utility); return (STS$K_ERROR | STS$M_INHIB_MSG); } NamVersionPtr[0] = '\0'; if (Debug) fprintf (stdout, "ExpFileName |%s|\n", ExpFileName); if (!HtmlDirectoryPtr[0]) { c = NamNamePtr[0]; NamNamePtr[0] = '\0'; strcpy (HtmlDirectoryPtr, NamDevicePtr); for (cptr = HtmlDirectoryPtr; *cptr; cptr++) *cptr = tolower(*cptr); NamNamePtr[0] = c; } NamTypePtr[0] = '\0'; strcpy (HtmlName, NamNamePtr); for (cptr = HtmlName; *cptr; cptr++) *cptr = tolower(*cptr); NamTypePtr[0] = '.'; if (Debug) fprintf (stdout, "|%s|%s|\n", HtmlDirectoryPtr, HtmlName); NamVersionPtr[0] = '\0'; strcpy (SdmlFile.FileName, ExpFileName); if (DoVerbose) fprintf (stdout, "%%%s-I-FILE, %s\n", Utility, ExpFileName); NamVersionPtr[0] = ';'; SdmlFile.InLine[0] = HtmlFile.FileName[0] = HtmlFile.NameOfFile[0] = '\0'; if (DoFramed) { FrameTargetPage = " target=\"frame_page\""; FrameTargetSelf = " target=\"_self\""; FrameTargetToc = " target=\"frame_toc\""; FrameTargetTop = " target=\"_top\" "; } else FrameTargetPage = FrameTargetSelf = FrameTargetToc = FrameTargetTop = ""; if (!HtmlBodyTag[0]) strcpy (HtmlBodyTag, "\n"); /**************/ /* first pass */ /**************/ /* count chapters, gets title, etc., */ PassNumber = 1; if (DoVerbose) fprintf (stdout, "%%%s-I-PASS, 1\n", Utility); strcpy (DocumentTitle, "*** UNTITLED ***"); TotalChapters = 0; FrontMatterCount = InsideComment = InsideFormalExample = InsideFormalTable = InsideLiteral = InsidePreformattedText = InsideTagCount = PopUpNumber = PreLeadSpaceCount = ReferenceNumber = SectionNumber[0] = TableOfContentsLevel = UnknownTagCount = 0; memset (&ParagraphCount, ParagraphIndex = 0, sizeof(ParagraphCount)); HtmlOn = true; UrlLinkOn = false; if (VMSnok (status = ProcessSdmlFile (&SdmlFile, &HtmlFile))) return (status); TotalChapters = SectionNumber[0]; if (ExternalHrefPtr) return (ExternalHref (0)); /***************/ /* second pass */ /***************/ /* outputs document */ PassNumber = 2; if (DoVerbose) fprintf (stdout, "%%%s-I-PASS, 2\n", Utility); FrontMatterCount = InsideComment = InsideFormalExample = InsideFormalTable = InsideLiteral = InsidePreformattedText = InsideTagCount = PopUpNumber = PreLeadSpaceCount = ReferenceNumber = SectionNumber[0] = TableOfContentsLevel = UnknownTagCount = 0; SdmlFile.CommentHref = false; memset (&ParagraphCount, ParagraphIndex = 0, sizeof(ParagraphCount)); HtmlOn = true; UrlLinkOn = false; if (StyleSheetPtr && !*StyleSheetPtr) sprintf (StyleSheetPtr = DefaultStyleSheet, "./%s.css", HtmlName); BeginContents (&SdmlFile); status = ProcessSdmlFile (&SdmlFile, &HtmlFile); EndHtmlFile (&SdmlFile, &HtmlFile); EndContents (); if (DoFramed) WriteFrameFile (&SdmlFile); if (IndexPageName[0]) WriteIndexPage (); if (DoVerbose && UnknownTagCount) fprintf (stdout, "%%%s-W-TAG, unknown tag(s) encountered %d time(s)\n", Utility, UnknownTagCount); return (status); } /*****************************************************************************/ /* Recursively called function. Open input SDML text file, process into HTML text file. */ int ProcessSdmlFile ( struct SdmlFileData *SdmlFilePtr, struct HtmlFileData *HtmlFilePtr ) { int status; char *cptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ProcessSdmlFile() |%s|\n", SdmlFilePtr->FileName); SdmlFilePtr->FilePtr = fopen (SdmlFilePtr->FileName, "r"); if (SdmlFilePtr->FilePtr == NULL) { status = vaxc$errno; if (Debug) fprintf (stdout, "fopen() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-SDMLFILE, opening %s\n-%s\n", Utility, SdmlFilePtr->FileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } if (!fgetname (SdmlFilePtr->FilePtr, SdmlFilePtr->ExpFileName)) { status = vaxc$errno; if (Debug) fprintf (stdout, "fopen() %%X%08.08X\n", status); fprintf (stdout, "%%%s-E-SDMLFILE, getting full name %s\n-%s\n", Utility, SdmlFilePtr->FileName, SysGetMsg(status)+1); exit (status | STS$M_INHIB_MSG); } for (cptr = SdmlFilePtr->ExpFileName; *cptr && *cptr != ';'; cptr++); if (*cptr) *cptr = '\0'; if (!DoQuiet) fprintf (stdout, "[Processing %s]\n", SdmlFilePtr->FileName); if (ReadSdmlLine (SdmlFilePtr) == NULL) { fclose (SdmlFilePtr->FilePtr); SdmlFilePtr->FilePtr = NULL; return (SS$_NORMAL); } ProcessSdmlLines (SdmlFilePtr, HtmlFilePtr, SdmlFilePtr->InLine); fclose (SdmlFilePtr->FilePtr); SdmlFilePtr->FilePtr = NULL; return (SS$_NORMAL); } /*****************************************************************************/ /* Recursively called function. Read lines (records) in the SDML text file, processing into HTML text. This line processing can be terminated by end-of-file or by a tag returning a pseudo-tag indicating that a recursive call to this function should be concluded. In this case a single SDML source file may not yet be exhausted. If an opening '<' of a tag is encountered the function ProcessTag() is called to process this tag. If it is tag with no parameters then a conversion into SDML will be made and returned in 'Scratch'. If it has parameter (e.g. (...)), then it will in turn call function ProcessTagParameter(), which may in turn encounter tags within the parameter itself (e.g. "(this is some (example\BOLD) text)"). Eventually this function will be returned to with text built up into 'Scratch', which is then copied to the HTML output buffer. */ char* ProcessSdmlLines ( struct SdmlFileData *SdmlFilePtr, struct HtmlFileData *HtmlFilePtr, char *sdptr ) { static int RecursionLevel = 0; int cnt, len, status, Capacity; char *cptr; char Scratch [BUFFER_SIZE]; struct ErrorData ErrorInfo; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ProcessSdmlLines(%d)\n", ++RecursionLevel); ErrorInfo.SdmlFileNamePtr = SdmlFilePtr->FileName; FlushOutputLine (HtmlFilePtr); Capacity = sizeof(OutputLine); /*******************/ /* read lines loop */ /*******************/ for (;;) { /*********************/ /* process line loop */ /*********************/ if (InsidePreformattedText) { /* absorb any leading space in code-example text */ if (PreLeadSpaceCount == -1) CountPreLeadSpace (sdptr, __LINE__); for (cnt = PreLeadSpaceCount; cnt && *sdptr == ' '; cnt--) sdptr++; if (!*sdptr) fputc ('\n', HtmlFilePtr->FilePtr); } while (*sdptr) { if (*sdptr == '<') { ErrorInfo.TagNamePtr = sdptr; ErrorInfo.TagLineNumber = SdmlFilePtr->LineNumber; sdptr = ProcessTag (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr, Scratch, sizeof(Scratch)); /***********************************************************/ /* detect pseudo-tag to exit from a recusive function call */ /***********************************************************/ if (strsame (Scratch, "", -1)) { FlushOutputLine (HtmlFilePtr); RecursionLevel--; return (sdptr); } Capacity = sizeof(OutputLine) - 1 - ((int)OutputLinePtr - (int)OutputLine); OutputLinePtr = StringCopy (NULL, OutputLinePtr, &Capacity, Scratch, -1); } else if (InsidePreformattedText && PreLeadSpaceCount == -1) { /* just in case of the perverse "" */ CountPreLeadSpace (sdptr, __LINE__); for (cnt = PreLeadSpaceCount; cnt && *sdptr == ' '; cnt--) sdptr++; if (!*sdptr) fputc ('\n', HtmlFilePtr->FilePtr); } else { if (UrlLinkOn) { /****************/ /* look for URL */ /****************/ if (!memcmp (sdptr, "http://", len = 7) || !memcmp (sdptr, "https://", len = 8) || !memcmp (sdptr, "ftp://", len = 6)) { for (cptr = sdptr + len; *cptr && !isspace(*cptr) && *cptr != '/'; cptr++); if (*cptr != '/') cptr = NULL; } else if (!memcmp (sdptr, "mailto:", len = 7)) { for (cptr = sdptr + len; *cptr && !isspace(*cptr) && *cptr != '@'; cptr++); if (*cptr != '@') cptr = NULL; } else cptr = NULL; if (cptr) { /***************/ /* make a link */ /***************/ while (*cptr && !isspace(*cptr)) cptr++; OutputLinePtr = StringCopy (NULL, OutputLinePtr, &Capacity, "", -1); OutputLinePtr = StringCopy (NULL, OutputLinePtr, &Capacity, sdptr, cptr-sdptr); OutputLinePtr = StringCopy (NULL, OutputLinePtr, &Capacity, "", -1); sdptr = cptr; } } else cptr = NULL; if (cptr == NULL) { /********************/ /* copy a character */ /********************/ if (HtmlOn && (!InsideComment || IncludeComments)) OutputLinePtr = HtmlCopy (NULL, OutputLinePtr, &Capacity, sdptr, 1); sdptr++; } } } /*************************/ /* end process line loop */ /*************************/ FlushOutputLine (HtmlFilePtr); Capacity = sizeof(OutputLine); if (ReadSdmlLine (SdmlFilePtr) == NULL) { /***************/ /* end-of-file */ /***************/ FlushOutputLine (HtmlFilePtr); RecursionLevel--; return (sdptr); } sdptr = SdmlFilePtr->InLine; } } /*****************************************************************************/ /* Recursively called function. Some SDML tags have parameters. One, or more, strings between parentheses, e.g. "(...)". If multiple parameters then each is separated by a backslash, e.g. "\". This function obtains one parameter from between the tag's "(...)". If multiple parameters exists then each may be obtained by calling this function multiple times. The terminating character, a ")" or "\" is returned being pointed at by 'sdptr' so that progress may be determined by the calling routine. Calling this function with parameter 'htptr' set to NULL effectively absorbs any tag parameter. */ char* ProcessTagParameter ( struct SdmlFileData *SdmlFilePtr, struct HtmlFileData *HtmlFilePtr, struct ErrorData *ErrorInfoPtr, char *sdptr, char *htptr, int Capacity ) { static int RecursionLevel = 0; int cnt, len, status, ParenthesesCount = 0; char *cptr; char Buffer [BUFFER_SIZE]; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ProcessTagParameter(%d)\n", ++RecursionLevel); /* allow for the terminating null */ if (Capacity) Capacity--; /*******************/ /* read lines loop */ /*******************/ for (;;) { /*********************/ /* process line loop */ /*********************/ if (InsidePreformattedText) { /* absorb any leading space in code-example text */ if (PreLeadSpaceCount == -1) CountPreLeadSpace (sdptr, __LINE__); for (cnt = PreLeadSpaceCount; cnt && *sdptr == ' '; cnt--) sdptr++; if (!*sdptr) fputc ('\n', HtmlFilePtr->FilePtr); } while (*sdptr) { if (!InsideComment && *sdptr == '<') { /********************************************/ /* start of nested tag, process recursively */ /********************************************/ sdptr = ProcessTag (SdmlFilePtr, HtmlFilePtr, ErrorInfoPtr, sdptr, Buffer, sizeof(Buffer)); if (htptr != NULL) { ErrorInfoPtr->SourceLineNumber = __LINE__; htptr = StringCopy (ErrorInfoPtr, htptr, &Capacity, Buffer, -1); } } else if (!InsideLiteral && *sdptr == '\\') { /**************************/ /* start of new parameter */ /**************************/ RecursionLevel--; return (sdptr); } else if (*sdptr == '(') { /*****************************************/ /* opening parenthesis (not tag-related) */ /*****************************************/ ParenthesesCount++; if (htptr != NULL) { ErrorInfoPtr->SourceLineNumber = __LINE__; htptr = StringCopy (ErrorInfoPtr, htptr, &Capacity, sdptr, 1); } sdptr++; } else if (*sdptr == ')') { if (!ParenthesesCount) { /********************/ /* end of parameter */ /********************/ InsideTagCount--; RecursionLevel--; /* return pointing at the tag parameter termination character */ return (sdptr); } else { /*****************************************/ /* closing parenthesis (not tag-related) */ /*****************************************/ ParenthesesCount--; if (htptr != NULL) { ErrorInfoPtr->SourceLineNumber = __LINE__; htptr = StringCopy (ErrorInfoPtr, htptr, &Capacity, sdptr, 1); } sdptr++; } } else { if (UrlLinkOn) { /****************/ /* look for URL */ /****************/ if (!memcmp (sdptr, "http://", len = 7) || !memcmp (sdptr, "https://", len = 8) || !memcmp (sdptr, "ftp://", len = 6)) { for (cptr = sdptr + len; *cptr && !isspace(*cptr) && *cptr != '/'; cptr++); if (*cptr != '/') cptr = NULL; } else if (!memcmp (sdptr, "mailto:", len = 7)) { for (cptr = sdptr + len; *cptr && !isspace(*cptr) && *cptr != '@'; cptr++); if (*cptr != '@') cptr = NULL; } else cptr = NULL; if (cptr) { /***************/ /* make a link */ /***************/ while (*cptr && !isspace(*cptr)) cptr++; htptr = StringCopy (NULL, htptr, &Capacity, "", -1); htptr = StringCopy (NULL, htptr, &Capacity, sdptr, cptr-sdptr); htptr = StringCopy (NULL, htptr, &Capacity, "", -1); sdptr = cptr; } } else cptr = NULL; if (cptr == NULL) { /********************/ /* copy a character */ /********************/ if (htptr != NULL) { ErrorInfoPtr->SourceLineNumber = __LINE__; htptr = HtmlCopy (ErrorInfoPtr, htptr, &Capacity, sdptr, 1); } sdptr++; } } } if (Debug) fprintf (stdout, "ReadSdmlLine() %d\n", __LINE__); if (ReadSdmlLine (SdmlFilePtr) == NULL) { /***************/ /* end-of-file */ /***************/ RecursionLevel--; return (sdptr); } sdptr = SdmlFilePtr->InLine; /* add a new line to the output buffer */ if (htptr != NULL) { ErrorInfoPtr->SourceLineNumber = __LINE__; htptr = StringCopy (ErrorInfoPtr, htptr, &Capacity, "\n", 1); } } } /*****************************************************************************/ /* Recursively called function. Sorry about its length! The opening '<' of an SDML tag has been encountered. It is pointed to by 'sdptr'. Get the tag name. By string comparison find it, and process it. If not a known tag then absorb it if a tag without parameters, e.g. "", or absorb all between the parentheses if a tag with parameters, e.g. "(...)". The 'htptr' that the tag is processed into is not directly for output into the HTML output file. When functions ProcessSdmlLines() and ProcessTagParameters() encounter an opening '<' of a tag this function, ProcessTag(), is called with 'htptr' pointing at a fixed sized buffer. When function ProcessTag() finishes processing the tag and returns the function that called it resumes with that buffer containing the */ char* ProcessTag ( struct SdmlFileData *SdmlFilePtr, struct HtmlFileData *HtmlFilePtr, struct ErrorData *ErrorInfoPtr, char *sdptr, char *htptr, int Capacity ) { #define INCLUDE_MAX 4 static int IncludeLevel = -1, RecursionLevel = 0, TableRowCount = 0; int status, Count; char *cptr, *sptr, *zptr; char HeadDigit; char Buffer [BUFFER_SIZE], NumberString [32], Scratch [BUFFER_SIZE], Symbol [SYMBOL_SIZE], TagName [TAG_NAME_SIZE]; struct HtmlFileData PopUpFile; struct SdmlFileData IncludeFile[INCLUDE_MAX]; struct ErrorData ErrorInfo; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ProcessTag(%d)\n", ++RecursionLevel); /* allow for the terminating null */ if (Capacity) Capacity--; *htptr = Buffer[0] = Scratch[0] = Symbol[0] = '\0'; /****************************/ /* handle literal tag first */ /****************************/ if (InsideLiteral) { if (strsame (sdptr, "", 12)) { InsideLiteral--; sdptr += 12; } else { ErrorInfoPtr->SourceLineNumber = __LINE__; htptr = HtmlCopy (ErrorInfoPtr, htptr, &Capacity, sdptr++, 1); } RecursionLevel--; return (sdptr); } /**********************************************/ /* handle HTML control sequences specifically */ /**********************************************/ if (strsame (sdptr, "(", 10)) { ErrorInfo.TagNamePtr = ""; ErrorInfo.TagLineNumber = SdmlFilePtr->LineNumber; ErrorInfo.SdmlFileNamePtr = SdmlFilePtr->FileName; if (strsame (sdptr+10, "HREF=", 5)) { if (PassNumber == 1 || ExternalHrefPtr != NULL) { SdmlFilePtr->CommentHref = true; while (*sdptr && *sdptr != ')') sdptr++; if (*sdptr == ')') sdptr++; RecursionLevel--; return (sdptr); } /* "[-.directory]file.SDML!../path/#reference" */ zptr = (sptr = Scratch) + sizeof(Scratch)-1; for (cptr = "SDM2HTM/QUIET "; *cptr && sptr < zptr; *sptr++ = *cptr++); for (cptr = sdptr + 15; *cptr && *cptr != '!' && *cptr != ')' && sptr < zptr; *sptr++ = *cptr++); if (*cptr != '!') goto HrefError; sdptr = ++cptr; for (cptr = " /HREF=\""; *cptr && sptr < zptr; *sptr++ = *cptr++); for (cptr = sdptr; *cptr && *cptr != '#' && *cptr != ')' && sptr < zptr; *sptr++ = *cptr++); if (*cptr != '#') goto HrefError; while (*cptr && *cptr != ')' && sptr < zptr) *sptr++ = *cptr++; sdptr = cptr; if (*sdptr == ')') sdptr++; if (sptr < zptr) *sptr++ = '\"'; *sptr = '\0'; /* see ExternalHref() for processing detail */ system (Scratch); cptr = getenv ("SDM2HTM_HREF"); if (!cptr) sprintf (cptr = Buffer, "#BADREF(%s)", Scratch); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, cptr, -1); /* delete the logical name */ ExternalHref (1); RecursionLevel--; return (sdptr); HrefError: { fprintf (stdout, "%%%s-E-HREF, (href=) syntax, line %d of %s\n", Utility, SdmlFilePtr->LineNumber, SdmlFilePtr->FileName); while (*sdptr && *sdptr != ')') sdptr++; if (*sdptr) sdptr++; RecursionLevel--; return (sdptr); } } if (strsame (sdptr+10, "HTML=", 5)) { SentenceSpacing = false; sdptr = RawHtml (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+15, Buffer, sizeof(Buffer)); if (*sdptr == ')') sdptr++; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); RecursionLevel--; SentenceSpacing = true; return (sdptr); } if (strsame (sdptr+10, "HTML/ON)", 8)) { SentenceSpacing = true; HtmlOn = true; sdptr += 18; RecursionLevel--; return (sdptr); } if (strsame (sdptr+10, "HTML/OFF)", 9)) { SentenceSpacing = false; HtmlOn = false; sdptr += 19; RecursionLevel--; return (sdptr); } if (strsame (sdptr+10, "URL/ON)", 7)) { UrlLinkOn = true; sdptr += 17; RecursionLevel--; return (sdptr); } if (strsame (sdptr+10, "URL/OFF)", 8)) { UrlLinkOn = false; sdptr += 18; RecursionLevel--; return (sdptr); } if (strsame (sdptr+10, "HTML/POPUP=", 11)) { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+21, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Symbol, sizeof(Symbol)); if (*sdptr == ')') sdptr++; GenerateHtmlFileName (&PopUpFile, SectionNumber[0], ++PopUpNumber); /* create an HTML anchor point in the document for the example file */ if (!Buffer[0]) strcpy (Buffer, "(no title)"); sprintf (Scratch, "\n\

    \n\ %s\n\

    \n", PopUpFile.NameOfFile, FrameTargetSelf, Buffer); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); /* flush any remaining output into the current HTML file */ FlushOutputLine (HtmlFilePtr); CreateHtmlFile (&PopUpFile, SdmlFilePtr); sprintf (OutputLinePtr, "%s\ \n\ \n\ %s\ %s\n\ \n\ %s\ \n\ %s\

    %s

    \n\
    ", HTML_DOCTYPE, MetaInformation(SdmlFilePtr), UnmarkupTitle(ChapterTitle), HtmlBodyTag, StringHash(Symbol), ++ReferenceNumber, Buffer); while (*OutputLinePtr) OutputLinePtr++; NoteReference (HtmlFilePtr, Symbol, "", Buffer, 0); /* recursive call to process the SDML text into the example file */ sdptr = ProcessSdmlLines (SdmlFilePtr, &PopUpFile, sdptr); strcpy (OutputLinePtr, "\n\n"); while (*OutputLinePtr) OutputLinePtr++; /* flush output into the current HTML file */ FlushOutputLine (&PopUpFile); CloseHtmlFile (&PopUpFile); RecursionLevel--; return (sdptr); } if (strsame (sdptr+10, "HTML/ENDPOPUP)", 14)) { /* This psuedo-tag is detected and actioned in function ProcessSdmlLines() to terminate the recursive call made to it by "HTML/POPUP=". */ sdptr += 24; strcpy (htptr, ""); htptr += 12; RecursionLevel--; return (sdptr); } } if (!HtmlOn) { /* absorb the '<' character */ sdptr++; RecursionLevel--; return (sdptr); } /********************/ /* get the tag name */ /********************/ /* put the tag information into the error data structure */ ErrorInfo.TagNamePtr = sdptr; ErrorInfo.TagLineNumber = SdmlFilePtr->LineNumber; ErrorInfo.SdmlFileNamePtr = SdmlFilePtr->FileName; ErrorInfo.SourceLineNumber = __LINE__; Count = sizeof(TagName)-1; cptr = TagName; while (*sdptr && *sdptr != '>') { *cptr++ = *sdptr++; if (!Count--) BufferOverflow (&ErrorInfo); } *cptr++ = *sdptr++; *cptr = '\0'; if (Debug) fprintf (stdout, "TagName |%s|\n", TagName); /* put the tag name into the error data structure */ ErrorInfo.TagNamePtr = TagName; /***********************************/ /* handle comment tag specifically */ /***********************************/ if (strsame (TagName, "", -1)) { if (InsideComment) InsideComment--; if (IncludeComments && !InsideComment) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, " -->", -1); } RecursionLevel--; return (sdptr); } if (InsideComment) { if (IncludeComments) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, TagName, -1); } RecursionLevel--; return (sdptr); } if (strsame (TagName, "", -1)) { if (*sdptr == '(') { if (IncludeComments && !InsideComment++) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } } } else { if (IncludeComments && !InsideComment) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n\

    %s - %s

    \n\ \n", StringHash(Symbol), ++ReferenceNumber, NumberString, ChapterTitle); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); ErrorInfo.SourceLineNumber = __LINE__; htptr = ChapterReferences (&ErrorInfo, htptr, &Capacity, NumberString); } sptr = NavigationButtons (false); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, sptr, -1); if (CompatibilityLevel < 11000) { sprintf (Scratch, "\n\

    %s - %s

    \n\
    \n", StringHash(Symbol), ++ReferenceNumber, NumberString, ChapterTitle); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); } NoteReference (HtmlFilePtr, Symbol, NumberString, ChapterTitle, 0); WriteContentsItem (HtmlFilePtr, 0, Symbol); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1) || strsame (TagName, "", -1)) { /* do not interfere with any periods in this test */ SentenceSpacing = false; ParagraphIndex++; if (!InsidePreformattedText++) { PreLeadSpaceCount = -1; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n
    ", -1);
          }
          if (*sdptr == '(')
          {
             sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo,
                                          sdptr+1, Buffer, sizeof(Buffer));
             while (*sdptr == '\\')
                sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo,
                                             sdptr+1, NULL, 0);
             if (*sdptr == ')') sdptr++;
             if (strsame (Buffer, "KEEP", -1) ||
                 strsame (Buffer, "WIDE", -1) ||
                 strsame (Buffer, "WIDE/MAXIMUM", -1) ||
                 strsame (Buffer, "MAXIMUM", -1))
             {
                /* prevent a newline being generated immediately after "
    " */
                while (*sdptr && isspace(*sdptr)) sdptr++;
             }
             else
             {
                if (ParagraphCount[ParagraphIndex])
                {
                   htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } if (ParagraphIndex) ParagraphIndex--; if (InsidePreformattedText) InsidePreformattedText--; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); if (!InsidePreformattedText) { PreLeadSpaceCount = 0; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); } } } else { /* prevent a newline being generated immediately after the "
    " */
             while (*sdptr && isspace(*sdptr)) sdptr++;
          }
       }
       else
       /*------------------------------------------------------------------------*/
       if (strsame (TagName, "", -1) ||
           strsame (TagName, "", -1))
       {
          SentenceSpacing = true;
          if (ParagraphCount[ParagraphIndex])
          {
             htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } if (ParagraphIndex) ParagraphIndex--; if (InsidePreformattedText) InsidePreformattedText--; if (!InsidePreformattedText) { PreLeadSpaceCount = 0; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { EndHtmlFile (SdmlFilePtr, HtmlFilePtr); strcpy (ChapterTitle, "Copyright Page"); GenerateHtmlFileName (HtmlFilePtr, 0, ++FrontMatterCount); CreateHtmlFile (HtmlFilePtr, SdmlFilePtr); sprintf (Scratch, "%s\n

    %s

    \n", UnmarkupTitle(ChapterTitle), DocumentTitle); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); /* in this case 'Symbol' will be generated by NoteReference() */ ReferenceNumber++; NoteReference (HtmlFilePtr, Symbol, "", ChapterTitle, 0); WriteContentsItem (HtmlFilePtr, 0, Symbol); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, HTML_DOCTYPE, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n\n", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, MetaInformation(SdmlFilePtr), -1); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n", -1); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, HtmlBodyTag, -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n\n", -1); EndHtmlFile (SdmlFilePtr, HtmlFilePtr); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, ")", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\"", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; if (InsidePreformattedText) htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n.\n.\n.\n", -1); else htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    .\n
    .\n
    .\n
    ", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Scratch, sizeof(Scratch)); if (*sdptr == ')') sdptr++; } ErrorInfo.SourceLineNumber = __LINE__; if (strsame (Scratch, "BOLD", -1)) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } else if (strsame (Scratch, "SMALLCAPS", -1)) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } else { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { /* its got a caption, its a formal example, into a file of its own */ InsideFormalExample++; /* This is a reasonably complex tag to implement because it generates a separate HTML output file. It makes use of a recursive call to function ProcessSdmlLines(). */ sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Symbol, sizeof(Symbol)); if (*sdptr == ')') sdptr++; GenerateHtmlFileName (&PopUpFile, SectionNumber[0], ++PopUpNumber); /* create an HTML anchor point in the document for the example file */ if (!Buffer[0]) strcpy (Buffer, "(no title)"); sprintf (Scratch, "\n

    \n[Example: %s]

    \n", PopUpFile.NameOfFile, FrameTargetSelf, Buffer); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); /* flush any remaining output into the current HTML file */ FlushOutputLine (HtmlFilePtr); CreateHtmlFile (&PopUpFile, SdmlFilePtr); sprintf (OutputLinePtr, "%s\ \n\ \n\ %s\ %s\n\ \n\ %s\

    %s

    \n\ \n\ \n\

    %s

    \n\
    ", HTML_DOCTYPE, MetaInformation(SdmlFilePtr), UnmarkupTitle(Buffer), HtmlBodyTag, ChapterTitle, StringHash(Symbol), ++ReferenceNumber, Buffer); while (*OutputLinePtr) OutputLinePtr++; sprintf (Scratch, "Example: %s", Buffer); NoteReference (HtmlFilePtr, Symbol, "", Scratch, 0); /* recursive call to process the SDML text into the example file */ sdptr = ProcessSdmlLines (SdmlFilePtr, &PopUpFile, sdptr); strcpy (OutputLinePtr, "\n\n"); while (*OutputLinePtr) OutputLinePtr++; /* flush output into the current HTML file */ FlushOutputLine (&PopUpFile); CloseHtmlFile (&PopUpFile); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (InsideFormalExample) { InsideFormalExample--; /* This psuedo-tag is detected and actioned in function ProcessSdmlLines() to terminate the recursive call made to it by processing. */ strcpy (htptr, ""); htptr += 12; } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (ParagraphCount[ParagraphIndex=0]) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } if (isdigit (TagName[5])) { HeadDigit = atol (TagName+5); if (HeadDigit > MAX_HEAD_TAG) HeadDigit = 0; } else HeadDigit = 0; if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Symbol, sizeof(Symbol)); if (*sdptr == ')') sdptr++; } if (HeadDigit) { /* numbered heading */ sptr = NumberString; /* increment the current heading level ('HeadDigit' always >= 2) */ SectionNumber[HeadDigit]++; /* output the heading numbering into the heading string */ for (Count = 0; Count <= HeadDigit; Count++) { if (Count) *sptr++ = '.'; sprintf (sptr, "%d", SectionNumber[Count]); while (*sptr) sptr++; } sprintf (Scratch, "\n\ \n\

    %s - %s

    \n\
    ", StringHash(Symbol), ++ReferenceNumber, NumberString, Buffer); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); /* create a reference for the numbered heading */ NoteReference (HtmlFilePtr, Symbol, NumberString, Buffer, 0); /* create a table of contents entry for the numbered heading */ WriteContentsItem (HtmlFilePtr, HeadDigit, Symbol); /* reset the remainder of the heading counters to zero */ for (Count = HeadDigit+1; Count <= MAX_HEAD_TAG; SectionNumber[Count++] = 0); } else { /* non-numbered heading */ if (strsame (TagName, "", -1)) { sprintf (Scratch, "\n\ \n\

    %s

    \n\
    ", StringHash(Symbol), ++ReferenceNumber, Buffer); } else { sprintf (Scratch, "\n\ \n\

    %s

    \n\
    ", StringHash(Symbol), ++ReferenceNumber, Buffer); } ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); /* create a reference for the non-numbered heading */ NoteReference (HtmlFilePtr, Symbol, "", Buffer, 0); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1) || strsame (TagName, "", -1) || strsame (TagName, "", -1) || strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; if (SdmlFilePtr->CommentHref) { /* (HREF=..) has been processed - ignore */ SdmlFilePtr->CommentHref = false; } else { if (IncludeLevel >= INCLUDE_MAX) { fprintf (stdout, "%%%s-E-INCLUDE, exceeds maximum\n", Utility); exit (SS$_BUGCHECK | STS$M_INHIB_MSG); } IncludeLevel++; memset (&IncludeFile[IncludeLevel], 0, sizeof(struct SdmlFileData)); strcpy (IncludeFile[IncludeLevel].FileName, Buffer); if (DoVerbose) fprintf (stdout, "[Include %s (%d)]\n", IncludeFile[IncludeLevel].FileName, IncludeLevel+1); ProcessSdmlFile (&IncludeFile[IncludeLevel], HtmlFilePtr); IncludeLevel--; if (DoVerbose) fprintf (stdout, "[Resuming %s (%d)]\n", SdmlFilePtr->FileName, IncludeLevel+1); } } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; if (ParagraphCount[ParagraphIndex]) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } if (EndListTagIndex && strsame (EndListTag[EndListTagIndex-1], "", 5)) { if (ListItemCount[EndListTagIndex]) htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); } else { if (ListItemCount[EndListTagIndex]++) htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
  • ", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "...", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; } ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); if (strsame (Buffer, "SMALLSKIP", -1)) htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); if (strsame (Buffer, "BIGSKIP", -1)) htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { InsideLiteral++; if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); ErrorInfo.SourceLineNumber = __LINE__; while (*sdptr == '\\') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); } if (*sdptr == ')') sdptr++; InsideLiteral--; } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ParagraphIndex++; ErrorInfo.SourceLineNumber = __LINE__; if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; } if (strsame (Buffer, "NUMBERED", -1)) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
      ", -1); strcpy (EndListTag[EndListTagIndex++], "
    \n"); } else if (strsame (Buffer, "SIMPLE", -1)) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); strcpy (EndListTag[EndListTagIndex++], "
    \n"); } else if (strsame (Buffer, "ALPHABETIC", -1)) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
      ", -1); strcpy (EndListTag[EndListTagIndex++], "
    \n"); } else { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
      ", -1); strcpy (EndListTag[EndListTagIndex++], "
    \n"); } ListItemCount[EndListTagIndex] = 0; } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (EndListTagIndex) { ErrorInfo.SourceLineNumber = __LINE__; if (ParagraphCount[ParagraphIndex]) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } if (ParagraphIndex) ParagraphIndex--; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, EndListTag[--EndListTagIndex], -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; ParagraphIndex++; if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); if (ParagraphCount[ParagraphIndex]) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } if (ParagraphIndex) ParagraphIndex--; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); } else htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    NOTE
    \
    \n", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; if (ParagraphCount[ParagraphIndex]) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } if (ParagraphIndex) ParagraphIndex--; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    \n", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') sdptr = AbsorbTagParameter (SdmlFilePtr, sdptr+1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "(", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "

    ", -1)) { ErrorInfo.SourceLineNumber = __LINE__; if (ParagraphCount[ParagraphIndex]) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n

    ", -1); ParagraphCount[ParagraphIndex]++; } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Symbol, sizeof(Symbol)); if (*sdptr == ')') sdptr++; } EndHtmlFile (SdmlFilePtr, HtmlFilePtr); strcpy (ChapterTitle, "Preface"); GenerateHtmlFileName (HtmlFilePtr, 0, ++FrontMatterCount); CreateHtmlFile (HtmlFilePtr, SdmlFilePtr); sprintf (Scratch, "%s\n

    %s

    \n", UnmarkupTitle(ChapterTitle), DocumentTitle); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); ReferenceNumber++; NoteReference (HtmlFilePtr, Symbol, "", ChapterTitle, 0); WriteContentsItem (HtmlFilePtr, 0, Symbol); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, HTML_DOCTYPE, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n\n", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, MetaInformation(SdmlFilePtr), -1); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n", -1); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, HtmlBodyTag, -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n\n", -1); EndHtmlFile (SdmlFilePtr, HtmlFilePtr); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { /* just absorb this parameter-less tag */ } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, """, -1); if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, """, -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, """, -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { Buffer[0] = '\0'; if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Symbol, sizeof(Symbol)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, NULL, 0); if (*sdptr == ')') sdptr++; } if (Symbol[0]) htptr = MakeReference (HtmlFilePtr, &ErrorInfo, htptr, &Capacity, Symbol); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { Scratch[0] = Buffer[0] = '\0'; if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Scratch, sizeof(Scratch)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); if (*sdptr == ')') sdptr++; if (!Scratch[0]) strcpy (Scratch, "Revision Information"); ErrorInfo.SourceLineNumber = __LINE__; /* Original code htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n

    ", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); */ /* New Mcj code */ htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n
  • \n
    ", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n
    \n", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n
    \n", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1) || strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n
    ", -1); ParagraphIndex++; } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1) || strsame (TagName, "", -1)) { ErrorInfo.SourceLineNumber = __LINE__; if (ParagraphCount[ParagraphIndex]) { htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "

    \n", -1); ParagraphCount[ParagraphIndex] = 0; } if (ParagraphIndex) ParagraphIndex--; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    \n", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Scratch, sizeof(Scratch)); if (*sdptr == ')') sdptr++; } ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Scratch, sizeof(Scratch)); if (*sdptr == ')') sdptr++; } ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { TableRowCount = 0; if (*sdptr == '(') { /* its got a caption, its a formal table, into a file of its own */ InsideFormalTable++; /* This is a reasonably complex tag to implement because it generates a separate HTML output file. It makes use of a recursive call to function ProcessSdmlLines(). It also flushes any HTML text in the output buffer (hence the global variable 'OutputLinePtr') before and after processing the table. */ sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); while (*sdptr == '\\') sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Symbol, sizeof(Symbol)); if (*sdptr == ')') sdptr++; GenerateHtmlFileName (&PopUpFile, SectionNumber[0], ++PopUpNumber); /* create an HTML anchor point in the document for the table file */ if (!Buffer[0]) strcpy (Buffer, "(no title)"); sprintf (Scratch, "\n

    \n[Table: %s]

    \n", PopUpFile.NameOfFile, FrameTargetSelf, Buffer); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Scratch, -1); /* flush any remaining output into the current HTML file */ FlushOutputLine (HtmlFilePtr); CreateHtmlFile (&PopUpFile, SdmlFilePtr); sprintf (OutputLinePtr, "%s\ \n\ \n\ %s\ %s\n\ \n\ %s\

    %s

    \n\ \n\
    \n\
    \n\ \n\
    \n\ \n\ \n\ \n\ ", HTML_DOCTYPE, MetaInformation(SdmlFilePtr), UnmarkupTitle(Buffer), HtmlBodyTag, ChapterTitle, StringHash(Symbol), ++ReferenceNumber, Buffer); while (*OutputLinePtr) OutputLinePtr++; /* recursive call to process the SDML text into the table file */ sdptr = ProcessSdmlLines (SdmlFilePtr, &PopUpFile, sdptr); strcpy (OutputLinePtr, "
    table: %s
    \n\
    \n\ \n\ \n\n"); while (*OutputLinePtr) OutputLinePtr++; /* flush output into the current HTML file */ FlushOutputLine (&PopUpFile); CloseHtmlFile (&PopUpFile); } else { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "\n
    \n\ \n\ \n\
    \n\ ", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (InsideFormalTable) { InsideFormalTable--; /* This psuedo-tag is detected and actioned in function ProcessSdmlLines() to terminate the recursive call made to it by
    processing. */ strcpy (htptr, ""); htptr += 12; } else { ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    \n\
    \n\
    \n", -1); } } else /*------------------------------------------------------------------------*/ if (strsame (TagName, "", -1)) { if (*sdptr == '(') { sdptr = ProcessTagParameter (SdmlFilePtr, HtmlFilePtr, &ErrorInfo, sdptr+1, Buffer, sizeof(Buffer)); ErrorInfo.SourceLineNumber = __LINE__; htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "
    ", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "", -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, Buffer, -1); htptr = StringCopy (&ErrorInfo, htptr, &Capacity, "