• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Log file output.
2    Copyright (C) 2003, 2005, 2009 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU Lesser General Public License as published by
6    the Free Software Foundation; either version 2.1 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16 
17 /* Written by Bruno Haible <bruno@clisp.org>.  */
18 
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 /* Handle multi-threaded applications.  */
28 #ifdef _LIBC
29 # include <bits/libc-lock.h>
30 #else
31 # include "lock.h"
32 #endif
33 
34 /* Separator between msgctxt and msgid in .mo files.  */
35 #define MSGCTXT_SEPARATOR '\004'  /* EOT */
36 
37 /* Print an ASCII string with quotes and escape sequences where needed.  */
38 static void
print_escaped(FILE * stream,const char * str,const char * str_end)39 print_escaped (FILE *stream, const char *str, const char *str_end)
40 {
41   putc ('"', stream);
42   for (; str != str_end; str++)
43     if (*str == '\n')
44       {
45         fputs ("\\n\"", stream);
46         if (str + 1 == str_end)
47           return;
48         fputs ("\n\"", stream);
49       }
50     else
51       {
52         if (*str == '"' || *str == '\\')
53           putc ('\\', stream);
54         putc (*str, stream);
55       }
56   putc ('"', stream);
57 }
58 
59 static char *last_logfilename = NULL;
60 static FILE *last_logfile = NULL;
__libc_lock_define_initialized(static,lock)61 __libc_lock_define_initialized (static, lock)
62 
63 static inline void
64 _nl_log_untranslated_locked (const char *logfilename, const char *domainname,
65                              const char *msgid1, const char *msgid2, int plural)
66 {
67   FILE *logfile;
68   const char *separator;
69 
70   /* Can we reuse the last opened logfile?  */
71   if (last_logfilename == NULL || strcmp (logfilename, last_logfilename) != 0)
72     {
73       /* Close the last used logfile.  */
74       if (last_logfilename != NULL)
75         {
76           if (last_logfile != NULL)
77             {
78               fclose (last_logfile);
79               last_logfile = NULL;
80             }
81           free (last_logfilename);
82           last_logfilename = NULL;
83         }
84       /* Open the logfile.  */
85       last_logfilename = (char *) malloc (strlen (logfilename) + 1);
86       if (last_logfilename == NULL)
87         return;
88       strcpy (last_logfilename, logfilename);
89       last_logfile = fopen (logfilename, "a");
90       if (last_logfile == NULL)
91         return;
92     }
93   logfile = last_logfile;
94 
95   fprintf (logfile, "domain ");
96   print_escaped (logfile, domainname, domainname + strlen (domainname));
97   separator = strchr (msgid1, MSGCTXT_SEPARATOR);
98   if (separator != NULL)
99     {
100       /* The part before the MSGCTXT_SEPARATOR is the msgctxt.  */
101       fprintf (logfile, "\nmsgctxt ");
102       print_escaped (logfile, msgid1, separator);
103       msgid1 = separator + 1;
104     }
105   fprintf (logfile, "\nmsgid ");
106   print_escaped (logfile, msgid1, msgid1 + strlen (msgid1));
107   if (plural)
108     {
109       fprintf (logfile, "\nmsgid_plural ");
110       print_escaped (logfile, msgid2, msgid2 + strlen (msgid2));
111       fprintf (logfile, "\nmsgstr[0] \"\"\n");
112     }
113   else
114     fprintf (logfile, "\nmsgstr \"\"\n");
115   putc ('\n', logfile);
116 }
117 
118 /* Add to the log file an entry denoting a failed translation.  */
119 void
_nl_log_untranslated(const char * logfilename,const char * domainname,const char * msgid1,const char * msgid2,int plural)120 _nl_log_untranslated (const char *logfilename, const char *domainname,
121                       const char *msgid1, const char *msgid2, int plural)
122 {
123   __libc_lock_lock (lock);
124   _nl_log_untranslated_locked (logfilename, domainname, msgid1, msgid2, plural);
125   __libc_lock_unlock (lock);
126 }
127