~ubuntu-branches/ubuntu/utopic/gettext/utopic

« back to all changes in this revision

Viewing changes to gettext-tools/src/read-properties.c

  • Committer: Colin Watson
  • Date: 2010-08-01 21:36:08 UTC
  • mfrom: (2.1.10 sid)
  • Revision ID: cjwatson@canonical.com-20100801213608-yy7vkm8lpatep3ci
merge from Debian 0.18.1.1-1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Reading Java .properties files.
2
 
   Copyright (C) 2003, 2005-2007 Free Software Foundation, Inc.
 
2
   Copyright (C) 2003, 2005-2007, 2009 Free Software Foundation, Inc.
3
3
   Written by Bruno Haible <bruno@clisp.org>, 2003.
4
4
 
5
5
   This program is free software: you can redistribute it and/or modify
82
82
  if (c == EOF)
83
83
    {
84
84
      if (ferror (fp))
85
 
        {
86
 
          const char *errno_description = strerror (errno);
87
 
          po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false,
88
 
                     xasprintf ("%s: %s",
89
 
                                xasprintf (_("error while reading \"%s\""),
90
 
                                           real_file_name),
91
 
                                errno_description));
92
 
        }
 
85
        {
 
86
          const char *errno_description = strerror (errno);
 
87
          po_xerror (PO_SEVERITY_FATAL_ERROR, NULL, NULL, 0, 0, false,
 
88
                     xasprintf ("%s: %s",
 
89
                                xasprintf (_("error while reading \"%s\""),
 
90
                                           real_file_name),
 
91
                                errno_description));
 
92
        }
93
93
      return EOF;
94
94
    }
95
95
 
122
122
      c = phase1_getc ();
123
123
 
124
124
      if (c == '\r')
125
 
        {
126
 
          int c2 = phase1_getc ();
127
 
          if (c2 == '\n')
128
 
            c = c2;
129
 
          else
130
 
            phase1_ungetc (c2);
131
 
        }
 
125
        {
 
126
          int c2 = phase1_getc ();
 
127
          if (c2 == '\n')
 
128
            c = c2;
 
129
          else
 
130
            phase1_ungetc (c2);
 
131
        }
132
132
    }
133
133
 
134
134
  if (c == '\n')
159
159
  for (;;)
160
160
    {
161
161
      if (c != '\\')
162
 
        return c;
 
162
        return c;
163
163
 
164
164
      c = phase2_getc ();
165
165
      if (c != '\n')
166
 
        {
167
 
          phase2_ungetc (c);
168
 
          return '\\';
169
 
        }
 
166
        {
 
167
          phase2_ungetc (c);
 
168
          return '\\';
 
169
        }
170
170
 
171
171
      /* Skip the backslash-newline and all whitespace that follows it.  */
172
172
      do
173
 
        c = phase2_getc ();
 
173
        c = phase2_getc ();
174
174
      while (c == ' ' || c == '\t' || c == '\r' || c == '\f');
175
175
    }
176
176
}
197
197
      int c2 = phase3_getc ();
198
198
 
199
199
      if (c2 == 't')
200
 
        return '\t';
 
200
        return '\t';
201
201
      if (c2 == 'n')
202
 
        return '\n';
 
202
        return '\n';
203
203
      if (c2 == 'r')
204
 
        return '\r';
 
204
        return '\r';
205
205
      if (c2 == 'f')
206
 
        return '\f';
 
206
        return '\f';
207
207
      if (c2 == 'u')
208
 
        {
209
 
          unsigned int n = 0;
210
 
          int i;
211
 
 
212
 
          for (i = 0; i < 4; i++)
213
 
            {
214
 
              int c1 = phase3_getc ();
215
 
 
216
 
              if (c1 >= '0' && c1 <= '9')
217
 
                n = (n << 4) + (c1 - '0');
218
 
              else if (c1 >= 'A' && c1 <= 'F')
219
 
                n = (n << 4) + (c1 - 'A' + 10);
220
 
              else if (c1 >= 'a' && c1 <= 'f')
221
 
                n = (n << 4) + (c1 - 'a' + 10);
222
 
              else
223
 
                {
224
 
                  phase3_ungetc (c1);
225
 
                  po_xerror (PO_SEVERITY_ERROR, NULL,
226
 
                             real_file_name, gram_pos.line_number, (size_t)(-1),
227
 
                             false, _("warning: invalid \\uxxxx syntax for Unicode character"));
228
 
                  return 'u';
229
 
                }
230
 
            }
231
 
          return n;
232
 
        }
 
208
        {
 
209
          unsigned int n = 0;
 
210
          int i;
 
211
 
 
212
          for (i = 0; i < 4; i++)
 
213
            {
 
214
              int c1 = phase3_getc ();
 
215
 
 
216
              if (c1 >= '0' && c1 <= '9')
 
217
                n = (n << 4) + (c1 - '0');
 
218
              else if (c1 >= 'A' && c1 <= 'F')
 
219
                n = (n << 4) + (c1 - 'A' + 10);
 
220
              else if (c1 >= 'a' && c1 <= 'f')
 
221
                n = (n << 4) + (c1 - 'a' + 10);
 
222
              else
 
223
                {
 
224
                  phase3_ungetc (c1);
 
225
                  po_xerror (PO_SEVERITY_ERROR, NULL,
 
226
                             real_file_name, gram_pos.line_number, (size_t)(-1),
 
227
                             false, _("warning: invalid \\uxxxx syntax for Unicode character"));
 
228
                  return 'u';
 
229
                }
 
230
            }
 
231
          return n;
 
232
        }
233
233
 
234
234
      return c2;
235
235
    }
254
254
      const char *str_limit = str + length;
255
255
 
256
256
      while (str < str_limit)
257
 
        {
258
 
          unsigned int uc = (unsigned char) *str++;
259
 
          int n = u8_uctomb (q, uc, 6);
260
 
          assert (n > 0);
261
 
          q += n;
262
 
        }
 
257
        {
 
258
          unsigned int uc = (unsigned char) *str++;
 
259
          int n = u8_uctomb (q, uc, 6);
 
260
          assert (n > 0);
 
261
          q += n;
 
262
        }
263
263
      *q = '\0';
264
264
      assert (q - utf8_string <= 2 * length);
265
265
 
281
281
  while (*p != '\0')
282
282
    {
283
283
      if (p[0] == '\\' && p[1] == 'u')
284
 
        {
285
 
          unsigned int n = 0;
286
 
          int i;
287
 
 
288
 
          for (i = 0; i < 4; i++)
289
 
            {
290
 
              int c1 = (unsigned char) p[2 + i];
291
 
 
292
 
              if (c1 >= '0' && c1 <= '9')
293
 
                n = (n << 4) + (c1 - '0');
294
 
              else if (c1 >= 'A' && c1 <= 'F')
295
 
                n = (n << 4) + (c1 - 'A' + 10);
296
 
              else if (c1 >= 'a' && c1 <= 'f')
297
 
                n = (n << 4) + (c1 - 'a' + 10);
298
 
              else
299
 
                goto just_one_byte;
300
 
            }
301
 
 
302
 
          if (i == 4)
303
 
            {
304
 
              unsigned int uc;
305
 
 
306
 
              if (n >= 0xd800 && n < 0xdc00)
307
 
                {
308
 
                  if (p[6] == '\\' && p[7] == 'u')
309
 
                    {
310
 
                      unsigned int m = 0;
311
 
 
312
 
                      for (i = 0; i < 4; i++)
313
 
                        {
314
 
                          int c1 = (unsigned char) p[8 + i];
315
 
 
316
 
                          if (c1 >= '0' && c1 <= '9')
317
 
                            m = (m << 4) + (c1 - '0');
318
 
                          else if (c1 >= 'A' && c1 <= 'F')
319
 
                            m = (m << 4) + (c1 - 'A' + 10);
320
 
                          else if (c1 >= 'a' && c1 <= 'f')
321
 
                            m = (m << 4) + (c1 - 'a' + 10);
322
 
                          else
323
 
                            goto just_one_byte;
324
 
                        }
325
 
 
326
 
                      if (i == 4 && (m >= 0xdc00 && m < 0xe000))
327
 
                        {
328
 
                          /* Combine two UTF-16 words to a character.  */
329
 
                          uc = 0x10000 + ((n - 0xd800) << 10) + (m - 0xdc00);
330
 
                          p += 12;
331
 
                        }
332
 
                      else
333
 
                        goto just_one_byte;
334
 
                    }
335
 
                  else
336
 
                    goto just_one_byte;
337
 
                }
338
 
              else
339
 
                {
340
 
                  uc = n;
341
 
                  p += 6;
342
 
                }
343
 
 
344
 
              q += u8_uctomb (q, uc, 6);
345
 
              continue;
346
 
            }
347
 
        }
 
284
        {
 
285
          unsigned int n = 0;
 
286
          int i;
 
287
 
 
288
          for (i = 0; i < 4; i++)
 
289
            {
 
290
              int c1 = (unsigned char) p[2 + i];
 
291
 
 
292
              if (c1 >= '0' && c1 <= '9')
 
293
                n = (n << 4) + (c1 - '0');
 
294
              else if (c1 >= 'A' && c1 <= 'F')
 
295
                n = (n << 4) + (c1 - 'A' + 10);
 
296
              else if (c1 >= 'a' && c1 <= 'f')
 
297
                n = (n << 4) + (c1 - 'a' + 10);
 
298
              else
 
299
                goto just_one_byte;
 
300
            }
 
301
 
 
302
          if (i == 4)
 
303
            {
 
304
              unsigned int uc;
 
305
 
 
306
              if (n >= 0xd800 && n < 0xdc00)
 
307
                {
 
308
                  if (p[6] == '\\' && p[7] == 'u')
 
309
                    {
 
310
                      unsigned int m = 0;
 
311
 
 
312
                      for (i = 0; i < 4; i++)
 
313
                        {
 
314
                          int c1 = (unsigned char) p[8 + i];
 
315
 
 
316
                          if (c1 >= '0' && c1 <= '9')
 
317
                            m = (m << 4) + (c1 - '0');
 
318
                          else if (c1 >= 'A' && c1 <= 'F')
 
319
                            m = (m << 4) + (c1 - 'A' + 10);
 
320
                          else if (c1 >= 'a' && c1 <= 'f')
 
321
                            m = (m << 4) + (c1 - 'a' + 10);
 
322
                          else
 
323
                            goto just_one_byte;
 
324
                        }
 
325
 
 
326
                      if (i == 4 && (m >= 0xdc00 && m < 0xe000))
 
327
                        {
 
328
                          /* Combine two UTF-16 words to a character.  */
 
329
                          uc = 0x10000 + ((n - 0xd800) << 10) + (m - 0xdc00);
 
330
                          p += 12;
 
331
                        }
 
332
                      else
 
333
                        goto just_one_byte;
 
334
                    }
 
335
                  else
 
336
                    goto just_one_byte;
 
337
                }
 
338
              else
 
339
                {
 
340
                  uc = n;
 
341
                  p += 6;
 
342
                }
 
343
 
 
344
              q += u8_uctomb (q, uc, 6);
 
345
              continue;
 
346
            }
 
347
        }
348
348
      just_one_byte:
349
 
        *q++ = (unsigned char) *p++;
 
349
        *q++ = (unsigned char) *p++;
350
350
    }
351
351
  *q = '\0';
352
352
  return string;
387
387
  for (;;)
388
388
    {
389
389
      if (in_key && (c == '=' || c == ':'
390
 
                     || c == ' ' || c == '\t' || c == '\r' || c == '\f'))
391
 
        {
392
 
          /* Skip whitespace after the string.  */
393
 
          while (c == ' ' || c == '\t' || c == '\r' || c == '\f')
394
 
            c = phase3_getc ();
395
 
          /* Skip '=' or ':' separator.  */
396
 
          if (!(c == '=' || c == ':'))
397
 
            phase3_ungetc (c);
398
 
          break;
399
 
        }
 
390
                     || c == ' ' || c == '\t' || c == '\r' || c == '\f'))
 
391
        {
 
392
          /* Skip whitespace after the string.  */
 
393
          while (c == ' ' || c == '\t' || c == '\r' || c == '\f')
 
394
            c = phase3_getc ();
 
395
          /* Skip '=' or ':' separator.  */
 
396
          if (!(c == '=' || c == ':'))
 
397
            phase3_ungetc (c);
 
398
          break;
 
399
        }
400
400
 
401
401
      phase3_ungetc (c);
402
402
 
403
403
      /* Read the next UTF-16 codepoint.  */
404
404
      c = phase4_getuc ();
405
405
      if (c < 0)
406
 
        break;
 
406
        break;
407
407
      /* Append it to the buffer.  */
408
408
      if (buflen >= bufmax)
409
 
        {
410
 
          bufmax += 100;
411
 
          buffer = xrealloc (buffer, bufmax * sizeof (unsigned short));
412
 
        }
 
409
        {
 
410
          bufmax += 100;
 
411
          buffer = xrealloc (buffer, bufmax * sizeof (unsigned short));
 
412
        }
413
413
      buffer[buflen++] = c;
414
414
 
415
415
      c = phase3_getc ();
416
416
      if (c == EOF || c == '\n')
417
 
        {
418
 
          if (in_key)
419
 
            phase3_ungetc (c);
420
 
          break;
421
 
        }
 
417
        {
 
418
          if (in_key)
 
419
            phase3_ungetc (c);
 
420
          break;
 
421
        }
422
422
    }
423
423
 
424
424
  /* Now convert from UTF-16 to UTF-8.  */
431
431
    utf8_string = XNMALLOC (3 * buflen + 1, unsigned char);
432
432
    for (pos = 0, q = utf8_string; pos < buflen; )
433
433
      {
434
 
        unsigned int uc;
435
 
        int n;
 
434
        ucs4_t uc;
 
435
        int n;
436
436
 
437
 
        pos += u16_mbtouc (&uc, buffer + pos, buflen - pos);
438
 
        n = u8_uctomb (q, uc, 6);
439
 
        assert (n > 0);
440
 
        q += n;
 
437
        pos += u16_mbtouc (&uc, buffer + pos, buflen - pos);
 
438
        n = u8_uctomb (q, uc, 6);
 
439
        assert (n > 0);
 
440
        q += n;
441
441
      }
442
442
    *q = '\0';
443
443
    assert (q - utf8_string <= 3 * buflen);
451
451
   abstract_catalog_reader_class_ty methods.  */
452
452
static void
453
453
properties_parse (abstract_catalog_reader_ty *this, FILE *file,
454
 
                  const char *real_filename, const char *logical_filename)
 
454
                  const char *real_filename, const char *logical_filename)
455
455
{
456
456
  fp = file;
457
457
  real_file_name = real_filename;
467
467
      c = phase2_getc ();
468
468
 
469
469
      if (c == EOF)
470
 
        break;
 
470
        break;
471
471
 
472
472
      comment = false;
473
473
      hidden = false;
474
474
      if (c == '#')
475
 
        comment = true;
 
475
        comment = true;
476
476
      else if (c == '!')
477
 
        {
478
 
          /* For compatibility with write-properties.c, we treat '!' not
479
 
             followed by space as a fuzzy or untranslated message.  */
480
 
          int c2 = phase2_getc ();
481
 
          if (c2 == ' ' || c2 == '\n' || c2 == EOF)
482
 
            comment = true;
483
 
          else
484
 
            hidden = true;
485
 
          phase2_ungetc (c2);
486
 
        }
 
477
        {
 
478
          /* For compatibility with write-properties.c, we treat '!' not
 
479
             followed by space as a fuzzy or untranslated message.  */
 
480
          int c2 = phase2_getc ();
 
481
          if (c2 == ' ' || c2 == '\n' || c2 == EOF)
 
482
            comment = true;
 
483
          else
 
484
            hidden = true;
 
485
          phase2_ungetc (c2);
 
486
        }
487
487
      else
488
 
        phase2_ungetc (c);
 
488
        phase2_ungetc (c);
489
489
 
490
490
      if (comment)
491
 
        {
492
 
          /* A comment line.  */
493
 
          static char *buffer;
494
 
          static size_t bufmax;
495
 
          static size_t buflen;
496
 
 
497
 
          buflen = 0;
498
 
          for (;;)
499
 
            {
500
 
              c = phase2_getc ();
501
 
 
502
 
              if (buflen >= bufmax)
503
 
                {
504
 
                  bufmax += 100;
505
 
                  buffer = xrealloc (buffer, bufmax);
506
 
                }
507
 
 
508
 
              if (c == EOF || c == '\n')
509
 
                break;
510
 
 
511
 
              buffer[buflen++] = c;
512
 
            }
513
 
          buffer[buflen] = '\0';
514
 
 
515
 
          po_callback_comment_dispatcher (conv_from_java (conv_from_iso_8859_1 (buffer)));
516
 
        }
 
491
        {
 
492
          /* A comment line.  */
 
493
          static char *buffer;
 
494
          static size_t bufmax;
 
495
          static size_t buflen;
 
496
 
 
497
          buflen = 0;
 
498
          for (;;)
 
499
            {
 
500
              c = phase2_getc ();
 
501
 
 
502
              if (buflen >= bufmax)
 
503
                {
 
504
                  bufmax += 100;
 
505
                  buffer = xrealloc (buffer, bufmax);
 
506
                }
 
507
 
 
508
              if (c == EOF || c == '\n')
 
509
                break;
 
510
 
 
511
              buffer[buflen++] = c;
 
512
            }
 
513
          buffer[buflen] = '\0';
 
514
 
 
515
          po_callback_comment_dispatcher (conv_from_java (conv_from_iso_8859_1 (buffer)));
 
516
        }
517
517
      else
518
 
        {
519
 
          /* A key/value pair.  */
520
 
          char *msgid;
521
 
          lex_pos_ty msgid_pos;
522
 
 
523
 
          msgid_pos = gram_pos;
524
 
          msgid = read_escaped_string (true);
525
 
          if (msgid == NULL)
526
 
            /* Skip blank line.  */
527
 
            ;
528
 
          else
529
 
            {
530
 
              char *msgstr;
531
 
              lex_pos_ty msgstr_pos;
532
 
              bool force_fuzzy;
533
 
 
534
 
              msgstr_pos = gram_pos;
535
 
              msgstr = read_escaped_string (false);
536
 
              if (msgstr == NULL)
537
 
                msgstr = xstrdup ("");
538
 
 
539
 
              /* Be sure to make the message fuzzy if it was commented out
540
 
                 and if it is not already header/fuzzy/untranslated.  */
541
 
              force_fuzzy = (hidden && msgid[0] != '\0' && msgstr[0] != '\0');
542
 
 
543
 
              po_callback_message (NULL, msgid, &msgid_pos, NULL,
544
 
                                   msgstr, strlen (msgstr) + 1, &msgstr_pos,
545
 
                                   NULL, NULL, NULL,
546
 
                                   force_fuzzy, false);
547
 
            }
548
 
        }
 
518
        {
 
519
          /* A key/value pair.  */
 
520
          char *msgid;
 
521
          lex_pos_ty msgid_pos;
 
522
 
 
523
          msgid_pos = gram_pos;
 
524
          msgid = read_escaped_string (true);
 
525
          if (msgid == NULL)
 
526
            /* Skip blank line.  */
 
527
            ;
 
528
          else
 
529
            {
 
530
              char *msgstr;
 
531
              lex_pos_ty msgstr_pos;
 
532
              bool force_fuzzy;
 
533
 
 
534
              msgstr_pos = gram_pos;
 
535
              msgstr = read_escaped_string (false);
 
536
              if (msgstr == NULL)
 
537
                msgstr = xstrdup ("");
 
538
 
 
539
              /* Be sure to make the message fuzzy if it was commented out
 
540
                 and if it is not already header/fuzzy/untranslated.  */
 
541
              force_fuzzy = (hidden && msgid[0] != '\0' && msgstr[0] != '\0');
 
542
 
 
543
              po_callback_message (NULL, msgid, &msgid_pos, NULL,
 
544
                                   msgstr, strlen (msgstr) + 1, &msgstr_pos,
 
545
                                   NULL, NULL, NULL,
 
546
                                   force_fuzzy, false);
 
547
            }
 
548
        }
549
549
    }
550
550
 
551
551
  fp = NULL;
555
555
 
556
556
const struct catalog_input_format input_format_properties =
557
557
{
558
 
  properties_parse,                     /* parse */
559
 
  true                                  /* produces_utf8 */
 
558
  properties_parse,                     /* parse */
 
559
  true                                  /* produces_utf8 */
560
560
};