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 struct getl_script *getl_head;
63 struct getl_script *getl_tail;
66 /* Returns a string that represents the directory that the syntax file
67 currently being read resides in. If there is no syntax file then
68 returns the OS current working directory. Return value must be
71 getl_get_current_directory (void)
73 return getl_head ? fn_dirname (getl_head->fn) : fn_get_cwd ();
76 /* Delete everything from the include path. */
78 getl_clear_include_path (void)
80 ds_clear (&getl_include_path);
83 /* Add to the include path. */
85 getl_add_include_dir (const char *path)
87 if (ds_length (&getl_include_path))
88 ds_putc (&getl_include_path, PATH_DELIMITER);
90 ds_puts (&getl_include_path, path);
93 /* Adds FN to the tail end of the list of script files to execute.
94 OPTIONS is the value to stick in the options field of the
95 getl_script struct. If WHERE is zero then the file is added after
96 all other files; otherwise it is added before all other files (this
97 can be done only if parsing has not yet begun). */
99 getl_add_file (const char *fn, int separate, int where)
101 struct getl_script *n = xmalloc (sizeof *n);
105 if (getl_tail == NULL)
106 getl_head = getl_tail = n;
108 getl_tail = getl_tail->next = n;
111 assert (getl_head->f == NULL);
115 n->included_from = n->includes = NULL;
116 n->fn = xstrdup (fn);
119 n->separate = separate;
120 n->first_line = NULL;
123 /* Inserts the given file with filename FN into the current file after
126 getl_include (const char *fn)
128 struct getl_script *n;
132 char *cur_dir = getl_get_current_directory ();
133 real_fn = fn_search_path (fn, ds_c_str (&getl_include_path), cur_dir);
139 msg (SE, _("Can't find `%s' in include file search path."), fn);
145 getl_add_file (real_fn, 0, 0);
150 n = xmalloc (sizeof *n);
151 n->included_from = getl_head;
152 getl_head = getl_head->includes = n;
159 n->first_line = NULL;
163 /* Add the virtual file FILE to the list of files to be processed.
164 The first_line field in FILE must already have been initialized. */
166 getl_add_virtual_file (struct getl_script *file)
168 if (getl_tail == NULL)
169 getl_head = getl_tail = file;
171 getl_tail = getl_tail->next = file;
172 file->included_from = file->includes = NULL;
174 file->fn = file->first_line->line;
175 file->ln = -file->first_line->len - 1;
178 file->cur_line = NULL;
179 file->remaining_loops = 1;
180 file->loop_index = -1;
184 /* Causes the DO REPEAT virtual file passed in FILE to be included in
185 the current file. The first_line, cur_line, remaining_loops,
186 loop_index, and macros fields in FILE must already have been
189 getl_add_DO_REPEAT_file (struct getl_script *file)
194 file->included_from = getl_head;
195 getl_head = getl_head->includes = file;
196 file->includes = NULL;
198 assert (file->first_line->len < 0);
199 file->fn = file->first_line->line;
200 file->ln = -file->first_line->len - 1;
205 /* Reads a single line from the line buffer associated with getl_head.
206 Returns 1 if a line was successfully read or 0 if no more lines are
209 getl_handle_line_buffer (void)
211 struct getl_script *s = getl_head;
213 /* Check that we're not all done. */
216 if (s->cur_line == NULL)
219 if (s->remaining_loops-- == 0)
221 s->cur_line = s->first_line;
224 if (s->cur_line->len < 0)
226 s->ln = -s->cur_line->len - 1;
227 s->fn = s->cur_line->line;
228 s->cur_line = s->cur_line->next;
232 while (s->cur_line == NULL);
234 ds_concat (&getl_buf, s->cur_line->line, s->cur_line->len);
236 /* Advance pointers. */
237 s->cur_line = s->cur_line->next;
243 /* Closes the current file, whether it be a main file or included
244 file, then moves getl_head to the next file in the chain. */
246 getl_close_file (void)
248 struct getl_script *s = getl_head;
252 assert (getl_tail != NULL);
256 struct getl_line_list *cur, *next;
258 s->fn = NULL; /* It will be freed below. */
259 for (cur = s->first_line; cur; cur = next)
269 if (s->f && EOF == fn_close (s->fn, s->f))
270 msg (MW, _("Closing `%s': %s."), s->fn, strerror (errno));
273 if (s->included_from)
275 getl_head = s->included_from;
276 getl_head->includes = NULL;
281 if (NULL == getl_head)
288 /* Closes all files. */
290 getl_close_all (void)
297 getl_is_separate(void)
299 return (getl_head && getl_head->separate);
303 getl_set_separate(bool sep)
307 getl_head->separate = sep ;
311 /* Puts the current file and line number in *FN and *LN, respectively,
312 or NULL and -1 if none. */
314 getl_location (const char **fn, int *ln)
317 *fn = getl_head ? getl_head->fn : NULL;
319 *ln = getl_head ? getl_head->ln : -1;
323 getl_reading_script (void)
325 return (getl_head != NULL);
328 /* File locator stack. */
329 static const struct file_locator **file_loc;
330 static int nfile_loc, mfile_loc;
334 getl_uninitialize (void)
337 ds_destroy (&getl_buf);
338 ds_destroy (&getl_include_path);
341 nfile_loc = mfile_loc = 0;
345 /* File locator stack functions. */
347 /* Pushes F onto the stack of file locations. */
349 err_push_file_locator (const struct file_locator *f)
351 if (nfile_loc >= mfile_loc)
358 file_loc = xnrealloc (file_loc, mfile_loc, sizeof *file_loc);
361 file_loc[nfile_loc++] = f;
364 /* Pops F off the stack of file locations.
365 Argument F is only used for verification that that is actually the
366 item on top of the stack. */
368 err_pop_file_locator (const struct file_locator *f)
370 assert (nfile_loc >= 0 && file_loc[nfile_loc - 1] == f);
374 /* Puts the current file and line number in F, or NULL and -1 if
377 err_location (struct file_locator *f)
380 *f = *file_loc[nfile_loc - 1];
382 getl_location (&f->filename, &f->line_number);