/*
 * Jeffrey Friedl
 * Omron Corporation			オムロン（株）
 * Nagaokakyoshi, Japan			〒617長岡京下海印寺
 *
 * jfriedl@nff.ncl.omron.co.jp
 *
 * This work is placed under the terms of the GNU General Purpose License
 * (the "GNU Copyleft").
 *
 * October 1993
 *
 * Routine to load a file and to load, create, and/or write an accompanying
 * index. WRT loadfile, a "file" is a rather high-level object that has
 * an index and other substructures associated with it.
 *
 * On a lower level is "readfile" which deals with filesystem files
 * as singular entities.
 */

#include "config.h"
#include "assert.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "xmalloc.h"	/* for xmalloc () */
#include "strsave.h"	/* for strsave() */
#include "system.h"
#ifndef strlen
# if defined(_HAVE_STRINGS_H_) /* might be defined in system.h */
#   include <strings.h>
# else
#   include <string.h>
#   define index strchr
#   define rindex strrchr
# endif
#endif
#include "loadfile.h"
#include "output.h"

/*
 * Given the name of a text file, return the name of its associated index
 * file (or what it would be called were it to exist). The returned string
 * should eventually be free'd by the user.
 */
char *indexfile_name(const char *datafile_name)
{
    char *indexname = xmalloc((unsigned)(strlen((void*)datafile_name)+
					 strlen(LOADFILE_INDEX_EXTENTION)+2));
    strcpy(indexname, datafile_name);
    strcat(indexname, LOADFILE_INDEX_EXTENTION);
    return indexname;
}

/*
 * If LOADFILE_READINDEX is set, the index is read from "FILENAME.jdx".
 * Otherwise, it is created internally.
 *
 * If LOADFILE_WRITEINDEX is set, the index is written to "FILENAME.jdx".
 *
 * It's stupid to have both LOADFILE_READINDEX and LOADFILE_WRITEINDEX set.
 */
struct fileinfo *
loadfile(const char *filename, unsigned percent, unsigned flags)
{
    struct fileinfo *info = xmalloc(sizeof(struct fileinfo));
    long int filesize;
    struct stat statbuf;

    /* stat for various uses */
    if (stat(filename, &statbuf) < 0) {
	warn("[can't stat \"%s\": %n]\n", filename);
	return 0;
    }

    if (statbuf.st_size == 0)
	warn("[warning: file \"%s\" is empty]\n", filename);

    /* open file */
    info->v = OpenVertFile(filename);

    /* note the short filename */
    info->short_filename = (const char *)rindex((void*)info->v->filename, '/');
    if (info->short_filename == 0)
	info->short_filename = info->v->filename;
    else
	info->short_filename++; /* skip over "/" */

    if (flags & (LOADFILE_READINDEX|LOADFILE_READifPRESENT))
    {
	char *name = indexfile_name(filename);
	int just_try = flags & LOADFILE_READifPRESENT;
	if (flags & LOADFILE_NO_MEM_INDEX)
	    info->index = read_index_file(name, just_try, flags);
	else
	    info->index = mem_read_index_file(name);

	if (info->index == 0)
	{
	    if (flags & LOADFILE_READifPRESENT)
	    {
		free(name);
		goto build_index;
	    }
	    warn("[error: couldn't read \"%s\": %n]\n", name);
	    free(name);
	    free(info);
	    return 0;
	}
	info->indexfile = name;
	if (info->index->st__mtime != statbuf.st_mtime) {
	    warn("<WARNING, [%s] has been updated since index was written>\n",
		filename);
	}
    } else {
	struct index *i;
      build_index:
	i = create_index(info->v, percent, flags);
	i->st__mtime = statbuf.st_mtime;
	i->FileP = NULL; /* no file -- it's in memory */
	info->index = i;
    }

    if (flags & LOADFILE_WRITEINDEX)
    {
	char *name = indexfile_name(filename);
	if (write_index_file(name, info->index) != 0)
	{
	    warn("[error: couldn't write \"%s\": %n]\n", name);
	    free(name);
	}
	else
	{
	    warn("[wrote index file \"%s\"]\n", name);
	    info->indexfile = name;
	}
    }
    return info;
}
