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. */
46 /* Linked list of file handles. */
47 struct file_handle_list
49 struct file_handle *handle;
50 struct file_handle_list *next;
53 static struct file_handle_list *file_handles;
54 struct file_handle *inline_file;
56 static struct file_handle *create_file_handle (const char *handle_name,
57 const char *filename);
62 recform=recform:fixed/!variable/spanned;
64 mode=mode:!character/image/binary/multipunch/_360.
69 static struct file_handle *
70 get_handle_with_name (const char *handle_name)
72 struct file_handle_list *iter;
74 for (iter = file_handles; iter != NULL; iter = iter->next)
75 if (!strcmp (handle_name, iter->handle->private->name))
80 static struct file_handle *
81 get_handle_for_filename (const char *filename)
83 struct file_identity *identity;
84 struct file_handle_list *iter;
86 /* First check for a file with the same identity. */
87 identity = fn_get_identity (filename);
90 for (iter = file_handles; iter != NULL; iter = iter->next)
91 if (iter->handle->private->identity != NULL
92 && !fn_compare_file_identities (identity,
93 iter->handle->private->identity))
95 fn_free_identity (identity);
98 fn_free_identity (identity);
101 /* Then check for a file with the same name. */
102 for (iter = file_handles; iter != NULL; iter = iter->next)
103 if (!strcmp (filename, iter->handle->private->filename))
110 cmd_file_handle (void)
114 struct cmd_file_handle cmd;
115 struct file_handle *handle;
117 if (!lex_force_id ())
119 strcpy (handle_name, tokid);
121 handle = get_handle_with_name (handle_name);
124 msg (SE, _("File handle %s already refers to "
125 "file %s. File handle cannot be redefined within a "
127 tokid, handle->private->filename);
132 if (!lex_force_match ('/'))
135 if (!parse_file_handle (&cmd))
140 lex_error (_("expecting end of command"));
144 if (cmd.s_name == NULL)
146 msg (SE, _("The FILE HANDLE required subcommand NAME "
151 handle = create_file_handle (handle_name, cmd.s_name);
155 handle->private->mode = MODE_TEXT;
158 handle->private->mode = MODE_BINARY;
159 if (cmd.n_lrecl == NOT_LONG)
161 msg (SE, _("Fixed-length records were specified on /RECFORM, but "
162 "record length was not specified on /LRECL. "
163 "Assuming 1024-character records."));
164 handle->private->length = 1024;
166 else if (cmd.n_lrecl < 1)
168 msg (SE, _("Record length (%ld) must be at least one byte. "
169 "1-character records will be assumed."), cmd.n_lrecl);
170 handle->private->length = 1;
173 handle->private->length = cmd.n_lrecl;
182 free_file_handle (&cmd);
186 /* File handle functions. */
188 /* Creates and returns a new file handle with the given values
189 and defaults for other values. Adds the created file handle
190 to the global list. */
191 static struct file_handle *
192 create_file_handle (const char *handle_name, const char *filename)
194 struct file_handle *handle;
195 struct file_handle_list *list;
197 /* Create and initialize file handle. */
198 handle = xmalloc (sizeof *handle);
199 handle->private = xmalloc (sizeof *handle->private);
200 handle->private->name = xstrdup (handle_name);
201 handle->private->filename = xstrdup (filename);
202 handle->private->identity = fn_get_identity (filename);
203 handle->private->where.filename = handle->private->filename;
204 handle->private->where.line_number = 0;
205 handle->private->mode = MODE_TEXT;
206 handle->private->length = 1024;
208 handle->class = NULL;
210 /* Add file handle to global list. */
211 list = xmalloc (sizeof *list);
212 list->handle = handle;
213 list->next = file_handles;
219 /* Closes the stdio FILE associated with handle H. Frees internal
220 buffers associated with that file. Does *not* destroy the file
221 handle H. (File handles are permanent during a session.) */
223 fh_close_handle (struct file_handle *h)
228 if (h->class != NULL)
234 /* Initialize the hash of file handles; inserts the "inline file"
239 if (inline_file == NULL)
241 inline_file = create_file_handle ("INLINE", _("<Inline File>"));
242 inline_file->private->length = 80;
246 /* Parses a file handle name, which may be a filename as a string or
247 a file handle name as an identifier. Returns the file handle or
250 fh_parse_file_handle (void)
252 struct file_handle *handle;
254 if (token != T_ID && token != T_STRING)
256 lex_error (_("expecting a file name or handle name"));
260 /* Check for named handles first, then go by filename. */
263 handle = get_handle_with_name (tokid);
265 handle = get_handle_for_filename (ds_value (&tokstr));
268 char *filename = ds_value (&tokstr);
269 char *handle_name = xmalloc (strlen (filename) + 3);
270 sprintf (handle_name, "\"%s\"", filename);
271 handle = create_file_handle (handle_name, filename);
280 /* Returns the identifier of file HANDLE. If HANDLE was created
281 by referring to a filename instead of a handle name, returns
282 the filename, enclosed in double quotes. Return value is
283 owned by the file handle.
285 Useful for printing error messages about use of file handles. */
287 handle_get_name (const struct file_handle *handle)
289 return handle->private->name;
292 /* Returns the name of the file associated with HANDLE. */
294 handle_get_filename (const struct file_handle *handle)
296 return handle->private->filename;
299 /* Returns the mode of HANDLE. */
300 enum file_handle_mode
301 handle_get_mode (const struct file_handle *handle)
303 assert (handle != NULL);
304 return handle->private->mode;
307 /* Returns the width of a logical record on HANDLE. */
309 handle_get_record_width (const struct file_handle *handle)
311 assert (handle != NULL);
312 return handle->private->length;