/* mp4h -- A macro processor for HTML documents
Copyright 2000-2002, Denis Barbier
All rights reserved.
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, or (at your option)
any later version.
This program is a work based on GNU m4 version 1.4n. Below is the
original copyright.
*/
/* GNU m4 -- A simple macro processor
Copyright (C) 1989, 90, 91, 92, 93, 98 Free Software Foundation, Inc.
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, 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. */
/* Handling of path search of included files via the builtins "include"
and "sinclude". */
#include "mp4h.h"
#define DEBUG_INCL
#undef DEBUG_INCL
static struct search_path_info dirpath; /* the list of path directories */
static void
search_path_add (struct search_path_info *info, const char *dir,
const int dirlen, const int userdef)
{
search_path *path;
path = (struct search_path *) xmalloc (sizeof (struct search_path));
path->next = NULL;
if (*dir == '\0')
{
path->len = 1;
path->dir = xstrdup (".");
}
else
{
if (-1 == dirlen)
{
path->len = strlen (dir);
path->dir = xstrdup (dir);
}
else
{
path->len = dirlen;
path->dir = (char *) xcalloc (dirlen + 1, 1);
strncpy ((char *) path->dir, dir, dirlen);
}
}
if (path->len > info->max_length) /* remember len of longest directory */
info->max_length = path->len;
if (userdef)
{
#ifdef DEBUG_INCL
fprintf (stderr, "search_path_add user (%s);\n", path->dir);
#endif
path->next = info->sys;
if (info->list_end == NULL)
info->list = path;
else
info->list_end->next = path;
info->list_end = path;
}
else
{
#ifdef DEBUG_INCL
fprintf (stderr, "search_path_add sys (%s);\n", path->dir);
#endif
if (info->sys_end == NULL)
info->sys = path;
else
info->sys_end->next = path;
info->sys_end = path;
}
}
static void
search_path_env_init (struct search_path_info *info, const char *path,
const int userdef)
{
char *path_end;
if (info == NULL || path == NULL)
return;
#ifdef DEBUG_INCL
fprintf (stderr, "search_path_env_init (%s);\n", path);
#endif
do
{
path_end = strchr (path, ':');
if (path_end)
search_path_add (info, path, (int) (path_end - path), userdef);
else
search_path_add (info, path, -1, userdef);
path = path_end + 1;
}
while (path_end);
}
void
include_init (void)
{
dirpath.list = NULL;
dirpath.list_end = NULL;
dirpath.sys = NULL;
dirpath.sys_end = NULL;
dirpath.max_length = strlen (MP4HLIBDIR);
/* dirpath.sys must be initialized first. */
search_path_env_init (&dirpath, MP4HLIBDIR, 0);
/* set dirpath.list to "." */
search_path_add (&dirpath, "", -1, 1);
}
void
include_deallocate (void)
{
search_path *path, *path_next;
path = dirpath.list;
while (path)
{
path_next = path->next;
xfree ((voidstar) path->dir);
xfree ((voidstar) path);
path = path_next;
}
}
/* Functions for normal input path search */
void
include_env_init (void)
{
search_path_env_init (&dirpath, getenv ("MP4HLIB"), 1);
}
void
add_include_directory (const char *dir)
{
search_path_add (&dirpath, dir, -1, 1);
}
FILE *
path_search (const char *dir, char **expanded_name)
{
FILE *fp;
struct search_path *incl;
char *name; /* buffer for constructed name */
/* Look in current working directory first. */
fp = fopen (dir, "r");
if (fp != NULL)
{
if (expanded_name != NULL)
*expanded_name = xstrdup (dir);
return fp;
}
/* If file not found, and filename absolute, fail. */
if (*dir == '/')
return NULL;
/* Look into user-defined path directories. */
name = (char *) xmalloc (dirpath.max_length + 1 + strlen (dir) + 1);
for (incl = dirpath.list; incl != NULL; incl = incl->next)
{
strncpy (name, incl->dir, incl->len);
name[incl->len] = '/';
strcpy (name + incl->len + 1, dir);
#ifdef DEBUG_INCL
fprintf (stderr, "path_search (%s) -- trying %s\n", dir, name);
#endif
fp = fopen (name, "r");
if (fp != NULL)
{
if (debug_level & DEBUG_TRACE_PATH)
DEBUG_MESSAGE2 ("Path search for `%s' found `%s'", dir, name);
if (expanded_name != NULL)
*expanded_name = xstrdup (name);
break;
}
}
xfree ((voidstar) name);
return fp;
}