diff --git a/lib/sl/lex.l b/lib/sl/lex.l new file mode 100644 index 000000000..0c5653b1b --- /dev/null +++ b/lib/sl/lex.l @@ -0,0 +1,119 @@ +%{ +/* + * Copyright (c) 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "make_cmds.h" +#include "parse.h" + +RCSID("$Id$"); + +static unsigned lineno = 1; +void error_message(char *, ...); +int getstring(void); + +%} + + +%% +command_table { return TABLE; } +request { return REQUEST; } +unknown { return UNKNOWN; } +unimplemented { return UNIMPLEMENTED; } +end { return END; } +#[^\n]* ; +[ \t] ; +\n { lineno++; } +\" { return getstring(); } +[a-zA-Z0-9_]+ { yylval.string = strdup(yytext); return STRING; } +. { return *yytext; } +%% + +#ifndef yywrap /* XXX */ +int +yywrap () +{ + return 1; +} +#endif + +int +getstring(void) +{ + char x[128]; + int i = 0; + int c; + int backslash = 0; + while((c = getc(yyin)) != EOF){ + if(backslash) { + if(c == 'n') + c = '\n'; + else if(c == 't') + c = '\t'; + x[i++] = c; + backslash = 0; + continue; + } + if(c == '\n'){ + error_message("unterminated string"); + lineno++; + break; + } + if(c == '\\'){ + backslash++; + continue; + } + if(c == '\"') + break; + x[i++] = c; + } + x[i] = '\0'; + yylval.string = strdup(x); + return STRING; +} + +void +error_message (char *format, ...) +{ + va_list args; + + va_start (args, format); + fprintf (stderr, "%s:%d: ", filename, lineno); + vfprintf (stderr, format, args); + va_end (args); + numerror++; +} diff --git a/lib/sl/make_cmds.c b/lib/sl/make_cmds.c new file mode 100644 index 000000000..7eaf387ed --- /dev/null +++ b/lib/sl/make_cmds.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "make_cmds.h" + +RCSID("$Id$"); + +#include +#include "parse.h" + +int numerror; +extern FILE *yyin; +FILE *c_file; + +extern void yyparse(void); + +#ifdef YYDEBUG +extern int yydebug = 1; +#endif + +char *filename; +char *table_name; + +static struct command_list *commands; + +void +add_command(char *function, + char *help, + struct string_list *aliases, + unsigned flags) +{ + struct command_list *cl = malloc(sizeof(*cl)); + cl->function = function; + cl->help = help; + cl->aliases = aliases; + cl->flags = flags; + cl->next = NULL; + if(commands) { + *commands->tail = cl; + commands->tail = &cl->next; + return; + } + cl->tail = &cl->next; + commands = cl; +} + +static char * +quote(const char *str) +{ + char buf[1024]; /* XXX */ + const char *p; + char *q; + q = buf; + + *q++ = '\"'; + for(p = str; *p != '\0'; p++) { + if(*p == '\n') { + *q++ = '\\'; + *q++ = 'n'; + continue; + } + if(*p == '\t') { + *q++ = '\\'; + *q++ = 't'; + continue; + } + if(*p == '\"' || *p == '\\') + *q++ = '\\'; + *q++ = *p; + } + *q++ = '\"'; + *q++ = '\0'; + return strdup(buf); +} + +static void +generate_commands(void) +{ + char base[128]; + char cfn[128]; + const char *p; + p = strrchr(table_name, '/'); + if(p == NULL) + p = table_name; + else + p++; + strcpy(base, p); + p = strrchr(base, '.'); + if(p) + *p == '\0'; + + snprintf(cfn, sizeof(cfn), "%s.c", base); + c_file = fopen(cfn, "w"); + + fprintf(c_file, "/* Generated from %s */\n", filename); + fprintf(c_file, "\n"); + fprintf(c_file, "#include \n"); + fprintf(c_file, "#include \n"); + fprintf(c_file, "\n"); + + { + struct string_list *sl; + struct command_list *cl, *xl; + char *p, *q; + + for(cl = commands; cl; cl = cl->next) { + for(xl = commands; xl != cl; xl = xl->next) + if(strcmp(cl->function, xl->function) == 0) + break; + if(xl != cl) + continue; + /* XXX hack for ss_quit */ + if(strcmp(cl->function, "ss_quit") == 0) { + fprintf(c_file, "int %s (int, char**);\n", cl->function); + fprintf(c_file, "#define _ss_quit_wrap ss_quit\n\n", + cl->function, cl->function); + continue; + } + fprintf(c_file, "void %s (int, char**);\n", cl->function); + fprintf(c_file, "static int _%s_wrap (int argc, char **argv)\n", + cl->function); + fprintf(c_file, "{\n"); + fprintf(c_file, " %s (argc, argv);\n", cl->function); + fprintf(c_file, " return 0;\n"); + fprintf(c_file, "}\n\n"); + } + + fprintf(c_file, "SL_cmd %s[] = {\n", table_name); + for(cl = commands; cl; cl = cl->next) { + p = quote(cl->function); + q = quote(cl->help); + fprintf(c_file, " { %s, _%s_wrap, %s },\n", p, cl->function, q); + free(p); + free(q); + + for(sl = cl->aliases; sl; sl = sl->next) { + p = quote(sl->string); + fprintf(c_file, " { %s },\n", p); + free(p); + } + } + fprintf(c_file, " { NULL },\n"); + fprintf(c_file, "};\n"); + fprintf(c_file, "\n"); + } + fclose(c_file); +} + +int +main(int argc, char **argv) +{ + char *p; + set_progname(argv[0]); + + if(argc != 2) { + fprintf(stderr, "Usage: %s command_table\n", __progname); + exit(1); + } + filename = argv[1]; + yyin = fopen(filename, "r"); + if(yyin == NULL) + err(1, "%s", filename); + + yyparse(); + + generate_commands(); + + if(numerror) + return 1; + return 0; +} diff --git a/lib/sl/make_cmds.h b/lib/sl/make_cmds.h new file mode 100644 index 000000000..370641183 --- /dev/null +++ b/lib/sl/make_cmds.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef __MAKE_CMDS_H__ +#define __MAKE_CMDS_H__ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +extern char *filename; +extern char *table_name; +extern int numerror; + +struct command_list { + char *function; + char *help; + struct string_list *aliases; + unsigned flags; + struct command_list *next; + struct command_list **tail; +}; + +struct string_list { + char *string; + struct string_list *next; + struct string_list **tail; +}; + +void add_command(char*, char*, struct string_list*, unsigned); + +#endif /* __MAKE_CMDS_H__ */ diff --git a/lib/sl/parse.y b/lib/sl/parse.y new file mode 100644 index 000000000..9dcdbb05e --- /dev/null +++ b/lib/sl/parse.y @@ -0,0 +1,191 @@ +%{ +/* + * Copyright (c) 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "make_cmds.h" +RCSID("$Id$"); + +void yyerror (char *s); +long name2number(const char *str); + +struct string_list* append_string(struct string_list*, char*); +void free_string_list(struct string_list *list); +unsigned string_to_flag(const char *); +%} + +%union { + char *string; + unsigned number; + struct string_list *list; +} + +%token TABLE REQUEST UNKNOWN UNIMPLEMENTED END +%token STRING +%type flag flags +%type aliases + +%% + +file : /* */ + | statements + ; + +statements : statement + | statements statement + ; + +statement : TABLE STRING ';' + { + table_name = $2; + } + | REQUEST STRING ',' STRING ',' aliases ',' '(' flags ')' ';' + { + add_command($2, $4, $6, $9); + } + | REQUEST STRING ',' STRING ',' aliases ';' + { + add_command($2, $4, $6, 0); + } + | UNIMPLEMENTED STRING ',' STRING ',' aliases ';' + { + free($2); + free($4); + free_string_list($6); + } + | UNKNOWN aliases ';' + { + free_string_list($2); + } + | END ';' + { + return; + } + ; + +aliases : STRING + { + $$ = append_string(NULL, $1); + } + | aliases ',' STRING + { + $$ = append_string($1, $3); + } + ; + +flags : flag + { + $$ = $1; + } + | flags ',' flag + { + $$ = $1 | $3; + } + ; +flag : STRING + { + $$ = string_to_flag($1); + free($1); + } + ; + + + +%% + +long +name2number(const char *str) +{ + const char *p; + long base = 0; + const char *x = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789_"; + if(strlen(str) > 4) { + yyerror("table name too long"); + return 0; + } + for(p = str; *p; p++){ + char *q = strchr(x, *p); + if(q == NULL) { + yyerror("invalid character in table name"); + return 0; + } + base = (base << 6) + (q - x) + 1; + } + base <<= 8; + if(base > 0x7fffffff) + base = -(0xffffffff - base + 1); + return base; +} + +void +yyerror (char *s) +{ + error_message ("%s\n", s); +} + +struct string_list* +append_string(struct string_list *list, char *str) +{ + struct string_list *sl = malloc(sizeof(*sl)); + sl->string = str; + sl->next = NULL; + if(list) { + *list->tail = sl; + list->tail = &sl->next; + return list; + } + sl->tail = &sl->next; + return sl; +} + +void +free_string_list(struct string_list *list) +{ + while(list) { + struct string_list *sl = list->next; + free(list->string); + free(list); + list = sl; + } +} + +unsigned +string_to_flag(const char *string) +{ + return 0; +}