1 /* $NetBSD: mdb.c,v 1.22 2001/10/15 22:20:03 bjh21 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 #define MAX 1000 50 static int menu_no = 0; 51 static id_rec *menus[MAX]; 52 53 /* Other defines */ 54 #define OPT_SUB 1 55 #define OPT_ENDWIN 2 56 #define OPT_EXIT 4 57 58 59 /* get_menu returns a pointer to a newly created id_rec or an old one. */ 60 61 id_rec * 62 get_menu (char *name) 63 { 64 id_rec *temp; 65 66 temp = find_id (root, name); 67 68 if (temp == NULL) { 69 if (menu_no < MAX) { 70 temp = (id_rec *) malloc (sizeof(id_rec)); 71 temp->id = strdup(name); 72 temp->info = NULL; 73 temp->menu_no = menu_no; 74 menus[menu_no++] = temp; 75 insert_id (&root, temp); 76 } else { 77 (void) fprintf (stderr, "Too many menus. " 78 "Increase MAX.\n"); 79 exit(1); 80 } 81 } 82 83 return temp; 84 } 85 86 87 /* Verify that all menus are defined. */ 88 89 void 90 check_defined (void) 91 { 92 int i; 93 94 for (i=0; i<menu_no; i++) 95 if (!menus[i]->info) 96 yyerror ("Menu '%s' undefined.", menus[i]->id); 97 } 98 99 100 /* Write out the menu file. */ 101 void 102 write_menu_file (char *initcode) 103 { 104 FILE *out_file; 105 FILE *sys_file; 106 int i, j; 107 char hname[1024]; 108 char cname[1024]; 109 char sname[1024]; 110 char *sys_prefix; 111 char *tmpstr; 112 113 int nlen; 114 115 int ch; 116 117 optn_info *toptn; 118 119 /* Generate file names */ 120 snprintf (hname, 1024, "%s.h", out_name); 121 nlen = strlen(hname); 122 if (hname[nlen-2] != '.' || hname[nlen-1] != 'h') { 123 (void) fprintf (stderr, "%s: name `%s` too long.\n", 124 prog_name, out_name); 125 exit(1); 126 } 127 snprintf (cname, 1024, "%s.c", out_name); 128 129 /* Open the menu_sys file first. */ 130 sys_prefix = getenv ("MENUDEF"); 131 if (sys_prefix == NULL) 132 sys_prefix = _PATH_DEFSYSPREFIX; 133 snprintf (sname, 1024, "%s/%s", sys_prefix, sys_name); 134 sys_file = fopen (sname, "r"); 135 if (sys_file == NULL) { 136 (void) fprintf (stderr, "%s: could not open %s.\n", 137 prog_name, sname); 138 exit (1); 139 } 140 141 /* Output the .h file first. */ 142 out_file = fopen (hname, "w"); 143 if (out_file == NULL) { 144 (void) fprintf (stderr, "%s: could not open %s.\n", 145 prog_name, hname); 146 exit (1); 147 } 148 149 /* Write it */ 150 (void) fprintf (out_file, "%s", 151 "/* menu system definitions. */\n" 152 "\n" 153 "#ifndef MENU_DEFS_H\n" 154 "#define MENU_DEFS_H\n" 155 "#include <stdlib.h>\n" 156 "#include <string.h>\n" 157 "#include <ctype.h>\n" 158 "#include <curses.h>\n\n" 159 ); 160 161 if (do_dynamic) 162 (void) fprintf (out_file, "#define DYNAMIC_MENUS\n\n"); 163 164 (void) fprintf (out_file, 165 "struct menudesc;\n" 166 "typedef\n" 167 "struct menu_ent {\n" 168 " char *opt_name;\n" 169 " int opt_menu;\n" 170 " int opt_flags;\n" 171 " int (*opt_action)(struct menudesc *);\n" 172 "} menu_ent ;\n\n" 173 "#define OPT_SUB 1\n" 174 "#define OPT_ENDWIN 2\n" 175 "#define OPT_EXIT 4\n" 176 "#define OPT_NOMENU -1\n\n" 177 "typedef\n" 178 "struct menudesc {\n" 179 " char *title;\n" 180 " int y, x;\n" 181 " int h, w;\n" 182 " int mopt;\n" 183 " int numopts;\n" 184 " int cursel;\n" 185 " int topline;\n" 186 " menu_ent *opts;\n" 187 " WINDOW *mw;\n" 188 " char *helpstr;\n" 189 " char *exitstr;\n" 190 " void (*post_act)(void);\n" 191 " void (*exit_act)(void);\n" 192 "} menudesc ;\n" 193 "\n" 194 "/* defines for mopt field. */\n" 195 "#define MC_NOEXITOPT 1\n" 196 "#define MC_NOBOX 2\n" 197 "#define MC_SCROLL 4\n" 198 "#define MC_NOSHORTCUT 8\n" 199 "#define MC_VALID 256\n" 200 ); 201 202 (void) fprintf (out_file, "%s", 203 "\n" 204 "/* initilization flag */\n" 205 "extern int __m_endwin;\n" 206 "\n" 207 "/* Prototypes */\n" 208 "int menu_init (void);\n" 209 "void process_menu (int num);\n" 210 "void __menu_initerror (void);\n" 211 ); 212 213 if (do_dynamic) 214 (void) fprintf (out_file, "%s", 215 "int new_menu (char * title, menu_ent * opts, " 216 "int numopts, \n" 217 "\tint x, int y, int h, int w, int mopt,\n" 218 "\tvoid (*post_act)(void), " 219 "void (*exit_act)(void), " 220 "char * help);\n" 221 "void free_menu (int menu_no);\n" 222 ); 223 224 (void) fprintf (out_file, "\n/* Menu names */\n"); 225 for (i=0; i<menu_no; i++) { 226 (void) fprintf (out_file, "#define MENU_%s\t%d\n", 227 menus[i]->id, i); 228 } 229 230 if (do_dynamic) 231 (void) fprintf (out_file, "\n#define DYN_MENU_START\t%d", 232 menu_no); 233 234 (void) fprintf (out_file, "\n#define MAX_STRLEN %d\n" 235 "#endif\n", max_strlen); 236 fclose (out_file); 237 238 /* Now the C file */ 239 out_file = fopen (cname, "w"); 240 if (out_file == NULL) { 241 (void) fprintf (stderr, "%s: could not open %s.\n", 242 prog_name, cname); 243 exit (1); 244 } 245 246 /* initial code */ 247 fprintf (out_file, "#include \"%s\"\n\n", hname); 248 fprintf (out_file, "%s\n\n", initcode); 249 250 /* data definitions */ 251 252 /* func defs */ 253 for (i=0; i<menu_no; i++) { 254 if (strlen(menus[i]->info->postact.code)) { 255 (void) fprintf (out_file, 256 "void menu_%d_postact(void);\n" 257 "void menu_%d_postact(void)\n{", i, i); 258 if (menus[i]->info->postact.endwin) 259 (void) fprintf (out_file, "\tendwin();\n" 260 "\t__m_endwin = 1;\n"); 261 (void) fprintf (out_file, 262 "\t%s\n}\n", 263 menus[i]->info->postact.code); 264 } 265 if (strlen(menus[i]->info->exitact.code)) { 266 (void) fprintf (out_file, 267 "void menu_%d_exitact(void);\n" 268 "void menu_%d_exitact(void)\n{", i, i); 269 if (menus[i]->info->exitact.endwin) 270 (void) fprintf (out_file, "\tendwin();\n" 271 "\t__m_endwin = 1;\n"); 272 (void) fprintf (out_file, "\t%s\n}\n\n", 273 menus[i]->info->exitact.code); 274 } 275 j = 0; 276 toptn = menus[i]->info->optns; 277 while (toptn != NULL) { 278 if (strlen(toptn->optact.code)) { 279 (void) fprintf (out_file, 280 "int opt_act_%d_%d(menudesc *m);\n" 281 "int opt_act_%d_%d(menudesc *m)\n" 282 "{\t%s\n\treturn %s;\n}\n\n", 283 i, j, i, j, toptn->optact.code, 284 (toptn->doexit ? "1" : "0")); 285 286 287 } 288 j++; 289 toptn = toptn->next; 290 } 291 292 } 293 294 /* optentX */ 295 for (i=0; i<menu_no; i++) { 296 if (menus[i]->info->numopt > 53) { 297 (void) fprintf (stderr, "Menu %s has " 298 "too many options.\n", 299 menus[i]->info->title); 300 exit (1); 301 } 302 toptn = menus[i]->info->optns; 303 j = 0; 304 (void) fprintf (out_file, 305 "static menu_ent optent%d[] = {\n", i); 306 while (toptn != NULL) { 307 (void) fprintf (out_file, "\t{\"%s,%d,%d,", 308 toptn->name+1, toptn->menu, 309 (toptn->issub ? OPT_SUB : 0) 310 +(toptn->doexit ? OPT_EXIT : 0) 311 +(toptn->optact.endwin ? OPT_ENDWIN : 0)); 312 if (strlen(toptn->optact.code)) 313 (void) fprintf (out_file, "opt_act_%d_%d}", 314 i, j); 315 else 316 (void) fprintf (out_file, "NULL}"); 317 (void) fprintf (out_file, "%s\n", 318 (toptn->next ? "," : "")); 319 j++; 320 toptn = toptn->next; 321 } 322 (void) fprintf (out_file, "\t};\n\n"); 323 324 } 325 326 327 /* menus */ 328 (void) fprintf (out_file, "static struct menudesc menu_def[] = {\n"); 329 for (i=0; i<menu_no; i++) { 330 (void) fprintf (out_file, 331 "\t{%s,%d,%d,%d,%d,%d,%d,0,0,optent%d,NULL,", 332 menus[i]->info->title, menus[i]->info->y, 333 menus[i]->info->x, menus[i]->info->h, 334 menus[i]->info->w, menus[i]->info->mopt, 335 menus[i]->info->numopt, i); 336 if (menus[i]->info->helpstr == NULL) 337 (void) fprintf (out_file, "NULL"); 338 else { 339 tmpstr = menus[i]->info->helpstr; 340 /* Skip an initial newline. */ 341 if (*tmpstr == '\n') 342 tmpstr++; 343 (void) fprintf (out_file, "\n\""); 344 while (*tmpstr) 345 if (*tmpstr != '\n') 346 fputc (*tmpstr++, out_file); 347 else { 348 (void) fprintf (out_file, "\\n\\\n"); 349 tmpstr++; 350 } 351 (void) fprintf (out_file, "\""); 352 } 353 (void) fprintf (out_file, ","); 354 if (menus[i]->info->mopt & NOEXITOPT) 355 (void) fprintf (out_file, "NULL"); 356 else if (menus[i]->info->exitstr != NULL) 357 (void) fprintf (out_file, "%s", 358 menus[i]->info->exitstr); 359 else 360 (void) fprintf (out_file, "\"Exit\""); 361 if (strlen(menus[i]->info->postact.code)) 362 (void) fprintf (out_file, ",menu_%d_postact", i); 363 else 364 (void) fprintf (out_file, ",NULL"); 365 if (strlen(menus[i]->info->exitact.code)) 366 (void) fprintf (out_file, ",menu_%d_exitact", i); 367 else 368 (void) fprintf (out_file, ",NULL"); 369 370 (void) fprintf (out_file, "},\n"); 371 372 } 373 (void) fprintf (out_file, "{NULL}};\n\n"); 374 375 /* __menu_initerror: initscr failed. */ 376 (void) fprintf (out_file, 377 "/* __menu_initerror: initscr failed. */\n" 378 "void __menu_initerror (void) {\n"); 379 if (error_act.code == NULL) { 380 (void) fprintf (out_file, 381 "\t(void) fprintf (stderr, " 382 "\"%%s: Could not initialize curses\\n\", " 383 "getprogname());\n" 384 "\texit(1);\n" 385 "}\n"); 386 } else { 387 if (error_act.endwin) 388 (void) fprintf (out_file, "\tendwin();\n"); 389 (void) fprintf (out_file, "%s\n}\n", error_act.code); 390 } 391 392 /* Copy menu_sys.def file. */ 393 while ((ch = fgetc(sys_file)) != '\014') /* Control-L */ 394 fputc(ch, out_file); 395 396 if (do_dynamic) { 397 while ((ch = fgetc(sys_file)) != '\n') 398 /* skip it */; 399 while ((ch = fgetc(sys_file)) != EOF) 400 fputc(ch, out_file); 401 } 402 403 fclose (out_file); 404 fclose (sys_file); 405 } 406