1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
39 #define _(msgid) gettext (msgid)
41 static struct string getl_include_path;
43 /* Number of levels of DO REPEAT structures we're nested inside. If
44 this is greater than zero then DO REPEAT macro substitutions are
46 static int DO_REPEAT_level;
48 struct string getl_buf;
51 /* Initialize getl. */
53 getl_initialize (void)
55 ds_create (&getl_include_path,
56 fn_getenv_default ("STAT_INCLUDE_PATH", include_path));
57 ds_init (&getl_buf, 256);
62 getl_uninitialize (void)
65 ds_destroy (&getl_buf);
66 ds_destroy (&getl_include_path);
70 struct getl_script *getl_head;
71 struct getl_script *getl_tail;
74 /* Returns a string that represents the directory that the syntax file
75 currently being read resides in. If there is no syntax file then
76 returns the OS current working directory. Return value must be
79 getl_get_current_directory (void)
81 return getl_head ? fn_dirname (getl_head->fn) : fn_get_cwd ();
84 /* Delete everything from the include path. */
86 getl_clear_include_path (void)
88 ds_clear (&getl_include_path);
91 /* Add to the include path. */
93 getl_add_include_dir (const char *path)
95 if (ds_length (&getl_include_path))
96 ds_putc (&getl_include_path, PATH_DELIMITER);
98 ds_puts (&getl_include_path, path);
101 /* Adds FN to the tail end of the list of script files to execute.
102 OPTIONS is the value to stick in the options field of the
103 getl_script struct. If WHERE is zero then the file is added after
104 all other files; otherwise it is added before all other files (this
105 can be done only if parsing has not yet begun). */
107 getl_add_file (const char *fn, int separate, int where)
109 struct getl_script *n = xmalloc (sizeof *n);
113 if (getl_tail == NULL)
114 getl_head = getl_tail = n;
116 getl_tail = getl_tail->next = n;
119 assert (getl_head->f == NULL);
123 n->included_from = n->includes = NULL;
124 n->fn = xstrdup (fn);
127 n->separate = separate;
128 n->first_line = NULL;
131 /* Inserts the given file with filename FN into the current file after
134 getl_include (const char *fn)
136 struct getl_script *n;
140 char *cur_dir = getl_get_current_directory ();
141 real_fn = fn_search_path (fn, ds_c_str (&getl_include_path), cur_dir);
147 msg (SE, _("Can't find `%s' in include file search path."), fn);
153 getl_add_file (real_fn, 0, 0);
158 n = xmalloc (sizeof *n);
159 n->included_from = getl_head;
160 getl_head = getl_head->includes = n;
167 n->first_line = NULL;
171 /* Add the virtual file FILE to the list of files to be processed.
172 The first_line field in FILE must already have been initialized. */
174 getl_add_virtual_file (struct getl_script *file)
176 if (getl_tail == NULL)
177 getl_head = getl_tail = file;
179 getl_tail = getl_tail->next = file;
180 file->included_from = file->includes = NULL;
182 file->fn = file->first_line->line;
183 file->ln = -file->first_line->len - 1;
186 file->cur_line = NULL;
187 file->remaining_loops = 1;
188 file->loop_index = -1;
192 /* Causes the DO REPEAT virtual file passed in FILE to be included in
193 the current file. The first_line, cur_line, remaining_loops,
194 loop_index, and macros fields in FILE must already have been
197 getl_add_DO_REPEAT_file (struct getl_script *file)
202 file->included_from = getl_head;
203 getl_head = getl_head->includes = file;
204 file->includes = NULL;
206 assert (file->first_line->len < 0);
207 file->fn = file->first_line->line;
208 file->ln = -file->first_line->len - 1;
213 /* Reads a single line from the line buffer associated with getl_head.
214 Returns 1 if a line was successfully read or 0 if no more lines are
217 getl_handle_line_buffer (void)
219 struct getl_script *s = getl_head;
221 /* Check that we're not all done. */
224 if (s->cur_line == NULL)
227 if (s->remaining_loops-- == 0)
229 s->cur_line = s->first_line;
232 if (s->cur_line->len < 0)
234 s->ln = -s->cur_line->len - 1;
235 s->fn = s->cur_line->line;
236 s->cur_line = s->cur_line->next;
240 while (s->cur_line == NULL);
242 ds_concat (&getl_buf, s->cur_line->line, s->cur_line->len);
244 /* Advance pointers. */
245 s->cur_line = s->cur_line->next;
251 /* Closes the current file, whether it be a main file or included
252 file, then moves getl_head to the next file in the chain. */
254 getl_close_file (void)
256 struct getl_script *s = getl_head;
260 assert (getl_tail != NULL);
264 struct getl_line_list *cur, *next;
266 s->fn = NULL; /* It will be freed below. */
267 for (cur = s->first_line; cur; cur = next)
277 if (s->f && EOF == fn_close (s->fn, s->f))
278 msg (MW, _("Closing `%s': %s."), s->fn, strerror (errno));
281 if (s->included_from)
283 getl_head = s->included_from;
284 getl_head->includes = NULL;
289 if (NULL == getl_head)
296 /* Closes all files. */
298 getl_close_all (void)
305 getl_is_separate(void)
307 return (getl_head && getl_head->separate);
311 getl_set_separate(bool sep)
315 getl_head->separate = sep ;
319 /* Puts the current file and line number in *FN and *LN, respectively,
320 or NULL and -1 if none. */
322 getl_location (const char **fn, int *ln)
325 *fn = getl_head ? getl_head->fn : NULL;
327 *ln = getl_head ? getl_head->ln : -1;
331 getl_reading_script (void)
333 return (getl_head != NULL);