1 /* $NetBSD: mdb.c,v 1.23 2002/03/07 20:43:29 tv 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 "int opt_act_%d_%d(menudesc *m)\n" 283 "{\t%s\n\treturn %s;\n}\n\n", 284 i, j, i, j, toptn->optact.code, 285 (toptn->doexit ? "1" : "0")); 286 287 288 } 289 j++; 290 toptn = toptn->next; 291 } 292 293 } 294 295 /* optentX */ 296 for (i=0; i<menu_no; i++) { 297 if (menus[i]->info->numopt > 53) { 298 (void) fprintf (stderr, "Menu %s has " 299 "too many options.\n", 300 menus[i]->info->title); 301 exit (1); 302 } 303 toptn = menus[i]->info->optns; 304 j = 0; 305 (void) fprintf (out_file, 306 "static menu_ent optent%d[] = {\n", i); 307 while (toptn != NULL) { 308 (void) fprintf (out_file, "\t{\"%s,%d,%d,", 309 toptn->name+1, toptn->menu, 310 (toptn->issub ? OPT_SUB : 0) 311 +(toptn->doexit ? OPT_EXIT : 0) 312 +(toptn->optact.endwin ? OPT_ENDWIN : 0)); 313 if (strlen(toptn->optact.code)) 314 (void) fprintf (out_file, "opt_act_%d_%d}", 315 i, j); 316 else 317 (void) fprintf (out_file, "NULL}"); 318 (void) fprintf (out_file, "%s\n", 319 (toptn->next ? "," : "")); 320 j++; 321 toptn = toptn->next; 322 } 323 (void) fprintf (out_file, "\t};\n\n"); 324 325 } 326 327 328 /* menus */ 329 (void) fprintf (out_file, "static struct menudesc menu_def[] = {\n"); 330 for (i=0; i<menu_no; i++) { 331 (void) fprintf (out_file, 332 "\t{%s,%d,%d,%d,%d,%d,%d,0,0,optent%d,NULL,", 333 menus[i]->info->title, menus[i]->info->y, 334 menus[i]->info->x, menus[i]->info->h, 335 menus[i]->info->w, menus[i]->info->mopt, 336 menus[i]->info->numopt, i); 337 if (menus[i]->info->helpstr == NULL) 338 (void) fprintf (out_file, "NULL"); 339 else { 340 tmpstr = menus[i]->info->helpstr; 341 /* Skip an initial newline. */ 342 if (*tmpstr == '\n') 343 tmpstr++; 344 (void) fprintf (out_file, "\n\""); 345 while (*tmpstr) 346 if (*tmpstr != '\n') 347 fputc (*tmpstr++, out_file); 348 else { 349 (void) fprintf (out_file, "\\n\\\n"); 350 tmpstr++; 351 } 352 (void) fprintf (out_file, "\""); 353 } 354 (void) fprintf (out_file, ","); 355 if (menus[i]->info->mopt & NOEXITOPT) 356 (void) fprintf (out_file, "NULL"); 357 else if (menus[i]->info->exitstr != NULL) 358 (void) fprintf (out_file, "%s", 359 menus[i]->info->exitstr); 360 else 361 (void) fprintf (out_file, "\"Exit\""); 362 if (strlen(menus[i]->info->postact.code)) 363 (void) fprintf (out_file, ",menu_%d_postact", i); 364 else 365 (void) fprintf (out_file, ",NULL"); 366 if (strlen(menus[i]->info->exitact.code)) 367 (void) fprintf (out_file, ",menu_%d_exitact", i); 368 else 369 (void) fprintf (out_file, ",NULL"); 370 371 (void) fprintf (out_file, "},\n"); 372 373 } 374 (void) fprintf (out_file, "{NULL}};\n\n"); 375 376 /* __menu_initerror: initscr failed. */ 377 (void) fprintf (out_file, 378 "/* __menu_initerror: initscr failed. */\n" 379 "void __menu_initerror (void) {\n"); 380 if (error_act.code == NULL) { 381 (void) fprintf (out_file, 382 "\t(void) fprintf (stderr, " 383 "\"%%s: Could not initialize curses\\n\", " 384 "getprogname());\n" 385 "\texit(1);\n" 386 "}\n"); 387 } else { 388 if (error_act.endwin) 389 (void) fprintf (out_file, "\tendwin();\n"); 390 (void) fprintf (out_file, "%s\n}\n", error_act.code); 391 } 392 393 /* Copy menu_sys.def file. */ 394 while ((ch = fgetc(sys_file)) != '\014') /* Control-L */ 395 fputc(ch, out_file); 396 397 if (do_dynamic) { 398 while ((ch = fgetc(sys_file)) != '\n') 399 /* skip it */; 400 while ((ch = fgetc(sys_file)) != EOF) 401 fputc(ch, out_file); 402 } 403 404 fclose (out_file); 405 fclose (sys_file); 406 } 407