From 67d3b5846d84d4a2e5a31d4e268bc9d51495d7e0 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 3 Sep 2009 19:38:20 -0400 Subject: the C implementation properly loads the plugins, then creates a dependancy tree --- c/Makefile | 2 +- c/plugin-debug.c | 69 +++++++++++++++++++++---- c/plugin-depend.c | 102 +++++++++++++++++++++++++++++++++++++ c/plugin-parse.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++ c/plugin.c | 149 ++++++++++++++++-------------------------------------- c/plugin.h | 6 +-- c/plugins | 1 - c/rvs.c | 5 +- c/rvs.h | 29 ++++++++--- c/test.c | 5 +- plugins/file | 0 11 files changed, 370 insertions(+), 133 deletions(-) create mode 100644 c/plugin-depend.c create mode 100644 c/plugin-parse.c delete mode 120000 c/plugins delete mode 100644 plugins/file diff --git a/c/Makefile b/c/Makefile index fa0a285..61a4763 100755 --- a/c/Makefile +++ b/c/Makefile @@ -4,5 +4,5 @@ CC = gcc all : $(CC) rvs.c -Wall -ansi -g -o rvs -test : +test : test.c rvs.h plugin.c plugin.h plugin-debug.c plugin-depends.c $(CC) test.c -Wall -ansi -g -o test diff --git a/c/plugin-debug.c b/c/plugin-debug.c index 50e5497..553237d 100644 --- a/c/plugin-debug.c +++ b/c/plugin-debug.c @@ -18,23 +18,70 @@ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -void print_commands(struct plugin_command *command) +size_t xstrlen (const char *s) { - printf(" - %s\n",command->name); - if (command->depends != NULL) { - printf(" depend: %s\n",command->depends); + printf("xstrlen(%p)\n",s); + size_t size=0; + while (s[size] != '\0') { + printf("%i = %p `%c'\n",size,&s[size],s[size]); + size++; } - if (command->p_next != NULL) { - print_commands(command->p_next); + return size; +} + +void _plugin_print_plugin_command(struct plugin_command *command) +{ + if (command != NULL) { + printf(" - %s\n",command->name); + if (command->depends != NULL) + printf(" depend string: %s\n",command->depends); + if (command->depend->plugin == NULL) { + puts (" depend: "); + } else { + printf(" depend: %s / %s\n", + command->depend->plugin->name, + command->depend->name); + } + _plugin_print_plugin_command(command->p_next); + } +} + +void _plugin_print_plugin(struct plugin *plugin) +{ + if (plugin != NULL) { + printf(" %s\n",plugin->name); + _plugin_print_plugin_command(plugin->child); + _plugin_print_plugin(plugin->next); } } -void print_plugins(struct plugin *plugin) +void _plugin_print_depend(struct plugin_command *command,size_t indent) { - printf("%s\n",plugin->name); - print_commands(plugin->child); - if (plugin->next != NULL) { - print_plugins(plugin->next); + int i=0; + while (i < indent) { + printf(" "); + i++; } + if (command->name == NULL) { + puts(""); + } else { + printf("%s / %s\n", + command->plugin->name, + command->name); + } + if (command->child != NULL) { + _plugin_print_depend(command->child,indent+1); + } + if (command->d_next != NULL) { + _plugin_print_depend(command->d_next,indent); + } +} + +void _plugin_print(struct plugin_tree *tree) +{ + puts("Plugins:"); + _plugin_print_plugin(tree->plugins); + puts("\nDepends:"); + _plugin_print_depend(tree->depends,0); } diff --git a/c/plugin-depend.c b/c/plugin-depend.c new file mode 100644 index 0000000..4101fe1 --- /dev/null +++ b/c/plugin-depend.c @@ -0,0 +1,102 @@ +/* Copyright (C) 2009 Luke Shumaker + + This file is part of rvs. + + rvs 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. + + rvs 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 rvs; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* translates a string in syntax `plugin/command' into a pointer to the commnad + DON'T plan on using the string again, it will be mutilated! + (so we go ahead and free() it) */ +struct plugin_command * +_plugin_depend_parse(struct plugin *root, char *string) +{ + char *c=strchr(string,'/'); + c[0]='\0'; + return _plugin_find_command( + _plugin_find_plugin(root,string)->child, + &c[1]); + xfree(string); +} + +/* used by _plugin_depend_add */ +void +_plugin_depend_add2(struct plugin_command *prev, struct plugin_command *next) +{ + if (prev->d_next==NULL) { + prev->d_next=next; + } else { + _plugin_depend_add2(prev->d_next,next); + } +} + +/* _plugin_depend_add(depend,depender) */ +void +_plugin_depend_add(struct plugin_command *depend, struct plugin_command *depender) +{ + if (depend->child==NULL) { + depend->child=depender; + } else { + _plugin_depend_add2(depend->child,depender); + } +} + +/* take care of depends for `command', and those after it (linked list) */ +void +_plugin_depend_command(struct plugin_command *command, struct plugin_tree *tree) +{ + if (command->depends == NULL) { + command->depend=tree->depends; + } else { + command->depend=_plugin_depend_parse(tree->plugins,command->depends); + command->depends=NULL; + } + _plugin_depend_add(command->depend,command); + if (command->p_next != NULL) + _plugin_depend_command(command->p_next,tree); +} + +/* take care of commands for a `plugin', and those after it (linked list) */ +void +_plugin_depend_plugin(struct plugin *plugin, struct plugin_tree *tree) +{ + _plugin_depend_command(plugin->child,tree); + if (plugin->next != NULL) { + _plugin_depend_plugin(plugin->next,tree); + } +} + +/* take care of all depends */ +void +_plugin_depend(struct plugin_tree *tree) +{ + /* add a blank `root' command for those that don't have depends */ + struct plugin_command *command; + command=(struct plugin_command *)xmalloc(sizeof(*command)); + command->name=NULL; + command->plugin=NULL; + command->p_next=NULL; + command->depend=NULL; + command->depends=NULL; + command->child=NULL;/*<--only variable of any value */ + command->d_next=NULL; + + tree->depends=command; + + /* parse all commands */ + _plugin_depend_plugin(tree->plugins,tree); +} + diff --git a/c/plugin-parse.c b/c/plugin-parse.c new file mode 100644 index 0000000..c333193 --- /dev/null +++ b/c/plugin-parse.c @@ -0,0 +1,135 @@ +/* Copyright (C) 2009 Luke Shumaker + + This file is part of rvs. + + rvs 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. + + rvs 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 rvs; see the file COPYING. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +void _plugin_parse_comment (FILE *file) +{ + char c; + while ( (c=getc(file)) != EOF ) { + if ( c == '\n' ) { + ungetc (c, file); + break; + } + } +} + +char _plugin_parse_escape(FILE *file) +{ + char c=getc(file); + switch (c) { + case 'n': + c = '\n'; + case '\\': + case '#': + case ':': + break; + default: + error(EXIT_FAILURE,0,"syntax error"); + break; + } + return c; +} + +char *_plugin_parse_depend (FILE *file) +{ + size_t nbytes = 10; + char *string = (char *)xmalloc(nbytes); + string[0]='\0'; + + char c[2] = " \0"; + char *cs = (char *)&c; + while ( (c[0]=getc(file)) != EOF ) { + if (c[0] == '\n') { + ungetc (c[0], file); + break; + } else { + switch (c[0]) { + case '\\': + c[0]=_plugin_parse_escape(file); + stradds(&nbytes,&string,cs); + break; + case '#': + _plugin_parse_comment(file); + break; + default: + stradds(&nbytes,&string,cs); + break; + } + } + } + return string; +} + +struct plugin_command *_plugin_parse (struct plugin *plugin, FILE *file) +{ + struct plugin_command *command; + command=(struct plugin_command *)xmalloc(sizeof(*command)); + + command->plugin=plugin; + command->p_next=NULL; + + command->depend=NULL; + command->depends=NULL; + command->child=NULL; + command->d_next=NULL; + + size_t nbytes = 10; + char *string = (char *)xmalloc(nbytes); + string[0]='\0'; + + char c[2] = " \0"; + char *cs = (char *)&c; + if ( (c[0]=getc(file)) == EOF ) { + return NULL; + } else { + ungetc (c[0], file); + } + while ( (c[0]=getc(file)) != EOF ) { + if (c[0] == '\n') { + if (strcmp(string,"")==0) { + xfree(command); + xfree(string); + command=_plugin_parse(plugin, file); + } else { + command->name=string; + command->p_next=_plugin_parse(plugin, file); + } + break; + } else { + switch (c[0]) { + case '\\': + c[0]=_plugin_parse_escape(file); + stradds(&nbytes,&string,cs); + break; + case '#': + _plugin_parse_comment(file); + break; + case ':': + command->depends=_plugin_parse_depend(file); + break; + default: + stradds(&nbytes,&string,cs); + break; + } + } + } + return command; +} + diff --git a/c/plugin.c b/c/plugin.c index 7b0146b..7182626 100644 --- a/c/plugin.c +++ b/c/plugin.c @@ -7,7 +7,7 @@ the Free Software Foundation; either version 2, or (at your option) any later version. - rvs is distributed in the hope 1. A user enters a username and passwthat it will be useful, but + rvs 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. @@ -32,137 +32,72 @@ #include "rvs.h" #include "plugin.h" -void _parse_comment (FILE *file) +/* finds a plugin with `name'. Start looking at `plugin' (linked list) */ +struct plugin * +_plugin_find_plugin(struct plugin *plugin, char *name) { - char c; - while ( (c=getc(file)) != EOF ) { - if ( c == '\n' ) { - ungetc (c, file); - break; - } - } -} - -char _parse_escape(FILE *file) -{ - char c=getc(file); - switch (c) { - case 'n': - c = '\n'; - case '\\': - case '#': - case ':': - break; - default: - error(EXIT_FAILURE,0,"syntax error"); - break; - } - return c; -} - -char *_parse_depend (FILE *file) -{ - size_t nbytes = 10; - char *string = (char *)xmalloc(nbytes); - - char c[2] = " \0"; - char *cs = (char *)&c; - while ( (c[0]=getc(file)) != EOF ) { - if (c[0] == '\n') { - ungetc (c[0], file); - break; + if (strcmp(plugin->name,name) == 0) { + return plugin; + } else { + if (plugin->next==NULL) { + error(EXIT_FAILURE,0,"cannot find plugin `%s'",name); + return NULL; } else { - switch (c[0]) { - case '\\': - c[0]=_parse_escape(file); - stradds(&nbytes,&string,cs); - break; - case '#': - _parse_comment(file); - break; - default: - stradds(&nbytes,&string,cs); - break; - } + return _plugin_find_plugin(plugin->next,name); } } - return string; } -struct plugin_command *_parse_plugin (struct plugin *plugin, FILE *file) +/* finds a command with `name'. Start looking at `command' (linked list) */ +struct plugin_command * +_plugin_find_command(struct plugin_command *command, char *name) { - struct plugin_command *command; - command=(struct plugin_command *)xmalloc(sizeof(*command)); - command->p_next=NULL; - command->depends=NULL; - - size_t nbytes = 10; - char *string = (char *)xmalloc(nbytes); - strcpy(string,""); - - char c[2] = " \0"; - char *cs = (char *)&c; - if ( (c[0]=getc(file)) == EOF ) { - return NULL; + if (strcmp(command->name,name) == 0) { + return command; } else { - ungetc (c[0], file); - } - while ( (c[0]=getc(file)) != EOF ) { - if (c[0] == '\n') { - if (strcmp(string,"")==0) { - free(command); - free(string); - return _parse_plugin(plugin, file); - } else { - command->name=string; - command->p_next=_parse_plugin(plugin, file); - break; - } + if (command->p_next==NULL) { + error(EXIT_FAILURE,0, + "plugin `%s' does not contain command `%s'", + command->plugin->name,name); + return NULL; } else { - switch (c[0]) { - case '\\': - c[0]=_parse_escape(file); - stradds(&nbytes,&string,cs); - break; - case '#': - _parse_comment(file); - break; - case ':': - command->depends=_parse_depend(file); - break; - default: - stradds(&nbytes,&string,cs); - break; - } + return _plugin_find_command(command->p_next,name); } } - return command; } -struct plugin *load_plugin (char *plug_name, char *plugin_conf) +#include "plugin-parse.c" +#include "plugin-depend.c" + +struct plugin * +_plugin_load (char *plug_name, char *plugin_conf) { - printf("loading plugin `%s'\n",plug_name); struct plugin *plugin=(struct plugin *)xmalloc(sizeof(*plugin)); - plugin->name=plug_name; + char *plug_name2 = (char *)xmalloc(strlen(plug_name)+1); + strcpy(plug_name2,plug_name); + plugin->name=plug_name2; plugin->next=NULL; - chdir(plug_name); + xchdir(plug_name); FILE *file = xfopen(plugin_conf,"r"); - plugin->child=_parse_plugin(plugin, file); + plugin->child=_plugin_parse(plugin, file); fclose( file ); - chdir(".."); + xchdir(".."); return plugin; } -struct plugin_tree *load_plugins (char *libexecdir, char *plugin_conf) +struct plugin_tree * +load_plugins (char *libexecdir, char *plugin_conf) { struct plugin_tree *tree=(struct plugin_tree *)xmalloc(sizeof(*tree)); struct plugin **last=&tree->plugins; + *last=NULL; struct plugin *plugin; - chdir(libexecdir); + xchdir(libexecdir); + DIR *cwd; struct dirent *dirent; int serr; @@ -173,13 +108,17 @@ struct plugin_tree *load_plugins (char *libexecdir, char *plugin_conf) (strcmp(dirent->d_name,"..")!=0)) { serr = stat(dirent->d_name, &sbuf); if (!serr && S_ISDIR(sbuf.st_mode)) { - plugin=load_plugin(dirent->d_name,plugin_conf); - *last=plugin; + plugin=_plugin_load(dirent->d_name,plugin_conf); + *last=plugin;/* this sets the last's `next' */ last=&plugin->next; } } } closedir (cwd); + + _plugin_depend(tree); + + xchdir(".."); return tree; } diff --git a/c/plugin.h b/c/plugin.h index 92deed2..d5ede8f 100644 --- a/c/plugin.h +++ b/c/plugin.h @@ -31,12 +31,12 @@ struct plugin_command char *name; /*plugin ID*/ - struct plugin *plugin; /* which plugin does it belong to? */ + struct plugin *plugin; /* which plugin does it belong to? */ struct plugin_command *p_next; /* next command in this plugin (linked list)*/ /*dependancy tree*/ struct plugin_command *depend; /* what does this depend on? */ - char *depends; /* what does this depend on? */ + char *depends;/* what does this depend on? */ struct plugin_command *child; /* what depends on this? (linked list) */ struct plugin_command *d_next; /* next command w/ same dependancy (linked list) */ }; @@ -44,6 +44,6 @@ struct plugin_command struct plugin_tree { struct plugin *plugins; - struct plugin_command *depend; + struct plugin_command *depends; }; diff --git a/c/plugins b/c/plugins deleted file mode 120000 index b1f2dbf..0000000 --- a/c/plugins +++ /dev/null @@ -1 +0,0 @@ -../plugins/ \ No newline at end of file diff --git a/c/rvs.c b/c/rvs.c index 6997596..56162ac 100644 --- a/c/rvs.c +++ b/c/rvs.c @@ -26,9 +26,10 @@ const char *ver="0.8c"; const char *libexecdir="./plugins"; const char *plugin_conf="plugin.conf"; -int main (void) +int +main (void) { - load_plugins(libexecdir,plugin_conf); + struct plugin_tree *plugins=load_plugins(libexecdir,plugin_conf); return 0; } diff --git a/c/rvs.h b/c/rvs.h index 1bcbacf..5301b09 100644 --- a/c/rvs.h +++ b/c/rvs.h @@ -18,6 +18,8 @@ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include +#include #include #include #include @@ -26,20 +28,34 @@ void *xmalloc (size_t size) { - register void *value = malloc (size); - if (value == 0) + void *value = malloc (size); + if (value == NULL) error(EXIT_FAILURE,0,"virtual memory exhausted"); return value; } void *xrealloc (void *ptr, size_t size) { - register void *value = realloc (ptr, size); - if (value == 0) + void *value = realloc (ptr, size); + if (value == NULL) error(EXIT_FAILURE,0,"virtual memory exhausted"); return value; } +void xfree (void *ptr) +{ + free (ptr); +} + +int xchdir (const char *filename) +{ + int ret=chdir(filename); + if (ret != 0) { + error(EXIT_FAILURE,errno,"%s/",filename); + } + return ret; +} + FILE *xfopen (const char *filename, const char *opentype) { FILE *file = fopen(filename,opentype); @@ -68,9 +84,8 @@ void stradds(size_t *size, char **dest, char *str) } else { *size = strlen(*dest) + strlen(str) + 1; - char *string; - string = (char *) xrealloc (*dest, *size); - strcat(string, str); + *dest = (char *) xrealloc (*dest, *size); + strcat(*dest, str); } } diff --git a/c/test.c b/c/test.c index 3a10711..3a9abc9 100644 --- a/c/test.c +++ b/c/test.c @@ -1,10 +1,9 @@ #include "plugin.c" #include "plugin-debug.c" -int main() -{ +int main() { struct plugin_tree *plugins=load_plugins("plugins","plugin.conf"); - print_plugins(plugins->plugins); + _plugin_print(plugins); return 0; } diff --git a/plugins/file b/plugins/file deleted file mode 100644 index e69de29..0000000 -- cgit v1.2.3