1/* 2 * Copyright (c) 1998-1999 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "make_cmds.h" 35#include <getarg.h> 36 37RCSID("$Id: make_cmds.c 15430 2005-06-16 19:25:45Z lha $"); 38 39#include <roken.h> 40#include <err.h> 41#include "parse.h" 42 43int numerror; 44extern FILE *yyin; 45FILE *c_file; 46 47extern void yyparse(void); 48 49#ifdef YYDEBUG 50extern int yydebug = 1; 51#endif 52 53char *filename; 54char *table_name; 55 56static struct command_list *commands; 57 58void 59add_command(char *function, 60 char *help, 61 struct string_list *aliases, 62 unsigned flags) 63{ 64 struct command_list *cl = malloc(sizeof(*cl)); 65 66 if (cl == NULL) 67 err (1, "malloc"); 68 cl->function = function; 69 cl->help = help; 70 cl->aliases = aliases; 71 cl->flags = flags; 72 cl->next = NULL; 73 if(commands) { 74 *commands->tail = cl; 75 commands->tail = &cl->next; 76 return; 77 } 78 cl->tail = &cl->next; 79 commands = cl; 80} 81 82static char * 83quote(const char *str) 84{ 85 char buf[1024]; /* XXX */ 86 const char *p; 87 char *q; 88 q = buf; 89 90 *q++ = '\"'; 91 for(p = str; *p != '\0'; p++) { 92 if(*p == '\n') { 93 *q++ = '\\'; 94 *q++ = 'n'; 95 continue; 96 } 97 if(*p == '\t') { 98 *q++ = '\\'; 99 *q++ = 't'; 100 continue; 101 } 102 if(*p == '\"' || *p == '\\') 103 *q++ = '\\'; 104 *q++ = *p; 105 } 106 *q++ = '\"'; 107 *q++ = '\0'; 108 return strdup(buf); 109} 110 111static void 112generate_commands(void) 113{ 114 char *base; 115 char *cfn; 116 char *p, *q; 117 118 p = strrchr(table_name, '/'); 119 if(p == NULL) 120 p = table_name; 121 else 122 p++; 123 124 base = strdup (p); 125 if (base == NULL) 126 err (1, "strdup"); 127 128 p = strrchr(base, '.'); 129 if(p) 130 *p = '\0'; 131 132 asprintf(&cfn, "%s.c", base); 133 if (cfn == NULL) 134 err (1, "asprintf"); 135 136 c_file = fopen(cfn, "w"); 137 if (c_file == NULL) 138 err (1, "cannot fopen %s", cfn); 139 140 fprintf(c_file, "/* Generated from %s */\n", filename); 141 fprintf(c_file, "\n"); 142 fprintf(c_file, "#include <stddef.h>\n"); 143 fprintf(c_file, "#include <sl.h>\n"); 144 fprintf(c_file, "\n"); 145 146 { 147 struct command_list *cl, *xl; 148 149 for(cl = commands; cl; cl = cl->next) { 150 for(xl = commands; xl != cl; xl = xl->next) 151 if(strcmp(cl->function, xl->function) == 0) 152 break; 153 if(xl != cl) 154 continue; 155 /* XXX hack for ss_quit */ 156 if(strcmp(cl->function, "ss_quit") == 0) { 157 fprintf(c_file, "int %s (int, char**);\n", cl->function); 158 fprintf(c_file, "#define _ss_quit_wrap ss_quit\n\n"); 159 continue; 160 } 161 fprintf(c_file, "void %s (int, char**);\n", cl->function); 162 fprintf(c_file, "static int _%s_wrap (int argc, char **argv)\n", 163 cl->function); 164 fprintf(c_file, "{\n"); 165 fprintf(c_file, " %s (argc, argv);\n", cl->function); 166 fprintf(c_file, " return 0;\n"); 167 fprintf(c_file, "}\n\n"); 168 } 169 170 fprintf(c_file, "SL_cmd %s[] = {\n", table_name); 171 for(cl = commands; cl; cl = cl->next) { 172 struct string_list *sl; 173 sl = cl->aliases; 174 p = quote(sl->string); 175 q = quote(cl->help); 176 fprintf(c_file, " { %s, _%s_wrap, %s },\n", p, cl->function, q); 177 free(p); 178 free(q); 179 180 for(sl = sl->next; sl; sl = sl->next) { 181 p = quote(sl->string); 182 fprintf(c_file, " { %s },\n", p); 183 free(p); 184 } 185 } 186 fprintf(c_file, " { NULL },\n"); 187 fprintf(c_file, "};\n"); 188 fprintf(c_file, "\n"); 189 } 190 fclose(c_file); 191 free(base); 192 free(cfn); 193} 194 195int version_flag; 196int help_flag; 197struct getargs args[] = { 198 { "version", 0, arg_flag, &version_flag }, 199 { "help", 0, arg_flag, &help_flag } 200}; 201int num_args = sizeof(args) / sizeof(args[0]); 202 203static void 204usage(int code) 205{ 206 arg_printusage(args, num_args, NULL, "command-table"); 207 exit(code); 208} 209 210int 211main(int argc, char **argv) 212{ 213 int optidx = 0; 214 215 setprogname(argv[0]); 216 if(getarg(args, num_args, argc, argv, &optidx)) 217 usage(1); 218 if(help_flag) 219 usage(0); 220 if(version_flag) { 221 print_version(NULL); 222 exit(0); 223 } 224 225 if(argc == optidx) 226 usage(1); 227 filename = argv[optidx]; 228 yyin = fopen(filename, "r"); 229 if(yyin == NULL) 230 err(1, "%s", filename); 231 232 yyparse(); 233 234 generate_commands(); 235 236 if(numerror) 237 return 1; 238 return 0; 239} 240