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