home *** CD-ROM | disk | FTP | other *** search
- /*
- addtoc.c V1.0 29.08.1993
-
- 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,GFILE/K,DFILE/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.
-
- 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)
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #ifndef FALSE
- #define FALSE 0
- #endif
- #ifndef TRUE
- #define TRUE (!FALSE)
- #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;
- };
- #define TYPE_UNNUMBERED 0
- #define TYPE_CHAPTER 1
- #define TYPE_SECTION 2
- #define TYPE_SUBSECTION 3
-
-
-
-
- /*
- 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);
- }
-
-
-
-
- /*
- The Scan() function scans the texinfo source file.
- */
- void Scan(struct node **first, char *tfile)
-
- { FILE *fh;
- struct node *node;
- char line[MAXLINE+1];
- char title[MAXLINE+1];
- char *titleptr;
- int lineno;
- extern int errno;
-
- if ((fh = fopen(tfile, "r")) == NULL)
- { fprintf(stderr, "Cannot open %s as source file!\n", tfile);
- exit(10);
- }
-
- *first = NULL;
- lineno = 0;
- while (fgets(line, sizeof(line), fh) != NULL)
- { ++lineno;
- 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, "Warning: Unknown sectioning command in line %d!\n",
- lineno);
- fprintf(stderr, " Expected @chapter, @section, @subsection "
- ", @unnumbered or @top.\n");
- }
- if (type != -1)
- { if ((node = malloc(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;
- *first = node;
- first = &node->next;
- }
- }
- }
- if (errno)
- { perror("addtoc");
- }
- 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 ScanGuide() function scans the AmigaGuide file, removes the menu
- in the top node and replaces it by the table of contents.
- */
- void ScanGuide(struct node *first, char *gtitle)
-
- { FILE *fhin;
- FILE *fhout;
- char *newtitle;
- struct node *node;
- int InMain;
- int lineno;
- char line[MAXLINE+1];
- char name[MAXLINE+1];
-
- /*
- Opening files
- */
- if ((newtitle = malloc(strlen(gtitle)+5)) == NULL)
- { memerror();
- }
- sprintf(newtitle, "%s.new", gtitle);
-
- if ((fhin = fopen(gtitle, "r")) == NULL)
- { fprintf(stderr, "Cannot open %s as input!\n", gtitle);
- exit(10);
- }
- if ((fhout = fopen(newtitle, "w")) == NULL)
- { fprintf(stderr, "Cannot open %s as output!\n", newtitle);
- exit(11);
- }
-
- /*
- Looking for the Top Node
- */
- InMain = FALSE;
- lineno = 0;
- while(fgets(line, sizeof(line), fhin) != NULL)
- { ++lineno;
- if (strnicmp(line, "@Node Main", 10) == 0)
- { InMain = TRUE;
- }
- else if (strnicmp(line, "@EndNode", 8) == 0)
- { InMain = FALSE;
- }
- if (InMain && strnicmp(ignorespace(line), "@{\"", 3) == 0)
- { if (myscan(line, name) == NULL)
- { fprintf(stderr,
- "Error: Cannot scan line %d of %s (unknown format)!\n",
- lineno, gtitle);
- }
- else
- { int blanks;
-
- fputs(line, fhout);
- blanks = ignorespace(line)-line;
- for (node = first; node != NULL; node = node->next)
- { if (strncmp(name, node->name, strlen(name)) == 0 &&
- (node->type == TYPE_CHAPTER || node->type == TYPE_UNNUMBERED))
- { break;
- }
- }
-
- node = node->next;
- while (node != NULL && node->type != TYPE_CHAPTER &&
- node->type != TYPE_UNNUMBERED)
- { switch (node->type)
- { case TYPE_UNNUMBERED:
- case TYPE_CHAPTER:
- break;
- case TYPE_SECTION:
- fprintf(fhout, " ");
- break;
- case TYPE_SUBSECTION:
- fprintf(fhout, " ");
- break;
- }
- fprintf(fhout, "@{\" %s \" Link \"%s\"}\n", node->title,
- node->name);
- node = node->next;
- }
- }
- }
- else
- { fputs(line, fhout);
- }
- }
- if (errno)
- { perror("addtoc");
- }
- fclose(fhin);
- fclose(fhout);
- }
-
-
-
-
- /*
- 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);
- }
-
-
-
-
- /*
- The ScanDoc function scans the Ascii document and adds the table of
- contents and section numbers.
- */
- void ScanDoc(struct node *first, char *dtitle)
-
- { FILE *fhin, *fhout;
- char *newtitle;
- int lineno;
- int chapter, section, subsection;
- int tocdone;
- char line[MAXLINE+1];
- char subline[MAXLINE+1];
- static char subchar[3] = "*=-";
- char c;
-
- /*
- Opening files
- */
- if ((newtitle = malloc(strlen(dtitle)+5)) == NULL)
- { memerror();
- }
- sprintf(newtitle, "%s.new", dtitle);
-
- if ((fhin = fopen(dtitle, "r")) == NULL)
- { fprintf(stderr, "Cannot open %s as input!\n", dtitle);
- exit(10);
- }
- if ((fhout = fopen(newtitle, "w")) == NULL)
- { fprintf(stderr, "Cannot open %s as output!\n", newtitle);
- exit(11);
- }
-
-
- /*
- Scanning for nodes
- */
- tocdone = FALSE;
- lineno = 0;
- chapter = section = subsection = 0;
- while (fgets(line, sizeof(line), fhin) != NULL)
- { ++lineno;
- if (first != NULL &&
- strncmp(line, first->title, strlen(first->title)) == 0 &&
- fgets(subline, sizeof(subline), fhin) != NULL)
- { ++lineno;
- switch(first->type)
- { case TYPE_UNNUMBERED:
- case TYPE_CHAPTER:
- c = subchar[0];
- break;
- case TYPE_SECTION:
- c = subchar[1];
- break;
- case TYPE_SUBSECTION:
- c = subchar[2];
- break;
- }
- if(subcmp(subline, c, strlen(first->title)) == 0)
- { int i;
- int level;
- struct node *node;
- char number[128];
-
- /*
- Add the table of contents, if we have found the first
- node.
- */
- if (!tocdone)
- { int chapter, section, subsection;
-
- chapter = section = subsection = 0;
- for (node = first; node != NULL; node = node->next)
- { if (node->type == TYPE_CHAPTER || node->type == TYPE_UNNUMBERED)
- { putc('\n', fhout);
- }
- switch (node->type)
- { case TYPE_CHAPTER:
- ++chapter;
- section = subsection = 0;
- fprintf(fhout, "%d. ", chapter);
- break;
- case TYPE_UNNUMBERED:
- break;
- case TYPE_SECTION:
- ++section;
- subsection = 0;
- fprintf(fhout, " %d. ", section);
- break;
- case TYPE_SUBSECTION:
- ++subsection;
- fprintf(fhout, " %d. ", subsection);
- break;
- }
- fprintf(fhout, "%s\n", node->title);
- }
- fprintf(fhout, "\n\n\n");
- tocdone = TRUE;
- }
-
- switch(first->type)
- { case TYPE_UNNUMBERED:
- strcpy(number, "");
- level = 0;
- break;
- case TYPE_CHAPTER:
- ++chapter;
- section = subsection = 0;
- sprintf(number, "%d. ", chapter);
- level = 0;
- break;
- case TYPE_SECTION:
- ++section;
- subsection = 0;
- sprintf(number, "%d.%d. ", chapter, section);
- level = 1;
- break;
- case TYPE_SUBSECTION:
- ++subsection;
- sprintf(number, "%d.%d.%d. ", chapter, section, subsection);
- level = 2;
- break;
- }
- fprintf(fhout, "%s%s", number, line);
- for (i = 0; i < strlen(number); i++)
- { putc((int) subchar[level], fhout);
- }
- fputs(subline, fhout);
- first = first->next;
- }
- else
- { fputs(line, fhout);
- fputs(subline, fhout);
- }
- }
- else
- { fputs(line, fhout);
- }
- }
- if (first != NULL)
- { fprintf(stderr, "Missing item, probably different text in header "
- "and menu:\n%s\n", first->title);
- }
- if (errno)
- { perror("addtoc");
- }
- fclose(fhin);
- fclose(fhout);
- }
-
-
-
-
- /*
- This prints the usage information and terminates.
- */
- void Usage(void)
-
- { fprintf(stderr,
- "Usage: addtoc TFILE/A,GFILE/K,DFILE/K\n\n"
- "TFILE is the texinfo source file.\n"
- "GFILE is the AmigaGuide file created from TFILE and DFILE the "
- "corresponding\n"
- "Ascii file. <GFILE>.new and <TFILE>.new, respectively, are created,\n"
- "if the latter options are present.\n\n");
- exit(1);
- }
-
-
-
-
- /*
- This is main(). Does nothing except processing the arguments and calling
- the Scan... functions.
- */
- void main(int argc, char *argv[])
-
- { char *tfile, *gfile, *dfile;
- struct node *first;
- int i;
-
- #ifdef DEBUG
- tfile = "/Amiga-FAQ.texinfo";
- gfile = "/Amiga-FAQ.guide";
- dfile = "/Amiga-FAQ.doc";
- #else
- if (argc < 2)
- { Usage();
- }
-
- tfile = NULL;
- gfile = NULL;
- dfile = NULL;
-
- for (i = 1; i < argc; i++)
- { if (stricmp(argv[i], "gfile") == 0)
- { if (++i == argc || gfile != NULL)
- { Usage();
- }
- gfile = argv[i];
- }
- else if (strnicmp(argv[i], "gfile=", 6) == 0)
- { if (gfile != NULL)
- { Usage();
- }
- gfile = &argv[i][6];
- }
- else if (stricmp(argv[i], "dfile") == 0)
- { if (++i == argc || dfile != NULL)
- { Usage();
- }
- dfile = argv[i];
- }
- else if (strnicmp(argv[i], "dfile=", 6) == 0)
- { if (dfile != NULL)
- { Usage();
- }
- dfile = &argv[i][6];
- }
- else
- { if (tfile != NULL)
- { Usage();
- }
- tfile = argv[i];
- }
- }
- if (tfile == NULL)
- { Usage();
- }
- #endif /* !DEBUG */
-
-
- Scan(&first, tfile);
- if (gfile)
- { ScanGuide(first, gfile);
- }
- if (dfile)
- { ScanDoc(first, dfile);
- }
- }
-