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"
22 #include "file-handle-def.h"
34 #include "file-handle-def.h"
38 #define _(msgid) gettext (msgid)
45 struct file_handle *next; /* Next in global list. */
46 char *name; /* File handle identifier. */
47 char *filename; /* Filename as provided by user. */
48 struct file_identity *identity; /* For checking file identity. */
49 struct file_locator where; /* Used for reporting error messages. */
50 enum file_handle_mode mode; /* File mode. */
51 size_t length; /* Length of fixed-format records. */
52 size_t tab_width; /* Tab width, 0=do not expand tabs. */
54 int open_cnt; /* 0=not open, otherwise # of openers. */
55 const char *type; /* If open, type of file. */
56 char open_mode[3]; /* "[rw][se]". */
57 void *aux; /* Aux data pointer for owner if any. */
61 static struct file_handle *file_handles;
65 get_handle_with_name (const char *handle_name)
67 struct file_handle *iter;
69 for (iter = file_handles; iter != NULL; iter = iter->next)
70 if (!strcasecmp (handle_name, iter->name))
76 get_handle_for_filename (const char *filename)
78 struct file_identity *identity;
79 struct file_handle *iter;
81 /* First check for a file with the same identity. */
82 identity = fn_get_identity (filename);
85 for (iter = file_handles; iter != NULL; iter = iter->next)
86 if (iter->identity != NULL
87 && !fn_compare_file_identities (identity, iter->identity))
89 fn_free_identity (identity);
92 fn_free_identity (identity);
95 /* Then check for a file with the same name. */
96 for (iter = file_handles; iter != NULL; iter = iter->next)
97 if (!strcmp (filename, iter->filename))
104 /* File handle functions. */
107 create_file_handle_with_defaults (const char *handle_name,
108 const char *filename)
110 return create_file_handle (handle_name, filename,
115 /* Creates and returns a new file handle with the given values
116 and defaults for other values. Adds the created file handle
117 to the global list. */
119 create_file_handle (const char *handle_name, const char *filename,
120 enum file_handle_mode mode,
125 struct file_handle *handle;
127 /* Create and initialize file handle. */
128 handle = xmalloc (sizeof *handle);
129 handle->next = file_handles;
130 handle->name = xstrdup (handle_name);
131 handle->filename = xstrdup (filename);
132 handle->identity = fn_get_identity (filename);
133 handle->where.filename = handle->filename;
134 handle->where.line_number = 0;
136 handle->length = length;
137 handle->tab_width = tab_width;
138 handle->open_cnt = 0;
141 file_handles = handle;
147 destroy_file_handle(void *fh_, void *aux UNUSED)
149 struct file_handle *fh = fh_;
152 fn_free_identity (fh->identity);
157 mode_name (const char *mode)
159 assert (mode != NULL);
160 assert (mode[0] == 'r' || mode[0] == 'w');
162 return mode[0] == 'r' ? "reading" : "writing";
166 /* Tries to open handle H with the given TYPE and MODE.
168 TYPE is the sort of file, e.g. "system file". Only one given
169 type of access is allowed on a given file handle at once.
171 MODE combines the read or write mode with the sharing mode.
172 The first character is 'r' for read, 'w' for write. The
173 second character is 's' to permit sharing, 'e' to require
176 Returns the address of a void * that the caller can use for
177 data specific to the file handle if successful, or a null
178 pointer on failure. For exclusive access modes the void *
179 will always be a null pointer at return. In shared access
180 modes the void * will necessarily be null only if no other
183 If successful, a reference to type is retained, so it should
184 probably be a string literal. */
186 fh_open (struct file_handle *h, const char *type, const char *mode)
189 assert (type != NULL);
190 assert (mode != NULL);
191 assert (mode[0] == 'r' || mode[0] == 'w');
192 assert (mode[1] == 's' || mode[1] == 'e');
193 assert (mode[2] == '\0');
195 if (h->open_cnt != 0)
197 if (strcmp (h->type, type))
199 msg (SE, _("Can't open %s as a %s because it is "
200 "already open as a %s"),
201 handle_get_name (h), type, h->type);
204 else if (strcmp (h->open_mode, mode))
206 msg (SE, _("Can't open %s as a %s for %s because it is "
207 "already open for %s"),
208 handle_get_name (h), type,
209 mode_name (mode), mode_name (h->open_mode));
212 else if (h->open_mode[1] == 'e')
214 msg (SE, _("Can't re-open %s as a %s for %s"),
215 handle_get_name (h), type, mode_name (mode));
222 strcpy (h->open_mode, mode);
223 assert (h->aux == NULL);
230 /* Closes file handle H, which must have been open for the
231 specified TYPE and MODE of access provided to fh_open().
232 Returns zero if the file is now closed, nonzero if it is still
233 open due to another reference. */
235 fh_close (struct file_handle *h, const char *type, const char *mode)
238 assert (h->open_cnt > 0);
239 assert (type != NULL);
240 assert (!strcmp (type, h->type));
241 assert (mode != NULL);
242 assert (!strcmp (mode, h->open_mode));
245 if (h->open_cnt == 0)
256 /* Returns the identifier of file HANDLE. If HANDLE was created
257 by referring to a filename instead of a handle name, returns
258 the filename, enclosed in double quotes. Return value is
259 owned by the file handle.
261 Useful for printing error messages about use of file handles. */
263 handle_get_name (const struct file_handle *handle)
265 assert (handle != NULL);
269 /* Returns the name of the file associated with HANDLE. */
271 handle_get_filename (const struct file_handle *handle)
273 assert (handle != NULL);
274 return handle->filename;
277 /* Returns the mode of HANDLE. */
278 enum file_handle_mode
279 handle_get_mode (const struct file_handle *handle)
281 assert (handle != NULL);
285 /* Returns the width of a logical record on HANDLE. */
287 handle_get_record_width (const struct file_handle *handle)
289 assert (handle != NULL);
290 return handle->length;
293 /* Returns the number of characters per tab stop for HANDLE, or
294 zero if tabs are not to be expanded. Applicable only to
297 handle_get_tab_width (const struct file_handle *handle)
299 assert (handle != NULL);
300 return handle->tab_width;