Change license from GPLv2+ to GPLv3+.
[pspp-builds.git] / src / libpspp / syntax-gen.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007 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 General Public License as published by
6    the Free Software Foundation, either version 3 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 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, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <stdbool.h>
19
20 #include "size_max.h"
21 #include <libpspp/str.h>
22 #include <libpspp/assertion.h>
23 #include <string.h>
24 #include <mbchar.h>
25
26 #include "syntax-gen.h"
27
28
29 static bool
30 has_single_quote (const struct string *str)
31 {
32   return (SIZE_MAX != ds_find_char (str, '\''));
33 }
34
35 static bool
36 has_double_quote (const struct string *str)
37 {
38   return (SIZE_MAX != ds_find_char (str, '"'));
39 }
40
41 /*
42    Quotes the string STR. If STR contains no '\'' character, then
43    the returned value will be enclosed in single quotes.  Else, if STR
44    contains no '"' character, then it will be enclosed in double
45    quotes. Otherwise, it will be enclosed in single quotes, and each
46    '\'' will be padded with another '\''.
47
48    STR must be encoded in UTF-8, and the quoted result will also be
49    encoded in UTF-8.
50 */
51 void
52 gen_quoted_string (struct string *str)
53 {
54   char c;
55   static const char single_quote[] = "'";
56   static const char double_quote[] = "\"";
57
58   struct string quoted_str;
59
60   bool pad_single_quotes = false;
61   const char *delimiter ;
62   char *s = ds_cstr (str);
63
64   if ( has_double_quote (str))
65     {
66       delimiter = single_quote;
67       if ( has_single_quote (str))
68         pad_single_quotes = true;
69     }
70   else
71     {
72       delimiter = double_quote;
73     }
74
75   /* This seemingly simple implementation is possible, because UTF-8
76      guarantees that bytes corresponding to basic characters (such as
77      '\'') cannot appear in a multi-byte character sequence except to
78      represent that basic character.
79   */
80   assert (is_basic ('\''));
81
82   /* Initialise with the opening delimiter */
83   ds_init_cstr (&quoted_str, delimiter);
84   while ((c = *s++))
85     {
86       ds_put_char (&quoted_str, c);
87
88       /* If c is a single quote, then append another one */
89       if ( c == '\'' && pad_single_quotes)
90         ds_put_char (&quoted_str, c);
91     }
92
93   /* Add the closing delimiter */
94   ds_put_cstr (&quoted_str, delimiter);
95
96   /* Copy the quoted string into str */
97   ds_swap (str, &quoted_str);
98   ds_destroy (&quoted_str);
99 }
100