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.
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.
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]
22 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
24 * sgsmsg generates several message files from an input template file. Messages
25 * are constructed for use with gettext(3i) - the default - or catgets(3c). The
28 * msg.h a header file containing definitions for each message. The -h
29 * option triggers the creation of these definitions and specifies
32 * msg.c a data array of message strings. The msg.h definitions are
33 * offsets into this array. The -d option triggers the creation of
34 * these definitions and specifies the name to use.
36 * messages a message file suitable for catgets(3c) or gettext(3i) use. The
37 * -m option triggers this output and specifies the filename to be
40 * The template file is processed based on the first character of each line:
42 * # or $ entries are copied (as is) to the message file (messages).
44 * @ token(s) entries are translated. Two translations are possible dependent
45 * on whether one or more tokens are supplied:
47 * A single token is interpreted as one of two reserved message
48 * output indicators, or a message identifier. The reserved output
49 * indicator _START_ enables output to the message file - Note that
50 * the occurance of any other @ token will also enable message
51 * output. The reserved output indicator _END_ disables output to
52 * the message file. The use of these two indicators provides for
53 * only those message strings that require translation to be output
54 * to the message file.
56 * Besides the reserved output indicators, a single token is taken
57 * to be a message identifier which will be subsituted for a
58 * `setid' for catgets(3c) output, or a `domain' name for
59 * gettext(3i) output. This value is determine by substituting the
60 * token for the associated definition found in the message
61 * identifier file (specified with the -i option).
63 * Multiple tokens are taken to be a message definition followed by
64 * the associated message string. The message string is copied to
65 * the data array being built in msg.c. The index into this array
66 * becomes the `message' identifier created in the msg.h file.
77 #include <sys/param.h>
80 #include <_string_table.h>
83 * Define any error message strings.
86 * Errmsg_malt
= "sgsmsg: file %s: line %d: malformed input "
88 * Errmsg_nmem
= "sgsmsg: memory allocation failed: %s\n",
89 * Errmsg_opne
= "sgsmsg: file %s: open failed: %s\n",
90 * Errmsg_wrte
= "sgsmsg: file %s: write failed: %s\n",
91 * Errmsg_read
= "sgsmsg: file %s: read failed %s\n",
92 * Errmsg_stnw
= "sgsmsg: st_new(): failed: %s\n",
93 * Errmsg_stin
= "sgsmsg: Str_tbl insert failed: %s\n",
94 * Errmsg_mnfn
= "sgsmsg: message not found in Str_tbl: %s\n",
95 * Errmsg_use
= "usage: sgsmsg [-clv] [-d mesgdata] [-h mesgdefs] "
96 "[-m messages] [-n name] [-i mesgident] file ...\n";
99 * Define all output filenames and associated descriptors.
101 static FILE *fddefs
, *fddata
, *fdmsgs
, *fdmids
, *fddesc
;
102 static char *fldefs
, *fldata
, *flmsgs
, *flmids
, *fldesc
;
104 static char fllint
[MAXPATHLEN
];
106 static uint_t vflag
; /* verbose flag */
107 static Str_tbl
*stp
; /* string table */
110 * Define any default strings.
113 *nmlint
= "/tmp/sgsmsg.lint",
114 *interface
= "sgs_msg",
119 * Define any default flags and data items.
121 static int cflag
= 0, lflag
= 0, prtmsgs
= 0, line
, ptr
= 1, msgid
= 0;
122 static char *mesgid
= 0, *setid
= 0, *domain
= 0;
124 typedef struct msg_string
{
127 struct msg_string
*ms_next
;
130 static msg_string
*msg_head
;
131 static msg_string
*msg_tail
;
134 * message_append() is responsible for both inserting strings into
135 * the master Str_tbl as well as maintaining a list of the
136 * DEFINITIONS associated with each string.
138 * The list of strings is traversed at the end once the full
139 * Str_tbl has been constructed - and string offsets can be
143 message_append(const char *defn
, const char *message
)
146 if ((msg
= calloc(sizeof (msg_string
), 1)) == 0) {
147 (void) fprintf(stderr
, Errmsg_nmem
, strerror(errno
));
152 * Initialize the string table.
154 if ((stp
== 0) && ((stp
= st_new(FLG_STNEW_COMPRESS
)) == NULL
)) {
155 (void) fprintf(stderr
, Errmsg_stnw
, strerror(errno
));
160 if ((msg
->ms_defn
= strdup(defn
)) == 0) {
161 (void) fprintf(stderr
, Errmsg_nmem
, strerror(errno
));
164 if ((msg
->ms_message
= strdup(message
)) == 0) {
165 (void) fprintf(stderr
, Errmsg_nmem
, strerror(errno
));
169 if (st_insert(stp
, msg
->ms_message
) == -1) {
170 (void) fprintf(stderr
, Errmsg_stin
,
176 msg_head
= msg_tail
= msg
;
179 msg_tail
->ms_next
= msg
;
184 * Initialize a setid value. Given a setid definition determine its numeric
185 * value from the specified message identifier file (specified with the -i
186 * option). Return a pointer to the numeric string.
191 char *buffer
, *token
, *_mesgid
= 0, *_setid
= 0, *_domain
= 0;
194 * If we're being asked to interpret a message id but the user didn't
195 * provide the required message identifier file (-i option) we're in
199 (void) fprintf(stderr
, "sgsmsg: file %s: line %d: mesgid %s: "
200 "unable to process mesgid\n\t"
201 "no message identifier file specified "
202 "(see -i option)\n", fldesc
, line
, id
);
206 if ((buffer
= malloc(LINE_MAX
)) == 0) {
207 (void) fprintf(stderr
, Errmsg_nmem
, strerror(errno
));
212 * Read the message identifier file and locate the required mesgid.
215 while (fgets(buffer
, LINE_MAX
, fdmids
) != NULL
) {
216 if ((token
= strstr(buffer
, id
)) == NULL
)
220 * Establish individual strings for the mesgid, setid and domain
224 while (!(isspace(*token
)))
228 while (isspace(*token
))
231 while (!(isspace(*token
)))
235 while (isspace(*token
))
238 while (!(isspace(*token
)))
245 * Did we find a match?
247 if ((_mesgid
== 0) || (_setid
== 0) || (_domain
== 0)) {
248 (void) fprintf(stderr
, "sgsmsg: file %s: line %d: mesgid %s: "
249 "unable to process mesgid\n\t"
250 "identifier does not exist in file %s\n",
251 fldesc
, line
, id
, flmids
);
256 * Have we been here before?
261 * If we're being asked to process more than one mesgid
262 * warn the user that only one mesgid can be used for
263 * the catgets(3c) call.
265 (void) fprintf(stderr
, "sgsmsg: file %s: line %d: "
266 "setid %s: warning: multiple mesgids "
268 "last setting used in messaging code\n",
278 * Generate the message file output (insure output flag is enabled).
282 if (fdmsgs
&& (prtmsgs
== 1)) {
284 if (fprintf(fdmsgs
, "$quote \"\n$set %s\n",
286 (void) fprintf(stderr
, Errmsg_wrte
, flmsgs
,
291 if (fprintf(fdmsgs
, "domain\t\"%s\"\n", domain
) < 0) {
292 (void) fprintf(stderr
, Errmsg_wrte
, flmsgs
,
300 * For catgets(3c) output generate a setid definition in the message
303 if (fddefs
&& (cflag
== 1) &&
304 (fprintf(fddefs
, "#define\t%s\t%s\n\n", mesgid
, setid
) < 0)) {
305 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
313 * Dump contents of String Table to standard out
316 dump_stringtab(Str_tbl
*stp
)
320 if ((stp
->st_flags
& FLG_STTAB_COMPRESS
) == 0) {
321 (void) printf("string table full size: %ld: uncompressed\n",
322 stp
->st_fullstrsize
);
326 (void) printf("string table full size: %ld compressed down to: %ld\n\n",
327 stp
->st_fullstrsize
, stp
->st_strsize
);
328 (void) printf("string table compression information [%d buckets]:\n",
331 for (cnt
= 0; cnt
< stp
->st_hbckcnt
; cnt
++) {
332 Str_hash
*sthash
= stp
->st_hashbcks
[cnt
];
337 (void) printf(" bucket: [%d]\n", cnt
);
340 size_t stroff
= sthash
->hi_mstr
->sm_strlen
-
344 (void) printf(" [%ld]: '%s' <master>\n",
345 sthash
->hi_refcnt
, sthash
->hi_mstr
->sm_str
);
347 (void) printf(" [%ld]: '%s' <suffix of: "
348 "'%s'>\n", sthash
->hi_refcnt
,
349 &sthash
->hi_mstr
->sm_str
[stroff
],
350 sthash
->hi_mstr
->sm_str
);
352 sthash
= sthash
->hi_next
;
358 * Initialize the message definition header file stream.
363 static char guard
[FILENAME_MAX
+ 6];
365 const char *iptr
, *_ptr
;
368 * Establish a header guard name using the files basename.
370 for (iptr
= 0, _ptr
= fldefs
; _ptr
&& (*_ptr
!= '\0'); _ptr
++) {
378 for (*optr
++ = '_'; iptr
&& (*iptr
!= '\0'); iptr
++, optr
++) {
386 *optr
= toupper(*iptr
);
389 if (fprintf(fddefs
, "#ifndef\t%s\n#define\t%s\n\n", guard
, guard
) < 0) {
390 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
394 if (fprintf(fddefs
, "#include <sgsmsg.h>\t/* Msg typedef */\n\n") < 0) {
395 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
399 if (fprintf(fddefs
, "#ifndef\t__lint\n\n") < 0) {
400 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
405 * The MSG_SGS_ARRAY_NAME macro supplies a generic way to
406 * reference the string table regardless of its name.
408 if (fprintf(fddefs
, "#define\tMSG_SGS_LOCAL_ARRAY\t__%s\n\n",
410 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
415 * If the associated data array is global define a prototype.
416 * Define a macro to access the array elements.
419 if (fprintf(fddefs
, "extern\tconst char\t__%s[];\n\n",
421 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
,
427 "#define\tMSG_ORIG_STRTAB(_x, _s)\t&_s[_x]\n\n") < 0) {
428 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
432 "#define\tMSG_ORIG(x)\tMSG_ORIG_STRTAB(x, __%s)\n\n",
434 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
439 * Generate a prototype to access the associated data array.
441 if (fprintf(fddefs
, "extern\tconst char *\t_%s(Msg);\n\n",
443 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
446 if (fprintf(fddefs
, "#define\tMSG_INTL(x)\t_%s(x)\n\n",
448 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
457 * Finish the message definition header file.
462 if (fprintf(fddefs
, "\n#else\t/* __lint */\n\n") < 0) {
463 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
467 if (fprintf(fddefs
, "extern\tconst char *\t_%s(Msg);\n\n",
469 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
473 if (fprintf(fddefs
, "#ifndef MSG_SGS_LOCAL_ARRAY\n"
474 "#define\tMSG_SGS_LOCAL_ARRAY\t\"\"\n#endif\n\n") < 0) {
475 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
480 if (fprintf(fddefs
, "extern\tconst char\t__%s[];\n\n",
482 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
,
489 "#define MSG_ORIG_STRTAB(_x, _s)\t_x\n"
490 "#define MSG_ORIG(x)\tx\n#define MSG_INTL(x)\tx\n") < 0) {
491 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
496 * Provide a way to get the array and function declarations above
497 * without also getting the actual messages. This is useful in
498 * our lintsup.c files that include more than one message header.
499 * lintsup doesn't need the actual messages, and this prevents
500 * macro name collisions.
502 if (fprintf(fddefs
, "\n#ifndef LINTSUP_SUPPRESS_STRINGS\n") < 0) {
503 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
508 * Copy the temporary lint defs file into the new header.
514 size
= ftell(fdlint
);
515 (void) rewind(fdlint
);
517 if ((buf
= malloc(size
)) == 0) {
518 (void) fprintf(stderr
, Errmsg_nmem
, strerror(errno
));
521 if (fread(buf
, size
, 1, fdlint
) == 0) {
522 (void) fprintf(stderr
, Errmsg_read
, fllint
,
526 if (fwrite(buf
, size
, 1, fddefs
) == 0) {
527 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
,
534 if (fprintf(fddefs
, "\n#endif\t/* LINTSUP_SUPPRESS_STRINGS */\n") < 0) {
535 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
539 if (fprintf(fddefs
, "\n#endif\t/* __lint */\n") < 0) {
540 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
544 if (fprintf(fddefs
, "\n#endif\n") < 0) {
545 (void) fprintf(stderr
, Errmsg_wrte
, fldefs
, strerror(errno
));
553 * The entire messaging file has been scanned - and all strings have been
554 * inserted into the string_table. We can now walk the message queue
555 * and create the '#define <DEFN>' for each string - with the strings
556 * assigned offset into the string_table.
565 stbufsize
= st_getstrtab_sz(stp
);
566 if ((stbuf
= malloc(stbufsize
)) == 0) {
567 (void) fprintf(stderr
, Errmsg_nmem
, strerror(errno
));
570 (void) st_setstrbuf(stp
, stbuf
, stbufsize
);
571 for (msg
= msg_head
; msg
; msg
= msg
->ms_next
) {
573 if ((st_setstring(stp
, msg
->ms_message
, &stoff
)) == -1) {
574 (void) fprintf(stderr
, Errmsg_mnfn
, msg
->ms_message
);
577 if (fprintf(fddefs
, "\n#define\t%s\t%ld\n",
578 msg
->ms_defn
, stoff
) < 0) {
579 (void) fprintf(stderr
, Errmsg_wrte
,
580 fldefs
, strerror(errno
));
583 if (fddefs
&& fprintf(fddefs
, "#define\t%s_SIZE\t%d\n",
584 msg
->ms_defn
, strlen(msg
->ms_message
)) < 0) {
585 (void) fprintf(stderr
, Errmsg_wrte
,
586 fldefs
, strerror(errno
));
595 * Finish off the data structure definition.
606 stbufsize
= st_getstrtab_sz(stp
);
607 stbuf
= st_getstrbuf(stp
);
612 * Determine from the local flag whether the data declaration should
616 fmtstr
= (const char *)"static const";
618 fmtstr
= (const char *)"const";
620 if (fprintf(fddata
, "\n%s char __%s[%ld] = { ",
621 fmtstr
, interface
, stbufsize
) < 0) {
622 (void) fprintf(stderr
, Errmsg_wrte
, fldata
, strerror(errno
));
626 for (ndx
= 0; ndx
< (stbufsize
- 1); ndx
++) {
628 if (fddata
&& fprintf(fddata
,
629 "\n/* %4ld */ 0x%.2x,", ndx
,
630 (unsigned char)stbuf
[ndx
]) < 0) {
631 (void) fprintf(stderr
, Errmsg_wrte
,
632 fldata
, strerror(errno
));
636 if (fddata
&& fprintf(fddata
, " 0x%.2x,",
637 (unsigned char)stbuf
[ndx
]) < 0) {
638 (void) fprintf(stderr
, Errmsg_wrte
,
639 fldata
, strerror(errno
));
649 fmtstr
= "\n\t0x%.2x };\n";
651 fmtstr
= " 0x%.2x };\n";
653 if (fprintf(fddata
, fmtstr
, (unsigned char)stbuf
[stbufsize
- 1]) < 0) {
654 (void) fprintf(stderr
, Errmsg_wrte
, fldata
, strerror(errno
));
664 char buffer
[LINE_MAX
], * token
;
670 if ((token_buffer
= malloc(LINE_MAX
)) == 0) {
671 (void) fprintf(stderr
, Errmsg_nmem
, strerror(errno
));
678 while ((token
= fgets(buffer
, LINE_MAX
, fddesc
)) != NULL
) {
679 char defn
[PATH_MAX
], * _defn
, * str
;
685 (void) fprintf(stderr
, Errmsg_malt
, fldesc
,
691 * If a msgid has been output a msgstr must follow
692 * before we digest the new token. A msgid is only set
693 * if fdmsgs is in use.
697 if (fprintf(fdmsgs
, "msgstr\t\"\"\n") < 0) {
698 (void) fprintf(stderr
, Errmsg_wrte
,
699 flmsgs
, strerror(errno
));
705 * Pass lines directly through to the output message
708 if (fdmsgs
&& (prtmsgs
== 1)) {
716 if (fprintf(fdmsgs
, "%c%s", comment
,
718 (void) fprintf(stderr
, Errmsg_wrte
,
719 flmsgs
, strerror(errno
));
727 (void) fprintf(stderr
, Errmsg_malt
, fldesc
,
733 * If a msgid has been output a msgstr must follow
734 * before we digest the new token.
738 if (fprintf(fdmsgs
, "msgstr\t\"\"\n") < 0) {
739 (void) fprintf(stderr
, Errmsg_wrte
,
740 flmsgs
, strerror(errno
));
746 * Determine whether we have one or more tokens.
749 while (isspace(*token
)) /* rid any whitespace */
751 _defn
= token
; /* definition start */
752 while (!(isspace(*token
)))
756 while (isspace(*token
)) /* rid any whitespace */
760 * Determine whether the single token is one of the
761 * reserved message output delimiters otherwise
762 * translate it as a message identifier.
765 if (strcmp(_defn
, start
) == 0)
767 else if (strcmp(_defn
, end
) == 0)
769 else if (getmesgid(_defn
) == 1)
775 * Multiple tokens are translated by taking the first
776 * token as the message definition, and the rest of the
777 * line as the message itself. A message line ending
778 * with an escape ('\') is expected to be continued on
783 if (fdmsgs
&& (prtmsgs
== 1)) {
785 * For catgets(3c) make sure a message
786 * identifier has been established (this is
787 * normally a domain for gettext(3i), but for
788 * sgsmsg use this could be argued as being
789 * redundent). Also make sure that the message
790 * definitions haven't exceeeded the maximum
791 * value allowed by gencat(1) before generating
792 * any message file entries.
796 (void) fprintf(stderr
, "file "
797 "%s: no message identifier "
798 "has been established\n",
802 if (ptr
> NL_MSGMAX
) {
803 (void) fprintf(stderr
, "file "
804 "%s: message definition "
805 "(%d) exceeds allowable "
806 "limit (NL_MSGMAX)\n",
813 * For catgets(3c) write the definition and the
814 * message string to the message file. For
815 * gettext(3i) write the message string as a
816 * mesgid - indicate a mesgid has been output
817 * so that a msgstr can follow.
820 if (fprintf(fdmsgs
, "%d\t%s", ptr
,
822 (void) fprintf(stderr
,
828 if (fprintf(fdmsgs
, "msgid\t\"") < 0) {
829 (void) fprintf(stderr
,
839 * The message itself is a quoted string as this makes
840 * embedding spaces at the start (or the end) of the
844 (void) fprintf(stderr
, Errmsg_malt
, fldesc
,
849 (void) strcpy(defn
, _defn
);
852 * Write the tag to the lint definitions.
855 if (fprintf(fdlint
, "\n#define\t%s\t",
857 (void) fprintf(stderr
, Errmsg_wrte
,
858 fllint
, strerror(errno
));
866 * Write each character of the message string to the
867 * data array. Translate any escaped characters - use
868 * the same specially recognized characters as defined
874 (fprintf(fdlint
, "%c", *token
) < 0)) {
875 (void) fprintf(stderr
, Errmsg_wrte
,
876 fllint
, strerror(errno
));
884 if ((*token
== '\\') && (escape
== 0)) {
886 if (fdlint
&& (*(token
+ 1) != '\n') &&
887 fprintf(fdlint
, "%c", *token
) < 0) {
888 (void) fprintf(stderr
,
899 else if (*token
== 't')
901 else if (*token
== 'v')
903 else if (*token
== 'b')
905 else if (*token
== 'f')
907 else if (*token
== '\\')
909 else if (*token
== '"')
911 else if (*token
== '\n')
916 if (fdmsgs
&& (prtmsgs
== 1) &&
917 (fprintf(fdmsgs
, "\\") < 0)) {
918 (void) fprintf(stderr
,
925 * If this is the trailing quote then
926 * thats the last of the message string.
927 * Eat up any remaining white space and
928 * unless an escape character is found
929 * terminate the data string with a 0.
933 if (fdlint
&& (fprintf(fdlint
,
934 "%c", *token
) < 0)) {
935 (void) fprintf(stderr
,
941 if (fdmsgs
&& (prtmsgs
== 1) &&
942 (fprintf(fdmsgs
, "%c",
944 (void) fprintf(stderr
,
960 if (fdmsgs
&& (prtmsgs
== 1) &&
961 (fprintf(fdmsgs
, "%c", *token
) < 0)) {
962 (void) fprintf(stderr
, Errmsg_wrte
,
963 flmsgs
, strerror(errno
));
967 if (fdlint
&& fprintf(fdlint
,
969 (void) fprintf(stderr
, Errmsg_wrte
,
970 fllint
, strerror(errno
));
974 if (len
>= bufsize
) {
976 if ((token_buffer
= realloc(
977 token_buffer
, bufsize
)) == 0) {
978 (void) fprintf(stderr
,
984 token_buffer
[len
] = _token
;
985 ptr
++, token
++, len
++;
993 * After the complete message string has been processed
994 * (including its continuation beyond one line), create
995 * a string size definition.
998 const char *form
= "#define\t%s_SIZE\t%d\n";
1000 token_buffer
[len
] = '\0';
1002 message_append(defn
, token_buffer
);
1004 if (fdlint
&& fprintf(fdlint
, form
, defn
,
1006 (void) fprintf(stderr
, Errmsg_wrte
,
1007 fllint
, strerror(errno
));
1015 * Empty lines are passed through to the message file.
1017 while (isspace(*token
))
1021 if (msgid
|| (fdmsgs
&& (prtmsgs
== 1))) {
1023 * If a msgid has been output a msgstr
1024 * must follow before we digest the new
1029 str
= "msgstr\t\"\"\n\n";
1033 if (fprintf(fdmsgs
, str
) < 0) {
1034 (void) fprintf(stderr
,
1035 Errmsg_wrte
, flmsgs
,
1044 * If an escape is in effect then any tokens are taken
1045 * to be message continuations.
1052 (void) fprintf(stderr
, "file %s: line %d: invalid "
1053 "input does not start with #, $ or @\n", fldesc
,
1066 main(int argc
, char ** argv
)
1069 while ((line
= getopt(argc
, argv
, "cd:h:lm:n:i:v")) != EOF
) {
1071 case 'c': /* catgets instead of gettext */
1074 case 'd': /* new message data filename */
1075 fldata
= optarg
; /* (msg.c is default) */
1077 case 'h': /* new message defs filename */
1078 fldefs
= optarg
; /* (msg.h is default) */
1080 case 'i': /* input message ids from */
1081 flmids
= optarg
; /* from this file */
1083 case 'l': /* define message data arrays */
1084 lflag
= 1; /* to be local (static) */
1086 case 'm': /* generate message database */
1087 flmsgs
= optarg
; /* to this file */
1089 case 'n': /* new data array and func */
1090 interface
= optarg
; /* name (msg is default) */
1093 vflag
= 1; /* set verbose flag */
1096 (void) fprintf(stderr
, Errmsg_use
, argv
[0]);
1104 * Validate the we have been given at least one input file.
1106 if ((argc
- optind
) < 1) {
1107 (void) fprintf(stderr
, Errmsg_use
);
1112 * Open all the required output files.
1115 if ((fddefs
= fopen(fldefs
, "w+")) == NULL
) {
1116 (void) fprintf(stderr
, Errmsg_opne
, fldefs
,
1122 if (fldefs
&& (strcmp(fldefs
, fldata
) == 0))
1124 else if ((fddata
= fopen(fldata
, "w+")) == NULL
) {
1125 (void) fprintf(stderr
, Errmsg_opne
, fldata
,
1130 if (fddefs
&& fddata
) {
1131 (void) sprintf(fllint
, "%s.%d.XXXXXX", nmlint
, (int)getpid());
1132 if ((mkstemp(fllint
) == -1) ||
1133 ((fdlint
= fopen(fllint
, "w+")) == NULL
)) {
1134 (void) fprintf(stderr
, Errmsg_opne
, fllint
,
1140 if ((fdmsgs
= fopen(flmsgs
, "w+")) == NULL
) {
1141 (void) fprintf(stderr
, Errmsg_opne
, flmsgs
,
1147 if ((fdmids
= fopen(flmids
, "r")) == NULL
) {
1148 (void) fprintf(stderr
, Errmsg_opne
, flmids
,
1156 * Initialize the message definition and message data streams.
1164 * Read the input message file, and for each line process accordingly.
1166 for (; optind
< argc
; optind
++) {
1169 fldesc
= argv
[optind
];
1171 if ((fddesc
= fopen(fldesc
, "r")) == NULL
) {
1172 (void) fprintf(stderr
, Errmsg_opne
, fldesc
,
1177 (void) fclose(fddesc
);
1184 * If a msgid has been output a msgstr must follow before we end the
1189 if (fprintf(fdmsgs
, "msgstr\t\"\"\n") < 0) {
1190 (void) fprintf(stderr
, Errmsg_wrte
, flmsgs
,
1197 (void) fclose(fdmids
);
1199 (void) fclose(fdmsgs
);
1207 * Finish off any generated data and header file.
1219 dump_stringtab(stp
);
1222 * Close up everything and go home.
1225 (void) fclose(fddata
);
1226 if (fddefs
&& (fddefs
!= fddata
))
1227 (void) fclose(fddefs
);
1228 if (fddefs
&& fddata
) {
1229 (void) fclose(fdlint
);
1230 (void) unlink(fllint
);