33#ifdef HAVE_DL_ITERATE_PHDR
47static void globfree (glob_t* pglob);
48static int glob (
GVC_t *
gvc,
char*,
int,
int (*errfunc)(
const char *,
int), glob_t*);
56#include <mach-o/dyld.h>
100 const char *package_path,
120static void separator(
int *nest,
char **tokens)
146 if (c ==
' ' || c ==
'\n' || c ==
'\t') {
159static char *token(
int *nest,
char **tokens)
166 || c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'{' || c ==
'}')
171 separator(nest, tokens);
176static int gvconfig_plugin_install_from_config(
GVC_t *
gvc,
char *
s)
178 char *package_path, *name;
184 separator(&nest, &
s);
186 package_path = token(&nest, &
s);
188 name = token(&nest, &
s);
191 package = gvplugin_package_record(gvc, package_path, name);
193 const char *api = token(&nest, &
s);
195 if (gv_api == (
api_t)-1) {
196 agerrorf(
"config error: %s %s not found\n", package_path, api);
201 type = token(&nest, &
s);
203 quality = atoi(token(&nest, &
s));
208 agerrorf(
"config error: %s %s %s\n", package_path, api,
type);
226 package = gvplugin_package_record(gvc, package_path, library->packagename);
228 for (i = 0; types[i].
type; i++) {
230 types[i].
quality, package, &types[i]);
243 if (name[0] ==
'g' && strstr(name,
"_LTX_library"))
248static void gvconfig_write_library_config(
GVC_t *
gvc,
char *lib_path,
253 fprintf(f,
"%s %s {\n", lib_path, library->
packagename);
256 for (
size_t i = 0; types[i].
type; i++) {
260 fprintf(f,
"#FAILS");
261 fprintf(f,
"\t\t%s %d\n", types[i].
type, types[i].quality);
269#define DOTLIBS "/.libs"
271#ifdef HAVE_DL_ITERATE_PHDR
272static int line_callback(
struct dl_phdr_info *
info,
size_t size,
void *line)
274 const char *p =
info->dlpi_name;
275 char *tmp = strstr(p,
"/libgvc.");
280 if (strcmp(strrchr(p,
'/'), DOTLIBS) != 0) {
281 memmove(line, p, strlen(p) + 1);
282 strcat(line,
"/graphviz");
292 static char line[
BSZ];
294 static bool dirShown =
false;
297 libdir=getenv(
"GVBINDIR");
303 MEMORY_BASIC_INFORMATION mbi;
305 agerrorf(
"failed to get handle for executable.\n");
308 r = GetModuleFileName ((HMODULE)mbi.AllocationBase, line,
BSZ);
309 if (!r || (r ==
BSZ)) {
310 agerrorf(
"failed to get path for executable.\n");
313 s = strrchr(line,
'\\');
315 agerrorf(
"no slash in path %s.\n", line);
323 uint32_t i, c = _dyld_image_count();
325 for (i = 0; i < c; ++i) {
326 const char *p = _dyld_get_image_name(i);
327 const char* tmp = strstr(p,
"/libgvc.");
331 const char *
s = tmp - 1;
333 while (*
s !=
'/' &&
s > p)
s--;
339 len = ind +
sizeof(
"/graphviz");
345 memmove(libdir, p, ind);
348 strcpy(libdir+ind,
"/graphviz");
352#elif defined(HAVE_DL_ITERATE_PHDR)
353 dl_iterate_phdr(line_callback, line);
356 FILE* f =
gv_fopen(
"/proc/self/maps",
"r");
359 if (!fgets (line,
sizeof (line), f))
361 if (!strstr (line,
" r-xp "))
363 char *p = strchr(line,
'/');
366 char* tmp = strstr(p,
"/libgvc.");
370 if (strcmp(strrchr(p,
'/'),
"/.libs") == 0)
372 memmove(line, p, strlen(p) + 1);
373 strcat(line,
"/graphviz");
385 fprintf (stderr,
"libdir = \"%s\"\n", (libdir ? libdir :
"<null>"));
394static bool is_plugin(
const char *filepath) {
396 if (filepath ==
NULL) {
401#if defined(DARWIN_DYLIB)
402 static const char SUFFIX[] =
".dylib";
403#elif defined(__MINGW32__) || defined(__CYGWIN__) || defined(_WIN32)
404 static const char SUFFIX[] =
".dll";
406 static const char SUFFIX[] =
"";
410 size_t len = strlen(filepath);
411 if (
len < strlen(SUFFIX)
412 || strcmp(filepath +
len - strlen(SUFFIX), SUFFIX) != 0) {
415 len -= strlen(SUFFIX);
417#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
420#elif defined(GVPLUGIN_VERSION)
422 #define STRINGIZE_(x) #x
423 #define STRINGIZE(x) STRINGIZE_(x)
424 static const char VERSION[] = STRINGIZE(GVPLUGIN_VERSION);
429 if (
len < strlen(VERSION)
433 len -= strlen(VERSION);
447#if defined(DARWIN_DYLIB)
451#elif defined(__MINGW32__) || defined(__CYGWIN__)
459#elif ((defined(__hpux__) || defined(__hpux)) && !(defined(__ia64)))
460 static const char SL[] =
".sl.";
465 static const char SO[] =
".so.";
474static void config_rescan(
GVC_t *
gvc,
char *config_path)
481#if defined(DARWIN_DYLIB)
482 char *plugin_glob =
"libgvplugin_*";
483#elif defined(__MINGW32__)
484 char *plugin_glob =
"libgvplugin_*";
485#elif defined(__CYGWIN__)
486 char *plugin_glob =
"cyggvplugin_*";
488 char *plugin_glob =
"gvplugin_*";
490 char *plugin_glob =
"libgvplugin_*";
496 agerrorf(
"failed to open %s for write.\n", config_path);
500 fprintf(f,
"# This file was generated by \"dot -c\" at time of install.\n\n");
501 fprintf(f,
"# You may temporarily disable a plugin by removing or commenting out\n");
502 fprintf(f,
"# a line in this file, or you can modify its \"quality\" value to affect\n");
503 fprintf(f,
"# default plugin selection.\n\n");
504 fprintf(f,
"# Manual edits to this file **will be lost** on upgrade.\n\n");
515 rc = glob(
gvc,
agxbuse(&config_glob), GLOB_NOSORT,
NULL, &globbuf);
517 rc = glob(
agxbuse(&config_glob), 0,
NULL, &globbuf);
520 for (
size_t i = 0; i < globbuf.gl_pathc; i++) {
521 if (is_plugin(globbuf.gl_pathv[i])) {
529 for (
size_t i = 0; i < globbuf.gl_pathc; i++) {
530 if (is_plugin(globbuf.gl_pathv[i])) {
533 char *p = strrchr(globbuf.gl_pathv[i],
DIRSEP[0]);
537 gvconfig_write_library_config(
gvc, p, library, f);
556 struct stat config_st;
558 char *config_text =
NULL;
560 char *config_file_name = GVPLUGIN_CONFIG_FILE;
572 if (access(libdir, F_OK) < 0) {
588 "config rescan performed without any prior first scan");
605 else if (config_st.st_size == 0) {
609 config_text =
gv_alloc((
size_t)config_st.st_size + 1);
610 size_t sz = fread(config_text, 1, (
size_t)config_st.st_size, f);
616 config_text[sz] =
'\0';
617 rc = gvconfig_plugin_install_from_config(
gvc, config_text);
645glob (
GVC_t*
gvc,
char* pattern,
int flags,
int (*errfunc)(
const char *,
int), glob_t *pglob)
653 pglob->gl_pathv =
NULL;
655 h = FindFirstFile (pattern, &wfd);
656 if (h == INVALID_HANDLE_VALUE)
return GLOB_NOMATCH;
660 strlen(libdir) + strlen(
DIRSEP) + strlen(wfd.cFileName) + 1;
661 char *
const entry =
malloc(size);
665 snprintf(entry, size,
"%s%s%s", libdir,
DIRSEP, wfd.cFileName);
666 if (strs_try_append(&strs, entry) != 0) {
670 }
while (FindNextFile (h, &wfd));
671 if (strs_try_append(&strs,
NULL) != 0) {
675 pglob->gl_pathc = strs_size(&strs);
676 pglob->gl_pathv = strs_detach(&strs);
686globfree (glob_t* pglob)
689 for (i = 0; i < pglob->gl_pathc; i++)
690 free (pglob->gl_pathv[i]);
691 free (pglob->gl_pathv);
static void agxbfree(agxbuf *xb)
free any malloced resources
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static WUR char * agxbuse(agxbuf *xb)
static char * agxbdisown(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static char * gv_strdup(const char *original)
static void * gv_alloc(size_t size)
static NORETURN void graphviz_exit(int status)
static double len(glCompPoint p)
void agerrorf(const char *fmt,...)
replacements for ctype.h functions
static bool gv_isdigit(int c)
FILE * gv_fopen(const char *filename, const char *mode)
wrapper around fopen for internal library usage
static gvplugin_package_t * gvplugin_package_record(GVC_t *gvc, const char *package_path, const char *name)
void gvconfig(GVC_t *gvc, bool rescan)
void textfont_dict_open(GVC_t *gvc)
void gvconfig_plugin_install_from_library(GVC_t *gvc, char *package_path, gvplugin_library_t *library)
static void gvconfig_plugin_install_builtins(GVC_t *gvc)
char * gvconfig_libdir(GVC_t *gvc)
gvplugin_library_t * gvplugin_library_load(GVC_t *gvc, const char *pathname)
api_t gvplugin_api(const char *str)
gvplugin_available_t * gvplugin_load(GVC_t *gvc, api_t api, const char *type, FILE *debug)
int gvtextlayout_select(GVC_t *gvc)
char * gvplugin_api_name(api_t api)
bool gvplugin_install(GVC_t *gvc, api_t api, const char *typestr, int quality, gvplugin_package_t *package, gvplugin_installed_t *typeptr)
static gvplugin_api_t apis[]
#define DEFINE_LIST_WITH_DTOR(name, type, dtor)
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
const lt_symlist_t * builtins
gvplugin_package_t * packages
gvplugin_installed_t * types
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t