X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffile-handle.q;h=c13be76beda44a320979200adb2418a6f04a6044;hb=53ceff2865473a6b561b521986fafd31a993a1a6;hp=77291a45e42836595c071150a754ab3691a0fa2d;hpb=f9d47b5bba8416419cf3bcd3aa23c2d40a05fcac;p=pspp diff --git a/src/file-handle.q b/src/file-handle.q index 77291a45e4..c13be76bed 100644 --- a/src/file-handle.q +++ b/src/file-handle.q @@ -1,5 +1,5 @@ /* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + 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 @@ -14,38 +14,38 @@ 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include #include "file-handle.h" -#include +#include "error.h" #include #include #include "alloc.h" #include "filename.h" #include "command.h" -#include "hash.h" #include "lexer.h" -#include "getline.h" +#include "getl.h" #include "error.h" #include "magic.h" +#include "str.h" #include "var.h" -/* (headers) */ +#include "linked-list.h" +#include "file-handle-def.h" -#include "debug-print.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) -static struct hsh_table *files; -struct file_handle *inline_file; +/* (headers) */ -static void init_file_handle (struct file_handle * handle); /* (specification) "FILE HANDLE" (fh_): name=string; - recform=recform:fixed/!variable/spanned; lrecl=integer; - mode=mode:!character/image/binary/multipunch/_360. + tabwidth=integer "x>=0" "%s must be nonnegative"; + mode=mode:!character/image/scratch. */ /* (declarations) */ /* (functions) */ @@ -53,26 +53,22 @@ static void init_file_handle (struct file_handle * handle); int cmd_file_handle (void) { - char handle_name[9]; - char *handle_name_p = handle_name; + char handle_name[LONG_NAME_LEN + 1]; + struct fh_properties properties = *fh_default_properties (); struct cmd_file_handle cmd; - struct file_handle *fp; + struct file_handle *handle; - lex_get (); if (!lex_force_id ()) return CMD_FAILURE; - strcpy (handle_name, tokid); + str_copy_trunc (handle_name, sizeof handle_name, tokid); - fp = NULL; - if (files) - fp = hsh_find (files, &handle_name_p); - if (fp) + handle = fh_from_name (handle_name); + if (handle != NULL) { - msg (SE, _("File handle %s had already been defined to refer to " - "file %s. It is not possible to redefine a file " - "handle within a session."), - tokid, fp->fn); + msg (SE, _("File handle %s is already defined. " + "Use CLOSE FILE HANDLE before redefining a file handle."), + handle_name); return CMD_FAILURE; } @@ -83,288 +79,136 @@ cmd_file_handle (void) if (!parse_file_handle (&cmd)) return CMD_FAILURE; - if (token != '.') - { - lex_error (_("expecting end of command")); - goto lossage; - } + if (lex_end_of_command () != CMD_SUCCESS) + goto lossage; - if (cmd.s_name == NULL) + if (cmd.s_name == NULL && cmd.mode != FH_SCRATCH) { - msg (SE, _("The FILE HANDLE required subcommand NAME " - "is not present.")); + lex_sbc_missing ("NAME"); goto lossage; } - fp = xmalloc (sizeof *fp); - init_file_handle (fp); - - switch (cmd.recform) - { - case FH_FIXED: - if (cmd.n_lrecl == NOT_LONG) - { - msg (SE, _("Fixed length records were specified on /RECFORM, but " - "record length was not specified on /LRECL. 80-character " - "records will be assumed.")); - cmd.n_lrecl = 80; - } - else if (cmd.n_lrecl < 1) - { - msg (SE, _("Record length (%ld) must be at least one byte. " - "80-character records will be assumed."), cmd.n_lrecl); - cmd.n_lrecl = 80; - } - fp->recform = FH_RF_FIXED; - fp->lrecl = cmd.n_lrecl; - break; - case FH_VARIABLE: - fp->recform = FH_RF_VARIABLE; - break; - case FH_SPANNED: - msg (SE, - _("%s is not implemented, as the author doesn't know what it is supposed to do. Send a note to %s.") , - "/RECFORM SPANNED",PACKAGE_BUGREPORT); - break; - default: - assert (0); - } - switch (cmd.mode) { case FH_CHARACTER: - fp->mode = FH_MD_CHARACTER; + properties.mode = FH_MODE_TEXT; + if (cmd.sbc_tabwidth) + properties.tab_width = cmd.n_tabwidth[0]; break; case FH_IMAGE: - msg (SE, - _("%s is not implemented, as the author doesn't know what it is supposed to do. Send a note to %s.") , - "/MODE IMAGE",PACKAGE_BUGREPORT); - break; - case FH_BINARY: - fp->mode = FH_MD_BINARY; - break; - case FH_MULTIPUNCH: - msg (SE, _("%s is not implemented. If you care, complain."),"/MODE MULTIPUNCH"); - break; - case FH__360: - msg (SE, _("%s is not implemented. If you care, complain."),"/MODE 360"); + properties.mode = FH_MODE_BINARY; + if (cmd.n_lrecl[0] == NOT_LONG) + msg (SE, _("Fixed-length records were specified on /RECFORM, but " + "record length was not specified on /LRECL. " + "Assuming %d-character records."), + properties.record_width); + else if (cmd.n_lrecl[0] < 1) + msg (SE, _("Record length (%ld) must be at least one byte. " + "Assuming %d-character records."), + cmd.n_lrecl[0], properties.record_width); + else + properties.record_width = cmd.n_lrecl[0]; break; default: assert (0); } - fp->name = xstrdup (handle_name); - fp->norm_fn = fn_normalize (cmd.s_name); - fp->where.filename = fp->fn = cmd.s_name; - hsh_force_insert (files, fp); + if (cmd.mode != FH_SCRATCH) + fh_create_file (handle_name, cmd.s_name, &properties); + else + fh_create_scratch (handle_name); + free_file_handle (&cmd); return CMD_SUCCESS; lossage: free_file_handle (&cmd); return CMD_FAILURE; } - -/* File handle functions. */ - -/* Sets up some fields in H; caller should fill in - H->{NAME,NORM_FN,FN}. */ -static void -init_file_handle (struct file_handle *h) -{ - h->recform = FH_RF_VARIABLE; - h->mode = FH_MD_CHARACTER; - h->ext = NULL; - h->class = NULL; -} -/* Returns the handle corresponding to FILENAME. Creates the handle - if no handle exists for that file. All filenames are normalized - first, so different filenames referring to the same file will - return the same file handle. */ -struct file_handle * -fh_get_handle_by_filename (const char *filename) +int +cmd_close_file_handle (void) { - struct file_handle f, *fp; - char *fn; - char *name; - int len; - - /* Get filename. */ - fn = fn_normalize (filename); - len = strlen (fn); + struct file_handle *handle; - /* Create handle name with invalid identifier character to prevent - conflicts with handles created with FILE HANDLE. */ - name = xmalloc (len + 2); - name[0] = '*'; - strcpy (&name[1], fn); + if (!lex_force_id ()) + return CMD_FAILURE; + handle = fh_from_name (tokid); + if (handle == NULL) + return CMD_FAILURE; - f.name = name; - fp = hsh_find (files, &f); - if (!fp) - { - fp = xmalloc (sizeof *fp); - init_file_handle (fp); - fp->name = name; - fp->norm_fn = fn; - fp->where.filename = fp->fn = xstrdup (filename); - hsh_force_insert (files, fp); - } - else - { - free (fn); - free (name); - } - return fp; -} + fh_free (handle); -/* Returns the handle with identifier NAME, if it exists; otherwise - reports error to user and returns NULL. */ -struct file_handle * -fh_get_handle_by_name (const char name[9]) -{ - struct file_handle f, *fp; - f.name = (char *) name; - fp = hsh_find (files, &f); - - if (!fp) - msg (SE, _("File handle `%s' has not been previously declared on " - "FILE HANDLE."), name); - return fp; + return CMD_SUCCESS; } -/* Returns the identifier of file HANDLE. If HANDLE was created by - referring to a filename (i.e., DATA LIST FILE='yyy' instead of FILE - HANDLE XXX='yyy'), returns the filename, enclosed in double quotes. - Return value is in a static buffer. - - Useful for printing error messages about use of file handles. */ -const char * -fh_handle_name (const struct file_handle *h) +/* Returns the name for REFERENT. */ +static const char * +referent_name (enum fh_referent referent) { - static char *buf = NULL; - - if (buf) - { - free (buf); - buf = NULL; - } - if (!h) - return NULL; - - if (h->name[0] == '*') + switch (referent) { - int len = strlen (h->fn); - - buf = xmalloc (len + 3); - strcpy (&buf[1], h->fn); - buf[0] = buf[len + 1] = '"'; - buf[len + 2] = 0; - return buf; + case FH_REF_FILE: + return _("file"); + case FH_REF_INLINE: + return _("inline file"); + case FH_REF_SCRATCH: + return _("scratch file"); + default: + abort (); } - return h->name; -} - -/* Closes the stdio FILE associated with handle H. Frees internal - buffers associated with that file. Does *not* destroy the file - handle H. (File handles are permanent during a session.) */ -void -fh_close_handle (struct file_handle *h) -{ - if (h == NULL) - return; - - debug_printf (("Closing %s%s.\n", fh_handle_name (h), - h->class == NULL ? " (already closed)" : "")); - - if (h->class) - h->class->close (h); - h->class = NULL; - h->ext = NULL; -} - -/* Hashes the name of file handle H. */ -static unsigned -hash_file_handle (const void *handle_, void *param UNUSED) -{ - const struct file_handle *handle = handle_; - - return hsh_hash_string (handle->name); } -/* Compares names of file handles A and B. */ -static int -cmp_file_handle (const void *a_, const void *b_, void *foo UNUSED) -{ - const struct file_handle *a = a_; - const struct file_handle *b = b_; - - return strcmp (a->name, b->name); -} - -/* Initialize the hash of file handles; inserts the "inline file" - inline_file. */ -void -fh_init_files (void) -{ - /* Create hash. */ - files = hsh_create (4, cmp_file_handle, hash_file_handle, NULL, NULL); - - /* Insert inline file. */ - inline_file = xmalloc (sizeof *inline_file); - init_file_handle (inline_file); - inline_file->name = "INLINE"; - inline_file->where.filename - = inline_file->fn = inline_file->norm_fn = (char *) _(""); - inline_file->where.line_number = 0; - hsh_force_insert (files, inline_file); -} - -/* Parses a file handle name, which may be a filename as a string or - a file handle name as an identifier. Returns the file handle or - NULL on failure. */ +/* Parses a file handle name, which may be a filename as a string + or a file handle name as an identifier. The allowed types of + file handle are restricted to those in REFERENT_MASK. Returns + the file handle when successful, a null pointer on failure. */ struct file_handle * -fh_parse_file_handle (void) +fh_parse (enum fh_referent referent_mask) { struct file_handle *handle; - if (token == T_ID) - handle = fh_get_handle_by_name (tokid); - else if (token == T_STRING) - handle = fh_get_handle_by_filename (ds_value (&tokstr)); - else + if (lex_match_id ("INLINE")) + handle = fh_inline_file (); + else { - lex_error (_("expecting a file name or handle")); - return NULL; + if (token != T_ID && token != T_STRING) + { + lex_error (_("expecting a file name or handle name")); + return NULL; + } + + handle = NULL; + if (token == T_ID) + handle = fh_from_name (tokid); + if (handle == NULL) + handle = fh_from_filename (ds_c_str (&tokstr)); + if (handle == NULL) + { + if (token != T_ID || tokid[0] != '#' || get_syntax () != ENHANCED) + { + char *filename = ds_c_str (&tokstr); + char *handle_name = xasprintf ("\"%s\"", filename); + handle = fh_create_file (handle_name, filename, + fh_default_properties ()); + free (handle_name); + } + else + handle = fh_create_scratch (tokid); + } + lex_get (); } - if (!handle) - return NULL; - lex_get (); + if (!(fh_get_referent (handle) & referent_mask)) + { + msg (SE, _("Handle for %s not allowed here."), + referent_name (fh_get_referent (handle))); + return NULL; + } return handle; } -/* Returns the (normalized) filename associated with file handle H. */ -char * -fh_handle_filename (struct file_handle * h) -{ - return h->norm_fn; -} - -/* Returns the width of a logical record on file handle H. */ -size_t -fh_record_width (struct file_handle *h) -{ - if (h == inline_file) - return 80; - else if (h->recform == FH_RF_FIXED) - return h->lrecl; - else - return 1024; -} - /* Local variables: mode: c