home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * hc.c
- *
- * Stand-alone FRACTINT help compiler. Compile in the COMPACT memory model.
- *
- * See HC.DOC for source file syntax.
- *
- *
- * Revision History:
- *
- * 02-26-91 EAN Initial version.
- *
- * 03-21-91 EAN Modified for automatic paragraph formatting.
- * Added several new commands:
- * Format[+/-] Enable/disable paragraph formatting
- * Doc[+/-] Enable/disable output to document.
- * Online[+/-] Enable/disable output to online help.
- * Label= Defines a label. Replaces ~(...)
- * FF Forces a form-feed. Replaces ~~
- * FormatExclude=val Exclude lines past val from
- * formatting. If before any topic sets
- * global default, otherwise set local.
- * FormatExclude= Set to global default.
- * FormatExclude=n Disable exclusion. (global or local)
- * FormatExclude[+/-] Enable/disable format exclusion.
- * Center[+/-] Enable/disable centering of text.
- * \ before nl Forces the end of a paragraph
- * Support for commands embedded in text with new
- * ~(...) format.
- * Support for multiple commands on a line separated by
- * commas.
- * Support for implict links; explicit links must now
- * start with an equal sign.
- * 04-03-91 EAN Added "include" command (works like #include)
- * 04-10-91 EAN Added support for "data" topics.
- * Added Comment/EndComment commands for multi-line
- * comments.
- * Added CompressSpaces[+/-] command.
- * Added DocContents command for document printing.
- * Added BinInc command which includes a binary file
- * in a data topic.
- * Fixed tables to flow down instead of across the page.
- * Makes no allowances for page breaks within tables.
- * 11-03-94 TIW Increased buffer size.
- *
- */
-
-
- #define HC_C
-
- #define INCLUDE_COMMON /* tell helpcom.h to include common code */
-
-
- #include <stdio.h>
- #ifndef XFRACT
- #include <io.h>
- #include <stdarg.h>
- #else
- #include <varargs.h>
- #define strupr strlwr
- #endif
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #ifdef __TURBOC__
- # include <dir.h>
- # define FNSPLIT fnsplit
- #else
- # define MAXFILE _MAX_FNAME
- # define MAXEXT _MAX_EXT
- # define FNSPLIT _splitpath
- #endif
-
-
- #include <assert.h>
- #include "helpcom.h"
-
-
- /*
- * When defined, SHOW_ERROR_LINE will cause the line number in HC.C where
- * errors/warnings/messages are generated to be displayed at the start of
- * the line.
- *
- * Used when debugging HC. Also useful for finding the line (in HC.C) that
- * generated a error or warning.
- */
-
- #ifndef XFRACT
- #define SHOW_ERROR_LINE
- #endif
-
-
- #define DEFAULT_SRC_FNAME "help.src"
- #define DEFAULT_HLP_FNAME "fractint.hlp"
- #define DEFAULT_EXE_FNAME "fractint.exe"
- #define DEFAULT_DOC_FNAME "fractint.doc"
-
- #define TEMP_FNAME "HC.$$$"
- #define SWAP_FNAME "HCSWAP.$$$"
-
- #define MAX_ERRORS (25) /* stop after this many errors */
- #define MAX_WARNINGS (25) /* stop after this many warnings */
- /* 0 = never stop */
-
- #define INDEX_LABEL "HELP_INDEX"
- #define DOCCONTENTS_TITLE "DocContent"
-
-
-
- /* #define BUFFER_SIZE (24*1024) */
- #define BUFFER_SIZE (30*1024)
-
-
- typedef struct
- {
- int type; /* 0 = name is topic title, 1 = name is label, */
- /* 2 = "special topic"; name is NULL and */
- /* topic_num/topic_off is valid */
- int topic_num; /* topic number to link to */
- unsigned topic_off; /* offset into topic to link to */
- int doc_page; /* document page # to link to */
- char *name; /* name of label or title of topic to link to */
- char *srcfile; /* .SRC file link appears in */
- int srcline; /* .SRC file line # link appears in */
- } LINK;
-
-
- typedef struct
- {
- unsigned offset; /* offset from start of topic text */
- unsigned length; /* length of page (in chars) */
- int margin; /* if > 0 then page starts in_para and text */
- /* should be indented by this much */
- } PAGE;
-
-
- /* values for TOPIC.flags */
-
- #define TF_IN_DOC (1) /* 1 if topic is part of the printed document */
- #define TF_DATA (2) /* 1 if it is a "data" topic */
-
-
- typedef struct
- {
- unsigned flags; /* see #defines for TF_??? */
- int doc_page; /* page number in document where topic starts */
- unsigned title_len; /* length of title */
- char *title; /* title for this topic */
- int num_page; /* number of pages */
- PAGE *page; /* list of pages */
- unsigned text_len; /* lenth of topic text */
- long text; /* topic text (all pages) */
- long offset; /* offset to topic from start of file */
- } TOPIC;
-
-
- typedef struct
- {
- char *name; /* its name */
- int topic_num; /* topic number */
- unsigned topic_off; /* offset of label in the topic's text */
- int doc_page;
- } LABEL;
-
-
- /* values for CONTENT.flags */
-
- #define CF_NEW_PAGE (1) /* true if section starts on a new page */
-
-
- #define MAX_CONTENT_TOPIC (10)
-
-
- typedef struct
- {
- unsigned flags;
- char *id;
- char *name;
- int doc_page;
- unsigned page_num_pos;
- int num_topic;
- char is_label[MAX_CONTENT_TOPIC];
- char *topic_name[MAX_CONTENT_TOPIC];
- int topic_num[MAX_CONTENT_TOPIC];
- char *srcfile;
- int srcline;
- } CONTENT;
-
-
- struct help_sig_info
- {
- unsigned long sig;
- int version;
- unsigned long base;
- } ;
-
-
- int num_topic = 0; /* topics */
- TOPIC *topic;
-
- int num_label = 0; /* labels */
- LABEL *label;
-
- int num_plabel = 0; /* private labels */
- LABEL *plabel;
-
- int num_link = 0; /* all links */
- LINK *a_link = 0;
-
- int num_contents = 0; /* the table-of-contents */
- CONTENT *contents;
-
- int quiet_mode = 0; /* true if "/Q" option used */
-
- int max_pages = 0; /* max. pages in any topic */
- int max_links = 0; /* max. links on any page */
- int num_doc_pages = 0; /* total number of pages in document */
-
- FILE *srcfile; /* .SRC file */
- int srcline = 0; /* .SRC line number (used for errors) */
- int srccol = 0; /* .SRC column. */
-
- int version = -1; /* help file version */
-
- int errors = 0, /* number of errors reported */
- warnings = 0; /* number of warnings reported */
-
- char src_fname[81] = ""; /* command-line .SRC filename */
- char hdr_fname[81] = ""; /* .H filename */
- char hlp_fname[81] = ""; /* .HLP filename */
- char *src_cfname = NULL; /* current .SRC filename */
-
- int format_exclude = 0; /* disable formatting at this col, 0 to */
- /* never disable formatting */
- FILE *swapfile;
- long swappos;
-
- char *buffer; /* alloc'ed as BUFFER_SIZE bytes */
- char *curr; /* current position in the buffer */
- char cmd[128]; /* holds the current command */
- int compress_spaces;
- int xonline;
- int xdoc;
-
- #define MAX_INCLUDE_STACK (5) /* allow 5 nested includes */
-
- struct
- {
- char *fname;
- FILE *file;
- int line;
- int col;
- } include_stack[MAX_INCLUDE_STACK];
- int include_stack_top = -1;
-
-
- #define CHK_BUFFER(off) { if ((unsigned)(curr+(off)) - (unsigned)buffer >= (BUFFER_SIZE-1024)) fatal(0,"Buffer overflowed -- Help topic too large."); }
-
- #ifdef __WATCOMC__
- #define putw( x1, x2 ) fprintf( x2, "%c%c", x1&0xFF, x1>>8 );
- #endif
-
- #ifdef XFRACT
- #define putw( x1, x2 ) fwrite( &(x1), 1, sizeof(int), x2);
- #endif
-
- /*
- * error/warning/message reporting functions.
- */
-
-
- void report_errors(void)
- {
- printf("\n");
- printf("Compiler Status:\n");
- printf("%8d Error%c\n", errors, (errors==1) ? ' ' : 's');
- printf("%8d Warning%c\n", warnings, (warnings==1) ? ' ' : 's');
- }
-
-
- void print_msg(char *type, int lnum, char *format, va_list arg)
- {
- if (type != NULL)
- {
- printf(" %s", type);
- if (lnum>0)
- printf(" %s %d", src_cfname, lnum);
- printf(": ");
- }
- vprintf(format, arg);
- printf("\n");
- }
-
-
- #ifndef XFRACT
- void fatal(int diff, char *format, ...)
- #else
- void fatal(va_alist)
- va_dcl
- #endif
- {
- va_list arg;
-
- #ifndef XFRACT
- va_start(arg, format);
- #else
- int diff;
- char *format;
- va_start(arg);
- diff = va_arg(arg,int);
- format = va_arg(arg,char *);
- #endif
-
- print_msg("Fatal", srcline-diff, format, arg);
- va_end(arg);
-
- if ( errors || warnings )
- report_errors();
-
- exit( errors + 1 );
- }
-
-
- #ifndef XFRACT
- void error(int diff, char *format, ...)
- #else
- void error(va_alist)
- va_dcl
- #endif
- {
- va_list arg;
-
- #ifndef XFRACT
- va_start(arg, format);
- #else
- int diff;
- char *format;
- va_start(arg);
- diff = va_arg(arg,int);
- format = va_arg(arg,char *);
- #endif
- print_msg("Error", srcline-diff, format, arg);
- va_end(arg);
-
- if (++errors >= MAX_ERRORS && MAX_ERRORS > 0)
- fatal(0,"Too many errors!");
- }
-
-
- #ifndef XFRACT
- void warn(int diff, char *format, ...)
- #else
- void warn(va_alist)
- va_dcl
- #endif
- {
- va_list arg;
- #ifndef XFRACT
- va_start(arg, format);
- #else
- int diff;
- char *format;
- va_start(arg);
- diff = va_arg(arg, int);
- format = va_arg(arg, char *);
- #endif
- print_msg("Warning", srcline-diff, format, arg);
- va_end(arg);
-
- if (++warnings >= MAX_WARNINGS && MAX_WARNINGS > 0)
- fatal(0,"Too many warnings!");
- }
-
-
- #ifndef XFRACT
- void notice(char *format, ...)
- #else
- void notice(va_alist)
- va_dcl
- #endif
- {
- va_list arg;
- #ifndef XFRACT
- va_start(arg, format);
- #else
- char *format;
-
- va_start(arg);
- format = va_arg(arg,char *);
- #endif
- print_msg("Note", srcline, format, arg);
- va_end(arg);
- }
-
-
- #ifndef XFRACT
- void msg(char *format, ...)
- #else
- void msg(va_alist)
- va_dcl
- #endif
- {
- va_list arg;
- #ifdef XFRACT
- char *format;
- #endif
-
- if (quiet_mode)
- return;
- #ifndef XFRACT
- va_start(arg, format);
- #else
- va_start(arg);
- format = va_arg(arg,char *);
- #endif
- print_msg(NULL, 0, format, arg);
- va_end(arg);
- }
-
-
- #ifdef SHOW_ERROR_LINE
- # define fatal (printf("[%04d] ", __LINE__), fatal)
- # define error (printf("[%04d] ", __LINE__), error)
- # define warn (printf("[%04d] ", __LINE__), warn)
- # define notice (printf("[%04d] ", __LINE__), notice)
- # define msg (printf((quiet_mode)?"":"[%04d] ", __LINE__), msg)
- #endif
-
-
- /*
- * store-topic-text-to-disk stuff.
- */
-
-
- void alloc_topic_text(TOPIC *t, unsigned size)
- {
- t->text_len = size;
- t->text = swappos;
- swappos += size;
- fseek(swapfile, t->text, SEEK_SET);
- fwrite(buffer, 1, t->text_len, swapfile);
- }
-
-
- char *get_topic_text(TOPIC *t)
- {
- fseek(swapfile, t->text, SEEK_SET);
- fread(buffer, 1, t->text_len, swapfile);
- return (buffer);
- }
-
-
- void release_topic_text(TOPIC *t, int save)
- {
- if ( save )
- {
- fseek(swapfile, t->text, SEEK_SET);
- fwrite(buffer, 1, t->text_len, swapfile);
- }
- }
-
-
- /*
- * memory-allocation functions.
- */
-
-
- #define new(item) (item *)newx(sizeof(item))
- #define delete(item) free(item)
-
-
- VOIDPTR newx(unsigned size)
- {
- VOIDPTR ptr;
-
- ptr = malloc(size);
-
- if (ptr == NULL)
- fatal(0,"Out of memory!");
-
- return (ptr);
- }
-
-
- VOIDPTR renewx(VOIDPTR ptr, unsigned size)
- {
- ptr = realloc(ptr, size);
-
- if (ptr == NULL)
- fatal(0,"Out of memory!");
-
- return (ptr);
- }
-
-
- char *dupstr(char *s, unsigned len)
- {
- char *ptr;
-
- if (len == 0)
- len = strlen(s) + 1;
-
- ptr = newx(len);
-
- memcpy(ptr, s, len);
-
- return (ptr);
- }
-
-
- #define LINK_ALLOC_SIZE (16)
-
-
- int add_link(LINK *l)
- {
- if (num_link == 0)
- a_link = newx( sizeof(LINK)*LINK_ALLOC_SIZE );
-
- else if (num_link%LINK_ALLOC_SIZE == 0)
- a_link = renewx(a_link, sizeof(LINK) * (num_link+LINK_ALLOC_SIZE) );
-
- a_link[num_link] = *l;
-
- return( num_link++ );
- }
-
-
- #define PAGE_ALLOC_SIZE (4)
-
-
- int add_page(TOPIC *t, PAGE *p)
- {
- if (t->num_page == 0)
- t->page = newx( sizeof(PAGE)*PAGE_ALLOC_SIZE );
-
- else if (t->num_page%PAGE_ALLOC_SIZE == 0)
- t->page = renewx(t->page, sizeof(PAGE) * (t->num_page+PAGE_ALLOC_SIZE) );
-
- t->page[t->num_page] = *p;
-
- return ( t->num_page++ );
- }
-
-
- #define TOPIC_ALLOC_SIZE (16)
-
-
- int add_topic(TOPIC *t)
- {
- if (num_topic == 0)
- topic = newx( sizeof(TOPIC)*TOPIC_ALLOC_SIZE );
-
- else if (num_topic%TOPIC_ALLOC_SIZE == 0)
- topic = renewx(topic, sizeof(TOPIC) * (num_topic+TOPIC_ALLOC_SIZE) );
-
- topic[num_topic] = *t;
-
- return ( num_topic++ );
- }
-
-
- #define LABEL_ALLOC_SIZE (16)
-
-
- int add_label(LABEL *l)
- {
- if (l->name[0] == '@') /* if it's a private label... */
- {
- if (num_plabel == 0)
- plabel = newx( sizeof(LABEL)*LABEL_ALLOC_SIZE );
-
- else if (num_plabel%LABEL_ALLOC_SIZE == 0)
- plabel = renewx(plabel, sizeof(LABEL) * (num_plabel+LABEL_ALLOC_SIZE) );
-
- plabel[num_plabel] = *l;
-
- return ( num_plabel++ );
- }
- else
- {
- if (num_label == 0)
- label = newx( sizeof(LABEL)*LABEL_ALLOC_SIZE );
-
- else if (num_label%LABEL_ALLOC_SIZE == 0)
- label = renewx(label, sizeof(LABEL) * (num_label+LABEL_ALLOC_SIZE) );
-
- label[num_label] = *l;
-
- return ( num_label++ );
- }
- }
-
-
- #define CONTENTS_ALLOC_SIZE (16)
-
-
- int add_content(CONTENT *c)
- {
- if (num_contents == 0)
- contents = newx( sizeof(CONTENT)*CONTENTS_ALLOC_SIZE );
-
- else if (num_contents%CONTENTS_ALLOC_SIZE == 0)
- contents = renewx(contents, sizeof(CONTENT) * (num_contents+CONTENTS_ALLOC_SIZE) );
-
- contents[num_contents] = *c;
-
- return ( num_contents++ );
- }
-
-
- /*
- * read_char() stuff
- */
-
-
- #define READ_CHAR_BUFF_SIZE (32)
-
-
- int read_char_buff[READ_CHAR_BUFF_SIZE];
- int read_char_buff_pos = -1;
- int read_char_sp = 0;
-
-
- void unread_char(int ch)
- /*
- * Will not handle new-lines or tabs correctly!
- */
- {
- if (read_char_buff_pos+1 >= READ_CHAR_BUFF_SIZE)
- fatal(0,"Compiler Error -- Read char buffer overflow!");
-
- read_char_buff[++read_char_buff_pos] = ch;
-
- --srccol;
- }
-
-
- void unread_string(char *s)
- {
- int p = strlen(s);
-
- while (p-- > 0)
- unread_char(s[p]);
- }
-
-
- int eos(void) /* end-of-source ? */
- {
- return ( !((read_char_sp==0) && (read_char_buff_pos==0) && feof(srcfile)) );
- }
-
-
- int _read_char(void)
- {
- int ch;
-
- if (srcline <= 0)
- {
- srcline = 1;
- srccol = 0;
- }
-
- if (read_char_buff_pos >= 0)
- {
- ++srccol;
- return ( read_char_buff[read_char_buff_pos--] );
- }
-
- if (read_char_sp > 0)
- {
- --read_char_sp;
- return (' ');
- }
-
- if ( feof(srcfile) )
- return (-1);
-
- while (1)
- {
- ch = getc(srcfile);
-
- switch (ch)
- {
- case '\t': /* expand a tab */
- {
- int diff = ( ( (srccol/8) + 1 ) * 8 ) - srccol;
-
- srccol += diff;
- read_char_sp += diff;
- break;
- }
-
- case ' ':
- ++srccol;
- ++read_char_sp;
- break;
-
- case '\n':
- read_char_sp = 0; /* delete spaces before a \n */
- srccol = 0;
- ++srcline;
- return ('\n');
-
- case -1: /* EOF */
- if (read_char_sp > 0)
- {
- --read_char_sp;
- return (' ');
- }
- return (-1);
-
- default:
- if (read_char_sp > 0)
- {
- ungetc(ch, srcfile);
- --read_char_sp;
- return (' ');
- }
-
- ++srccol;
- return (ch);
-
- } /* switch */
- }
- }
-
-
- int read_char(void)
- {
- int ch;
-
- ch = _read_char();
-
- while (ch == ';' && srccol==1) /* skip over comments */
- {
- ch = _read_char();
-
- while (ch!='\n' && ch!=-1 )
- ch = _read_char();
-
- ch = _read_char();
- }
-
- if (ch == '\\') /* process an escape code */
- {
- ch = _read_char();
-
- if (ch >= '0' && ch <= '9')
- {
- char buff[4];
- int ctr;
-
- for (ctr=0; ; ctr++)
- {
- if ( ch<'0' || ch>'9' || ch==-1 || ctr>=3 )
- {
- unread_char(ch);
- break;
- }
- buff[ctr] = ch;
- ch = _read_char();
- }
- buff[ctr] = '\0';
- ch = atoi(buff);
- }
-
- #ifdef XFRACT
- /* Convert graphics arrows into keyboard chars */
- if (ch>=24 && ch<=27) {
- ch = "KJHL"[ch-24];
- }
- #endif
- ch |= 0x100;
- }
-
- if ( (ch & 0xFF) == 0 )
- {
- error(0,"Null character (\'\\0\') not allowed!");
- ch = 0x1FF; /* since we've had an error the file will not be written; */
- /* the value we return doesn't really matter */
- }
-
- return(ch);
- }
-
-
- /*
- * misc. search functions.
- */
-
-
- LABEL *find_label(char *name)
- {
- int l;
- LABEL *lp;
-
- if (*name == '@')
- {
- for (l=0, lp=plabel; l<num_plabel; l++, lp++)
- if ( strcmp(name, lp->name) == 0 )
- return (lp);
- }
- else
- {
- for (l=0, lp=label; l<num_label; l++, lp++)
- if ( strcmp(name, lp->name) == 0 )
- return (lp);
- }
-
- return (NULL);
- }
-
-
- int find_topic_title(char *title)
- {
- int t;
- int len;
-
- while (*title == ' ')
- ++title;
-
- len = strlen(title) - 1;
- while ( title[len] == ' ' && len > 0 )
- --len;
-
- ++len;
-
- if ( len > 2 && title[0] == '\"' && title[len-1] == '\"' )
- {
- ++title;
- len -= 2;
- }
-
- for (t=0; t<num_topic; t++)
- if ( strlen(topic[t].title) == len &&
- strnicmp(title, topic[t].title, len) == 0 )
- return (t);
-
- return (-1); /* not found */
- }
-
-
- /*
- * .SRC file parser stuff
- */
-
-
- int validate_label_name(char *name)
- {
- if ( !isalpha(*name) && *name!='@' && *name!='_' )
- return (0); /* invalid */
-
- while (*(++name) != '\0')
- if ( !isalpha(*name) && !isdigit(*name) && *name!='_' )
- return(0); /* invalid */
-
- return (1); /* valid */
- }
-
-
- char *read_until(char *buff, int len, char *stop_chars)
- {
- int ch;
-
- while ( --len > 0 )
- {
- ch = read_char();
-
- if ( ch == -1 )
- {
- *buff++ = '\0';
- break;
- }
-
- if ( (ch&0xFF) <= MAX_CMD )
- *buff++ = CMD_LITERAL;
-
- *buff++ = ch;
-
- if ( (ch&0x100)==0 && strchr(stop_chars, ch) != NULL )
- break;
- }
-
- return ( buff-1 );
- }
-
-
- void skip_over(char *skip)
- {
- int ch;
-
- while (1)
- {
- ch = read_char();
-
- if ( ch == -1 )
- break;
-
- else if ( (ch&0x100) == 0 && strchr(skip, ch) == NULL )
- {
- unread_char(ch);
- break;
- }
- }
- }
-
-
- char *pchar(int ch)
- {
- static char buff[16];
-
- if ( ch >= 0x20 && ch <= 0x7E )
- sprintf(buff, "\'%c\'", ch);
- else
- sprintf(buff, "\'\\x%02X\'", ch&0xFF);
-
- return (buff);
- }
-
-
- void put_spaces(int how_many)
- {
- if (how_many > 2 && compress_spaces)
- {
- if (how_many > 255)
- {
- error(0,"Too many spaces (over 255).");
- how_many = 255;
- }
-
- *curr++ = CMD_SPACE;
- *curr++ = (BYTE)how_many;
- }
- else
- {
- while (how_many-- > 0)
- *curr++ = ' ';
- }
- }
-
-
- int get_next_item(void) /* used by parse_contents() */
- {
- int last;
- char *ptr;
-
- skip_over(" \t\n");
- ptr = read_until(cmd, 128, ",}");
- last = (*ptr == '}');
- --ptr;
- while ( ptr >= cmd && strchr(" \t\n",*ptr) ) /* strip trailing spaces */
- --ptr;
- *(++ptr) = '\0';
-
- return (last);
- }
-
-
- void process_contents(void)
- {
- CONTENT c;
- char *ptr;
- int indent;
- int ch;
- TOPIC t;
-
- t.flags = 0;
- t.title_len = strlen(DOCCONTENTS_TITLE)+1;
- t.title = dupstr(DOCCONTENTS_TITLE, t.title_len);
- t.doc_page = -1;
- t.num_page = 0;
-
- curr = buffer;
-
- c.flags = 0;
- c.id = dupstr("",1);
- c.name = dupstr("",1);
- c.doc_page = -1;
- c.page_num_pos = 0;
- c.num_topic = 1;
- c.is_label[0] = 0;
- c.topic_name[0] = dupstr(DOCCONTENTS_TITLE,0);
- c.srcline = -1;
- add_content(&c);
-
- while (1)
- {
- ch = read_char();
-
- if (ch == '{') /* process a CONTENT entry */
- {
- int last;
-
- c.flags = 0;
- c.num_topic = 0;
- c.doc_page = -1;
- c.srcfile = src_cfname;
- c.srcline = srcline;
-
- if ( get_next_item() )
- {
- error(0,"Unexpected end of DocContent entry.");
- continue;
- }
- c.id = dupstr(cmd,0);
-
- if ( get_next_item() )
- {
- error(0,"Unexpected end of DocContent entry.");
- continue;
- }
- indent = atoi(cmd);
-
- last = get_next_item();
-
- if ( cmd[0] == '\"' )
- {
- ptr = cmd+1;
- if (ptr[strlen(ptr)-1] == '\"')
- ptr[strlen(ptr)-1] = '\0';
- else
- warn(0,"Missing ending quote.");
-
- c.is_label[c.num_topic] = 0;
- c.topic_name[c.num_topic] = dupstr(ptr,0);
- ++c.num_topic;
- c.name = dupstr(ptr,0);
- }
- else
- c.name = dupstr(cmd,0);
-
- /* now, make the entry in the buffer */
-
- sprintf(curr, "%-5s %*.0s%s", c.id, indent*2, "", c.name);
- ptr = curr + strlen(curr);
- while ( (ptr-curr) < PAGE_WIDTH-10 )
- *ptr++ = '.';
- c.page_num_pos = (unsigned) ( (ptr-3) - buffer );
- curr = ptr;
-
- while (!last)
- {
- last = get_next_item();
-
- if ( stricmp(cmd, "FF") == 0 )
- {
- if ( c.flags & CF_NEW_PAGE )
- warn(0,"FF already present in this entry.");
- c.flags |= CF_NEW_PAGE;
- continue;
- }
-
- if (cmd[0] == '\"')
- {
- ptr = cmd+1;
- if (ptr[strlen(ptr)-1] == '\"')
- ptr[strlen(ptr)-1] = '\0';
- else
- warn(0,"Missing ending quote.");
-
- c.is_label[c.num_topic] = 0;
- c.topic_name[c.num_topic] = dupstr(ptr,0);
- }
- else
- {
- c.is_label[c.num_topic] = 1;
- c.topic_name[c.num_topic] = dupstr(cmd,0);
- }
-
- if ( ++c.num_topic >= MAX_CONTENT_TOPIC )
- {
- error(0,"Too many topics in DocContent entry.");
- break;
- }
- }
-
- add_content(&c);
- }
-
- else if (ch == '~') /* end at any command */
- {
- unread_char(ch);
- break;
- }
-
- else
- *curr++ = ch;
-
- CHK_BUFFER(0);
- }
-
- alloc_topic_text(&t, (unsigned) (curr - buffer) );
- add_topic(&t);
- }
-
-
- int parse_link(void) /* returns length of link or 0 on error */
- {
- char *ptr;
- char *end;
- int bad = 0;
- int len;
- LINK l;
- int lnum;
- int err_off;
-
- l.srcfile = src_cfname;
- l.srcline = srcline;
- l.doc_page = -1;
-
- end = read_until(cmd, 128, "}\n"); /* get the entire hot-link */
-
- if (*end == '\0')
- {
- error(0,"Unexpected EOF in hot-link.");
- return (0);
- }
-
- if (*end == '\n')
- {
- err_off = 1;
- warn(1,"Hot-link has no closing curly-brace (\'}\').");
- }
- else
- err_off = 0;
-
- *end = '\0';
-
- if (cmd[0] == '=') /* it's an "explicit" link to a label or "special" */
- {
- ptr = strchr(cmd, ' ');
-
- if (ptr == NULL)
- ptr = end;
- else
- *ptr++ = '\0';
-
- len = (int) (end - ptr);
-
- if ( cmd[1] == '-' )
- {
- l.type = 2; /* type 2 = "special" */
- l.topic_num = atoi(cmd+1);
- l.topic_off = 0;
- l.name = NULL;
- }
- else
- {
- l.type = 1; /* type 1 = to a label */
- if (strlen(cmd) > 32)
- warn(err_off, "Label is long.");
- if (cmd[1] == '\0')
- {
- error(err_off, "Explicit hot-link has no Label.");
- bad = 1;
- }
- else
- l.name = dupstr(cmd+1,0);
- }
- if (len == 0)
- warn(err_off, "Explicit hot-link has no title.");
- }
- else
- {
- ptr = cmd;
- l.type = 0; /* type 0 = topic title */
- len = (int) (end - ptr);
- if (len == 0)
- {
- error(err_off, "Implicit hot-link has no title.");
- bad = 1;
- }
- l.name = dupstr(ptr,len+1);
- l.name[len] = '\0';
- }
-
- if ( !bad )
- {
- CHK_BUFFER(1+3*sizeof(int)+len+1)
- lnum = add_link(&l);
- *curr++ = CMD_LINK;
- setint(curr,lnum);
- curr += 3*sizeof(int);
- memcpy(curr, ptr, len);
- curr += len;
- *curr++ = CMD_LINK;
- return (len);
- }
- else
- return (0);
- }
-
-
- #define MAX_TABLE_SIZE (100)
-
-
- int create_table(void)
- {
- char *ptr;
- int width;
- int cols;
- int start_off;
- int first_link;
- int rows;
- int r, c;
- int ch;
- int done;
- int len;
- int lnum;
- int count;
- char *title[MAX_TABLE_SIZE];
- char *table_start;
-
- ptr = strchr(cmd, '=');
-
- if (ptr == NULL)
- return (0); /* should never happen! */
-
- ptr++;
-
- len = sscanf(ptr, " %d %d %d", &width, &cols, &start_off);
-
- if (len < 3)
- {
- error(1,"Too few arguments to Table.");
- return (0);
- }
-
- if (width<=0 || width > 78 || cols<=0 || start_off<0 || start_off > 78)
- {
- error(1,"Argument out of range.");
- return (0);
- }
-
- done = 0;
-
- first_link = num_link;
- table_start = curr;
- count = 0;
-
- /* first, read all the links in the table */
-
- do
- {
-
- do
- ch = read_char();
- while ( ch=='\n' || ch == ' ' );
-
- if (done)
- break;
-
- switch (ch)
- {
- case -1:
- error(0,"Unexpected EOF in a Table.");
- return(0);
-
- case '{':
- if (count >= MAX_TABLE_SIZE)
- fatal(0,"Table is too large.");
- len = parse_link();
- curr = table_start; /* reset to the start... */
- title[count] = dupstr(curr+3*sizeof(int)+1, len+1);
- if (len >= width)
- {
- warn(1,"Link is too long; truncating.");
- len = width-1;
- }
- title[count][len] = '\0';
- ++count;
- break;
-
- case '~':
- {
- int imbedded;
-
- ch = read_char();
-
- if (ch=='(')
- imbedded = 1;
- else
- {
- imbedded = 0;
- unread_char(ch);
- }
-
- ptr = read_until(cmd, 128, ")\n,");
-
- ch = *ptr;
- *ptr = '\0';
-
- if ( stricmp(cmd, "EndTable") == 0 )
- done = 1;
- else
- {
- error(1,"Unexpected command in table \"%s\"", cmd);
- warn(1,"Command will be ignored.");
- }
-
- if (ch == ',')
- {
- if (imbedded)
- unread_char('(');
- unread_char('~');
- }
- }
- break;
-
- default:
- error(0,"Unexpected character %s.", pchar(ch));
- break;
- }
- }
- while (!done);
-
- /* now, put all the links into the buffer... */
-
- rows = 1 + ( count / cols );
-
- for (r=0; r<rows; r++)
- {
- put_spaces(start_off);
- for (c=0; c<cols; c++)
- {
- lnum = c*rows + r;
-
- if ( first_link+lnum >= num_link )
- break;
-
- len = strlen(title[lnum]);
- *curr++ = CMD_LINK;
- setint(curr,first_link+lnum);
- curr += 3*sizeof(int);
- memcpy(curr, title[lnum], len);
- curr += len;
- *curr++ = CMD_LINK;
-
- delete(title[lnum]);
-
- if ( c < cols-1 )
- put_spaces( width-len );
- }
- *curr++ = '\n';
- }
-
- return (1);
- }
-
-
- void process_comment(void)
- {
- int ch;
-
- while ( 1 )
- {
- ch = read_char();
-
- if (ch == '~')
- {
- int imbedded;
- char *ptr;
-
- ch = read_char();
-
- if (ch=='(')
- imbedded = 1;
- else
- {
- imbedded = 0;
- unread_char(ch);
- }
-
- ptr = read_until(cmd, 128, ")\n,");
-
- ch = *ptr;
- *ptr = '\0';
-
- if ( stricmp(cmd, "EndComment") == 0 )
- {
- if (ch == ',')
- {
- if (imbedded)
- unread_char('(');
- unread_char('~');
- }
- break;
- }
- }
-
- else if ( ch == -1 )
- {
- error(0,"Unexpected EOF in Comment");
- break;
- }
- }
- }
-
-
- void process_bininc(void)
- {
- int handle;
- long len;
-
- if ( (handle=open(cmd+7, O_RDONLY|O_BINARY)) == -1 )
- {
- error(0,"Unable to open \"%s\"", cmd+7);
- return ;
- }
-
- len = filelength(handle);
-
- if ( len >= BUFFER_SIZE )
- {
- error(0,"File \"%s\" is too large to BinInc (%dK).", cmd+7, (int)(len>>10));
- close(handle);
- return ;
- }
-
- /*
- * Since we know len is less than BUFFER_SIZE (and therefore less then
- * 64K) we can treat it as an unsigned.
- */
-
- CHK_BUFFER((unsigned)len);
-
- read(handle, curr, (unsigned)len);
-
- curr += (unsigned)len;
-
- close(handle);
- }
-
-
- void start_topic(TOPIC *t, char *title, int title_len)
- {
- t->flags = 0;
- t->title_len = title_len;
- t->title = dupstr(title, title_len+1);
- t->title[title_len] = '\0';
- t->doc_page = -1;
- t->num_page = 0;
- curr = buffer;
- }
-
-
- void end_topic(TOPIC *t)
- {
- alloc_topic_text(t, (unsigned) (curr - buffer) );
- add_topic(t);
- }
-
-
- int end_of_sentence(char *ptr) /* true if ptr is at the end of a sentence */
- {
- if ( *ptr == ')')
- --ptr;
-
- if ( *ptr == '\"')
- --ptr;
-
- return ( *ptr=='.' || *ptr=='?' || *ptr=='!' );
- }
-
-
- void add_blank_for_split(void) /* add space at curr for merging two lines */
- {
- if ( !is_hyphen(curr-1) ) /* no spaces if it's a hyphen */
- {
- if ( end_of_sentence(curr-1) )
- *curr++ = ' '; /* two spaces at end of a sentence */
- *curr++ = ' ';
- }
- }
-
-
- void put_a_char(int ch, TOPIC *t)
- {
- if (ch == '{' && !(t->flags & TF_DATA) ) /* is it a hot-link? */
- parse_link();
- else
- {
- if ( (ch&0xFF) <= MAX_CMD)
- *curr++ = CMD_LITERAL;
- *curr++ = ch;
- }
- }
-
-
- enum STATES /* states for FSM's */
- {
- S_Start, /* initial state, between paragraphs */
- S_StartFirstLine, /* spaces at start of first line */
- S_FirstLine, /* text on the first line */
- S_FirstLineSpaces, /* spaces on the first line */
- S_StartSecondLine, /* spaces at start of second line */
- S_Line, /* text on lines after the first */
- S_LineSpaces, /* spaces on lines after the first */
- S_StartLine, /* spaces at start of lines after second */
- S_FormatDisabled, /* format automatically disabled for this line */
- S_FormatDisabledSpaces, /* spaces in line which format is disabled */
- S_Spaces
- } ;
-
-
- void check_command_length(int eoff, int len)
- {
- if (strlen(cmd) != len)
- error(eoff, "Invalid text after a command \"%s\"", cmd+len);
- }
-
-
- void read_src(char *fname)
- {
- int ch;
- char *ptr;
- TOPIC t;
- LABEL lbl;
- char *margin_pos = NULL;
- int in_topic = 0,
- formatting = 1,
- state = S_Start,
- num_spaces = 0,
- margin = 0,
- in_para = 0,
- centering = 0,
- lformat_exclude = format_exclude,
- again;
-
- xonline = xdoc = 0;
-
- src_cfname = fname;
-
- if ( (srcfile = fopen(fname, "rt")) == NULL )
- fatal(0,"Unable to open \"%s\"", fname);
-
- msg("Compiling: %s", fname);
-
- in_topic = 0;
-
- curr = buffer;
-
- while ( 1 )
- {
-
- ch = read_char();
-
- if ( ch == -1 ) /* EOF? */
- {
- if ( include_stack_top >= 0)
- {
- fclose(srcfile);
- src_cfname = include_stack[include_stack_top].fname;
- srcfile = include_stack[include_stack_top].file;
- srcline = include_stack[include_stack_top].line;
- srccol = include_stack[include_stack_top].col;
- --include_stack_top;
- continue;
- }
- else
- {
- if (in_topic) /* if we're in a topic, finish it */
- end_topic(&t);
- if (num_topic == 0)
- warn(0,".SRC file has no topics.");
- break;
- }
- }
-
- if (ch == '~') /* is is a command? */
- {
- int imbedded;
- int eoff;
- int done;
-
- ch = read_char();
- if (ch == '(')
- {
- imbedded = 1;
- eoff = 0;
- }
- else
- {
- imbedded = 0;
- eoff=0;
- unread_char(ch);
- }
-
- done = 0;
-
- while ( !done )
- {
- do
- ch = read_char();
- while (ch == ' ');
- unread_char(ch);
-
- if (imbedded)
- ptr = read_until(cmd, 128, ")\n,");
- else
- ptr = read_until(cmd, 128, "\n,");
-
- done = 1;
-
- if ( *ptr == '\0' )
- {
- error(0,"Unexpected EOF in command.");
- break;
- }
-
- if (*ptr == '\n')
- ++eoff;
-
- if ( imbedded && *ptr == '\n' )
- error(eoff,"Imbedded command has no closing parend (\')\')");
-
- done = (*ptr != ','); /* we done if it's not a comma */
-
- if ( *ptr != '\n' && *ptr != ')' && *ptr != ',' )
- {
- error(0,"Command line too long.");
- break;
- }
-
- *ptr = '\0';
-
-
- /* commands allowed anytime... */
-
- if ( strnicmp(cmd, "Topic=", 6) == 0 )
- {
- if (in_topic) /* if we're in a topic, finish it */
- end_topic(&t);
- else
- in_topic = 1;
-
- if (cmd[6] == '\0')
- warn(eoff,"Topic has no title.");
-
- else if (strlen(cmd+6) > 70)
- error(eoff,"Topic title is too long.");
-
- else if (strlen(cmd+6) > 60)
- warn(eoff,"Topic title is long.");
-
- if ( find_topic_title(cmd+6) != -1 )
- error(eoff,"Topic title already exists.");
-
- start_topic(&t, cmd+6, (unsigned)(ptr-(cmd+6)));
- formatting = 1;
- centering = 0;
- state = S_Start;
- in_para = 0;
- num_spaces = 0;
- xonline = xdoc = 0;
- lformat_exclude = format_exclude;
- compress_spaces = 1;
- continue;
- }
-
- else if ( strnicmp(cmd, "Data=", 5) == 0 )
- {
- if (in_topic) /* if we're in a topic, finish it */
- end_topic(&t);
- else
- in_topic = 1;
-
- if (cmd[5] == '\0')
- warn(eoff,"Data topic has no label.");
-
- if ( !validate_label_name(cmd+5) )
- {
- error(eoff,"Label \"%s\" contains illegal characters.", cmd+5);
- continue;
- }
-
- if ( find_label(cmd+5) != NULL )
- {
- error(eoff,"Label \"%s\" already exists", cmd+5);
- continue;
- }
-
- if ( cmd[5] == '@' )
- warn(eoff, "Data topic has a local label.");
-
- start_topic(&t, "", 0);
- t.flags |= TF_DATA;
-
- if (strlen(cmd+5) > 32)
- warn(eoff,"Label name is long.");
-
- lbl.name = dupstr(cmd+5, 0);
- lbl.topic_num = num_topic;
- lbl.topic_off = 0;
- lbl.doc_page = -1;
- add_label(&lbl);
-
- formatting = 0;
- centering = 0;
- state = S_Start;
- in_para = 0;
- num_spaces = 0;
- xonline = xdoc = 0;
- lformat_exclude = format_exclude;
- compress_spaces = 0;
- continue;
- }
-
- else if ( strnicmp(cmd, "DocContents", 11) == 0 )
- {
- check_command_length(eoff, 11);
- if (in_topic) /* if we're in a topic, finish it */
- end_topic(&t);
- if (!done)
- {
- if (imbedded)
- unread_char('(');
- unread_char('~');
- done = 1;
- }
- compress_spaces = 1;
- process_contents();
- in_topic = 0;
- continue;
- }
-
- else if ( stricmp(cmd, "Comment") == 0 )
- {
- process_comment();
- continue;
- }
-
- else if ( strnicmp(cmd, "FormatExclude", 13) == 0 )
- {
- if (cmd[13] == '-')
- {
- check_command_length(eoff, 14);
- if ( in_topic )
- {
- if (lformat_exclude > 0)
- lformat_exclude = -lformat_exclude;
- else
- warn(eoff,"\"FormatExclude-\" is already in effect.");
- }
- else
- {
- if (format_exclude > 0)
- format_exclude = -format_exclude;
- else
- warn(eoff,"\"FormatExclude-\" is already in effect.");
- }
- }
- else if (cmd[13] == '+')
- {
- check_command_length(eoff,14);
- if ( in_topic )
- {
- if (lformat_exclude < 0)
- lformat_exclude = -lformat_exclude;
- else
- warn(eoff,"\"FormatExclude+\" is already in effect.");
- }
- else
- {
- if (format_exclude < 0)
- format_exclude = -format_exclude;
- else
- warn(eoff,"\"FormatExclude+\" is already in effect.");
- }
- }
- else if (cmd[13] == '=')
- {
- if (cmd[14] == 'n' || cmd[14] == 'N')
- {
- check_command_length(eoff,15);
- if (in_topic)
- lformat_exclude = 0;
- else
- format_exclude = 0;
- }
- else if (cmd[14] == '\0')
- lformat_exclude = format_exclude;
- else
- {
- int n = ( ( (in_topic) ? lformat_exclude : format_exclude) < 0 ) ? -1 : 1;
-
- lformat_exclude = atoi(cmd+14);
-
- if ( lformat_exclude <= 0 )
- {
- error(eoff,"Invalid argument to FormatExclude=");
- lformat_exclude = 0;
- }
-
- lformat_exclude *= n;
-
- if ( !in_topic )
- format_exclude = lformat_exclude;
- }
- }
- else
- error(eoff,"Invalid format for FormatExclude");
-
- continue;
- }
-
- else if ( strnicmp(cmd, "Include ", 8) == 0 )
- {
- if (include_stack_top >= MAX_INCLUDE_STACK-1)
- error(eoff, "Too many nested Includes.");
- else
- {
- ++include_stack_top;
- include_stack[include_stack_top].fname = src_cfname;
- include_stack[include_stack_top].file = srcfile;
- include_stack[include_stack_top].line = srcline;
- include_stack[include_stack_top].col = srccol;
- strupr(cmd+8);
- if ( (srcfile = fopen(cmd+8, "rt")) == NULL )
- {
- error(eoff, "Unable to open \"%s\"", cmd+8);
- srcfile = include_stack[include_stack_top--].file;
- }
- src_cfname = dupstr(cmd+8,0); /* never deallocate! */
- srcline = 1;
- srccol = 0;
- }
-
- continue;
- }
-
-
- /* commands allowed only before all topics... */
-
- if ( !in_topic )
- {
- if ( strnicmp(cmd, "HdrFile=", 8) == 0 )
- {
- if (hdr_fname[0] != '\0')
- warn(eoff,"Header Filename has already been defined.");
- strcpy(hdr_fname, cmd+8);
- strupr(hdr_fname);
- }
-
- else if ( strnicmp(cmd, "HlpFile=", 8) == 0 )
- {
- if (hlp_fname[0] != '\0')
- warn(eoff,"Help Filename has already been defined.");
- strcpy(hlp_fname, cmd+8);
- strupr(hlp_fname);
- }
-
- else if ( strnicmp(cmd, "Version=", 8) == 0 )
- {
- if (version != -1) /* an unlikely value */
- warn(eoff,"Help version has already been defined");
- version = atoi(cmd+8);
- }
-
- else
- error(eoff,"Bad or unexpected command \"%s\"", cmd);
-
- continue;
- }
-
-
- /* commands allowed only in a topic... */
-
- else
- {
- if (strnicmp(cmd, "FF", 2) == 0 )
- {
- check_command_length(eoff,2);
- if ( in_para )
- *curr++ = '\n'; /* finish off current paragraph */
- *curr++ = CMD_FF;
- state = S_Start;
- in_para = 0;
- num_spaces = 0;
- }
-
- else if (strnicmp(cmd, "DocFF", 5) == 0 )
- {
- check_command_length(eoff,5);
- if ( in_para )
- *curr++ = '\n'; /* finish off current paragraph */
- if (!xonline)
- *curr++ = CMD_XONLINE;
- *curr++ = CMD_FF;
- if (!xonline)
- *curr++ = CMD_XONLINE;
- state = S_Start;
- in_para = 0;
- num_spaces = 0;
- }
-
- else if (strnicmp(cmd, "OnlineFF", 8) == 0 )
- {
- check_command_length(eoff,8);
- if ( in_para )
- *curr++ = '\n'; /* finish off current paragraph */
- if (!xdoc)
- *curr++ = CMD_XDOC;
- *curr++ = CMD_FF;
- if (!xdoc)
- *curr++ = CMD_XDOC;
- state = S_Start;
- in_para = 0;
- num_spaces = 0;
- }
-
- else if ( strnicmp(cmd, "Label=", 6) == 0 )
- {
- if (strlen(cmd+6) <= 0)
- error(eoff,"Label has no name.");
-
- else if ( !validate_label_name(cmd+6) )
- error(eoff,"Label \"%s\" contains illegal characters.", cmd+6);
-
- else if ( find_label(cmd+6) != NULL )
- error(eoff,"Label \"%s\" already exists", cmd+6);
-
- else
- {
- if (strlen(cmd+6) > 32)
- warn(eoff,"Label name is long.");
-
- if ( (t.flags & TF_DATA) && cmd[6] == '@' )
- warn(eoff, "Data topic has a local label.");
-
- lbl.name = dupstr(cmd+6, 0);
- lbl.topic_num = num_topic;
- lbl.topic_off = (unsigned)(curr - buffer);
- lbl.doc_page = -1;
- add_label(&lbl);
- }
- }
-
- else if ( strnicmp(cmd, "Table=", 6) == 0 )
- {
- if ( in_para )
- {
- *curr++ = '\n'; /* finish off current paragraph */
- in_para = 0;
- num_spaces = 0;
- state = S_Start;
- }
-
- if (!done)
- {
- if (imbedded)
- unread_char('(');
- unread_char('~');
- done = 1;
- }
-
- create_table();
- }
-
- else if ( strnicmp(cmd, "FormatExclude", 12) == 0 )
- {
- if (cmd[13] == '-')
- {
- check_command_length(eoff,14);
- if (lformat_exclude > 0)
- lformat_exclude = -lformat_exclude;
- else
- warn(0,"\"FormatExclude-\" is already in effect.");
- }
- else if (cmd[13] == '+')
- {
- check_command_length(eoff,14);
- if (lformat_exclude < 0)
- lformat_exclude = -lformat_exclude;
- else
- warn(0,"\"FormatExclude+\" is already in effect.");
- }
- else
- error(eoff,"Unexpected or invalid argument to FormatExclude.");
- }
-
- else if ( strnicmp(cmd, "Format", 6) == 0 )
- {
- if (cmd[6] == '+')
- {
- check_command_length(eoff,7);
- if ( !formatting )
- {
- formatting = 1;
- in_para = 0;
- num_spaces = 0;
- state = S_Start;
- }
- else
- warn(eoff,"\"Format+\" is already in effect.");
- }
- else if (cmd[6] == '-')
- {
- check_command_length(eoff,7);
- if ( formatting )
- {
- if ( in_para )
- *curr++ = '\n'; /* finish off current paragraph */
- state = S_Start;
- in_para = 0;
- formatting = 0;
- num_spaces = 0;
- state = S_Start;
- }
- else
- warn(eoff,"\"Format-\" is already in effect.");
- }
- else
- error(eoff,"Invalid argument to Format.");
- }
-
- else if ( strnicmp(cmd, "Online", 6) == 0 )
- {
- if (cmd[6] == '+')
- {
- check_command_length(eoff,7);
-
- if ( xonline )
- {
- *curr++ = CMD_XONLINE;
- xonline = 0;
- }
- else
- warn(eoff,"\"Online+\" already in effect.");
- }
- else if (cmd[6] == '-')
- {
- check_command_length(eoff,7);
- if ( !xonline )
- {
- *curr++ = CMD_XONLINE;
- xonline = 1;
- }
- else
- warn(eoff,"\"Online-\" already in effect.");
- }
- else
- error(eoff,"Invalid argument to Online.");
- }
-
- else if ( strnicmp(cmd, "Doc", 3) == 0 )
- {
- if (cmd[3] == '+')
- {
- check_command_length(eoff,4);
- if ( xdoc )
- {
- *curr++ = CMD_XDOC;
- xdoc = 0;
- }
- else
- warn(eoff,"\"Doc+\" already in effect.");
- }
- else if (cmd[3] == '-')
- {
- check_command_length(eoff,4);
- if ( !xdoc )
- {
- *curr++ = CMD_XDOC;
- xdoc = 1;
- }
- else
- warn(eoff,"\"Doc-\" already in effect.");
- }
- else
- error(eoff,"Invalid argument to Doc.");
- }
-
- else if ( strnicmp(cmd, "Center", 6) == 0 )
- {
- if (cmd[6] == '+')
- {
- check_command_length(eoff,7);
- if ( !centering )
- {
- centering = 1;
- if ( in_para )
- {
- *curr++ = '\n';
- in_para = 0;
- }
- state = S_Start; /* for centering FSM */
- }
- else
- warn(eoff,"\"Center+\" already in effect.");
- }
- else if (cmd[6] == '-')
- {
- check_command_length(eoff,7);
- if ( centering )
- {
- centering = 0;
- state = S_Start; /* for centering FSM */
- }
- else
- warn(eoff,"\"Center-\" already in effect.");
- }
- else
- error(eoff,"Invalid argument to Center.");
- }
-
- else if ( strnicmp(cmd, "CompressSpaces", 14) == 0 )
- {
- check_command_length(eoff,15);
-
- if ( cmd[14] == '+' )
- {
- if ( compress_spaces )
- warn(eoff,"\"CompressSpaces+\" is already in effect.");
- else
- compress_spaces = 1;
- }
- else if ( cmd[14] == '-' )
- {
- if ( !compress_spaces )
- warn(eoff,"\"CompressSpaces-\" is already in effect.");
- else
- compress_spaces = 0;
- }
- else
- error(eoff,"Invalid argument to CompressSpaces.");
- }
-
- else if ( strnicmp("BinInc ", cmd, 7) == 0 )
- {
- if ( !(t.flags & TF_DATA) )
- error(eoff,"BinInc allowed only in Data topics.");
- else
- process_bininc();
- }
-
- else
- error(eoff,"Bad or unexpected command \"%s\".", cmd);
- } /* else */
-
- } /* while (!done) */
-
- continue;
- }
-
- if ( !in_topic )
- {
- cmd[0] = ch;
- ptr = read_until(cmd+1, 127, "\n~");
- if (*ptr == '~')
- unread_char('~');
- *ptr = '\0';
- error(0,"Text outside of any topic \"%s\".", cmd);
- continue;
- }
-
- if ( centering )
- {
- do
- {
- again = 0; /* default */
-
- switch (state)
- {
- case S_Start:
- if (ch == ' ')
- ; /* do nothing */
- else if ( (ch&0xFF) == '\n' )
- *curr++ = ch; /* no need to center blank lines. */
- else
- {
- *curr++ = CMD_CENTER;
- state = S_Line;
- again = 1;
- }
- break;
-
- case S_Line:
- put_a_char(ch, &t);
- if ( (ch&0xFF) == '\n')
- state = S_Start;
- break;
- } /* switch */
- }
- while (again);
- }
-
- else if ( formatting )
- {
- int again;
-
- do
- {
- again = 0; /* default */
-
- switch (state)
- {
- case S_Start:
- if ( (ch&0xFF) == '\n' )
- *curr++ = ch;
- else
- {
- state = S_StartFirstLine;
- num_spaces = 0;
- again = 1;
- }
- break;
-
- case S_StartFirstLine:
- if ( ch == ' ')
- ++num_spaces;
-
- else
- {
- if (lformat_exclude > 0 && num_spaces >= lformat_exclude )
- {
- put_spaces(num_spaces);
- num_spaces = 0;
- state = S_FormatDisabled;
- again = 1;
- }
- else
- {
- *curr++ = CMD_PARA;
- *curr++ = (char)num_spaces;
- *curr++ = (char)num_spaces;
- margin_pos = curr - 1;
- state = S_FirstLine;
- again = 1;
- in_para = 1;
- }
- }
- break;
-
- case S_FirstLine:
- if (ch == '\n')
- {
- state = S_StartSecondLine;
- num_spaces = 0;
- }
- else if (ch == ('\n'|0x100) ) /* force end of para ? */
- {
- *curr++ = '\n';
- in_para = 0;
- state = S_Start;
- }
- else if ( ch == ' ' )
- {
- state = S_FirstLineSpaces;
- num_spaces = 1;
- }
- else
- put_a_char(ch, &t);
- break;
-
- case S_FirstLineSpaces:
- if (ch == ' ')
- ++num_spaces;
- else
- {
- put_spaces(num_spaces);
- state = S_FirstLine;
- again = 1;
- }
- break;
-
- case S_StartSecondLine:
- if ( ch == ' ')
- ++num_spaces;
- else if ((ch&0xFF) == '\n') /* a blank line means end of a para */
- {
- *curr++ = '\n'; /* end the para */
- *curr++ = '\n'; /* for the blank line */
- in_para = 0;
- state = S_Start;
- }
- else
- {
- if (lformat_exclude > 0 && num_spaces >= lformat_exclude )
- {
- *curr++ = '\n';
- in_para = 0;
- put_spaces(num_spaces);
- num_spaces = 0;
- state = S_FormatDisabled;
- again = 1;
- }
- else
- {
- add_blank_for_split();
- margin = num_spaces;
- *margin_pos = (char)num_spaces;
- state = S_Line;
- again = 1;
- }
- }
- break;
-
- case S_Line: /* all lines after the first */
- if (ch == '\n')
- {
- state = S_StartLine;
- num_spaces = 0;
- }
- else if (ch == ('\n' | 0x100) ) /* force end of para ? */
- {
- *curr++ = '\n';
- in_para = 0;
- state = S_Start;
- }
- else if ( ch == ' ' )
- {
- state = S_LineSpaces;
- num_spaces = 1;
- }
- else
- put_a_char(ch, &t);
- break;
-
- case S_LineSpaces:
- if (ch == ' ')
- ++num_spaces;
- else
- {
- put_spaces(num_spaces);
- state = S_Line;
- again = 1;
- }
- break;
-
- case S_StartLine: /* for all lines after the second */
- if ( ch == ' ')
- ++num_spaces;
- else if ((ch&0xFF) == '\n') /* a blank line means end of a para */
- {
- *curr++ = '\n'; /* end the para */
- *curr++ = '\n'; /* for the blank line */
- in_para = 0;
- state = S_Start;
- }
- else
- {
- if ( num_spaces != margin )
- {
- *curr++ = '\n';
- in_para = 0;
- state = S_StartFirstLine; /* with current num_spaces */
- again = 1;
- }
- else
- {
- add_blank_for_split();
- state = S_Line;
- again = 1;
- }
- }
- break;
-
- case S_FormatDisabled:
- if ( ch == ' ' )
- {
- state = S_FormatDisabledSpaces;
- num_spaces = 1;
- }
- else
- {
- if ( (ch&0xFF) == '\n' )
- state = S_Start;
- put_a_char(ch, &t);
- }
- break;
-
- case S_FormatDisabledSpaces:
- if ( ch == ' ' )
- ++num_spaces;
- else
- {
- put_spaces(num_spaces);
- num_spaces = 0; /* is this needed? */
- state = S_FormatDisabled;
- again = 1;
- }
- break;
-
- } /* switch (state) */
- }
- while (again);
- }
-
- else
- {
- do
- {
- again = 0; /* default */
-
- switch (state)
- {
- case S_Start:
- if ( ch == ' ' )
- {
- state = S_Spaces;
- num_spaces = 1;
- }
- else
- put_a_char(ch, &t);
- break;
-
- case S_Spaces:
- if (ch == ' ')
- ++num_spaces;
- else
- {
- put_spaces(num_spaces);
- num_spaces = 0; /* is this needed? */
- state = S_Start;
- again = 1;
- }
- break;
- } /* switch */
- }
- while (again);
- }
-
- CHK_BUFFER(0)
- } /* while ( 1 ) */
-
- fclose(srcfile);
-
- srcline = -1;
- }
-
-
- /*
- * stuff to resolve hot-link references.
- */
-
-
- void make_hot_links(void)
- /*
- * calculate topic_num/topic_off for each link.
- */
- {
- LINK *l;
- LABEL *lbl;
- int lctr;
- int t;
- CONTENT *c;
- int ctr;
-
- msg("Making hot-links.");
-
- /*
- * Calculate topic_num for all entries in DocContents. Also set
- * "TF_IN_DOC" flag for all topics included in the document.
- */
-
- for (lctr=0, c=contents; lctr<num_contents; lctr++, c++)
- {
- for (ctr=0; ctr<c->num_topic; ctr++)
- {
- if ( c->is_label[ctr] )
- {
- lbl = find_label(c->topic_name[ctr]);
- if (lbl == NULL)
- {
- src_cfname = c->srcfile;
- srcline = c->srcline;
- error(0,"Cannot find DocContent label \"%s\".", c->topic_name[ctr]);
- srcline = -1;
- }
- else
- {
- if ( topic[lbl->topic_num].flags & TF_DATA )
- {
- src_cfname = c->srcfile;
- srcline = c->srcline;
- error(0,"Label \"%s\" is a data-only topic.", c->topic_name[ctr]);
- srcline = -1;
- }
- else
- {
- c->topic_num[ctr] = lbl->topic_num;
- if ( topic[lbl->topic_num].flags & TF_IN_DOC )
- warn(0,"Topic \"%s\" appears in document more than once.",
- topic[lbl->topic_num].title);
- else
- topic[lbl->topic_num].flags |= TF_IN_DOC;
- }
- }
-
- }
- else
- {
- t = find_topic_title(c->topic_name[ctr]);
-
- if (t == -1)
- {
- src_cfname = c->srcfile;
- srcline = c->srcline;
- error(0,"Cannot find DocContent topic \"%s\".", c->topic_name[ctr]);
- srcline = -1; /* back to reality */
- }
- else
- {
- c->topic_num[ctr] = t;
- if ( topic[t].flags & TF_IN_DOC )
- warn(0,"Topic \"%s\" appears in document more than once.",
- topic[t].title);
- else
- topic[t].flags |= TF_IN_DOC;
- }
- }
- }
- }
-
- /*
- * Find topic_num and topic_off for all hot-links. Also flag all hot-
- * links which will (probably) appear in the document.
- */
-
- for (lctr=0, l=a_link; lctr<num_link; l++, lctr++)
- {
- switch ( l->type )
- {
- case 0: /* name is the title of the topic */
- t = find_topic_title(l->name);
- if (t == -1)
- {
- src_cfname = l->srcfile;
- srcline = l->srcline; /* pretend we are still in the source... */
- error(0,"Cannot find implicit hot-link \"%s\".", l->name);
- srcline = -1; /* back to reality */
- }
- else
- {
- l->topic_num = t;
- l->topic_off = 0;
- l->doc_page = (topic[t].flags & TF_IN_DOC) ? 0 : -1;
- }
- break;
-
- case 1: /* name is the name of a label */
- lbl = find_label(l->name);
- if (lbl == NULL)
- {
- src_cfname = l->srcfile;
- srcline = l->srcline; /* pretend again */
- error(0,"Cannot find explicit hot-link \"%s\".", l->name);
- srcline = -1;
- }
- else
- {
- if ( topic[lbl->topic_num].flags & TF_DATA )
- {
- src_cfname = l->srcfile;
- srcline = l->srcline;
- error(0,"Label \"%s\" is a data-only topic.", l->name);
- srcline = -1;
- }
- else
- {
- l->topic_num = lbl->topic_num;
- l->topic_off = lbl->topic_off;
- l->doc_page = (topic[lbl->topic_num].flags & TF_IN_DOC) ? 0 : -1;
- }
- }
- break;
-
- case 2: /* it's a "special" link; topic_off already has the value */
- break;
- }
- }
-
- }
-
-
- /*
- * online help pagination stuff
- */
-
-
- void add_page_break(TOPIC *t, int margin, char *text, char *start, char *curr, int num_links)
- {
- PAGE p;
-
- p.offset = (unsigned) (start - text);
- p.length = (unsigned) (curr - start);
- p.margin = margin;
- add_page(t, &p);
-
- if (max_links < num_links)
- max_links = num_links;
- }
-
-
- void paginate_online(void) /* paginate the text for on-line help */
- { /* also calculates max_pages and max_links */
- int lnum;
- char *start;
- char *curr;
- char *text;
- TOPIC *t;
- int tctr;
- unsigned len;
- int skip_blanks;
- int num_links;
- int col;
- int tok;
- int size,
- width;
- int start_margin;
-
- msg("Paginating online help.");
-
- for (t=topic, tctr=0; tctr<num_topic; t++, tctr++)
- {
- if ( t->flags & TF_DATA )
- continue; /* don't paginate data topics */
-
- text = get_topic_text(t);
- curr = text;
- len = t->text_len;
-
- start = curr;
- skip_blanks = 0;
- lnum = 0;
- num_links = 0;
- col = 0;
- start_margin = -1;
-
- while (len > 0)
- {
- tok = find_token_length(ONLINE, curr, len, &size, &width);
-
- switch ( tok )
- {
- case TOK_PARA:
- {
- int indent,
- margin;
-
- ++curr;
-
- indent = *curr++;
- margin = *curr++;
-
- len -= 3;
-
- col = indent;
-
- while (1)
- {
- tok = find_token_length(ONLINE, curr, len, &size, &width);
-
- if (tok == TOK_DONE || tok == TOK_NL || tok == TOK_FF )
- break;
-
- if ( tok == TOK_PARA )
- {
- col = 0; /* fake a nl */
- ++lnum;
- break;
- }
-
- if (tok == TOK_XONLINE || tok == TOK_XDOC )
- {
- curr += size;
- len -= size;
- continue;
- }
-
- /* now tok is TOK_SPACE or TOK_LINK or TOK_WORD */
-
- if (col+width > SCREEN_WIDTH)
- { /* go to next line... */
- if ( ++lnum >= SCREEN_DEPTH )
- { /* go to next page... */
- add_page_break(t, start_margin, text, start, curr, num_links);
- start = curr + ( (tok == TOK_SPACE) ? size : 0 );
- start_margin = margin;
- lnum = 0;
- num_links = 0;
- }
- if ( tok == TOK_SPACE )
- width = 0; /* skip spaces at start of a line */
-
- col = margin;
- }
-
- col += width;
- curr += size;
- len -= size;
- }
-
- skip_blanks = 0;
- width = size = 0;
- break;
- }
-
- case TOK_NL:
- if (skip_blanks && col == 0)
- {
- start += size;
- break;
- }
- ++lnum;
- if ( lnum >= SCREEN_DEPTH || (col == 0 && lnum==SCREEN_DEPTH-1) )
- {
- add_page_break(t, start_margin, text, start, curr, num_links);
- start = curr + size;
- start_margin = -1;
- lnum = 0;
- num_links = 0;
- skip_blanks = 1;
- }
- col = 0;
- break;
-
- case TOK_FF:
- col = 0;
- if (skip_blanks)
- {
- start += size;
- break;
- }
- add_page_break(t, start_margin, text, start, curr, num_links);
- start_margin = -1;
- start = curr + size;
- lnum = 0;
- num_links = 0;
- break;
-
- case TOK_DONE:
- case TOK_XONLINE: /* skip */
- case TOK_XDOC: /* ignore */
- case TOK_CENTER: /* ignore */
- break;
-
- case TOK_LINK:
- ++num_links;
-
- /* fall-through */
-
- default: /* TOK_SPACE, TOK_LINK, TOK_WORD */
- skip_blanks = 0;
- break;
-
- } /* switch */
-
- curr += size;
- len -= size;
- col += width;
- } /* while */
-
- if (!skip_blanks)
- add_page_break(t, start_margin, text, start, curr, num_links);
-
- if (max_pages < t->num_page)
- max_pages = t->num_page;
-
- release_topic_text(t, 0);
- } /* for */
- }
-
-
- /*
- * paginate document stuff
- */
-
-
- #define CNUM 0
- #define TNUM 1
- #define LINK_DEST_WARN 2
-
-
- typedef struct
- {
- int cnum, /* must match above #defines so pd_get_info() will work */
- tnum,
- link_dest_warn;
-
- char far *start;
- CONTENT *c;
- LABEL *lbl;
-
- } PAGINATE_DOC_INFO;
-
-
- LABEL *find_next_label_by_topic(int t)
- {
- LABEL *temp, *g, *p;
- int ctr;
-
- g = p = NULL;
-
- for (temp=label, ctr=0; ctr<num_label; ctr++, temp++)
- if ( temp->topic_num == t && temp->doc_page == -1 )
- {
- g = temp;
- break;
- }
- else if (temp->topic_num > t)
- break;
-
- for (temp=plabel, ctr=0; ctr<num_plabel; ctr++, temp++)
- if ( temp->topic_num == t && temp->doc_page == -1 )
- {
- p = temp;
- break;
- }
- else if (temp->topic_num > t)
- break;
-
- if ( p == NULL )
- return (g);
-
- else if ( g == NULL )
- return (p);
-
- else
- return ( (g->topic_off < p->topic_off) ? g : p );
- }
-
-
- void set_hot_link_doc_page(void)
- /*
- * Find doc_page for all hot-links.
- */
- {
- LINK *l;
- LABEL *lbl;
- int lctr;
- int t;
-
- for (lctr=0, l=a_link; lctr<num_link; l++, lctr++)
- {
- switch ( l->type )
- {
- case 0: /* name is the title of the topic */
- t = find_topic_title(l->name);
- if (t == -1)
- {
- src_cfname = l->srcfile;
- srcline = l->srcline; /* pretend we are still in the source... */
- error(0,"Cannot find implicit hot-link \"%s\".", l->name);
- srcline = -1; /* back to reality */
- }
- else
- l->doc_page = topic[t].doc_page;
- break;
-
- case 1: /* name is the name of a label */
- lbl = find_label(l->name);
- if (lbl == NULL)
- {
- src_cfname = l->srcfile;
- srcline = l->srcline; /* pretend again */
- error(0,"Cannot find explicit hot-link \"%s\".", l->name);
- srcline = -1;
- }
- else
- l->doc_page = lbl->doc_page;
- break;
-
- case 2: /* special topics don't appear in the document */
- break;
- }
- }
- }
-
-
- void set_content_doc_page(void)
- /*
- * insert page #'s in the DocContents
- */
- {
- CONTENT *c;
- TOPIC *t;
- char *base;
- int tnum;
- int ctr;
- char buf[4];
- int len;
-
- tnum = find_topic_title(DOCCONTENTS_TITLE);
- assert(tnum>=0);
- t = &topic[tnum];
-
- base = get_topic_text(t);
-
- for (ctr=1, c=contents+1; ctr<num_contents; ctr++, c++)
- {
- assert(c->doc_page>=1);
- sprintf(buf, "%d", c->doc_page);
- len = strlen(buf);
- assert(len<=3);
- memcpy(base+c->page_num_pos+(3-len), buf, len);
- }
-
- release_topic_text(t, 1);
- }
-
-
- int pd_get_info(int cmd, PD_INFO *pd, int *info)
- { /* this funtion also used by print_document() */
- CONTENT *c;
-
- switch (cmd)
- {
- case PD_GET_CONTENT:
- if ( ++info[CNUM] >= num_contents )
- return (0);
- c = &contents[info[CNUM]];
- info[TNUM] = -1;
- pd->id = c->id;
- pd->title = c->name;
- pd->new_page = (c->flags & CF_NEW_PAGE) ? 1 : 0;
- return (1);
-
- case PD_GET_TOPIC:
- c = &contents[info[CNUM]];
- if ( ++info[TNUM] >= c->num_topic )
- return (0);
- pd->curr = get_topic_text( &topic[c->topic_num[info[TNUM]]] );
- pd->len = topic[c->topic_num[info[TNUM]]].text_len;
- return (1);
-
- case PD_GET_LINK_PAGE:
- if ( a_link[getint(pd->s)].doc_page == -1 )
- {
- if ( info[LINK_DEST_WARN] )
- {
- src_cfname = a_link[getint(pd->s)].srcfile;
- srcline = a_link[getint(pd->s)].srcline;
- warn(0,"Hot-link destination is not in the document.");
- srcline = -1;
- }
- return (0);
- }
- pd->i = a_link[getint(pd->s)].doc_page;
- return (1);
-
- case PD_RELEASE_TOPIC:
- c = &contents[info[CNUM]];
- release_topic_text(&topic[c->topic_num[info[TNUM]]], 0);
- return (1);
-
- default:
- return (0);
- }
- }
-
-
- int paginate_doc_output(int cmd, PD_INFO *pd, PAGINATE_DOC_INFO *info)
- {
- switch (cmd)
- {
- case PD_FOOTING:
- case PD_PRINT:
- case PD_PRINTN:
- case PD_PRINT_SEC:
- return (1);
-
- case PD_HEADING:
- ++num_doc_pages;
- return (1);
-
- case PD_START_SECTION:
- info->c = &contents[info->cnum];
- return (1);
-
- case PD_START_TOPIC:
- info->start = pd->curr;
- info->lbl = find_next_label_by_topic(info->c->topic_num[info->tnum]);
- return (1);
-
- case PD_SET_SECTION_PAGE:
- info->c->doc_page = pd->pnum;
- return (1);
-
- case PD_SET_TOPIC_PAGE:
- topic[info->c->topic_num[info->tnum]].doc_page = pd->pnum;
- return (1);
-
- case PD_PERIODIC:
- while ( info->lbl != NULL && (unsigned)(pd->curr - info->start) >= info->lbl->topic_off)
- {
- info->lbl->doc_page = pd->pnum;
- info->lbl = find_next_label_by_topic(info->c->topic_num[info->tnum]);
- }
- return (1);
-
- default:
- return (0);
- }
- }
-
-
- void paginate_document(void)
- {
- PAGINATE_DOC_INFO info;
-
- if (num_contents == 0)
- return ;
-
- msg("Paginating document.");
-
- info.cnum = info.tnum = -1;
- info.link_dest_warn = 1;
-
- process_document((PD_FUNC)pd_get_info, (PD_FUNC)paginate_doc_output, &info);
-
- set_hot_link_doc_page();
- set_content_doc_page();
- }
-
-
- /*
- * label sorting stuff
- */
-
-
- int fcmp_LABEL(VOIDCONSTPTR a, VOIDCONSTPTR b)
- {
- char *an = ((LABEL *)a)->name,
- *bn = ((LABEL *)b)->name;
- int diff;
-
- /* compare the names, making sure that the index goes first */
-
- if ( (diff=strcmp(an,bn)) == 0 )
- return (0);
-
- if ( strcmp(an, INDEX_LABEL) == 0 )
- return (-1);
-
- if ( strcmp(bn, INDEX_LABEL) == 0 )
- return (1);
-
- return ( diff );
- }
-
-
- void sort_labels(void)
- {
- qsort(label, num_label, sizeof(LABEL), fcmp_LABEL);
- qsort(plabel, num_plabel, sizeof(LABEL), fcmp_LABEL);
- }
-
-
- /*
- * file write stuff.
- */
-
-
- int compare_files(FILE *f1, FILE *f2) /* returns TRUE if different */
- {
- if ( filelength(fileno(f1)) != filelength(fileno(f2)) )
- return (1); /* different if sizes are not the same */
-
- while ( !feof(f1) && !feof(f2) )
- if ( getc(f1) != getc(f2) )
- return (1);
-
- return ( ( feof(f1) && feof(f2) ) ? 0 : 1);
- }
-
-
- void _write_hdr(char *fname, FILE *file)
- {
- int ctr;
- char nfile[MAXFILE],
- next[MAXEXT];
-
- FNSPLIT(fname, NULL, NULL, nfile, next);
- fprintf(file, "\n/*\n * %s%s\n", nfile, next);
- FNSPLIT(src_fname, NULL, NULL, nfile, next);
- fprintf(file, " *\n * Contains #defines for help.\n *\n");
- fprintf(file, " * Generated by HC from: %s%s\n *\n */\n\n\n", nfile, next);
-
- fprintf(file, "/* current help file version */\n");
- fprintf(file, "\n");
- fprintf(file, "#define %-32s %3d\n", "HELP_VERSION", version);
- fprintf(file, "\n\n");
-
- fprintf(file, "/* labels */\n\n");
-
- for (ctr=0; ctr<num_label; ctr++)
- if (label[ctr].name[0] != '@') /* if it's not a local label... */
- {
- fprintf(file, "#define %-32s %3d", label[ctr].name, ctr);
- if ( strcmp(label[ctr].name, INDEX_LABEL) == 0 )
- fprintf(file, " /* index */");
- fprintf(file, "\n");
- }
-
- fprintf(file, "\n\n");
- }
-
-
- void write_hdr(char *fname)
- {
- FILE *temp,
- *hdr;
-
- hdr = fopen(fname, "rt");
-
- if (hdr == NULL)
- { /* if no prev. hdr file generate a new one */
- hdr = fopen(fname, "wt");
- if (hdr == NULL)
- fatal(0,"Cannot create \"%s\".", fname);
- msg("Writing: %s", fname);
- _write_hdr(fname, hdr);
- fclose(hdr);
- notice("FRACTINT must be re-compiled.");
- return ;
- }
-
- msg("Comparing: %s", fname);
-
- temp = fopen(TEMP_FNAME, "wt");
-
- if (temp == NULL)
- fatal(0,"Cannot create temporary file: \"%s\".", TEMP_FNAME);
-
- _write_hdr(fname, temp);
-
- fclose(temp);
- temp = fopen(TEMP_FNAME, "rt");
-
- if (temp == NULL)
- fatal(0,"Cannot open temporary file: \"%s\".", TEMP_FNAME);
-
- if ( compare_files(temp, hdr) ) /* if they are different... */
- {
- msg("Updating: %s", fname);
- fclose(temp);
- fclose(hdr);
- unlink(fname); /* delete the old hdr file */
- rename(TEMP_FNAME, fname); /* rename the temp to the hdr file */
- notice("FRACTINT must be re-compiled.");
- }
- else
- { /* if they are the same leave the original alone. */
- fclose(temp);
- fclose(hdr);
- unlink(TEMP_FNAME); /* delete the temp */
- }
- }
-
-
- void calc_offsets(void) /* calc file offset to each topic */
- {
- int t;
- TOPIC *tp;
- long offset;
- CONTENT *cp;
- int c;
-
- /* NOTE: offsets do NOT include 6 bytes for signature & version! */
-
- offset = sizeof(int) + /* max_pages */
- sizeof(int) + /* max_links */
- sizeof(int) + /* num_topic */
- sizeof(int) + /* num_label */
- sizeof(int) + /* num_contents */
- sizeof(int) + /* num_doc_pages */
- num_topic*sizeof(long) +/* offsets to each topic */
- num_label*2*sizeof(int);/* topic_num/topic_off for all public labels */
-
- for (c=0, cp=contents; c<num_contents; c++, cp++)
- offset += sizeof(int) + /* flags */
- 1 + /* id length */
- strlen(cp->id) + /* id text */
- 1 + /* name length */
- strlen(cp->name) + /* name text */
- 1 + /* number of topics */
- cp->num_topic*sizeof(int); /* topic numbers */
-
- for (t=0, tp=topic; t<num_topic; t++, tp++)
- {
- tp->offset = offset;
- offset += (long)sizeof(int) + /* topic flags */
- sizeof(int) + /* number of pages */
- tp->num_page*3*sizeof(int) + /* page offset, length & starting margin */
- 1 + /* length of title */
- tp->title_len + /* title */
- sizeof(int) + /* length of text */
- tp->text_len; /* text */
- }
-
- }
-
-
- void insert_real_link_info(char *curr, unsigned len)
- /*
- * Replaces link indexes in the help text with topic_num, topic_off and
- * doc_page info.
- */
- {
- int size;
- int tok;
- LINK *l;
-
- while (len > 0)
- {
- tok = find_token_length(0, curr, len, &size, NULL);
-
- if ( tok == TOK_LINK )
- {
- l = &a_link[ getint(curr+1) ];
- setint(curr+1,l->topic_num);
- setint(curr+1+sizeof(int),l->topic_off);
- setint(curr+1+2*sizeof(int),l->doc_page);
- }
-
- len -= size;
- curr += size;
- }
- }
-
-
- void _write_help(FILE *file)
- {
- int t, p, l, c;
- char *text;
- TOPIC *tp;
- CONTENT *cp;
- struct help_sig_info hs;
-
- /* write the signature and version */
-
- hs.sig = HELP_SIG; /* Edit line 17 of helpcom.h if this is a syntax error */
- hs.version = version;
-
- fwrite(&hs, sizeof(long)+sizeof(int), 1, file);
-
- /* write max_pages & max_links */
-
- putw(max_pages, file);
- putw(max_links, file);
-
- /* write num_topic, num_label and num_contents */
-
- putw(num_topic, file);
- putw(num_label, file);
- putw(num_contents, file);
-
- /* write num_doc_page */
-
- putw(num_doc_pages, file);
-
- /* write the offsets to each topic */
-
- for (t=0; t<num_topic; t++)
- fwrite(&topic[t].offset, sizeof(long), 1, file);
-
- /* write all public labels */
-
- for (l=0; l<num_label; l++)
- {
- putw(label[l].topic_num, file);
- putw(label[l].topic_off, file);
- }
-
- /* write contents */
-
- for (c=0, cp=contents; c<num_contents; c++, cp++)
- {
- putw(cp->flags, file);
-
- t = strlen(cp->id);
- putc((BYTE)t, file);
- fwrite(cp->id, 1, t, file);
-
- t = strlen(cp->name);
- putc((BYTE)t, file);
- fwrite(cp->name, 1, t, file);
-
- putc((BYTE)cp->num_topic, file);
- fwrite(cp->topic_num, sizeof(int), cp->num_topic, file);
- }
-
- /* write topics */
-
- for (t=0, tp=topic; t<num_topic; t++, tp++)
- {
- /* write the topics flags */
-
- putw(tp->flags, file);
-
- /* write offset, length and starting margin for each page */
-
- putw(tp->num_page, file);
- for (p=0; p<tp->num_page; p++)
- {
- putw(tp->page[p].offset, file);
- putw(tp->page[p].length, file);
- putw(tp->page[p].margin, file);
- }
-
- /* write the help title */
-
- putc((BYTE)tp->title_len, file);
- fwrite(tp->title, 1, tp->title_len, file);
-
- /* insert hot-link info & write the help text */
-
- text = get_topic_text(tp);
-
- if ( !(tp->flags & TF_DATA) ) /* don't process data topics... */
- insert_real_link_info(text, tp->text_len);
-
- putw(tp->text_len, file);
- fwrite(text, 1, tp->text_len, file);
-
- release_topic_text(tp, 0); /* don't save the text even though */
- /* insert_real_link_info() modified it */
- /* because we don't access the info after */
- /* this. */
-
- }
- }
-
-
- void write_help(char *fname)
- {
- FILE *hlp;
-
- hlp = fopen(fname, "wb");
-
- if (hlp == NULL)
- fatal(0,"Cannot create .HLP file: \"%s\".", fname);
-
- msg("Writing: %s", fname);
-
- _write_help(hlp);
-
- fclose(hlp);
- }
-
-
- /*
- * print document stuff.
- */
-
-
- typedef struct
- {
-
- /*
- * Note: Don't move these first three or pd_get_info will work not
- * correctly.
- */
-
- int cnum;
- int tnum;
- int link_dest_warn; /* = 0 */
-
- FILE *file;
- int margin;
- int start_of_line;
- int spaces;
- } PRINT_DOC_INFO;
-
-
- void printerc(PRINT_DOC_INFO *info, int c, int n)
- {
- while ( n-- > 0 )
- {
- if (c==' ')
- ++info->spaces;
-
- else if (c=='\n' || c=='\f')
- {
- info->start_of_line = 1;
- info->spaces = 0; /* strip spaces before a new-line */
- putc(c, info->file);
- }
-
- else
- {
- if (info->start_of_line)
- {
- info->spaces += info->margin;
- info->start_of_line = 0;
- }
-
- while (info->spaces > 0)
- {
- fputc(' ', info->file);
- --info->spaces;
- }
-
- fputc(c, info->file);
- }
- }
- }
-
-
- void printers(PRINT_DOC_INFO *info, char far *s, int n)
- {
- if (n > 0)
- {
- while ( n-- > 0 )
- printerc(info, *s++, 1);
- }
- else
- {
- while ( *s != '\0' )
- printerc(info, *s++, 1);
- }
- }
-
-
- int print_doc_output(int cmd, PD_INFO *pd, PRINT_DOC_INFO *info)
- {
- switch (cmd)
- {
- case PD_HEADING:
- {
- char buff[20];
-
- info->margin = 0;
- printers(info, "\n Fractint Version xx.xx Page ", 0);
- sprintf(buff, "%d\n\n", pd->pnum);
- printers(info, buff, 0);
- info->margin = PAGE_INDENT;
- return (1);
- }
-
- case PD_FOOTING:
- info->margin = 0;
- printerc(info, '\f', 1);
- info->margin = PAGE_INDENT;
- return (1);
-
- case PD_PRINT:
- printers(info, pd->s, pd->i);
- return (1);
-
- case PD_PRINTN:
- printerc(info, *pd->s, pd->i);
- return (1);
-
- case PD_PRINT_SEC:
- info->margin = TITLE_INDENT;
- if (pd->id[0] != '\0')
- {
- printers(info, pd->id, 0);
- printerc(info, ' ', 1);
- }
- printers(info, pd->title, 0);
- printerc(info, '\n', 1);
- info->margin = PAGE_INDENT;
- return (1);
-
- case PD_START_SECTION:
- case PD_START_TOPIC:
- case PD_SET_SECTION_PAGE:
- case PD_SET_TOPIC_PAGE:
- case PD_PERIODIC:
- return (1);
-
- default:
- return (0);
- }
- }
-
-
- void print_document(char *fname)
- {
- PRINT_DOC_INFO info;
-
- if (num_contents == 0)
- fatal(0,".SRC has no DocContents.");
-
- msg("Printing to: %s", fname);
-
- info.cnum = info.tnum = -1;
- info.link_dest_warn = 0;
-
- if ( (info.file = fopen(fname, "wt")) == NULL )
- fatal(0,"Couldn't create \"%s\"", fname);
-
- info.margin = PAGE_INDENT;
- info.start_of_line = 1;
- info.spaces = 0;
-
- process_document((PD_FUNC)pd_get_info, (PD_FUNC)print_doc_output, &info);
-
- fclose(info.file);
- }
-
-
- /*
- * compiler status and memory usage report stuff.
- */
-
-
- void report_memory(void)
- {
- long string = 0, /* bytes in strings */
- text = 0, /* bytes in topic text (stored on disk) */
- data = 0, /* bytes in active data structure */
- dead = 0; /* bytes in unused data structure */
- int ctr, ctr2;
-
- for (ctr=0; ctr<num_topic; ctr++)
- {
- data += sizeof(TOPIC);
- string += topic[ctr].title_len;
- text += topic[ctr].text_len;
- data += topic[ctr].num_page * sizeof(PAGE);
-
- dead += (PAGE_ALLOC_SIZE-(topic[ctr].num_page%PAGE_ALLOC_SIZE)) * sizeof(PAGE);
- }
-
- for (ctr=0; ctr<num_link; ctr++)
- {
- data += sizeof(LINK);
- string += strlen(a_link[ctr].name);
- }
-
- if (num_link > 0)
- dead += (LINK_ALLOC_SIZE-(num_link%LINK_ALLOC_SIZE)) * sizeof(LINK);
-
- for (ctr=0; ctr<num_label; ctr++)
- {
- data += sizeof(LABEL);
- string += strlen(label[ctr].name) + 1;
- }
-
- if (num_label > 0)
- dead += (LABEL_ALLOC_SIZE-(num_label%LABEL_ALLOC_SIZE)) * sizeof(LABEL);
-
- for (ctr=0; ctr<num_plabel; ctr++)
- {
- data += sizeof(LABEL);
- string += strlen(plabel[ctr].name) + 1;
- }
-
- if (num_plabel > 0)
- dead += (LABEL_ALLOC_SIZE-(num_plabel%LABEL_ALLOC_SIZE)) * sizeof(LABEL);
-
- for (ctr=0; ctr<num_contents; ctr++)
- {
- int t;
-
- t = ( MAX_CONTENT_TOPIC - contents[ctr].num_topic ) *
- ( sizeof(contents[0].is_label[0]) +
- sizeof(contents[0].topic_name[0]) +
- sizeof(contents[0].topic_num[0]) );
- data += sizeof(CONTENT) - t;
- dead += t;
- string += strlen(contents[ctr].id) + 1;
- string += strlen(contents[ctr].name) + 1;
- for (ctr2=0; ctr2<contents[ctr].num_topic; ctr2++)
- string += strlen(contents[ctr].topic_name[ctr2]) + 1;
- }
-
- dead += (CONTENTS_ALLOC_SIZE-(num_contents%CONTENTS_ALLOC_SIZE)) * sizeof(CONTENT);
-
- printf("\n");
- printf("Memory Usage:\n");
- printf("%8ld Bytes in buffers.\n", (long)BUFFER_SIZE);
- printf("%8ld Bytes in strings.\n", string);
- printf("%8ld Bytes in data.\n", data);
- printf("%8ld Bytes in dead space.\n", dead);
- printf("--------\n");
- printf("%8ld Bytes total.\n", (long)BUFFER_SIZE+string+data+dead);
- printf("\n");
- printf("Disk Usage:\n");
- printf("%8ld Bytes in topic text.\n", text);
- }
-
-
- void report_stats(void)
- {
- int pages = 0;
- int t;
-
- for (t=0; t<num_topic; t++)
- pages += topic[t].num_page;
-
- printf("\n");
- printf("Statistics:\n");
- printf("%8d Topics\n", num_topic);
- printf("%8d Links\n", num_link);
- printf("%8d Labels\n", num_label);
- printf("%8d Private labels\n", num_plabel);
- printf("%8d Table of contents (DocContent) entries\n", num_contents);
- printf("%8d Online help pages\n", pages);
- printf("%8d Document pages\n", num_doc_pages);
- }
-
-
- /*
- * add/delete help from .EXE functions.
- */
-
-
- void add_hlp_to_exe(char *hlp_fname, char *exe_fname)
- {
- int exe, /* handles */
- hlp;
- long len,
- count;
- int size;
- struct help_sig_info hs;
-
- if ( (exe=open(exe_fname, O_RDWR|O_BINARY)) == -1 )
- fatal(0,"Unable to open \"%s\"", exe_fname);
-
- if ( (hlp=open(hlp_fname, O_RDONLY|O_BINARY)) == -1 )
- fatal(0,"Unable to open \"%s\"", hlp_fname);
-
- msg("Appending %s to %s", hlp_fname, exe_fname);
-
- /* first, check and see if any help is currently installed */
-
- lseek(exe, filelength(exe) - sizeof(struct help_sig_info), SEEK_SET);
-
- read(exe, (char *)&hs, 10);
-
- if ( hs.sig == HELP_SIG )
- warn(0,"Overwriting previous help. (Version=%d)", hs.version);
- else
- hs.base = filelength(exe);
-
- /* now, let's see if their help file is for real (and get the version) */
-
- read(hlp, (char *)&hs, sizeof(long)+sizeof(int));
-
- if (hs.sig != HELP_SIG )
- fatal(0,"Help signature not found in %s", hlp_fname);
-
- msg("Help file %s Version=%d", hlp_fname, hs.version);
-
- /* append the help stuff, overwriting old help (if any) */
-
- lseek(exe, hs.base, SEEK_SET);
-
- len = filelength(hlp) - sizeof(long) - sizeof(int); /* adjust for the file signature & version */
-
- for (count=0; count<len; )
- {
- size = (int) min((long)BUFFER_SIZE, len-count);
- read(hlp, buffer, size);
- write(exe, buffer, size);
- count += size;
- }
-
- /* add on the signature, version and offset */
-
- write(exe, (char *)&hs, 10);
-
- chsize(exe, lseek(exe,0L,SEEK_CUR));/* truncate if old help was longer */
-
- close(exe);
- close(hlp);
- }
-
-
- void delete_hlp_from_exe(char *exe_fname)
- {
- int exe; /* file handle */
- struct help_sig_info hs;
-
- if ( (exe=open(exe_fname, O_RDWR|O_BINARY)) == -1 )
- fatal(0,"Unable to open \"%s\"", exe_fname);
-
- msg("Deleting help from %s", exe_fname);
-
- /* see if any help is currently installed */
-
- #ifndef XFRACT
- lseek(exe, filelength(exe) - 10, SEEK_SET);
- read(exe, (char *)&hs, 10);
- #else
- lseek(exe, filelength(exe) - 12, SEEK_SET);
- read(exe, (char *)&hs, 12);
- #endif
-
- if ( hs.sig == HELP_SIG )
- {
- chsize(exe, hs.base); /* truncate at the start of the help */
- close(exe);
- }
- else
- {
- close(exe);
- fatal(0,"No help found in %s", exe_fname);
- }
- }
-
-
- /*
- * command-line parser, etc.
- */
-
-
- #define MODE_COMPILE 1
- #define MODE_PRINT 2
- #define MODE_APPEND 3
- #define MODE_DELETE 4
-
-
- int main(int argc, char *argv[])
- {
- int show_stats = 0,
- show_mem = 0;
- int mode = 0;
-
- char **arg;
- char fname1[81],
- fname2[81];
- char swappath[81];
-
- fname1[0] = fname2[0] = swappath[0] = 0;
-
- printf("HC - FRACTINT Help Compiler.\n\n");
-
- buffer = malloc(BUFFER_SIZE);
-
- if (buffer == NULL)
- fatal(0,"Not enough memory to allocate buffer.");
-
- for (arg= &argv[1]; argc>1; argc--, arg++)
- {
- switch ( (*arg)[0] )
- {
- case '/':
- case '-':
- switch ( (*arg)[1] )
- {
- case 'c':
- if (mode == 0)
- mode = MODE_COMPILE;
- else
- fatal(0,"Cannot have /c with /a, /d or /p");
- break;
-
- case 'a':
- if (mode == 0)
- mode = MODE_APPEND;
- else
- fatal(0,"Cannot have /a with /c, /d or /p");
- break;
-
- case 'd':
- if (mode == 0)
- mode = MODE_DELETE;
- else
- fatal(0,"Cannot have /d with /c, /a or /p");
- break;
-
- case 'p':
- if (mode == 0)
- mode = MODE_PRINT;
- else
- fatal(0,"Cannot have /p with /c, /a or /d");
- break;
-
- case 'm':
- if (mode == MODE_COMPILE)
- show_mem = 1;
- else
- fatal(0,"/m switch allowed only when compiling (/c)");
- break;
-
- case 's':
- if (mode == MODE_COMPILE)
- show_stats = 1;
- else
- fatal(0,"/s switch allowed only when compiling (/c)");
- break;
-
- case 'r':
- if (mode == MODE_COMPILE || mode == MODE_PRINT)
- strcpy(swappath, (*arg)+2);
- else
- fatal(0,"/r switch allowed when compiling (/c) or printing (/p)");
- break;
-
- case 'q':
- quiet_mode = 1;
- break;
-
- default:
- fatal(0,"Bad command-line switch /%c", (*arg)[1]);
- break;
- }
- break;
-
- default: /* assume it is a fname */
- if (fname1[0] == '\0')
- strcpy(fname1, *arg);
- else if (fname2[0] == '\0')
- strcpy(fname2, *arg);
- else
- fatal(0,"Unexpected command-line argument \"%s\"", *arg);
- break;
- } /* switch */
- } /* for */
-
- strupr(fname1);
- strupr(fname2);
- strupr(swappath);
-
- switch (mode)
- {
- case 0:
- printf( "To compile a .SRC file:\n");
- printf( " HC /c [/s] [/m] [/r[path]] [src_file]\n");
- printf( " /s = report statistics.\n");
- printf( " /m = report memory usage.\n");
- printf( " /r[path] = set swap file path.\n");
- printf( " src_file = .SRC file. Default is \"%s\"\n", DEFAULT_SRC_FNAME);
- printf( "To print a .SRC file:\n");
- printf( " HC /p [/r[path]] [src_file] [out_file]\n");
- printf( " /r[path] = set swap file path.\n");
- printf( " src_file = .SRC file. Default is \"%s\"\n", DEFAULT_SRC_FNAME);
- printf( " out_file = Filename to print to. Default is \"%s\"\n",
- DEFAULT_DOC_FNAME);
- printf( "To append a .HLP file to an .EXE file:\n");
- printf( " HC /a [hlp_file] [exe_file]\n");
- printf( " hlp_file = .HLP file. Default is \"%s\"\n", DEFAULT_HLP_FNAME);
- printf( " exe_file = .EXE file. Default is \"%s\"\n", DEFAULT_EXE_FNAME);
- printf( "To delete help info from an .EXE file:\n");
- printf( " HC /d [exe_file]\n");
- printf( " exe_file = .EXE file. Default is \"%s\"\n", DEFAULT_EXE_FNAME);
- printf( "\n");
- printf( "Use \"/q\" for quiet mode. (No status messages.)\n");
- break;
-
- case MODE_COMPILE:
- if (fname2[0] != '\0')
- fatal(0,"Unexpected command-line argument \"%s\"", fname2);
-
- strcpy(src_fname, (fname1[0]=='\0') ? DEFAULT_SRC_FNAME : fname1);
-
- strcat(swappath, SWAP_FNAME);
-
- if ( (swapfile=fopen(swappath, "w+b")) == NULL )
- fatal(0,"Cannot create swap file \"%s\"", swappath);
- swappos = 0;
-
- read_src(src_fname);
-
- if (hdr_fname[0] == '\0')
- error(0,"No .H file defined. (Use \"~HdrFile=\")");
- if (hlp_fname[0] == '\0')
- error(0,"No .HLP file defined. (Use \"~HlpFile=\")");
- if (version == -1)
- warn(0,"No help version has been defined. (Use \"~Version=\")");
-
- /* order of these is very important... */
-
- make_hot_links(); /* do even if errors since it may report */
- /* more... */
-
- if ( !errors ) paginate_online();
- if ( !errors ) paginate_document();
- if ( !errors ) calc_offsets();
- if ( !errors ) sort_labels();
- if ( !errors ) write_hdr(hdr_fname);
- if ( !errors ) write_help(hlp_fname);
-
- if ( show_stats )
- report_stats();
-
- if ( show_mem )
- report_memory();
-
- if ( errors || warnings )
- report_errors();
-
- fclose(swapfile);
- remove(swappath);
-
- break;
-
- case MODE_PRINT:
- strcpy(src_fname, (fname1[0]=='\0') ? DEFAULT_SRC_FNAME : fname1);
-
- strcat(swappath, SWAP_FNAME);
-
- if ( (swapfile=fopen(swappath, "w+b")) == NULL )
- fatal(0,"Cannot create swap file \"%s\"", swappath);
- swappos = 0;
-
- read_src(src_fname);
-
- make_hot_links();
-
- if ( !errors ) paginate_document();
- if ( !errors ) print_document( (fname2[0]=='\0') ? DEFAULT_DOC_FNAME : fname2 );
-
- if ( errors || warnings )
- report_errors();
-
- fclose(swapfile);
- remove(swappath);
-
- break;
-
- case MODE_APPEND:
- add_hlp_to_exe( (fname1[0]=='\0') ? DEFAULT_HLP_FNAME : fname1,
- (fname2[0]=='\0') ? DEFAULT_EXE_FNAME : fname2);
- break;
-
- case MODE_DELETE:
- if (fname2[0] != '\0')
- fatal(0,"Unexpected argument \"%s\"", fname2);
- delete_hlp_from_exe((fname1[0]=='\0') ? DEFAULT_EXE_FNAME : fname1);
- break;
- }
-
- free(buffer);
-
- return ( errors ); /* return the number of errors */
- }
-
-
-