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
21 #include "file-handle.h"
33 #include "file-handle-def.h"
37 #define _(msgid) gettext (msgid)
44 struct file_handle *next; /* Next in global list. */
45 char *name; /* File handle identifier. */
46 char *filename; /* Filename as provided by user. */
47 struct file_identity *identity; /* For checking file identity. */
48 struct file_locator where; /* Used for reporting error messages. */
49 enum file_handle_mode mode; /* File mode. */
50 size_t length; /* Length of fixed-format records. */
51 size_t tab_width; /* Tab width, 0=do not expand tabs. */
53 int open_cnt; /* 0=not open, otherwise # of openers. */
54 const char *type; /* If open, type of file. */
55 char open_mode[3]; /* "[rw][se]". */
56 void *aux; /* Aux data pointer for owner if any. */
60 static struct file_handle *file_handles;
64 get_handle_with_name (const char *handle_name)
66 struct file_handle *iter;
68 for (iter = file_handles; iter != NULL; iter = iter->next)
69 if (!strcasecmp (handle_name, iter->name))
75 get_handle_for_filename (const char *filename)
77 struct file_identity *identity;
78 struct file_handle *iter;
80 /* First check for a file with the same identity. */
81 identity = fn_get_identity (filename);
84 for (iter = file_handles; iter != NULL; iter = iter->next)
85 if (iter->identity != NULL
86 && !fn_compare_file_identities (identity, iter->identity))
88 fn_free_identity (identity);
91 fn_free_identity (identity);
94 /* Then check for a file with the same name. */
95 for (iter = file_handles; iter != NULL; iter = iter->next)
96 if (!strcmp (filename, iter->filename))
103 /* File handle functions. */
106 create_file_handle_with_defaults (const char *handle_name,
107 const char *filename)
109 return create_file_handle (handle_name, filename,
114 /* Creates and returns a new file handle with the given values
115 and defaults for other values. Adds the created file handle
116 to the global list. */
118 create_file_handle (const char *handle_name, const char *filename,
119 enum file_handle_mode mode,
124 struct file_handle *handle;
126 /* Create and initialize file handle. */
127 handle = xmalloc (sizeof *handle);
128 handle->next = file_handles;
129 handle->name = xstrdup (handle_name);
130 handle->filename = xstrdup (filename);
131 handle->identity = fn_get_identity (filename);
132 handle->where.filename = handle->filename;
133 handle->where.line_number = 0;
135 handle->length = length;
136 handle->tab_width = tab_width;
137 handle->open_cnt = 0;
140 file_handles = handle;
146 destroy_file_handle(void *fh_, void *aux UNUSED)
148 struct file_handle *fh = fh_;
151 fn_free_identity (fh->identity);
156 mode_name (const char *mode)
158 assert (mode != NULL);
159 assert (mode[0] == 'r' || mode[0] == 'w');
161 return mode[0] == 'r' ? "reading" : "writing";
165 /* Tries to open handle H with the given TYPE and MODE.
167 TYPE is the sort of file, e.g. "system file". Only one given
168 type of access is allowed on a given file handle at once.
170 MODE combines the read or write mode with the sharing mode.
171 The first character is 'r' for read, 'w' for write. The
172 second character is 's' to permit sharing, 'e' to require
175 Returns the address of a void * that the caller can use for
176 data specific to the file handle if successful, or a null
177 pointer on failure. For exclusive access modes the void *
178 will always be a null pointer at return. In shared access
179 modes the void * will necessarily be null only if no other
182 If successful, a reference to type is retained, so it should
183 probably be a string literal. */
185 fh_open (struct file_handle *h, const char *type, const char *mode)
188 assert (type != NULL);
189 assert (mode != NULL);
190 assert (mode[0] == 'r' || mode[0] == 'w');
191 assert (mode[1] == 's' || mode[1] == 'e');
192 assert (mode[2] == '\0');
194 if (h->open_cnt != 0)
196 if (strcmp (h->type, type))
198 msg (SE, _("Can't open %s as a %s because it is "
199 "already open as a %s"),
200 handle_get_name (h), type, h->type);
203 else if (strcmp (h->open_mode, mode))
205 msg (SE, _("Can't open %s as a %s for %s because it is "
206 "already open for %s"),
207 handle_get_name (h), type,
208 mode_name (mode), mode_name (h->open_mode));
211 else if (h->open_mode[1] == 'e')
213 msg (SE, _("Can't re-open %s as a %s for %s"),
214 handle_get_name (h), type, mode_name (mode));
221 strcpy (h->open_mode, mode);
222 assert (h->aux == NULL);
229 /* Closes file handle H, which must have been open for the
230 specified TYPE and MODE of access provided to fh_open().
231 Returns zero if the file is now closed, nonzero if it is still
232 open due to another reference. */
234 fh_close (struct file_handle *h, const char *type, const char *mode)
237 assert (h->open_cnt > 0);
238 assert (type != NULL);
239 assert (!strcmp (type, h->type));
240 assert (mode != NULL);
241 assert (!strcmp (mode, h->open_mode));
244 if (h->open_cnt == 0)
255 /* Returns the identifier of file HANDLE. If HANDLE was created
256 by referring to a filename instead of a handle name, returns
257 the filename, enclosed in double quotes. Return value is
258 owned by the file handle.
260 Useful for printing error messages about use of file handles. */
262 handle_get_name (const struct file_handle *handle)
264 assert (handle != NULL);
268 /* Returns the name of the file associated with HANDLE. */
270 handle_get_filename (const struct file_handle *handle)
272 assert (handle != NULL);
273 return handle->filename;
276 /* Returns the mode of HANDLE. */
277 enum file_handle_mode
278 handle_get_mode (const struct file_handle *handle)
280 assert (handle != NULL);
284 /* Returns the width of a logical record on HANDLE. */
286 handle_get_record_width (const struct file_handle *handle)
288 assert (handle != NULL);
289 return handle->length;
292 /* Returns the number of characters per tab stop for HANDLE, or
293 zero if tabs are not to be expanded. Applicable only to
296 handle_get_tab_width (const struct file_handle *handle)
298 assert (handle != NULL);
299 return handle->tab_width;