X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Ffile-handle-def.c;h=c7ba23d58aeb1fda8162e73124fd7a1508f31370;hb=6999c6d125665923b52ae15cbad83d06c92a8875;hp=66ee25f5f88c0a33885a70c6ea0a87e3127c1ea0;hpb=a19b858e0ac3c69e4a28c0ca6d8674427268a863;p=pspp-builds.git diff --git a/src/data/file-handle-def.c b/src/data/file-handle-def.c index 66ee25f5..c7ba23d5 100644 --- a/src/data/file-handle-def.c +++ b/src/data/file-handle-def.c @@ -1,35 +1,36 @@ -/* PSPP - computes sample statistics. +/* PSPP - a program for statistical analysis. Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. - Written by Ben Pfaff . - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this program. If not, see . */ #include + #include "file-handle-def.h" -#include + +#include #include #include #include + #include #include -#include "filename.h" -#include #include -#include "variable.h" -#include "scratch-handle.h" +#include +#include +#include +#include +#include #include "gettext.h" #define _(msgid) gettext (msgid) @@ -37,20 +38,21 @@ /* (headers) */ /* File handle. */ -struct file_handle +struct file_handle { struct file_handle *next; /* Next in global list. */ int open_cnt; /* 0=not open, otherwise # of openers. */ bool deleted; /* Destroy handle when open_cnt goes to 0? */ - char *name; /* File handle identifier. */ + char id[LONG_NAME_LEN + 1]; /* Identifier token; empty string if none. */ + char *name; /* User-friendly identifying name. */ const char *type; /* If open, type of file. */ char open_mode[3]; /* "[rw][se]". */ void *aux; /* Aux data pointer for owner if any. */ enum fh_referent referent; /* What the file handle refers to. */ /* FH_REF_FILE only. */ - char *filename; /* Filename as provided by user. */ + char *file_name; /* File name as provided by user. */ struct file_identity *identity; /* For checking file identity. */ enum fh_mode mode; /* File mode. */ @@ -72,25 +74,26 @@ static struct file_handle *default_handle; /* The "file" that reads from BEGIN DATA...END DATA. */ static struct file_handle *inline_file; -static struct file_handle *create_handle (const char *name, enum fh_referent); +static struct file_handle *create_handle (const char *id, + const char *name, enum fh_referent); /* File handle initialization routine. */ -void +void fh_init (void) { - inline_file = create_handle ("INLINE", FH_REF_INLINE); + inline_file = create_handle ("INLINE", "INLINE", FH_REF_INLINE); inline_file->record_width = 80; inline_file->tab_width = 8; } /* Free HANDLE and remove it from the global list. */ static void -free_handle (struct file_handle *handle) +free_handle (struct file_handle *handle) { /* Remove handle from global list. */ if (file_handles == handle) file_handles = handle->next; - else + else { struct file_handle *iter = file_handles; while (iter->next != handle) @@ -100,46 +103,46 @@ free_handle (struct file_handle *handle) /* Free data. */ free (handle->name); - free (handle->filename); + free (handle->file_name); fn_free_identity (handle->identity); scratch_handle_destroy (handle->sh); free (handle); } /* Frees all the file handles. */ -void +void fh_done (void) { - while (file_handles != NULL) + while (file_handles != NULL) free_handle (file_handles); } -/* Returns the handle named HANDLE_NAME, or a null pointer if +/* Returns the handle with the given ID, or a null pointer if there is none. */ struct file_handle * -fh_from_name (const char *handle_name) +fh_from_id (const char *id) { struct file_handle *iter; for (iter = file_handles; iter != NULL; iter = iter->next) - if (!iter->deleted && !strcasecmp (handle_name, iter->name)) + if (!iter->deleted && !strcasecmp (id, iter->id)) return iter; return NULL; } -/* Returns the handle for the file named FILENAME, +/* Returns the handle for the file named FILE_NAME, or a null pointer if none exists. Different names for the same file (e.g. "x" and "./x") are considered equivalent. */ struct file_handle * -fh_from_filename (const char *filename) +fh_from_file_name (const char *file_name) { struct file_identity *identity; struct file_handle *iter; - + /* First check for a file with the same identity. */ - identity = fn_get_identity (filename); - if (identity != NULL) + identity = fn_get_identity (file_name); + if (identity != NULL) { for (iter = file_handles; iter != NULL; iter = iter->next) if (!iter->deleted @@ -148,7 +151,7 @@ fh_from_filename (const char *filename) && !fn_compare_file_identities (identity, iter->identity)) { fn_free_identity (identity); - return iter; + return iter; } fn_free_identity (identity); } @@ -156,25 +159,28 @@ fh_from_filename (const char *filename) /* Then check for a file with the same name. */ for (iter = file_handles; iter != NULL; iter = iter->next) if (!iter->deleted - && iter->referent == FH_REF_FILE && !strcmp (filename, iter->filename)) - return iter; + && iter->referent == FH_REF_FILE && !strcmp (file_name, iter->file_name)) + return iter; return NULL; } -/* Creates a new handle with name HANDLE_NAME that refers to - REFERENT. Links the new handle into the global list. Returns - the new handle. +/* Creates a new handle with identifier ID (which may be null) + and name HANDLE_NAME that refers to REFERENT. Links the new + handle into the global list. Returns the new handle. The new handle is not fully initialized. The caller is responsible for completing its initialization. */ static struct file_handle * -create_handle (const char *handle_name, enum fh_referent referent) +create_handle (const char *id, const char *handle_name, + enum fh_referent referent) { struct file_handle *handle = xzalloc (sizeof *handle); + assert (id == NULL || fh_from_id (id) == NULL); handle->next = file_handles; handle->open_cnt = 0; handle->deleted = false; + str_copy_trunc (handle->id, sizeof handle->id, id != NULL ? id : ""); handle->name = xstrdup (handle_name); handle->type = NULL; handle->aux = NULL; @@ -187,36 +193,43 @@ create_handle (const char *handle_name, enum fh_referent referent) which refers to the "inline file" that represents character data in the command file between BEGIN DATA and END DATA. */ struct file_handle * -fh_inline_file (void) +fh_inline_file (void) { return inline_file; } -/* Creates a new file handle named HANDLE_NAME, which must not be - the name of an existing file handle. The new handle is - associated with file FILENAME and the given PROPERTIES. */ +/* Creates a new file handle with the given ID, which may be + null. If it is non-null, it must be unique among existing + file identifiers. The new handle is associated with file + FILE_NAME and the given PROPERTIES. */ struct file_handle * -fh_create_file (const char *handle_name, const char *filename, +fh_create_file (const char *id, const char *file_name, const struct fh_properties *properties) { + char *handle_name; struct file_handle *handle; - assert (fh_from_name (handle_name) == NULL); - handle = create_handle (handle_name, FH_REF_FILE); - handle->filename = xstrdup (filename); - handle->identity = fn_get_identity (filename); + + handle_name = id != NULL ? (char *) id : xasprintf ("\"%s\"", file_name); + handle = create_handle (id, handle_name, FH_REF_FILE); + if (id == NULL) + free (handle_name); + handle->file_name = xstrdup (file_name); + handle->identity = fn_get_identity (file_name); handle->mode = properties->mode; handle->record_width = properties->record_width; handle->tab_width = properties->tab_width; return handle; } -/* Creates a new file handle named HANDLE_NAME, which must not be - the name of an existing file handle. The new handle is +/* Creates a new file handle with the given ID, which must be + unique among existing file identifiers. The new handle is associated with a scratch file (initially empty). */ struct file_handle * -fh_create_scratch (const char *handle_name) +fh_create_scratch (const char *id) { - struct file_handle *handle = create_handle (handle_name, FH_REF_SCRATCH); + struct file_handle *handle; + assert (id != NULL); + handle = create_handle (id, id, FH_REF_SCRATCH); handle->sh = NULL; return handle; } @@ -236,7 +249,7 @@ fh_default_properties (void) destroyed later when it is closed. Normally needed only if a file_handle needs to be re-assigned. Otherwise, just let fh_done() destroy the handle. */ -void +void fh_free (struct file_handle *handle) { if (handle == fh_inline_file () || handle == NULL || handle->deleted) @@ -253,7 +266,7 @@ fh_free (struct file_handle *handle) /* Returns an English description of MODE, which is in the format of the MODE argument to fh_open(). */ static const char * -mode_name (const char *mode) +mode_name (const char *mode) { assert (mode != NULL); assert (mode[0] == 'r' || mode[0] == 'w'); @@ -284,7 +297,7 @@ mode_name (const char *mode) sharers are active. */ void ** fh_open (struct file_handle *h, enum fh_referent mask UNUSED, - const char *type, const char *mode) + const char *type, const char *mode) { assert (h != NULL); assert ((fh_get_referent (h) & mask) != 0); @@ -294,16 +307,16 @@ fh_open (struct file_handle *h, enum fh_referent mask UNUSED, assert (mode[1] == 's' || mode[1] == 'e'); assert (mode[2] == '\0'); - if (h->open_cnt != 0) + if (h->open_cnt != 0) { - if (strcmp (h->type, type)) + if (strcmp (h->type, type)) { msg (SE, _("Can't open %s as a %s because it is " "already open as a %s."), fh_get_name (h), type, h->type); - return NULL; + return NULL; } - else if (strcmp (h->open_mode, mode)) + else if (strcmp (h->open_mode, mode)) { msg (SE, _("Can't open %s as a %s for %s because it is " "already open for %s."), @@ -318,7 +331,7 @@ fh_open (struct file_handle *h, enum fh_referent mask UNUSED, return NULL; } } - else + else { h->type = type; strcpy (h->open_mode, mode); @@ -347,7 +360,7 @@ fh_close (struct file_handle *h, const char *type, const char *mode) assert (mode != NULL); assert (!strcmp (mode, h->open_mode)); - if (--h->open_cnt == 0) + if (--h->open_cnt == 0) { h->type = NULL; h->aux = NULL; @@ -361,15 +374,26 @@ fh_close (struct file_handle *h, const char *type, const char *mode) /* Is the file open? BEGIN DATA...END DATA uses this to detect whether the inline file is actually in use. */ bool -fh_is_open (const struct file_handle *handle) +fh_is_open (const struct file_handle *handle) { return handle->open_cnt > 0; } -/* Returns the identifier of file HANDLE. If HANDLE was created - by referring to a filename instead of a handle name, returns - the filename, enclosed in double quotes. Return value is - owned by the file handle. +/* Returns the identifier that may be used in syntax to name the + given HANDLE, which takes the form of a PSPP identifier. If + HANDLE has no identifier, returns a null pointer. + + Return value is owned by the file handle.*/ +const char * +fh_get_id (const struct file_handle *handle) +{ + return handle->id[0] != '\0' ? handle->id : NULL; +} + +/* Returns a user-friendly string to identify the given HANDLE. + If HANDLE was created by referring to a file name, returns the + file name, enclosed in double quotes. Return value is owned + by the file handle. Useful for printing error messages about use of file handles. */ const char * @@ -380,22 +404,22 @@ fh_get_name (const struct file_handle *handle) /* Returns the type of object that HANDLE refers to. */ enum fh_referent -fh_get_referent (const struct file_handle *handle) +fh_get_referent (const struct file_handle *handle) { return handle->referent; } /* Returns the name of the file associated with HANDLE. */ const char * -fh_get_filename (const struct file_handle *handle) +fh_get_file_name (const struct file_handle *handle) { assert (handle->referent == FH_REF_FILE); - return handle->filename; + return handle->file_name; } /* Returns the mode of HANDLE. */ enum fh_mode -fh_get_mode (const struct file_handle *handle) +fh_get_mode (const struct file_handle *handle) { assert (handle->referent == FH_REF_FILE); return handle->mode; @@ -413,7 +437,7 @@ fh_get_record_width (const struct file_handle *handle) zero if tabs are not to be expanded. Applicable only to FH_MODE_TEXT files. */ size_t -fh_get_tab_width (const struct file_handle *handle) +fh_get_tab_width (const struct file_handle *handle) { assert (handle->referent & (FH_REF_FILE | FH_REF_INLINE)); return handle->tab_width; @@ -422,7 +446,7 @@ fh_get_tab_width (const struct file_handle *handle) /* Returns the scratch file handle associated with HANDLE. Applicable to only FH_REF_SCRATCH files. */ struct scratch_handle * -fh_get_scratch_handle (struct file_handle *handle) +fh_get_scratch_handle (struct file_handle *handle) { assert (handle->referent == FH_REF_SCRATCH); return handle->sh; @@ -439,14 +463,14 @@ fh_set_scratch_handle (struct file_handle *handle, struct scratch_handle *sh) /* Returns the current default handle. */ struct file_handle * -fh_get_default_handle (void) +fh_get_default_handle (void) { return default_handle ? default_handle : fh_inline_file (); } /* Sets NEW_DEFAULT_HANDLE as the default handle. */ void -fh_set_default_handle (struct file_handle *new_default_handle) +fh_set_default_handle (struct file_handle *new_default_handle) { assert (new_default_handle == NULL || (new_default_handle->referent & (FH_REF_INLINE | FH_REF_FILE)));