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.
182 If successful, a reference to TYPE is retained, so it should
183 probably be a string literal.
185 MODE combines the read or write mode with the sharing mode.
186 The first character is 'r' for read, 'w' for write. The
187 second character is 's' to permit sharing, 'e' to require
190 Returns the address of a void * that the caller can use for
191 data specific to the file handle if successful, or a null
192 pointer on failure. For exclusive access modes the void *
193 will always be a null pointer at return. In shared access
194 modes the void * will necessarily be null only if no other
195 sharers are active. */
197 fh_open (struct file_handle *h, const char *type, const char *mode)
200 assert (type != NULL);
201 assert (mode != NULL);
202 assert (mode[0] == 'r' || mode[0] == 'w');
203 assert (mode[1] == 's' || mode[1] == 'e');
204 assert (mode[2] == '\0');
206 if (h->open_cnt != 0)
208 if (strcmp (h->type, type))
210 msg (SE, _("Can't open %s as a %s because it is "
211 "already open as a %s"),
212 fh_get_name (h), type, h->type);
215 else if (strcmp (h->open_mode, mode))
217 msg (SE, _("Can't open %s as a %s for %s because it is "
218 "already open for %s"),
219 fh_get_name (h), type, mode_name (mode),
220 mode_name (h->open_mode));
223 else if (h->open_mode[1] == 'e')
225 msg (SE, _("Can't re-open %s as a %s for %s"),
226 fh_get_name (h), type, mode_name (mode));
233 strcpy (h->open_mode, mode);
234 assert (h->aux == NULL);
241 /* Closes file handle H, which must have been open for the
242 specified TYPE and MODE of access provided to fh_open().
243 Returns zero if the file is now closed, nonzero if it is still
244 open due to another reference. */
246 fh_close (struct file_handle *h, const char *type, const char *mode)
249 assert (h->open_cnt > 0);
250 assert (type != NULL);
251 assert (!strcmp (type, h->type));
252 assert (mode != NULL);
253 assert (!strcmp (mode, h->open_mode));
256 if (h->open_cnt == 0)
264 /* Returns the identifier of file HANDLE. If HANDLE was created
265 by referring to a filename instead of a handle name, returns
266 the filename, enclosed in double quotes. Return value is
267 owned by the file handle.
269 Useful for printing error messages about use of file handles. */
271 fh_get_name (const struct file_handle *handle)
273 assert (handle != NULL);
277 /* Returns the name of the file associated with HANDLE. */
279 fh_get_filename (const struct file_handle *handle)
281 assert (handle != NULL);
282 return handle->filename;
285 /* Returns the mode of HANDLE. */
287 fh_get_mode (const struct file_handle *handle)
289 assert (handle != NULL);
293 /* Returns the width of a logical record on HANDLE. */
295 fh_get_record_width (const struct file_handle *handle)
297 assert (handle != NULL);
298 return handle->record_width;
301 /* Returns the number of characters per tab stop for HANDLE, or
302 zero if tabs are not to be expanded. Applicable only to
305 fh_get_tab_width (const struct file_handle *handle)
307 assert (handle != NULL);
308 return handle->tab_width;