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