📄 gbi.c
字号:
/*************************************************************************** gbi.c component informer (c) 2000-2004 Beno顃 Minisini <gambas@users.sourceforge.net> 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 1, 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.***************************************************************************/#include <config.h>#include "gb_limit.h"#include "gb_common.h"#include "gb_alloc.h"#ifdef __GNU_LIBRARY__#define _GNU_SOURCE#include <getopt.h>#endif#include <stdlib.h>#include <string.h>#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/time.h>#include <dirent.h>#include <dlfcn.h>#include <ltdl.h>#include <ctype.h>#include "gb_component.h"#include "gb_file.h"#include "gb_str.h"#include "gambas.h"static char _root[MAX_PATH + 1] = { 0 };static char _lib_path[MAX_PATH + 1];static char _info_path[MAX_PATH + 1];static char _buffer[MAX_PATH + 1];static FILE *out_info;static FILE *out_list;static bool _verbose = FALSE;static bool _format = FALSE;static bool _nopreload = FALSE;#ifdef __GNU_LIBRARY__static struct option LongOptions[] ={ { "version", 0, NULL, 'V' }, { "verbose", 0, NULL, 'v' }, { "format", 0, NULL, 'f' }, { "help", 0, NULL, 'h' }, { "all", 0, NULL, 'a' }, { "root", 1, NULL, 'r' }, { 0 }};#endifstatic void print(const char *fmt, ...){ va_list args; va_start(args, fmt); vfprintf(out_info, fmt, args);}static void error(const char *msg){ fprintf(stderr, "%s\n", msg); exit(1);}static void error2(const char *msg, const char *msg2){ fprintf(stderr, "%s: %s\n", msg, msg2); exit(1);}static void init(char *exec){ const char *path; /* chemin d'installation de Gambas */ if (!_root[0]) { path = FILE_find_gambas(exec); strncpy(_root, FILE_get_dir(FILE_get_dir(path)), MAX_PATH); } strcpy(_lib_path, FILE_cat(_root, "lib/gambas", NULL)); strcpy(_info_path, FILE_cat(_root, "share/gambas/info", NULL)); if (lt_dlinit()) error2("Cannot initialize plug-in management", lt_dlerror()); /*if (putenv("LD_BIND_NOW=true")) error2("Cannot set LD_BIND_NOW", strerror(errno)); if (putenv("KDE_MALLOC=0")) error2("Cannot set KDE_MALLOC", strerror(errno));*/}static void newline(){ print("\n");}static bool print_type(const char *type){ switch (*type) { case 'b': print("Boolean"); break; case 'i': print("Integer"); break; case 's': print("String"); break; case 'd': print("Date"); break; case 'f': print("Float"); break; case 'v': print("Variant"); break; case 'o': print("Object"); break; default: while (*type && *type != ';') { print("%c", *type); type++; } return TRUE; } return FALSE;}static void dump_value(const char *type, long value){ char *p; switch(*type) { case 'i': print("%ld", value, value); break; case 'f': print("%s", (char *)value); break; case 's': p = (char *)value; while (*p) { if (*p == '\n') print("\\n"); else if (*p == '\t') print("\\t"); else print("%c", *p); p++; } break; default: print("?"); break; }}static void print_value(const char *type, long value){ char *p; switch(*type) { case 'i': print("%ld ( &H%lX )", value, value); break; case 'f': print("\"%s\"", (char *)value); break; case 's': p = (char *)value; print("\""); while (*p) { if (*p == '\n') print("\\n"); else if (*p == '\t') print("\\t"); else print("%c", *p); p++; } print("\""); break; default: print("?"); break; }}static void print_signature(const char *sign){ char mode = 0; char c; bool comma = FALSE; if (!sign) return; while ((c = *sign)) { if (!mode) { if (c == '(') { if (comma) print(" ,"); print(_format ? " <i>" : " "); mode = ')'; } else if (c == '<') mode = '>'; else if (c == '[') print(_format ? " <b>[</b>" : " ["); else if (c == ']') print(_format ? " <b>]</b>" : " ]"); else if (c == '.') print(" ..."); else { print(" AS "); if (print_type(sign)) mode = ';'; comma = TRUE; } } else if (c == mode) { if (mode == ')' && _format) print("</i>"); mode = 0; } else if (mode == ')') { print("%c", c); } sign++; }}void analyze_symbol(GB_DESC *desc){ char type; char *name; type = *desc->name; name = &desc->name[1]; print("%s\n", name); if (isupper(type)) { if (type != 'C') print("STATIC "); type = tolower(type); } if (type == ':') name++; switch (type) { case 'c': print(_format ? "CONST <b>%s</b> AS " : "CONST %s AS ", name); print_type((char *)desc->val1); print(" = "); print_value((char *)desc->val1, desc->val2); newline(); break; case 'p': print(_format ? "PROPERTY <b>%s</b> AS " : "PROPERTY %s AS ", name); print_type((char *)desc->val1); newline(); break; case 'r': print(_format ? "PROPERTY READ <b>%s</b> AS " : "PROPERTY READ %s AS ", name); print_type((char *)desc->val1); newline(); break; case 'm': case ':': if (type == ':') print(_format ? "EVENT <b>%s</b> (" : "EVENT %s (", name); else print(_format ? "%s <b>%s</b> (" : "%s %s (", desc->val1 ? "FUNCTION" : "SUB", name); print_signature((char *)desc->val3); print(" )"); if (desc->val1) { print(" AS "); print_type((char *)desc->val1); } newline(); break; }}void dump_symbol(GB_DESC *desc){ char *name; name = &desc->name[1]; print("%s\n", name); print("%c\n", *desc->name); if (desc->val1) print("%s", desc->val1); newline(); if (*desc->name == 'C') dump_value((char *)desc->val1, desc->val2); else if (desc->val3) print("%s", (char *)desc->val3); newline();}void analyze_class(GB_DESC *desc){ char *name = desc->name; char *parent = NULL; bool nonew = FALSE; bool autocreate = FALSE; ulong hook; if (out_list && name[0] != '.') fprintf(out_list, "%s\n", name); desc++; while (desc->name) { hook = (ulong)desc->name; if (hook == (ulong)GB_INHERITS_ID) parent = (char *)desc->val1; else if ((hook == (ulong)GB_HOOK_NEW_ID) && desc->val1 == 0) nonew = TRUE; else if (hook == (ulong)GB_AUTO_CREATABLE_ID) autocreate = TRUE; else if (hook > 16) break; desc++; } if (_format) { print("CLASS %s\n", name); if (parent) print("INHERITS %s\n", parent); if (!nonew) print("CREATABLE\n"); if (autocreate) print("AUTOCREATABLE\n"); } else { print("#%s\n", name); if (parent) print("%s", parent); newline(); if (!nonew) print("C"); if (autocreate) print("A"); newline(); } while (desc->name) { if (_format) analyze_symbol(desc); else dump_symbol(desc); desc++; } if (_format) newline();}bool analyze(const char *path){ lt_dlhandle lib; /*void *dlib;*/ GB_DESC **desc; bool ret = FALSE; /* if (strcmp(name, "gb") == 0) { sprintf(path, LIB_PATTERN, _lib_path, name); dlib = dlopen("/usr/bin/gbx", RTLD_NOW); if (!dlib) error2("Cannot open component:", dlerror()); desc = dlsym(lib, LIB_CLASS); if (!desc) error("Cannot find symbol " LIB_CLASS); } else */ if (_verbose) fprintf(stderr, "Loading: %s\n", path); lt_dlopen_flag = RTLD_LAZY; /* | RTLD_GLOBAL;*/ if (access(path, F_OK)) error2(path, "not found"); lib = lt_dlopenext(path); if (!lib) error2(path, lt_dlerror()); desc = lt_dlsym(lib, LIB_CLASS); if (desc) { while (*desc) { analyze_class(*desc); desc++; } } else ret = TRUE; lt_dlclose(lib); return ret;}void preload(char **argv, char *lib){#if DO_PRELOADING char buf[256]; if (_nopreload || getenv("GAMBAS_PRELOAD")) return; sprintf(buf, "LD_PRELOAD=%s", lib); putenv(buf); putenv("GAMBAS_PRELOAD=1"); execv("/usr/bin/gbi", argv);#endif}int main(int argc, char **argv){ DIR *dir; struct dirent *dirent; char *name; char *path_list; char *path_info; int all = FALSE; int opt; int save_fd; bool res; #ifdef __GNU_LIBRARY__ int ind = 0; #endif /*#ifdef __FreeBSD__ optind = 1; #else optind = 0; #endif*/ for(;;) { #ifdef __GNU_LIBRARY__ opt = getopt_long(argc, argv, "vVhafpr:", LongOptions, &ind); #else opt = getopt(argc, argv, "vVhafpr:"); #endif if (opt < 0) break; switch (opt) { case 'V': printf("gbi-" VERSION "\n"); exit(0); case 'a': all = TRUE; break; case 'v': _verbose = TRUE; break; case 'f': _format = TRUE; break; case 'p': _nopreload = TRUE; break; case 'r': strncpy(_root, optarg, MAX_PATH); break; case 'h': printf( "\n" "GAMBAS Component Informer version " VERSION " " __DATE__ " " __TIME__ "\n" COPYRIGHT "Usage: gbi [options] <component name>\n" " gbi -a\n\n" "Options:" #ifdef __GNU_LIBRARY__ "\n" " -V --version display version\n" " -h --help display this help\n" " -f --format format output in HTML\n" " -p disable preloading\n" " -a --all generate info for every component\n" " -r --root <directory> gives the gambas installation directory\n" #else " (no long options on this system)\n" " -V display version\n" " -h display this help\n" " -f format output in HTML\n" " -p disable preloading\n" " -a generate info for every component\n" " -r --root <directory> gives the gambas installation directory\n" #endif "\n" ); exit(0); } } init(argv[0]); if (!all) { if (optind == argc #ifdef __sun__ /* solaris bug ? */ || optind == 0 #endif ) error("gbi: no component specified."); if (strncasecmp(argv[optind], "gb.qt", 5) == 0) preload(argv, "libqt-mt.so.3"); else if (strncasecmp(argv[optind], "gb.qt.kde", 9) == 0) preload(argv, "libkdecore.so.4"); sprintf(_buffer, LIB_PATTERN, _lib_path, argv[optind]); out_info = stdout; out_list = NULL; analyze(_buffer); } else { preload(argv, "libqt-mt.so.3 " #if HAVE_KDE_COMPONENT "libkdecore.so.4 " #endif ); dir = opendir(_lib_path); if (dir == NULL) error2("Cannot read directory", _lib_path); save_fd = dup(STDOUT_FILENO); while ((dirent = readdir(dir)) != NULL) { name = dirent->d_name; if (strcmp(FILE_get_ext(name), "component")) continue; path_info = STR_copy(FILE_set_ext(FILE_cat(_info_path, &name[4], NULL), "info")); out_info = fopen(path_info, "w"); if (!out_info) error2("Cannot write file", path_info); path_list = STR_copy(FILE_set_ext(FILE_cat(_info_path, &name[4], NULL), "list")); out_list = fopen(path_list, "w"); if (!out_list) error2("Cannot write file", path_list); name = STR_copy(FILE_get_basename(&name[4])); sprintf(_buffer, LIB_PATTERN, _lib_path, name); res = analyze(_buffer); fclose(out_info); fclose(out_list); if (res) { unlink(path_info); unlink(path_list); } else puts(path_info); STR_free(path_info); STR_free(path_list); STR_free(name); } closedir(dir); } exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -