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