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. */
70 /* Destroy file handle.
71 Normally needed only if a file_handle needs to be re-assigned.
72 Otherwise, just let fh_done clean destroy the handle.
75 fh_free(struct file_handle *fh)
83 fn_free_identity (fh->identity);
88 /* Frees all the file handles. */
92 struct file_handle *fh, *next;
94 for (fh = file_handles; fh != NULL; fh = next)
102 /* Returns the handle named HANDLE_NAME, or a null pointer if
105 fh_from_name (const char *handle_name)
107 struct file_handle *iter;
109 for (iter = file_handles; iter != NULL; iter = iter->next)
110 if (!strcasecmp (handle_name, iter->name))
115 /* Returns the handle for the file named FILENAME,
116 or a null pointer if none exists.
117 Different names for the same file (e.g. "x" and "./x") are
118 considered equivalent. */
120 fh_from_filename (const char *filename)
122 struct file_identity *identity;
123 struct file_handle *iter;
125 /* First check for a file with the same identity. */
126 identity = fn_get_identity (filename);
127 if (identity != NULL)
129 for (iter = file_handles; iter != NULL; iter = iter->next)
130 if (iter->identity != NULL
131 && !fn_compare_file_identities (identity, iter->identity))
133 fn_free_identity (identity);
136 fn_free_identity (identity);
139 /* Then check for a file with the same name. */
140 for (iter = file_handles; iter != NULL; iter = iter->next)
141 if (!strcmp (filename, iter->filename))
147 /* Creates and returns a new file handle with the given values
148 and defaults for other values. Adds the created file handle
149 to the global list. */
151 fh_create (const char *handle_name, const char *filename,
152 const struct fh_properties *properties)
154 struct file_handle *handle;
159 /* Create and initialize file handle. */
160 handle = xmalloc (sizeof *handle);
161 handle->next = file_handles;
162 handle->name = xstrdup (handle_name);
163 handle->filename = xstrdup (filename);
164 handle->identity = fn_get_identity (filename);
165 handle->where.filename = handle->filename;
166 handle->where.line_number = 0;
167 handle->mode = properties->mode;
168 handle->record_width = properties->record_width;
169 handle->tab_width = properties->tab_width;
170 handle->open_cnt = 0;
173 file_handles = handle;
178 /* Returns a set of default properties for a file handle. */
179 const struct fh_properties *
180 fh_default_properties (void)
182 static const struct fh_properties default_properties = {MODE_TEXT, 1024, 4};
183 return &default_properties;
186 /* Returns an English description of MODE,
187 which is in the format of the MODE argument to fh_open(). */
189 mode_name (const char *mode)
191 assert (mode != NULL);
192 assert (mode[0] == 'r' || mode[0] == 'w');
194 return mode[0] == 'r' ? "reading" : "writing";
197 /* Tries to open handle H with the given TYPE and MODE.
199 TYPE is the sort of file, e.g. "system file". Only one given
200 type of access is allowed on a given file handle at once.
201 If successful, a reference to TYPE is retained, so it should
202 probably be a string literal.
204 MODE combines the read or write mode with the sharing mode.
205 The first character is 'r' for read, 'w' for write. The
206 second character is 's' to permit sharing, 'e' to require
209 Returns the address of a void * that the caller can use for
210 data specific to the file handle if successful, or a null
211 pointer on failure. For exclusive access modes the void *
212 will always be a null pointer at return. In shared access
213 modes the void * will necessarily be null only if no other
214 sharers are active. */
216 fh_open (struct file_handle *h, const char *type, const char *mode)
219 assert (type != NULL);
220 assert (mode != NULL);
221 assert (mode[0] == 'r' || mode[0] == 'w');
222 assert (mode[1] == 's' || mode[1] == 'e');
223 assert (mode[2] == '\0');
225 if (h->open_cnt != 0)
227 if (strcmp (h->type, type))
229 msg (SE, _("Can't open %s as a %s because it is "
230 "already open as a %s"),
231 fh_get_name (h), type, h->type);
234 else if (strcmp (h->open_mode, mode))
236 msg (SE, _("Can't open %s as a %s for %s because it is "
237 "already open for %s"),
238 fh_get_name (h), type, mode_name (mode),
239 mode_name (h->open_mode));
242 else if (h->open_mode[1] == 'e')
244 msg (SE, _("Can't re-open %s as a %s for %s"),
245 fh_get_name (h), type, mode_name (mode));
252 strcpy (h->open_mode, mode);
253 assert (h->aux == NULL);
260 /* Closes file handle H, which must have been open for the
261 specified TYPE and MODE of access provided to fh_open().
262 Returns zero if the file is now closed, nonzero if it is still
263 open due to another reference. */
265 fh_close (struct file_handle *h, const char *type, const char *mode)
268 assert (h->open_cnt > 0);
269 assert (type != NULL);
270 assert (!strcmp (type, h->type));
271 assert (mode != NULL);
272 assert (!strcmp (mode, h->open_mode));
275 if (h->open_cnt == 0)
283 /* Returns the identifier of file HANDLE. If HANDLE was created
284 by referring to a filename instead of a handle name, returns
285 the filename, enclosed in double quotes. Return value is
286 owned by the file handle.
288 Useful for printing error messages about use of file handles. */
290 fh_get_name (const struct file_handle *handle)
292 assert (handle != NULL);
296 /* Returns the name of the file associated with HANDLE. */
298 fh_get_filename (const struct file_handle *handle)
300 assert (handle != NULL);
301 return handle->filename;
304 /* Returns the mode of HANDLE. */
306 fh_get_mode (const struct file_handle *handle)
308 assert (handle != NULL);
312 /* Returns the width of a logical record on HANDLE. */
314 fh_get_record_width (const struct file_handle *handle)
316 assert (handle != NULL);
317 return handle->record_width;
320 /* Returns the number of characters per tab stop for HANDLE, or
321 zero if tabs are not to be expanded. Applicable only to
324 fh_get_tab_width (const struct file_handle *handle)
326 assert (handle != NULL);
327 return handle->tab_width;