b3d49521052cd1485abc47183d0f1191df8e76db
[pspp-builds.git] / src / libpspp / syntax-gen.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA. */
18
19 #include <config.h>
20 #include <stdbool.h>
21
22 #include "size_max.h"
23 #include <libpspp/str.h>
24 #include <libpspp/assertion.h>
25 #include <string.h>
26 #include <mbchar.h>
27
28 #include "syntax-gen.h"
29
30
31 static bool
32 has_single_quote (const struct string *str)
33 {
34   return (SIZE_MAX != ds_find_char (str, '\''));
35 }
36
37 static bool
38 has_double_quote (const struct string *str)
39 {
40   return (SIZE_MAX != ds_find_char (str, '"'));
41 }
42
43 /*
44    Quotes the string STR. If STR contains no '\'' character, then
45    the returned value will be enclosed in single quotes.  Else, if STR
46    contains no '"' character, then it will be enclosed in double
47    quotes. Otherwise, it will be enclosed in single quotes, and each
48    '\'' will be padded with another '\''.
49
50    STR must be encoded in UTF-8, and the quoted result will also be
51    encoded in UTF-8.
52 */
53 void
54 gen_quoted_string (struct string *str)
55 {
56   char c;
57   static const char single_quote[] = "'";
58   static const char double_quote[] = "\"";
59
60   struct string quoted_str;
61
62   bool pad_single_quotes = false;
63   const char *delimiter ;
64   char *s = ds_cstr (str);
65
66   if ( has_double_quote (str))
67     {
68       delimiter = single_quote;
69       if ( has_single_quote (str))
70         pad_single_quotes = true;
71     }
72   else
73     {
74       delimiter = double_quote;
75     }
76
77   /* This seemingly simple implementation is possible, because UTF-8
78      guarantees that bytes corresponding to basic characters (such as
79      '\'') cannot appear in a multi-byte character sequence except to
80      represent that basic character.
81   */
82   assert (is_basic ('\''));
83
84   /* Initialise with the opening delimiter */
85   ds_init_cstr (&quoted_str, delimiter);
86   while ((c = *s++))
87     {
88       ds_put_char (&quoted_str, c);
89
90       /* If c is a single quote, then append another one */
91       if ( c == '\'' && pad_single_quotes)
92         ds_put_char (&quoted_str, c);
93     }
94
95   /* Add the closing delimiter */
96   ds_put_cstr (&quoted_str, delimiter);
97
98   /* Copy the quoted string into str */
99   ds_swap (str, &quoted_str);
100   ds_destroy (&quoted_str);
101 }
102