1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  *      Read an errgen status resource file (*.err) from standard input and
  28  *      write an SPCS error code C header file (-c), Java resource file (-j),
  29  *      libspcs Java exception class file(-e), error text file (-m) or JNI
  30  *      exception trinket table to standard output. Lines starting with "#"
  31  *      are ignored.
  32  *
  33  *      Use "errgen -h" to get usage info including module codes and example
  34  *      input and output.
  35  */
  36 
  37 
  38 #include <stdio.h>
  39 #include <stdlib.h>
  40 #include <string.h>
  41 #include <ctype.h>
  42 #include <libgen.h>
  43 #include <limits.h>
  44 #include <sys/param.h>
  45 
  46 /* The public error info header file.  */
  47 
  48 #include <sys/unistat/spcs_s.h>
  49 
  50 /* The private error info header file */
  51 
  52 #include <sys/unistat/spcs_s_impl.h>
  53 
  54 
  55 /*  locals  */
  56 
  57 static enum {C_MODE, J_MODE, M_MODE, E_MODE, T_MODE, X_MODE} mode = E_MODE;
  58 static  char key[SPCS_S_MAXKEY];
  59 static  char text[SPCS_S_MAXTEXT];
  60 static int mod_number;
  61 
  62 static char help_path[PATH_MAX];
  63 
  64 static int count = 1;
  65 
  66 static char key[SPCS_S_MAXKEY];
  67 static char text[SPCS_S_MAXTEXT];
  68 static char modname[SPCS_S_MAXMODNAME];
  69 
  70 /*
  71  *      Display help info
  72  */
  73 
  74 static void
  75 help()
  76 {
  77         char line[SPCS_S_MAXLINE];
  78         FILE *h = fopen(help_path, "r");
  79 
  80         if (h) {
  81                 while (! feof(h)) {
  82                         (void) fgets(line, SPCS_S_MAXLINE, h);
  83                         if (! feof(h))
  84                                 (void) fputs(line, stderr);
  85                 }
  86         } else {
  87                 perror(strcat("could not open: ", help_path));
  88                 exit(1);
  89         }
  90 }
  91 
  92 /*
  93  *      Put out a message with terse instructions and err out
  94  */
  95 
  96 static void
  97 fatal(char *msg)
  98 {
  99         (void) fprintf(stderr, "%s\n\n", msg);
 100         (void) fprintf(stderr, "use errgen -h for help\n");
 101         exit(1);
 102 }
 103 
 104 /*
 105  *      Put out the output file preamble
 106  */
 107 
 108 static void
 109 do_preamble()
 110 {
 111         switch (mode) {
 112         case M_MODE:
 113                 (void) fprintf(stdout,
 114                         "static\nchar *SPCS_MSG_%s[] = {\n", modname);
 115                 (void) fprintf(stdout, "\t\"\",\n");
 116                 break;
 117         case T_MODE:
 118                 (void) fprintf(stdout,
 119                         "static\nchar *SPCS_TRNK_%s[] = {\n", modname);
 120                 (void) fprintf(stdout, "\t\"\",\n");
 121                 break;
 122         }
 123 }
 124 
 125 /*
 126  *      Put out the output file trailer
 127  */
 128 
 129 static void
 130 do_trailer()
 131 {
 132         switch (mode) {
 133         case M_MODE:
 134                 (void) fprintf(stdout, "};\n");
 135                 (void) fprintf(stdout,
 136                         "#define\tSPCS_MSGLEN_%s %d\t/* total codes */\n",
 137                         modname, count-1);
 138                 break;
 139         case T_MODE:
 140                 (void) fprintf(stdout, "};\n");
 141                 (void) fprintf(stdout,
 142                         "#define\tSPCS_TRNKLEN_%s %d\t/* total codes */\n",
 143                         modname, count-1);
 144                 break;
 145         }
 146 }
 147 
 148 /*
 149  *      Process a single input line
 150  */
 151 
 152 static void
 153 do_line()
 154 {
 155         spcs_s_udata_t c;
 156         int fc = 0;
 157         int len = 0;
 158         char ptext[SPCS_S_MAXTEXT];
 159         char keystring[SPCS_S_MAXKEY+SPCS_S_MAXPRE];
 160         char *p = text;
 161         int tlen;
 162         char *pt = ptext;
 163         char havebytestream = 0;
 164 
 165         c.i = 0;
 166         (void) sprintf(keystring, "%s_E%s", modname, key);
 167         while (*p) {
 168                 if (*p == '%') {
 169                         if (*(p + 1) != 's') {
 170                                 (void) fprintf(stderr,
 171                                     "ERRGEN: Error in .err file\n");
 172                                 (void) fprintf(stderr,
 173                                     "%c is an illegal format spec after %%",
 174                                     *p);
 175                                 (void) fprintf(stderr,
 176                                     " at line: %d pos: %d\n", count,
 177                                         /* LINTED possible ptrdiff_t overflow */
 178                                     (int)(p - text));
 179                                 fatal("");
 180                         }
 181                         len = sprintf(pt, "{%d}", fc);
 182                         pt += len;
 183                         p++;
 184                         fc += 1;
 185                         if (fc > SPCS_S_MAXSUPP) {
 186                                 (void) fprintf(stderr,
 187                                         "ERRGEN: Error in .err file\n");
 188                                 (void) fprintf(stderr,
 189                                     "SPCS_S_MAXSUPP exceeeded\n");
 190                                 fatal("Too many %%s specifiers");
 191                         }
 192                 } else
 193                         *pt++ = *p;
 194                 p++;
 195         }
 196 
 197         /* look for a bytestream indicator */
 198 
 199         tlen = strlen(text);
 200 
 201         if ((tlen > 2) && (text[tlen - 1] == '@') && (text[tlen - 2] == '@')) {
 202                 if (fc)
 203                         fatal("ERRGEN: cannot have %%s and @@ ending too");
 204 
 205                 /* bump the item count and set the bytestream flag */
 206                 fc += 1;
 207                 havebytestream = 1;
 208         }
 209 
 210         *pt = 0;
 211 
 212         switch (mode) {
 213         case C_MODE:
 214                 c.f.bytestream = havebytestream;
 215                 c.f.sup_count = fc;
 216                 c.f.module = mod_number;
 217                 c.f.code = count;
 218                 (void) fprintf(stdout, "#define\t%s 0x%x /* %s */\n",
 219                         keystring, c.i, text);
 220                 break;
 221         case J_MODE:
 222                 (void) fprintf(stdout, "`%s` = %s\n", keystring, ptext);
 223                 break;
 224         case X_MODE:
 225                 (void) fprintf(stdout,
 226                     "#define\tT_%s \"`%s`\"\n", keystring, keystring);
 227                 break;
 228         case T_MODE:
 229                 (void) fprintf(stdout, "\t\"`%s`\",\n", keystring);
 230                 break;
 231         case M_MODE:
 232                 (void) fprintf(stdout, "\t\"%s\",\n", text);
 233                 break;
 234         case E_MODE:
 235                 (void) fprintf(stdout, "    /**\n     * %s\n    **/\n",
 236                         text);
 237                 (void) fprintf(stdout, "    public static final String %s",
 238                             keystring);
 239                 (void) fprintf(stdout, " = `%s`;\n\n", keystring);
 240                 break;
 241         }
 242 }
 243 
 244 int
 245 main(int argc, char **argv)
 246 {
 247         int i;
 248         int searching = 1;
 249         char searchname[SPCS_S_MAXMODNAME];
 250         char line[SPCS_S_MAXLINE];
 251         char tline[SPCS_S_MAXLINE];
 252         char *p, *p2;
 253 
 254         (void) strcpy(help_path, dirname(argv[0]));
 255         (void) strcat(help_path, "/errgen.help");
 256         if ((argc == 1) || ((argc == 2) && (strcmp(argv[1], "-h") == 0))) {
 257                 help();
 258                 exit(0);
 259         }
 260 
 261         if (argc != 3)
 262                 fatal("Bad number of arguments");
 263 
 264         p = argv[2];
 265         p2 = modname;
 266 
 267         while (*p)
 268                 *p2++ = toupper(*p++);
 269         *p2 = 0;
 270 
 271         switch (argv[1][1]) {
 272         case 'c':
 273                 mode = C_MODE;
 274                 break;
 275         case 'j':
 276                 mode = J_MODE;
 277                 break;
 278         case 'e':
 279                 mode = E_MODE;
 280                 break;
 281         case 'm':
 282                 mode = M_MODE;
 283                 break;
 284         case 't':
 285                 mode = T_MODE;
 286                 break;
 287         case 'x':
 288                 mode = X_MODE;
 289                 break;
 290         default:
 291                 fatal("Unknown option switch");
 292         }
 293 
 294         if (strcmp(modname, "DSW") == 0) {
 295                 (void) strcpy(searchname, "II");
 296         } else if (strcmp(modname, "RDC") == 0) {
 297                 (void) strcpy(searchname, "SNDR");
 298         } else if (strcmp(modname, "SDCTL") == 0) {
 299                 (void) strcpy(searchname, "NSCTL");
 300         } else {
 301                 (void) strcpy(searchname, modname);
 302         }
 303 
 304         i = 0;
 305         do {
 306                 if (strcmp(module_names[i++], searchname) == 0) {
 307                         searching = 0;
 308                         mod_number = i - 1;
 309                         break;
 310                 }
 311         } while (module_names[i]);
 312 
 313         if (searching) {
 314                 if (i != SPCS_M_MAX)
 315                         (void) fprintf(stderr,
 316                         "NULL in module_names before SPCS_M_MAX\n");
 317                 fatal("Undefined module name");
 318         }
 319 
 320         do_preamble();
 321 
 322         while (!feof(stdin)) {
 323                 (void) fgets(line, SPCS_S_MAXLINE, stdin);
 324                 if (feof(stdin)) {
 325                         if (count == 0)
 326                                 fatal("errgen file empty");
 327 
 328                         do_trailer();
 329                         exit(0);
 330                 }
 331                 line[strlen(line)-1] = 0;
 332                 if ((strlen(line) != 0) && (line[0] != '#')) {
 333                     (void) strcpy(tline, line);
 334                     p = strchr(tline, ' ');
 335                     if (p == NULL) {
 336                         (void) fprintf(stderr,
 337                                     "blank separator missing at line: %d\n",
 338                                             count);
 339                             fatal("");
 340                     }
 341                     *p = 0;
 342                     if (strlen(p) > SPCS_S_MAXKEY) {
 343                             (void) fprintf(stderr,
 344                             "message label too long at line: %d\n", count);
 345                             fatal("");
 346                     }
 347                     (void) strcpy(key, tline);
 348                     if (strlen(key) == 0) {
 349                             (void) fprintf(stderr,
 350                                     "leading blank at line: %d\n", count);
 351                             fatal("");
 352                     }
 353                     p++;
 354                     if (*p != '=') {
 355                             (void) fprintf(stderr,
 356                                     "= separator missing at line: %d\n", count);
 357                             fatal("");
 358                     }
 359                     p++;
 360                     if (*p != ' ') {
 361                             (void) fprintf(stderr,
 362                                 "blank separator missing at line: %d\n", count);
 363                             fatal("");
 364                     }
 365                     p++;
 366                     if (! *p) {
 367                             (void) fprintf(stderr,
 368                                     "msg text missing at line:%d\n", count);
 369                             fatal("");
 370                     }
 371                     (void) strcpy(text, p);
 372 
 373                     do_line();
 374                     count++;
 375                 }
 376         }
 377 
 378         return (0);
 379 }