Imported Upstream version 0.18.1.1
[platform/upstream/gettext.git] / gettext-tools / src / x-rst.c
1 /* xgettext RST backend.
2    Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
3
4    This file was written by Bruno Haible <haible@clisp.cons.org>, 2001.
5
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 /* Specification.  */
24 #include "x-rst.h"
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stddef.h>
29 #include <stdlib.h>
30
31 #include "c-ctype.h"
32 #include "message.h"
33 #include "xgettext.h"
34 #include "error.h"
35 #include "error-progname.h"
36 #include "xalloc.h"
37 #include "gettext.h"
38
39 #define _(s) gettext(s)
40
41 /* RST stands for Resource String Table.
42
43    An RST file consists of several string definitions.  A string definition
44    starts at the beginning of a line and looks like this:
45        ModuleName.ConstName=StringExpression
46    A StringExpression consists of string pieces of the form 'xyz',
47    single characters of the form #nnn (decimal integer), and +
48    at the end of the line to designate continuation on the next line.
49    String definitions can be separated by blank lines or comment lines
50    beginning with '#'.
51
52    This backend attempts to be functionally equivalent to the 'rstconv'
53    program, part of the Free Pascal run time library, written by
54    Sebastian Guenther.  Except that the locations are output as
55    "ModuleName.ConstName", not "ModuleName:ConstName".
56  */
57
58 void
59 extract_rst (FILE *f,
60              const char *real_filename, const char *logical_filename,
61              flag_context_list_table_ty *flag_table,
62              msgdomain_list_ty *mdlp)
63 {
64   static char *buffer;
65   static int bufmax;
66   message_list_ty *mlp = mdlp->item[0]->messages;
67   int line_number;
68
69   line_number = 1;
70   for (;;)
71     {
72       int c;
73       int bufpos;
74       char *location;
75       char *msgid;
76       lex_pos_ty pos;
77
78       c = getc (f);
79       if (c == EOF)
80         break;
81
82       /* Ignore blank line.  */
83       if (c == '\n')
84         {
85           line_number++;
86           continue;
87         }
88
89       /* Ignore comment line.  */
90       if (c == '#')
91         {
92           do
93             c = getc (f);
94           while (c != EOF && c != '\n');
95           if (c == EOF)
96             break;
97           line_number++;
98           continue;
99         }
100
101       /* Read ModuleName.ConstName.  */
102       bufpos = 0;
103       for (;;)
104         {
105           if (c == EOF || c == '\n')
106             {
107               error_with_progname = false;
108               error (EXIT_FAILURE, 0, _("%s:%d: invalid string definition"),
109                      logical_filename, line_number);
110               error_with_progname = true;
111             }
112           if (bufpos >= bufmax)
113             {
114               bufmax = 2 * bufmax + 10;
115               buffer = xrealloc (buffer, bufmax);
116             }
117           if (c == '=')
118             break;
119           buffer[bufpos++] = c;
120           c = getc (f);
121           if (c == EOF && ferror (f))
122             goto bomb;
123         }
124       buffer[bufpos] = '\0';
125       location = xstrdup (buffer);
126
127       /* Read StringExpression.  */
128       bufpos = 0;
129       for (;;)
130         {
131           c = getc (f);
132           if (c == EOF)
133             break;
134           else if (c == '\n')
135             {
136               line_number++;
137               break;
138             }
139           else if (c == '\'')
140             {
141               for (;;)
142                 {
143                   c = getc (f);
144                   /* Embedded single quotes like 'abc''def' don't occur.
145                      See fpc-1.0.4/compiler/cresstr.pas.  */
146                   if (c == EOF || c == '\n' || c == '\'')
147                     break;
148                   if (bufpos >= bufmax)
149                     {
150                       bufmax = 2 * bufmax + 10;
151                       buffer = xrealloc (buffer, bufmax);
152                     }
153                   buffer[bufpos++] = c;
154                 }
155               if (c == EOF)
156                 break;
157               else if (c == '\n')
158                 {
159                   line_number++;
160                   break;
161                 }
162             }
163           else if (c == '#')
164             {
165               int n;
166               c = getc (f);
167               if (c == EOF && ferror (f))
168                 goto bomb;
169               if (c == EOF || !c_isdigit (c))
170                 {
171                   error_with_progname = false;
172                   error (EXIT_FAILURE, 0, _("%s:%d: missing number after #"),
173                          logical_filename, line_number);
174                   error_with_progname = true;
175                 }
176               n = (c - '0');
177               for (;;)
178                 {
179                   c = getc (f);
180                   if (c == EOF || !c_isdigit (c))
181                     break;
182                   n = n * 10 + (c - '0');
183                 }
184               if (bufpos >= bufmax)
185                 {
186                   bufmax = 2 * bufmax + 10;
187                   buffer = xrealloc (buffer, bufmax);
188                 }
189               buffer[bufpos++] = (unsigned char) n;
190               if (c == EOF)
191                 break;
192               ungetc (c, f);
193             }
194           else if (c == '+')
195             {
196               c = getc (f);
197               if (c == EOF)
198                 break;
199               if (c == '\n')
200                 line_number++;
201               else
202                 ungetc (c, f);
203             }
204           else
205             {
206               error_with_progname = false;
207               error (EXIT_FAILURE, 0, _("%s:%d: invalid string expression"),
208                      logical_filename, line_number);
209               error_with_progname = true;
210             }
211         }
212       if (bufpos >= bufmax)
213         {
214           bufmax = 2 * bufmax + 10;
215           buffer = xrealloc (buffer, bufmax);
216         }
217       buffer[bufpos] = '\0';
218       msgid = xstrdup (buffer);
219
220       pos.file_name = location;
221       pos.line_number = (size_t)(-1);
222
223       remember_a_message (mlp, NULL, msgid, null_context, &pos, NULL, NULL);
224
225       /* Here c is the last read character: EOF or '\n'.  */
226       if (c == EOF)
227         break;
228     }
229
230   if (ferror (f))
231     {
232     bomb:
233       error (EXIT_FAILURE, errno, _("error while reading \"%s\""),
234              real_filename);
235     }
236 }