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