ceb78771d748fb6f18bb8cb79274a23421720eab
[pspp] / src / language / utilities / include.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 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
19 #include <ctype.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include <data/file-name.h>
26 #include <language/command.h>
27 #include <language/lexer/lexer.h>
28 #include <language/syntax-file.h>
29 #include <libpspp/getl.h>
30 #include <libpspp/message.h>
31 #include <libpspp/str.h>
32
33 #include "dirname.h"
34 #include "xalloc.h"
35
36 #include "gettext.h"
37 #define _(msgid) gettext (msgid)
38
39 static int parse_insert (struct lexer *lexer, char **filename);
40
41
42 int
43 cmd_include (struct lexer *lexer, struct dataset *ds UNUSED)
44 {
45   char *filename = NULL;
46   int status = parse_insert (lexer, &filename);
47
48   if ( CMD_SUCCESS != status)
49     return status;
50
51   lex_get (lexer);
52
53   status = lex_end_of_command (lexer);
54
55   if ( status == CMD_SUCCESS)
56     {
57       struct source_stream *ss = lex_get_source_stream (lexer);
58
59       assert (filename);
60       getl_include_source (ss, create_syntax_file_source (filename),
61                            GETL_BATCH, ERRMODE_STOP);
62       free (filename);
63     }
64
65   return status;
66 }
67
68
69 int
70 cmd_insert (struct lexer *lexer, struct dataset *ds UNUSED)
71 {
72   enum syntax_mode syntax_mode = GETL_INTERACTIVE;
73   enum error_mode error_mode = ERRMODE_CONTINUE;
74   char *filename = NULL;
75   int status = parse_insert (lexer, &filename);
76   bool cd = false;
77
78   if ( CMD_SUCCESS != status)
79     return status;
80
81   lex_get (lexer);
82
83   while ( '.' != lex_token (lexer))
84     {
85       if (lex_match_id (lexer, "SYNTAX"))
86         {
87           lex_match (lexer, '=');
88           if ( lex_match_id (lexer, "INTERACTIVE") )
89             syntax_mode = GETL_INTERACTIVE;
90           else if ( lex_match_id (lexer, "BATCH"))
91             syntax_mode = GETL_BATCH;
92           else
93             {
94               lex_error(lexer,
95                         _("Expecting BATCH or INTERACTIVE after SYNTAX."));
96               return CMD_FAILURE;
97             }
98         }
99       else if (lex_match_id (lexer, "CD"))
100         {
101           lex_match (lexer, '=');
102           if ( lex_match_id (lexer, "YES") )
103             {
104               cd = true;
105             }
106           else if ( lex_match_id (lexer, "NO"))
107             {
108               cd = false;
109             }
110           else
111             {
112               lex_error (lexer, _("Expecting YES or NO after CD."));
113               return CMD_FAILURE;
114             }
115         }
116       else if (lex_match_id (lexer, "ERROR"))
117         {
118           lex_match (lexer, '=');
119           if ( lex_match_id (lexer, "CONTINUE") )
120             {
121               error_mode = ERRMODE_CONTINUE;
122             }
123           else if ( lex_match_id (lexer, "STOP"))
124             {
125               error_mode = ERRMODE_STOP;
126             }
127           else
128             {
129               lex_error (lexer, _("Expecting CONTINUE or STOP after ERROR."));
130               return CMD_FAILURE;
131             }
132         }
133
134       else
135         {
136           lex_error (lexer, _("Unexpected token: `%s'."),
137                      lex_token_representation (lexer));
138
139           return CMD_FAILURE;
140         }
141     }
142
143   status = lex_end_of_command (lexer);
144
145   if ( status == CMD_SUCCESS)
146     {
147       struct source_stream *ss = lex_get_source_stream (lexer);
148
149       assert (filename);
150       getl_include_source (ss, create_syntax_file_source (filename),
151                            syntax_mode,
152                            error_mode);
153
154       if ( cd )
155         {
156           char *directory = dir_name (filename);
157           chdir (directory);
158           free (directory);
159         }
160
161       free (filename);
162     }
163
164   return status;
165 }
166
167
168 static int
169 parse_insert (struct lexer *lexer, char **filename)
170 {
171   char *target_fn;
172   char *relative_filename;
173
174   /* Skip optional FILE=. */
175   if (lex_match_id (lexer, "FILE"))
176     lex_match (lexer, '=');
177
178   /* File name can be identifier or string. */
179   if (lex_token (lexer) != T_ID && lex_token (lexer) != T_STRING)
180     {
181       lex_error (lexer, _("expecting file name"));
182       return CMD_FAILURE;
183     }
184
185   target_fn = ds_cstr (lex_tokstr (lexer));
186
187   relative_filename =
188     fn_search_path (target_fn,
189                     getl_include_path (lex_get_source_stream (lexer)));
190
191   if ( ! relative_filename)
192     {
193       msg (SE, _("Can't find `%s' in include file search path."),
194          target_fn);
195       return CMD_FAILURE;
196     }
197
198   *filename = relative_filename;
199   if (*filename == NULL) 
200     {
201       msg (SE, _("Unable to open `%s': %s."),
202            relative_filename, strerror (errno));
203       free (relative_filename);
204       return CMD_FAILURE;
205     }
206
207   return CMD_SUCCESS;
208 }