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 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
39 #include <sys/types.h>
44 #define SET_TOKEN "$set"
45 #define DELSET_TOKEN "$delset"
46 #define QUOTE_TOKEN "$quote"
48 #define SkipSpace(s) while (*(s) == ' ' || *(s) == '\t') s++
50 extern char *program
; /* from main.c */
51 extern char *mctag
; /* from main.c */
52 extern char *sctag
; /* from main.c */
53 extern char *premsg
; /* from main.c */
54 extern char *sufmsg
; /* from main.c */
55 extern int suppress_error
; /* from main.c */
56 extern void warning(char *); /* from genmsg.l */
58 typedef struct _SetID
*SetID
;
59 typedef struct _MsgID
*MsgID
;
61 typedef struct _SetID SetIDRec
;
69 typedef struct _MsgID MsgIDRec
;
81 /* Top pointer of the setid list. */
82 static SetID setid_top
;
84 /* comment for messages. */
85 static char *msg_comment
;
87 /* comment for set numbers. */
88 static char *set_comment
;
90 /* List of set number's maximum message numbers. */
91 static int msgid_table
[NL_SETMAX
+1];
93 /* Quote character to surround messages. */
94 static char quote
= QUOTE
;
96 /* Internal functions. */
97 static void add_msgid(SetID
, int, char *, char *, int, int);
98 static void add_setid(int, int, char *, char *, int, int);
99 static SetID
lookup_setid(int);
100 static MsgID
lookup_msgid(SetID
, int, char *, char *, int);
101 static void print_prefix(FILE *, char *, int, char *);
102 static int is_bs_terminated(char *);
103 static char *ustrdup(char *);
104 static void makeup_msg(char **);
107 add_msg(int setid
, int msgid
, char *msg
, char *file
, int line
, int no_write
)
111 if (si
= lookup_setid(setid
)) {
112 if (lookup_msgid(si
, msgid
, msg
, file
, line
)) {
113 return; /* we already have the one. */
115 add_msgid(si
, msgid
, msg
, file
, line
, no_write
);
118 add_setid(setid
, msgid
, msg
, file
, line
, no_write
);
123 is_writable(char *file
)
127 if (stat(file
, &buf
) == -1)
130 if (access(file
, W_OK
) == 0)
137 write_msgfile(char *file
)
140 SetID si
= setid_top
;
144 if (is_writable(file
) == FALSE
) {
145 prg_err(gettext("cannot create \"%s\": permission denied"),
150 if (IsActiveMode(AppendMode
)) {
154 if ((fp
= fopen(file
, mode
)) == NULL
) {
155 prg_err(gettext("cannot create \"%s\""), file
);
166 /* AppendMode is already turned off if the file doesn't exist. */
167 if (!IsActiveMode(AppendMode
)) {
168 (void) fprintf(fp
, "\n$quote %s\n\n", pquote
);
175 char msg
[NL_TEXTMAX
+32]; /* 32 is some other stuff. */
181 if (is_set
== FALSE
) {
183 !IsActiveMode(BackCommentMode
)) {
184 (void) fprintf(fp
, "\n");
185 print_prefix(fp
, "$ ", TRUE
,
187 (void) fprintf(fp
, "$set\t%d\n",
190 (void) fprintf(fp
, "\n$set\t%d\n",
194 IsActiveMode(BackCommentMode
)) {
195 print_prefix(fp
, "$ ", TRUE
,
198 (void) fprintf(fp
, "\n");
202 makeup_msg(&(mi
->msg
));
204 (void) snprintf(msg
, sizeof (msg
), "%d\t%s%s%s\n",
205 mi
->id
, pquote
, mi
->msg
, pquote
);
207 if (!IsActiveMode(BackCommentMode
)) {
208 if (mi
->line
&& mi
->file
&&
209 IsActiveMode(LineInfoMode
)) {
211 "$ File:%s, line:%d\n",
212 basename(mi
->file
), mi
->line
);
216 print_prefix(fp
, "$ ", TRUE
,
220 if (IsActiveMode(DoubleLineMode
)) {
221 print_prefix(fp
, "$ ", FALSE
, msg
);
225 (void) fprintf(fp
, "%s", msg
);
227 if (IsActiveMode(BackCommentMode
)) {
228 if (mi
->line
&& mi
->file
&&
229 IsActiveMode(LineInfoMode
)) {
231 "$ File:%s, line:%d\n",
232 basename(mi
->file
), mi
->line
);
236 print_prefix(fp
, "$ ", TRUE
,
240 if (IsActiveMode(DoubleLineMode
)) {
241 print_prefix(fp
, "$ ", FALSE
, msg
);
245 (void) fprintf(fp
, "\n");
258 SetID si
= setid_top
;
269 lookup_msgid(SetID si
, int msgid
, char *msg
, char *file
, int line
)
273 if (mi
->id
== msgid
) {
274 /* same setid & msgid, but different msg. */
275 if (strcmp(mi
->msg
, msg
)) {
276 src_err(file
, line
, gettext(
277 "multiple messages: set number %d, message number %d\n"
278 " current : \"%s\"\n"
279 " previous: \"%s\" : \"%s\", line %d"),
282 mi
->msg
, mi
->file
, mi
->line
);
292 add_msgid(SetID si
, int msgid
, char *msg
, char *file
, int line
, int no_write
)
294 MsgID mi
= si
->top
, newmi
, prev
= NULL
;
295 int len
= strlen(msg
);
298 src_err(file
, line
, gettext("improper message number: %d"),
303 if (msgid
> NL_MSGMAX
) {
304 src_err(file
, line
, gettext("too large message number: %d"),
309 if (len
> NL_TEXTMAX
) {
310 src_err(file
, line
, gettext("too long message text"));
315 if (mi
->id
> msgid
) {
322 if ((newmi
= malloc(sizeof (MsgIDRec
))) == NULL
) {
323 prg_err(gettext("fatal: out of memory"));
327 newmi
->no_write
= no_write
;
329 newmi
->msg
= ustrdup(msg
);
330 newmi
->file
= ustrdup(file
);
335 newmi
->comment
= ustrdup(msg_comment
);
339 newmi
->comment
= NULL
;
350 add_setid(int setid
, int msgid
, char *msg
, char *file
, int line
, int no_write
)
352 SetID si
= setid_top
, newsi
, prev
= NULL
;
355 if (si
->id
> setid
) {
362 if ((newsi
= malloc(sizeof (SetIDRec
))) == NULL
) {
363 prg_err(gettext("fatal: out of memory"));
372 newsi
->comment
= ustrdup(set_comment
);
376 newsi
->comment
= NULL
;
385 add_msgid(newsi
, msgid
, msg
, file
, line
, no_write
);
389 print_prefix(FILE *fp
, char *prefix
, int rm_blank
, char *str
)
391 (void) fprintf(fp
, "%s", prefix
);
393 (void) fputc(*str
, fp
);
394 if (*str
== '\n' && *(str
+1) != '\0') {
395 (void) fprintf(fp
, "%s", prefix
);
396 if (rm_blank
== TRUE
) {
404 if (*(str
-1) != '\n') {
405 (void) fputc('\n', fp
);
410 read_projfile(char *file
)
419 if ((fp
= fopen(file
, "r")) == NULL
) {
423 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
429 if (*p
== '#' || *p
== '\n') {
433 n
= sscanf(p
, "%d %d", &setid
, &msgid
);
436 if (setid
> NL_SETMAX
) {
437 prg_err(gettext("%s: too large set number: %d"),
441 msgid_table
[setid
] = msgid
;
444 "warning: %s: missing or invalid entry"), file
);
454 write_projfile(char *file
)
459 if (is_writable(file
) == FALSE
) {
460 prg_err(gettext("cannot create \"%s\": permission denied"),
465 if ((fp
= fopen(file
, "w")) == NULL
) {
466 prg_err(gettext("cannot create \"%s\""), file
);
470 for (i
= 1; i
<= NL_SETMAX
; i
++) {
471 if (msgid_table
[i
] > 0) {
475 if (IsActiveMode(SetCommentMode
) &&
476 (si
= lookup_setid(i
)) && si
->comment
) {
480 if (com
&& !IsActiveMode(BackCommentMode
)) {
481 print_prefix(fp
, "# ", TRUE
, com
);
484 (void) fprintf(fp
, "%d\t%d\n", i
, msgid_table
[i
]);
486 if (com
&& IsActiveMode(BackCommentMode
)) {
487 print_prefix(fp
, "# ", TRUE
, com
);
496 get_msgid(char *file
, int line
, int setid
, char *str
)
498 SetID si
= setid_top
;
499 int id
= msgid_table
[setid
];
502 if (si
->id
== setid
) {
505 if (strcmp(mi
->msg
, str
) == 0) {
516 if (id
> NL_MSGMAX
) {
518 gettext("run out of message number in set number: %d"),
523 return (msgid_table
[setid
] = id
);
527 set_msgid(int setid
, int msgid
)
529 if (msgid_table
[setid
] < msgid
) {
530 msgid_table
[setid
] = msgid
;
535 add_comment(Mode mode
, char *str
)
537 char *tag
= (mode
== MsgCommentMode
) ? mctag
: sctag
;
538 char **comment
= (mode
== MsgCommentMode
)
539 ? &msg_comment
: &set_comment
;
541 if (strstr(str
, tag
) == NULL
) {
549 *comment
= ustrdup(str
);
553 read_msgfile(char *file
)
559 int setid
= 0, unsetid
= -1, msgid
= 0;
562 if ((fp
= fopen(file
, "r")) == NULL
) {
563 prg_err(gettext("cannot open \"%s\""), file
);
564 ResetActiveMode(AppendMode
);
568 if (stat(file
, &buf
) == -1 && buf
.st_size
== 0) {
569 ResetActiveMode(AppendMode
);
579 char msg
[NL_TEXTMAX
];
581 if (fgets(buf
, sizeof (buf
), fp
) == NULL
) {
591 if ((*ptr
== '$' && (*(ptr
+1) == ' ' || *(ptr
+1) == '\t')) ||
592 ((*ptr
== '\n') && inmsg
== FALSE
)) {
597 if (strncmp(ptr
, SET_TOKEN
, sizeof (SET_TOKEN
) - 1) == 0) {
598 if (sscanf(ptr
, "%*s %d", &setid
) != 1) {
603 } else if (strncmp(ptr
, DELSET_TOKEN
,
604 sizeof (DELSET_TOKEN
) - 1) == 0) {
605 if (sscanf(ptr
, "%*s %d", &unsetid
) != 1) {
610 } else if (strncmp(ptr
, QUOTE_TOKEN
,
611 sizeof (QUOTE_TOKEN
) - 1) == 0) {
612 if (sscanf(ptr
, "%*s %c", &c
) != 1) {
620 if (setid
== unsetid
) {
625 if (is_bs_terminated(ptr
)) {
626 (void) strlcat(msg
, ptr
, sizeof (msg
));
629 int len
= strlen(ptr
);
630 *(ptr
+ len
- 1) = '\0';
631 if (c
&& (*(ptr
+ len
- 2) == c
)) {
632 *(ptr
+ len
- 2) = '\0';
634 (void) strlcat(msg
, ptr
, sizeof (msg
));
635 add_msg(setid
, msgid
, msg
, file
, line
, TRUE
);
641 if (isdigit((unsigned char)*ptr
)) {
646 msgid
= (int)strtol(ptr
, &pptr
, 10);
651 if (is_bs_terminated(ptr
)) {
652 (void) memset(msg
, 0, sizeof (msg
));
653 if (c
&& (*ptr
== c
)) {
656 (void) strlcpy(msg
, ptr
, sizeof (msg
));
659 int len
= strlen(ptr
);
660 *(ptr
+ len
- 1) = '\0';
661 if (c
&& ((*ptr
== c
) &&
662 (*(ptr
+ len
- 2) == c
))) {
663 *(ptr
+ len
- 2) = '\0';
666 add_msg(setid
, msgid
, ptr
, file
, line
, TRUE
);
676 is_bs_terminated(char *msg
)
678 int len
= strlen(msg
);
681 if (msg
[len
] == ' ' || msg
[len
] == '\t' || msg
[len
] == '\n') {
683 } else if (msg
[len
] == '\\') {
685 if (len
>= 0 && msg
[len
] == '\\')
698 char *tmp
= strdup(str
);
700 prg_err(gettext("fatal: out of memory"));
707 file_copy(char *in
, char *out
)
712 sigset_t newmask
, oldmask
;
714 (void) sigemptyset(&newmask
);
715 (void) sigaddset(&newmask
, SIGQUIT
);
716 (void) sigaddset(&newmask
, SIGINT
);
717 (void) sigaddset(&newmask
, SIGHUP
);
718 (void) sigaddset(&newmask
, SIGTERM
);
719 (void) sigprocmask(SIG_BLOCK
, &newmask
, &oldmask
);
721 if ((fin
= fopen(in
, "r")) == NULL
) {
722 prg_err(gettext("cannot open \"%s\""), in
);
727 if ((fout
= fopen(out
, "w")) == NULL
) {
728 prg_err(gettext("cannot create \"%s\""), out
);
733 while ((c
= getc(fin
)) != EOF
)
734 (void) putc(c
, fout
);
740 (void) sigprocmask(SIG_SETMASK
, &oldmask
, NULL
);
745 makeup_msg(char **pmsg
)
747 char buf
[NL_TEXTMAX
];
753 if (IsActiveMode(TripleMode
) && strchr(msg
, '%') == NULL
) {
754 /* there is no '%' in message. */
755 int len
= strlen(msg
);
757 if (msg
[len
-2] == '\\' && msg
[len
-1] == 'n') {
759 (void) strlcat(buf
, msg
, sizeof (buf
));
760 (void) strlcat(buf
, msg
, sizeof (buf
));
761 (void) strlcat(buf
, msg
, sizeof (buf
));
762 (void) strlcat(buf
, "\\n", sizeof (buf
));
764 (void) strlcat(buf
, msg
, sizeof (buf
));
765 (void) strlcat(buf
, msg
, sizeof (buf
));
766 (void) strlcat(buf
, msg
, sizeof (buf
));
769 *pmsg
= ustrdup(buf
);
775 if (IsActiveMode(PrefixMode
)) {
776 (void) strlcat(buf
, premsg
, sizeof (buf
));
777 (void) strlcat(buf
, msg
, sizeof (buf
));
779 *pmsg
= ustrdup(buf
);
785 if (IsActiveMode(SuffixMode
)) {
786 int len
= strlen(msg
);
788 if (msg
[len
-2] == '\\' && msg
[len
-1] == 'n') {
790 (void) strlcat(buf
, msg
, sizeof (buf
));
791 (void) strlcat(buf
, sufmsg
, sizeof (buf
));
792 (void) strlcat(buf
, "\\n", sizeof (buf
));
794 (void) strlcat(buf
, msg
, sizeof (buf
));
795 (void) strlcat(buf
, sufmsg
, sizeof (buf
));
798 *pmsg
= ustrdup(buf
);
803 prg_err(char *fmt
, ...)
809 (void) fprintf(stderr
, "%s: ", program
);
810 /* LINTED: E_SEC_PRINTF_VAR_FMT */
811 (void) vfprintf(stderr
, fmt
, ap
);
812 (void) fprintf(stderr
, "\n");
818 src_err(char *file
, int line
, char *fmt
, ...)
822 if (suppress_error
== TRUE
) {
828 (void) fprintf(stderr
, gettext("\"%s\", line %d: "), file
, line
);
829 /* LINTED: E_SEC_PRINTF_VAR_FMT */
830 (void) vfprintf(stderr
, fmt
, ap
);
831 (void) fprintf(stderr
, "\n");