[Bug 681] Handlers filenames and syntax versions

Kevin P. Fleming kpfleming at linuxfromscratch.org
Tue Sep 30 07:45:07 PDT 2003


Neven Has wrote:

> Sounds good.  There are a few functions in handlers that are used by
> main code to get some handler-specific information (see
> handler_alloc_execute_command() in execute.c for example).  Those
> would have to be stored in the structure too.  I'm still not sure
> what would be the best way to do that, as some handlers can (and do)
> have more than one of those.
> 

Warning: This message is long, and only eye-tested (not even compile 
tested)!

Here's what I would suggest... in handlers.h:

enum handler_type {
   HANDLER_ACTION, HANDLER_STAGE, HANDLER_PACKAGE, HANDLER_CONTAINER, 
HANDLER_TEXTDUMP, HANDLER_EXECUTE
};

enum handler_data {
   DATA_COMMAND, DATA_NAME, DATA_VERSION, DATA_FILE
};

struct handler_info {
   char *name;
   char *description;
   handler_type type;
   char *syntax_version;
   char *parameters[];
   char *attributes[];
   int (*main)(element_s *);
   char *(*alloc_data)(element_s *, handler_data data_needed);
};


Then, in a basic handler (not an action, all syntax versions use the 
same handler_main):

struct handler_info handlers[] = {
   { .name = "alfs",
     .description = "ALFS profile",
     .type = HANDLER_CONTAINER,
     .syntax_version = "2.0",
     .main = &handler_main
   },
   { .name = "alfs",
     .description = "ALFS profile",
     .type = HANDLER_CONTAINER,
     .syntax_version = "3.0",
     .main = &handler_main
   },
   { .name = "alfs",
     .description = "ALFS profile",
     .type = HANDLER_CONTAINER,
     .syntax_version = "3.1",
     .main = &handler_main
   },
   { .name = NULL }
};

The main code would then index through the array until it hits "name 
== NULL"; each structure it found would be listed as an available 
handler for the listed version.

Here's a more complex example:

struct handler_info handlers[] = {
   { .name = "execute",
     .description = "Execute",
     .type = HANDLER_EXECUTE,
     .syntax_version = "2.0",
     .parameters = {"base", "command", "param", NULL},
     .main = &handler_main_v2,
     .alloc_data = &handler_data_v2
   },
   { .name = "execute",
     .description = "Execute",
     .type = HANDLER_EXECUTE,
     .syntax_version = "3.0",
     .parameters = {"param", NULL},
     .attributes = {"base", "command", NULL},
     .main = &handler_main_v3,
     .alloc_data = &handler_data_v3
   },
   { .name = "execute",
     .description = "Execute",
     .type = HANDLER_EXECUTE,
     .syntax_version = "3.1",
     .parameters = {"param", NULL},
     .attributes = {"base", "command", NULL},
     .main = &handler_main_v3,
     .alloc_data = &handler_data_v3
   },
   { .name = NULL }
};

I'm not sure on the initialization of the array elements of the 
structure, but it should be possible.

In this example, the handler has two "main" functions because it 
handles two major syntax version differences. In addition, because it 
is listed as HANDLER_EXECUTE, the main code will call its alloc_data 
function asking for the DATA_COMMAND to be returned. If it was 
HANDLER_PACKAGE, the main code would call alloc_data twice asking for 
DATA_VERSION and DATA_NAME.

I know there are lots of questions left open here, but you get the 
idea. I'd suggest making things as generic as possible (that's the 
reason for alloc_data), and stop using typedefs (because they're not 
really necessary and anyone who works on kernel code has to get out of 
the habit of using them :-).

With this model it's easy to extend existing handlers to support a new 
syntax version (although slightly harder than before, but still mostly 
a copy & paste), and all the code for a handler can be kept in one 
source file. Also, when the configure system allows the user to 
specify a minimum syntax version to support, all the lower version 
code can just be #ifdef-ed away.

Thoughts?




More information about the alfs-log mailing list