home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
docs
/
misc
/
amigafaq
/
src
/
addtoc.c
Wrap
C/C++ Source or Header
|
1994-07-28
|
22KB
|
992 lines
/*
addtoc.c V1.1 25.07.1994
Copyright (C) 1993 Jochen Wiedmann
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
This scans a texinfo file and adds a table of contents to the relating
AmigaGuide and Ascii files. Note that they have to be created first and
MUST be up to date. Best way to ensure this is using a Makefile.
Usage: addtoc TFILE/A,SPLITCHAP/M/N,GFILE/K,DFILE/K,DIFFS/K
TFILE is the texinfo source, GFILE is the AmigaGuide file and DFILE is
the Ascii file. Files GFILE.new and DFILE.new are created.
SPLITCHAP are numbers indicating chapters, after which to split the
FAQ into different parts. (Each part will be preceded by a toc.) This
is available for Ascii files only and is used to split FAQs in different
parts. Note, that these numbers must be adjacent, for example the
numbers 7 and 11 to split after chapter 6 and 10.
DIFFS is the name of a file holding diffs to a previous version. This
must be produced using "gdiff -f new old". When creating the Ascii
version, changed or added lines will be marked with a "!" or "+",
respectively, together with the sections they belong to.
The texinfo file has to be in a special format: Each node (except the Top
node) MUST have a following line containing an @chapter, @section,
@subsection or @unnumbered command. The node commands MUST contain
nothing else than the node name. Note that @info and @tex commands are
ignored. In fact anything is ignored, except for the node and sectioning
commands.
Author: Jochen Wiedmann
Am Eisteich 9
72555 Metzingen (Germany)
Tel. 07123 / 14881
Computer: Amiga 1200 (should run on any Amiga)
Compiler: Dice and Aztec-C (should run through SAS and gcc)
V1.0 25.08.1993
V1.1 25.07.1994 Added support of @include
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#ifndef HAVE_STRICMP
#define stricmp strcasecmp
#define strnicmp strncasecmp
#endif
/*
Maximum length of a line in the source file. Probably works with longer
lines, but this may not be guaranteed. Even the line numbering WILL
be damaged.
*/
#define MAXLINE 1024 /* Maximum length of a node name. */
/*
This is used to hold the information we get by scanning the texinfo
source. Each node is represented by exactly one node structure.
*/
struct node
{ struct node *next;
char *name;
char *title;
int type;
int changed;
};
#define TYPE_UNNUMBERED 0
#define TYPE_CHAPTER 1
#define TYPE_SECTION 2
#define TYPE_SUBSECTION 3
/*
This is used to store the diffs information.
*/
struct diffs
{ struct diffs *next;
int type;
int from, to;
};
#define DIFFTYPE_DELETED 0
#define DIFFTYPE_CHANGED 1
#define DIFFTYPE_ADDED 2
/*
The ignorespace() function removes trailing blanks from a line.
*/
char *ignorespace(char *line)
{ while (*line == ' ' || *line == '\t')
{ ++line;
}
return(line);
}
/*
The salloc() function allocates memory for a string. Note, that it
removes trailing Line-Feeds.
*/
char *salloc(char *str)
{ char *ptr;
int len = strlen(str);
while (len > 0 && str[len-1] == '\n')
{ str[--len] = '\0';
}
if ((ptr = malloc(len+1)) != NULL)
{ strcpy(ptr, str);
}
return(ptr);
}
/*
The memerror() function reports a memory error and terminates the
program.
*/
void memerror(void)
{ fprintf(stderr, "Out of memory!\n");
exit(20);
}
/*
This is a subfunction of Scan() which is used to support @inclde:
It calls itself to do this.
*/
void ScanFILE(FILE *fh, char *filename, struct node **first)
{ extern int errno;
char line[MAXLINE+1];
char title[MAXLINE+1];
char *titleptr;
struct node *node;
int lineno = 0;
while (fgets(line, sizeof(line), fh) != NULL)
{ ++lineno;
if (strnicmp(line, "@include", 8) == 0)
{ char *includefilename = strtok(line+8, " \t\n\r\f");
FILE *includefh;
if (!(includefh = fopen(includefilename, "r")))
{ fprintf(stderr, "Cannot open %s as source file!\n", filename);
exit(10);
}
ScanFILE(includefh, includefilename, first);
fclose(includefh);
}
else if (strnicmp(line, "@node", 5) == 0 &&
fgets(title, sizeof(title), fh) != NULL)
{ int type;
++lineno;
type = -1;
if (strnicmp(title, "@unnumbered", 11) == 0)
{ type = TYPE_UNNUMBERED;
titleptr = title+11;
}
else if (strnicmp(title, "@chapter", 8) == 0)
{ type = TYPE_CHAPTER;
titleptr = title+8;
}
else if (strnicmp(title, "@section", 8) == 0)
{ type = TYPE_SECTION;
titleptr = title+8;
}
else if (strnicmp(title, "@subsection", 11) == 0)
{ type = TYPE_SUBSECTION;
titleptr = title+11;
}
else if (strnicmp(title, "@top", 4) != 0)
{ fprintf(stderr, "%s, %d, warning: Unknown sectioning command.\n",
lineno);
fprintf(stderr,
" Expected @chapter, @section, @subsection, @unnumbered or @top.\n");
}
if (type != -1)
{ if ((node = calloc(1, sizeof(*node))) == NULL)
{ memerror();
}
if ((node->name = salloc(ignorespace(line+5))) == NULL ||
(node->title = salloc(ignorespace(titleptr))) == NULL)
{ memerror();
}
node->next = NULL;
node->type = type;
/*
Look for the last node in the current list and add the
current node.
*/
{ struct node **last;
for (last = first; *last != NULL;
last = &((*last)->next))
{
}
*last = node;
}
}
}
}
if (errno)
{ perror("addtoc");
}
}
/*
The Scan() function scans the texinfo source file. It uses
ScanFILE in order to work recursively.
*/
void Scan(struct node **first, char *tfile)
{ FILE *fh;
if ((fh = fopen(tfile, "r")) == NULL)
{ fprintf(stderr, "Cannot open %s as source file!\n", tfile);
exit(10);
}
*first = NULL;
ScanFILE(fh, tfile, first);
fclose(fh);
}
/*
The myscan() function scans a string like @{"title" Link "name"} for
name.
*/
char *myscan(char *line, char *name)
{ line = ignorespace(line);
if (strncmp(line, "@{\"", 3) != 0)
{ return(NULL);
}
line += 3;
while (*line != '\"' && *line != '\0')
{ line++;
}
if (*line == '\0')
{ return(NULL);
}
++line;
line = ignorespace(line);
if (strnicmp(line, "Link", 4) != 0)
{ return(NULL);
}
line+=4;
line = ignorespace(line);
if (*(line++) != '\"')
{ return(NULL);
}
while (*line != '\"' && *line != '\0')
{ *(name++) = *(line++);
}
if (strncmp(line, "\"}", 2) != 0)
{ return(NULL);
}
*name = '\0';
return(line+2);
}
/*
The subcmp() function checks for len occurences of c. Result is 0, if
there are, nonzero otherwise.
*/
int subcmp(char *line, char c, int len)
{ int i;
for (i = 0; i < len; i++)
{ if (line[i] != c)
{ return(line[i]-c);
}
}
return(0);
}
/*
This function is used to read the diffs. These consist of lines like
am
cm n
dm n
where a means "following lines added after line m", c equals to "lines
m to n changed" and d is "lines m to n deleted". (n may be omitted, if
n == m.)
a and c lines are followed by the appropriate number of lines to add or
change, followed by a line with a point only.
When the lines are read, the doc file is scanned a first time to find,
which nodes are changed