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., 59 Temple Place - Suite 330, Boston, MA
21 #include "file-handle.h"
35 /* File handle private data. */
36 struct private_file_handle
38 char *name; /* File handle identifier. */
39 char *filename; /* Filename as provided by user. */
40 struct file_identity *identity; /* For checking file identity. */
41 struct file_locator where; /* Used for reporting error messages. */
42 enum file_handle_mode mode; /* File mode. */
43 size_t length; /* Length of fixed-format records. */
44 size_t tab_width; /* Tab width, 0=do not expand tabs. */
47 /* Linked list of file handles. */
48 struct file_handle_list
50 struct file_handle *handle;
51 struct file_handle_list *next;
54 static struct file_handle_list *file_handles;
55 struct file_handle *inline_file;
57 static struct file_handle *create_file_handle (const char *handle_name,
58 const char *filename);
64 tabwidth=integer "x>=0" "%s must be nonnegative";
65 mode=mode:!character/image.
70 static struct file_handle *
71 get_handle_with_name (const char *handle_name)
73 struct file_handle_list *iter;
75 for (iter = file_handles; iter != NULL; iter = iter->next)
76 if (!strcmp (handle_name, iter->handle->private->name))
81 static struct file_handle *
82 get_handle_for_filename (const char *filename)
84 struct file_identity *identity;
85 struct file_handle_list *iter;
87 /* First check for a file with the same identity. */
88 identity = fn_get_identity (filename);
91 for (iter = file_handles; iter != NULL; iter = iter->next)
92 if (iter->handle->private->identity != NULL
93 && !fn_compare_file_identities (identity,
94 iter->handle->private->identity))
96 fn_free_identity (identity);
99 fn_free_identity (identity);
102 /* Then check for a file with the same name. */
103 for (iter = file_handles; iter != NULL; iter = iter->next)
104 if (!strcmp (filename, iter->handle->private->filename))
111 cmd_file_handle (void)
115 struct cmd_file_handle cmd;
116 struct file_handle *handle;
118 if (!lex_force_id ())
120 strcpy (handle_name, tokid);
122 handle = get_handle_with_name (handle_name);
125 msg (SE, _("File handle %s already refers to "
126 "file %s. File handle cannot be redefined within a "
128 tokid, handle->private->filename);
133 if (!lex_force_match ('/'))
136 if (!parse_file_handle (&cmd))
141 lex_error (_("expecting end of command"));
145 if (cmd.s_name == NULL)
147 msg (SE, _("The FILE HANDLE required subcommand NAME "
152 handle = create_file_handle (handle_name, cmd.s_name);
156 handle->private->mode = MODE_TEXT;
157 if (cmd.sbc_tabwidth)
158 handle->private->tab_width = cmd.n_tabwidth;
160 handle->private->tab_width = 4;
163 handle->private->mode = MODE_BINARY;
164 if (cmd.n_lrecl == NOT_LONG)
166 msg (SE, _("Fixed-length records were specified on /RECFORM, but "
167 "record length was not specified on /LRECL. "
168 "Assuming 1024-character records."));
169 handle->private->length = 1024;
171 else if (cmd.n_lrecl < 1)
173 msg (SE, _("Record length (%ld) must be at least one byte. "
174 "1-character records will be assumed."), cmd.n_lrecl);
175 handle->private->length = 1;
178 handle->private->length = cmd.n_lrecl;
187 free_file_handle (&cmd);
191 /* File handle functions. */
193 /* Creates and returns a new file handle with the given values
194 and defaults for other values. Adds the created file handle
195 to the global list. */
196 static struct file_handle *
197 create_file_handle (const char *handle_name, const char *filename)
199 struct file_handle *handle;
200 struct file_handle_list *list;
202 /* Create and initialize file handle. */
203 handle = xmalloc (sizeof *handle);
204 handle->private = xmalloc (sizeof *handle->private);
205 handle->private->name = xstrdup (handle_name);
206 handle->private->filename = xstrdup (filename);
207 handle->private->identity = fn_get_identity (filename);
208 handle->private->where.filename = handle->private->filename;
209 handle->private->where.line_number = 0;
210 handle->private->mode = MODE_TEXT;
211 handle->private->length = 1024;
212 handle->private->tab_width = 4;
214 handle->class = NULL;
216 /* Add file handle to global list. */
217 list = xmalloc (sizeof *list);
218 list->handle = handle;
219 list->next = file_handles;
225 /* Closes the stdio FILE associated with handle H. Frees internal
226 buffers associated with that file. Does *not* destroy the file
227 handle H. (File handles are permanent during a session.) */
229 fh_close_handle (struct file_handle *h)
234 if (h->class != NULL)
240 /* Initialize the hash of file handles; inserts the "inline file"
245 if (inline_file == NULL)
247 inline_file = create_file_handle ("INLINE", _("<Inline File>"));
248 inline_file->private->length = 80;
252 /* Parses a file handle name, which may be a filename as a string or
253 a file handle name as an identifier. Returns the file handle or
256 fh_parse_file_handle (void)
258 struct file_handle *handle;
260 if (token != T_ID && token != T_STRING)
262 lex_error (_("expecting a file name or handle name"));
266 /* Check for named handles first, then go by filename. */
269 handle = get_handle_with_name (tokid);
271 handle = get_handle_for_filename (ds_c_str (&tokstr));
274 char *filename = ds_c_str (&tokstr);
275 char *handle_name = xmalloc (strlen (filename) + 3);
276 sprintf (handle_name, "\"%s\"", filename);
277 handle = create_file_handle (handle_name, filename);
286 /* Returns the identifier of file HANDLE. If HANDLE was created
287 by referring to a filename instead of a handle name, returns
288 the filename, enclosed in double quotes. Return value is
289 owned by the file handle.
291 Useful for printing error messages about use of file handles. */
293 handle_get_name (const struct file_handle *handle)
295 return handle->private->name;
298 /* Returns the name of the file associated with HANDLE. */
300 handle_get_filename (const struct file_handle *handle)
302 return handle->private->filename;
305 /* Returns the mode of HANDLE. */
306 enum file_handle_mode
307 handle_get_mode (const struct file_handle *handle)
309 assert (handle != NULL);
310 return handle->private->mode;
313 /* Returns the width of a logical record on HANDLE. Applicable
314 only to MODE_BINARY files. */
316 handle_get_record_width (const struct file_handle *handle)
318 assert (handle != NULL);
319 return handle->private->length;
322 /* Returns the number of characters per tab stop for HANDLE, or
323 zero if tabs are not to be expanded. Applicable only to
326 handle_get_tab_width (const struct file_handle *handle)
328 assert (handle != NULL);
329 return handle->private->tab_width;