1 /* $NetBSD: mdb.c,v 1.24 2003/01/10 20:00:50 christos Exp $ */ 2 3 /* 4 * Copyright 1997 Piermont Information Systems Inc. 5 * All rights reserved. 6 * 7 * Written by Philip A. Nelson for Piermont Information Systems Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software develooped for the NetBSD Project by 20 * Piermont Information Systems Inc. 21 * 4. The name of Piermont Information Systems Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 35 * THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 */ 38 39 /* mdb.c - menu database manipulation */ 40 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include "mdb.h" 45 #include "defs.h" 46 #include "pathnames.h" 47 48 /* Data */ 49 #undef MAX 50 #define MAX 1000 51 static int menu_no = 0; 52 static id_rec *menus[MAX]; 53 54 /* Other defines */ 55 #define OPT_SUB 1 56 #define OPT_ENDWIN 2 57 #define OPT_EXIT 4 58 59 60 /* get_menu returns a pointer to a newly created id_rec or an old one. */ 61 62 id_rec * 63 get_menu (char *name) 64 { 65 id_rec *temp; 66 67 temp = find_id (root, name); 68 69 if (temp == NULL) { 70 if (menu_no < MAX) { 71 temp = (id_rec *) malloc (sizeof(id_rec)); 72 temp->id = strdup(name); 73 temp->info = NULL; 74 temp->menu_no = menu_no; 75 menus[menu_no++] = temp; 76 insert_id (&root, temp); 77 } else { 78 (void) fprintf (stderr, "Too many menus. " 79 "Increase MAX.\n"); 80 exit(1); 81 } 82 } 83 84 return temp; 85 } 86 87 88 /* Verify that all menus are defined. */ 89 90 void 91 check_defined (void) 92 { 93 int i; 94 95 for (i=0; i<menu_no; i++) 96 if (!menus[i]->info) 97 yyerror ("Menu '%s' undefined.", menus[i]->id); 98 } 99 100 101 /* Write out the menu file. */ 102 void 103 write_menu_file (char *initcode) 104 { 105 FILE *out_file; 106 FILE *sys_file; 107 int i, j; 108 char hname[1024]; 109 char cname[1024]; 110 char sname[1024]; 111 char *sys_prefix; 112 char *tmpstr; 113 114 int nlen; 115 116 int ch; 117 118 optn_info *toptn; 119 120 /* Generate file names */ 121 snprintf (hname, 1024, "%s.h", out_name); 122 nlen = strlen(hname); 123 if (hname[nlen-2] != '.' || hname[nlen-1] != 'h') { 124 (void) fprintf (stderr, "%s: name `%s` too long.\n", 125 prog_name, out_name); 126 exit(1); 127 } 128 snprintf (cname, 1024, "%s.c", out_name); 129 130 /* Open the menu_sys file first. */ 131 sys_prefix = getenv ("MENUDEF"); 132 if (sys_prefix == NULL) 133 sys_prefix = _PATH_DEFSYSPREFIX; 134 snprintf (sname, 1024, "%s/%s", sys_prefix, sys_name); 135 sys_file = fopen (sname, "r"); 136 if (sys_file == NULL) { 137 (void) fprintf (stderr, "%s: could not open %s.\n", 138 prog_name, sname); 139 exit (1); 140 } 141 142 /* Output the .h file first. */ 143 out_file = fopen (hname, "w"); 144 if (out_file == NULL) { 145 (void) fprintf (stderr, "%s: could not open %s.\n", 146 prog_name, hname); 147 exit (1); 148 } 149 150 /* Write it */ 151 (void) fprintf (out_file, "%s", 152 "/* menu system definitions. */\n" 153 "\n" 154 "#ifndef MENU_DEFS_H\n" 155 "#define MENU_DEFS_H\n" 156 "#include <stdlib.h>\n" 157 "#include <string.h>\n" 158 "#include <ctype.h>\n" 159 "#include <curses.h>\n\n" 160 ); 161 162 if (do_dynamic) 163 (void) fprintf (out_file, "#define DYNAMIC_MENUS\n\n"); 164 165 (void) fprintf (out_file, 166 "struct menudesc;\n" 167 "typedef\n" 168 "struct menu_ent {\n" 169 " char *opt_name;\n" 170 " int opt_menu;\n" 171 " int opt_flags;\n" 172 " int (*opt_action)(struct menudesc *);\n" 173 "} menu_ent ;\n\n" 174 "#define OPT_SUB 1\n" 175 "#define OPT_ENDWIN 2\n" 176 "#define OPT_EXIT 4\n" 177 "#define OPT_NOMENU -1\n\n" 178 "typedef\n" 179 "struct menudesc {\n" 180 " char *title;\n" 181 " int y, x;\n" 182 " int h, w;\n" 183 " int mopt;\n" 184 " int numopts;\n" 185 " int cursel;\n" 186 " int topline;\n" 187 " menu_ent *opts;\n" 188 " WINDOW *mw;\n" 189 " char *helpstr;\n" 190 " char *exitstr;\n" 191 " void (*post_act)(void);\n" 192 " void (*exit_act)(void);\n" 193 "} menudesc ;\n" 194 "\n" 195 "/* defines for mopt field. */\n" 196 "#define MC_NOEXITOPT 1\n" 197 "#define MC_NOBOX 2\n" 198 "#define MC_SCROLL 4\n" 199 "#define MC_NOSHORTCUT 8\n" 200 "#define MC_VALID 256\n" 201 ); 202 203 (void) fprintf (out_file, "%s", 204 "\n" 205 "/* initilization flag */\n" 206 "extern int __m_endwin;\n" 207 "\n" 208 "/* Prototypes */\n" 209 "int menu_init (void);\n" 210 "void process_menu (int num);\n" 211 "void __menu_initerror (void);\n" 212 ); 213 214 if (do_dynamic) 215 (void) fprintf (out_file, "%s", 216 "int new_menu (char * title, menu_ent * opts, " 217 "int numopts, \n" 218 "\tint x, int y, int h, int w, int mopt,\n" 219 "\tvoid (*post_act)(void), " 220 "void (*exit_act)(void), " 221 "char * help);\n" 222 "void free_menu (int menu_no);\n" 223 ); 224 225 (void) fprintf (out_file, "\n/* Menu names */\n"); 226 for (i=0; i<menu_no; i++) { 227 (void) fprintf (out_file, "#define MENU_%s\t%d\n", 228 menus[i]->id, i); 229 } 230 231 if (do_dynamic) 232 (void) fprintf (out_file, "\n#define DYN_MENU_START\t%d", 233 menu_no); 234 235 (void) fprintf (out_file, "\n#define MAX_STRLEN %d\n" 236 "#endif\n", max_strlen); 237 fclose (out_file); 238 239 /* Now the C file */ 240 out_file = fopen (cname, "w"); 241 if (out_file == NULL) { 242 (void) fprintf (stderr, "%s: could not open %s.\n", 243 prog_name, cname); 244 exit (1); 245 } 246 247 /* initial code */ 248 fprintf (out_file, "#include \"%s\"\n\n", hname); 249 fprintf (out_file, "%s\n\n", initcode); 250 251 /* data definitions */ 252 253 /* func defs */ 254 for (i=0; i<menu_no; i++) { 255 if (strlen(menus[i]->info->postact.code)) { 256 (void) fprintf (out_file, 257 "void menu_%d_postact(void);\n" 258 "void menu_%d_postact(void)\n{", i, i); 259 if (menus[i]->info->postact.endwin) 260 (void) fprintf (out_file, "\tendwin();\n" 261 "\t__m_endwin = 1;\n"); 262 (void) fprintf (out_file, 263 "\t%s\n}\n", 264 menus[i]->info->postact.code); 265 } 266 if (strlen(menus[i]->info->exitact.code)) { 267 (void) fprintf (out_file, 268 "void menu_%d_exitact(void);\n" 269 "void menu_%d_exitact(void)\n{", i, i); 270 if (menus[i]->info->exitact.endwin) 271 (void) fprintf (out_file, "\tendwin();\n" 272 "\t__m_endwin = 1;\n"); 273 (void) fprintf (out_file, "\t%s\n}\n\n", 274 menus[i]->info->exitact.code); 275 } 276 j = 0; 277 toptn = menus[i]->info->optns; 278 while (toptn != NULL) { 279 if (strlen(toptn->optact.code)) { 280 (void) fprintf (out_file, 281 "int opt_act_%d_%d(menudesc *m);\n" 282 "/*ARGSUSED*/\n" 283 "int opt_act_%d_%d(menudesc *m)\n" 284 "{\t%s\n\treturn %s;\n}\n\n", 285 i, j, i, j, toptn->optact.code, 286 (toptn->doexit ? "1" : "0")); 287 288 289 } 290 j++; 291 toptn = toptn->next; 292 } 293 294 } 295 296 /* optentX */ 297 for (i=0; i<menu_no; i++) { 298 if (menus[i]->info->numopt > 53) { 299 (void) fprintf (stderr, "Menu %s has " 300 "too many options.\n", 301 menus[i]->info->title); 302 exit (1); 303 } 304 toptn = menus[i]->info->optns; 305 j = 0; 306 (void) fprintf (out_file, 307 "static menu_ent optent%d[] = {\n", i); 308 while (toptn != NULL) { 309 (void) fprintf (out_file, "\t{\"%s,%d,%d,", 310 toptn->name+1, toptn->menu, 311 (toptn->issub ? OPT_SUB : 0) 312 +(toptn->doexit ? OPT_EXIT : 0) 313 +(toptn->optact.endwin ? OPT_ENDWIN : 0)); 314 if (strlen(toptn->optact.code)) 315 (void) fprintf (out_file, "opt_act_%d_%d}", 316 i, j); 317 else 318 (void) fprintf (out_file, "NULL}"); 319 (void) fprintf (out_file, "%s\n", 320 (toptn->next ? "," : "")); 321 j++; 322 toptn = toptn->next; 323 } 324 (void) fprintf (out_file, "\t};\n\n"); 325 326 } 327 328 329 /* menus */ 330 (void) fprintf (out_file, "static struct menudesc menu_def[] = {\n"); 331 for (i=0; i<menu_no; i++) { 332 (void) fprintf (out_file, 333 "\t{%s,%d,%d,%d,%d,%d,%d,0,0,optent%d,NULL,", 334 menus[i]->info->title, menus[i]->info->y, 335 menus[i]->info->x, menus[i]->info->h, 336 menus[i]->info->w, menus[i]->info->mopt, 337 menus[i]->info->numopt, i); 338 if (menus[i]->info->helpstr == NULL) 339 (void) fprintf (out_file, "NULL"); 340 else { 341 tmpstr = menus[i]->info->helpstr; 342 /* Skip an initial newline. */ 343 if (*tmpstr == '\n') 344 tmpstr++; 345 (void) fprintf (out_file, "\n\""); 346 while (*tmpstr) 347 if (*tmpstr != '\n') 348 fputc (*tmpstr++, out_file); 349 else { 350 (void) fprintf (out_file, "\\n\\\n"); 351 tmpstr++; 352 } 353 (void) fprintf (out_file, "\""); 354 } 355 (void) fprintf (out_file, ","); 356 if (menus[i]->info->mopt & NOEXITOPT) 357 (void) fprintf (out_file, "NULL"); 358 else if (menus[i]->info->exitstr != NULL) 359 (void) fprintf (out_file, "%s", 360 menus[i]->info->exitstr); 361 else 362 (void) fprintf (out_file, "\"Exit\""); 363 if (strlen(menus[i]->info->postact.code)) 364 (void) fprintf (out_file, ",menu_%d_postact", i); 365 else 366 (void) fprintf (out_file, ",NULL"); 367 if (strlen(menus[i]->info->exitact.code)) 368 (void) fprintf (out_file, ",menu_%d_exitact", i); 369 else 370 (void) fprintf (out_file, ",NULL"); 371 372 (void) fprintf (out_file, "},\n"); 373 374 } 375 (void) fprintf (out_file, "{NULL}};\n\n"); 376 377 /* __menu_initerror: initscr failed. */ 378 (void) fprintf (out_file, 379 "/* __menu_initerror: initscr failed. */\n" 380 "void __menu_initerror (void) {\n"); 381 if (error_act.code == NULL) { 382 (void) fprintf (out_file, 383 "\t(void) fprintf (stderr, " 384 "\"%%s: Could not initialize curses\\n\", " 385 "getprogname());\n" 386 "\texit(1);\n" 387 "}\n"); 388 } else { 389 if (error_act.endwin) 390 (void) fprintf (out_file, "\tendwin();\n"); 391 (void) fprintf (out_file, "%s\n}\n", error_act.code); 392 } 393 394 /* Copy menu_sys.def file. */ 395 while ((ch = fgetc(sys_file)) != '\014') /* Control-L */ 396 fputc(ch, out_file); 397 398 if (do_dynamic) { 399 while ((ch = fgetc(sys_file)) != '\n') 400 /* skip it */; 401 while ((ch = fgetc(sys_file)) != EOF) 402 fputc(ch, out_file); 403 } 404 405 fclose (out_file); 406 fclose (sys_file); 407 } 408