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 fh_mode mode; /* File mode. */
51 size_t record_width; /* 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. */
60 static struct file_handle *file_handles;
62 /* File handle initialization routine. */
66 /* Currently nothing to do. */
69 /* Frees all the file handles. */
73 struct file_handle *fh, *next;
75 for (fh = file_handles; fh != NULL; fh = next)
80 fn_free_identity (fh->identity);
86 /* Returns the handle named HANDLE_NAME, or a null pointer if
89 fh_from_name (const char *handle_name)
91 struct file_handle *iter;
93 for (iter = file_handles; iter != NULL; iter = iter->next)
94 if (!strcasecmp (handle_name, iter->name))
99 /* Returns the handle for the file named FILENAME,
100 or a null pointer if none exists.
101 Different names for the same file (e.g. "x" and "./x") are
102 considered equivalent. */
104 fh_from_filename (const char *filename)
106 struct file_identity *identity;
107 struct file_handle *iter;
109 /* First check for a file with the same identity. */
110 identity = fn_get_identity (filename);
111 if (identity != NULL)
113 for (iter = file_handles; iter != NULL; iter = iter->next)
114 if (iter->identity != NULL
115 && !fn_compare_file_identities (identity, iter->identity))
117 fn_free_identity (identity);
120 fn_free_identity (identity);
123 /* Then check for a file with the same name. */
124 for (iter = file_handles; iter != NULL; iter = iter->next)
125 if (!strcmp (filename, iter->filename))
131 /* Creates and returns a new file handle with the given values
132 and defaults for other values. Adds the created file handle
133 to the global list. */
135 fh_create (const char *handle_name, const char *filename,
136 const struct fh_properties *properties)
138 struct file_handle *handle;
140 /* Create and initialize file handle. */
141 handle = xmalloc (sizeof *handle);
142 handle->next = file_handles;
143 handle->name = xstrdup (handle_name);
144 handle->filename = xstrdup (filename);
145 handle->identity = fn_get_identity (filename);
146 handle->where.filename = handle->filename;
147 handle->where.line_number = 0;
148 handle->mode = properties->mode;
149 handle->record_width = properties->record_width;
150 handle->tab_width = properties->tab_width;
151 handle->open_cnt = 0;
154 file_handles = handle;
159 /* Returns a set of default properties for a file handle. */
160 const struct fh_properties *
161 fh_default_properties (void)
163 static const struct fh_properties default_properties = {MODE_TEXT, 1024, 4};
164 return &default_properties;
167 /* Returns an English description of MODE,
168 which is in the format of the MODE argument to fh_open(). */
170 mode_name (const char *mode)
172 assert (mode != NULL);
173 assert (mode[0] == 'r' || mode[0] == 'w');
175 return mode[0] == 'r' ? "reading" : "writing";
178 /* Tries to open handle H with the given TYPE and MODE.
180 TYPE is the sort of file, e.g. "system file". Only one given
181 type of access is allowed on a given file handle at once.
183 MODE combines the read or write mode with the sharing mode.
184 The first character is 'r' for read, 'w' for write. The
185 second character is 's' to permit sharing, 'e' to require
188 Returns the address of a void * that the caller can use for
189 data specific to the file handle if successful, or a null
190 pointer on failure. For exclusive access modes the void *
191 will always be a null pointer at return. In shared access
192 modes the void * will necessarily be null only if no other
195 If successful, a reference to type is retained, so it should
196 probably be a string literal. */
198 fh_open (struct file_handle *h, const char *type, const char *mode)
201 assert (type != NULL);
202 assert (mode != NULL);
203 assert (mode[0] == 'r' || mode[0] == 'w');
204 assert (mode[1] == 's' || mode[1] == 'e');
205 assert (mode[2] == '\0');
207 if (h->open_cnt != 0)
209 if (strcmp (h->type, type))
211 msg (SE, _("Can't open %s as a %s because it is "
212 "already open as a %s"),
213 fh_get_name (h), type, h->type);
216 else if (strcmp (h->open_mode, mode))
218 msg (SE, _("Can't open %s as a %s for %s because it is "
219 "already open for %s"),
220 fh_get_name (h), type, mode_name (mode),
221 mode_name (h->open_mode));
224 else if (h->open_mode[1] == 'e')
226 msg (SE, _("Can't re-open %s as a %s for %s"),
227 fh_get_name (h), type, mode_name (mode));
234 strcpy (h->open_mode, mode);
235 assert (h->aux == NULL);
242 /* Closes file handle H, which must have been open for the
243 specified TYPE and MODE of access provided to fh_open().
244 Returns zero if the file is now closed, nonzero if it is still
245 open due to another reference. */
247 fh_close (struct file_handle *h, const char *type, const char *mode)
250 assert (h->open_cnt > 0);
251 assert (type != NULL);
252 assert (!strcmp (type, h->type));
253 assert (mode != NULL);
254 assert (!strcmp (mode, h->open_mode));
257 if (h->open_cnt == 0)
265 /* Returns the identifier of file HANDLE. If HANDLE was created
266 by referring to a filename instead of a handle name, returns
267 the filename, enclosed in double quotes. Return value is
268 owned by the file handle.
270 Useful for printing error messages about use of file handles. */
272 fh_get_name (const struct file_handle *handle)
274 assert (handle != NULL);
278 /* Returns the name of the file associated with HANDLE. */
280 fh_get_filename (const struct file_handle *handle)
282 assert (handle != NULL);
283 return handle->filename;
286 /* Returns the mode of HANDLE. */
288 fh_get_mode (const struct file_handle *handle)
290 assert (handle != NULL);
294 /* Returns the width of a logical record on HANDLE. */
296 fh_get_record_width (const struct file_handle *handle)
298 assert (handle != NULL);
299 return handle->record_width;
302 /* Returns the number of characters per tab stop for HANDLE, or
303 zero if tabs are not to be expanded. Applicable only to
306 fh_get_tab_width (const struct file_handle *handle)
308 assert (handle != NULL);
309 return handle->tab_width;