#include #include #include #include #define TABSIZE 8 #define COMMAND_CHAR '.' #define COL2 64 #define COL3 96 typedef char PATH[MAXPATHLEN]; FILE *master_index, *index_stb; void ScanStoryboard (); void ScanNameMap (); char *Relativize (); char *Absolutize (); main (argc, argv) int argc; char *argv[]; { char pathlist[4 * BUFSIZ]; PATH path; int i; if (argc < 2) Error ("need pathname(s)"); strcpy (pathlist, ". "); for (i = 2; i < argc; i++) { strcpy (path, argv[i]); if ((path[0] == '/') || (path[0] == '~')) Absolutize (path, "."); else Relativize (path, argv[1]); strcat (pathlist, path); strcat (pathlist, " "); } if (chdir (argv[1])) Error ("under-specified or bad first pathname"); if (rename ("master-index", "master-index.old")) Error ("can't access master-index"); if ((master_index = fopen ("master-index", "w")) == NULL) Error ("can't create master-index"); unlink ("index.st0"); if ((index_stb = fopen ("index.stx", "w")) == NULL) Error ("can't create index storyboard"); fputs (".title\nMaster Index\n\n.synonyms\n!index\n\n.content\n\n", index_stb); fclose (index_stb); fputs ("----- ARTICLES -----\n\n", master_index); fputs ("\"Master Index\"", master_index); TabTo (strlen ("\"Master Index\""), COL2, master_index); fputs ("./index.st0\n", master_index); fputs ("\"!index\"\n", master_index); ScanDirectories (ScanStoryboard, pathlist, "*.st[0-9]"); fputs ("----- PICTURES -----\n\n", master_index); ScanDirectories (ScanNameMap, pathlist, "*.pn[0-9]"); fputs ("----- TARGETS -----\n\n", master_index); ScanDirectories (ScanNameMap, pathlist, "*.tn[0-9]"); if (rename ("index.stx", "index.st0")) Error ("can't make index.st0"); exit (0); } ScanDirectories (ScanFunc, pathlist, pattern) void (*ScanFunc) (); char *pathlist, *pattern; { FILE *filelist; char shell_command[4 * BUFSIZ], file[BUFSIZ]; FILE *stream; int i; strcpy (shell_command, "find "); strcat (shell_command, pathlist); strcat (shell_command, "-name '"); strcat (shell_command, pattern); strcat (shell_command, "' -print"); if ((filelist = popen (shell_command, "r")) == NULL) Error ("can't run find"); if ((index_stb = popen ("sort -f >> index.stx", "w")) == NULL) Error ("can't run sort"); while (fgets (file, sizeof (file), filelist)) { /* strip trailing newline */ file[strlen (file) - 1] = '\0'; puts (file); if ((stream = fopen (file, "r")) == NULL) puts ("can't open"); else { (*ScanFunc) (stream, file); fclose (stream); } } pclose (filelist); pclose (index_stb); fputs ("\n\n", master_index); return; } void ScanStoryboard (storyboard, file) FILE *storyboard; char *file; { char arg[BUFSIZ]; long start, args, next; start = 0; FindCommand ("title ", &start, &args, &next, storyboard); if ((start == EOF) || (args == next)) printf ("missing title in %s\n", file); else { GetArg (&args, arg, storyboard); fprintf (master_index, "\"%s\"", arg); if (arg[0] != '!') fprintf (index_stb, ".~ %s~ .nl\n", arg); TabTo (strlen (arg) + 2, COL2, master_index); fprintf (master_index, "%s\n", file); start = 0; FindCommand ("synonyms synonym ", &start, &args, &next, storyboard); while (args != next) { GetArg (&args, arg, storyboard); fprintf (master_index, "\"%s\"\n", arg); } putc ('\n', master_index); } fclose (storyboard); return; } void ScanNameMap (namemap, file) FILE *namemap; char *file; { char line[BUFSIZ]; long offset, length, args; int c; offset = 0; while (offset != EOF) { args = offset; GetArg (&args, line, namemap); GetArg (&args, line, namemap); while ((((c = getc (namemap)) != '\n') || ((c = getc (namemap)) != '\n')) && (c != EOF)) ; if (c == EOF) length = -1; else length = ftell (namemap) - offset - 1; fprintf (master_index, "%s", line); TabTo (strlen (line), COL2, master_index); fprintf (master_index, "%s", file); if ((offset > 0) || (length >= 0)) { TabTo (COL2 + strlen (file), COL3, master_index); fprintf (master_index, "%d\t%d", offset, length); } fputs ("\n", master_index); if (c == EOF) offset = EOF; else offset += (length + 1); } fclose (namemap); return; } FindCommand (cmdlist, start, args, next, file) char *cmdlist; long *start, *args, *next; FILE *file; { char arg[BUFSIZ]; int c; while (NextCommand (start, file), *start != EOF) { fscanf (file, "%*c%s", arg); if (InString (arg, cmdlist)) break; *start = ftell (file); } while (c = getc (file), isspace (c)) ; if (c == EOF) *next = *args = EOF; else { fseek (file, -1L, 1); *next = *args = ftell (file); NextCommand (next, file); } return; } NextCommand (pos, file) long *pos; FILE *file; { int c; fseek (file, *pos, 0); while ((c = getc (file)) != EOF) if ((c == COMMAND_CHAR) && ((c = getc (file)) != EOF) && !isspace (c)) { fseek (file, -2L, 1); break; } if (c == EOF) *pos = EOF; else *pos = ftell (file); return; } int InString (s, list) char *s, *list; { char *sp; int len; for (sp = s; *sp != '\0'; sp++) if (isupper (*sp)) *sp = tolower (*sp); len = strlen (s); while (*list != '\0') { if (!strncmp (s, list, len) && (list[len] == ' ')) break; list = index (list, ' ') + 1; } return (*list != '\0'); } GetArg (args, arg, file) long *args; char *arg; FILE *file; { int i; if (*args != EOF) { fseek (file, *args, 0); i = 0; while (((arg[i] = getc (file)) != '\n') && (arg[i] != EOF)) ++i; /* strip trailing space */ while ((--i >= 0) && isspace (arg[i])) ; arg[++i] = '\0'; /* advance to next non-blank */ while (((i = getc (file)) != EOF) && isspace (i)) ; if (i == EOF) *args = EOF; else { fseek (file, -1L, 1); *args = ftell (file); } } else arg[0] = '\0'; return; } TabTo (from, to, file) int from, to; FILE *file; { /* always at least one tab */ putc ('\t', file); from = from - (from % TABSIZE) + TABSIZE; for (; from < to; from += TABSIZE) putc ('\t', file); return; } Error (message) char *message; { fputs (message, stderr); fputs ("\n", stderr); exit (1); } char *Absolutize (path, base) char *path, *base; { PATH curr; getwd (curr); if (chdir (base)) Error ("can't access path"); if (chdir (path)) Error ("can't access path"); getwd (path); chdir (curr); return (path); } char *Relativize (path, base) char *path, *base; { PATH abspath, absbase; char *p, *b; strcpy (abspath, path); strcpy (absbase, base); Absolutize (abspath, "."); Absolutize (absbase, "."); /* find common part */ for (p = abspath, b = absbase; (*p == *b) && (*p != '\0'); p++, b++) ; if (*p != '\0') /* backup to directory marker */ for (p--, b--; *p != '/'; p--, b--) ; /* always start relative path with . */ strcpy (path, "."); /* for every directory remaining in base, backup a level in path */ for (; *b != '\0'; b++) if (*b == '/') strcat (path, "/.."); /* now, can move down directory tree to end of path */ strcat (path, p); return (path); }