/[pspp]/pspp/src/file-handle.q
ViewVC logotype

Diff of /pspp/src/file-handle.q

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.22 by blp, Sun Jul 31 21:42:46 2005 UTC revision 1.23 by jmd, Thu Oct 27 03:19:07 2005 UTC
# Line 31  Line 31 
31  #include "magic.h"  #include "magic.h"
32  #include "var.h"  #include "var.h"
33  #include "linked-list.h"  #include "linked-list.h"
34    #include "file-handle-def.h"
35    
36  #include "gettext.h"  #include "gettext.h"
37  #define _(msgid) gettext (msgid)  #define _(msgid) gettext (msgid)
38    
39  /* (headers) */  /* (headers) */
40    
 /* File handle. */  
 struct file_handle  
   {  
     struct file_handle *next;   /* Next in global list. */  
     char *name;                 /* File handle identifier. */  
     char *filename;             /* Filename as provided by user. */  
     struct file_identity *identity; /* For checking file identity. */  
     struct file_locator where;  /* Used for reporting error messages. */  
     enum file_handle_mode mode; /* File mode. */  
     size_t length;              /* Length of fixed-format records. */  
     size_t tab_width;           /* Tab width, 0=do not expand tabs. */  
   
     int open_cnt;               /* 0=not open, otherwise # of openers. */  
     const char *type;           /* If open, type of file. */  
     char open_mode[3];          /* "[rw][se]". */  
     void *aux;                  /* Aux data pointer for owner if any. */  
   };  
   
 static struct file_handle *file_handles;  
   
 static struct file_handle *create_file_handle (const char *handle_name,  
                                                const char *filename);  
41    
42  /* (specification)  /* (specification)
43     "FILE HANDLE" (fh_):     "FILE HANDLE" (fh_):
# Line 70  static struct file_handle *create_file_h Line 49  static struct file_handle *create_file_h
49  /* (declarations) */  /* (declarations) */
50  /* (functions) */  /* (functions) */
51    
 static struct file_handle *  
 get_handle_with_name (const char *handle_name)  
 {  
   struct file_handle *iter;  
   
   for (iter = file_handles; iter != NULL; iter = iter->next)  
     if (!strcasecmp (handle_name, iter->name))  
       return iter;  
   return NULL;  
 }  
   
 static struct file_handle *  
 get_handle_for_filename (const char *filename)  
 {  
   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)  
     {  
       for (iter = file_handles; iter != NULL; iter = iter->next)  
         if (iter->identity != NULL  
             && !fn_compare_file_identities (identity, iter->identity))  
           {  
             fn_free_identity (identity);  
             return iter;  
           }  
       fn_free_identity (identity);  
     }  
   
   /* Then check for a file with the same name. */  
   for (iter = file_handles; iter != NULL; iter = iter->next)  
     if (!strcmp (filename, iter->filename))  
       return iter;  
   
   return NULL;  
 }  
52    
53  int  int
54  cmd_file_handle (void)  cmd_file_handle (void)
# Line 126  cmd_file_handle (void) Line 67  cmd_file_handle (void)
67      {      {
68        msg (SE, _("File handle %s already refers to file %s.  "        msg (SE, _("File handle %s already refers to file %s.  "
69                   "File handles cannot be redefined within a session."),                   "File handles cannot be redefined within a session."),
70             handle_name, handle->filename);             handle_name, handle_get_filename(handle));
71        return CMD_FAILURE;        return CMD_FAILURE;
72      }      }
73    
# Line 150  cmd_file_handle (void) Line 91  cmd_file_handle (void)
91        goto lossage;        goto lossage;
92      }      }
93    
94    handle = create_file_handle (handle_name, cmd.s_name);  
95      enum file_handle_mode mode = MODE_TEXT;
96      size_t length = 1024;
97      size_t tab_width = 4;
98    
99    
100    switch (cmd.mode)    switch (cmd.mode)
101      {      {
102      case FH_CHARACTER:      case FH_CHARACTER:
103        handle->mode = MODE_TEXT;        mode = MODE_TEXT;
104        if (cmd.sbc_tabwidth)        if (cmd.sbc_tabwidth)
105          handle->tab_width = cmd.n_tabwidth[0];          tab_width = cmd.n_tabwidth[0];
106        else        else
107          handle->tab_width = 4;          tab_width = 4;
108        break;        break;
109      case FH_IMAGE:      case FH_IMAGE:
110        handle->mode = MODE_BINARY;        mode = MODE_BINARY;
111        if (cmd.n_lrecl[0] == NOT_LONG)        if (cmd.n_lrecl[0] == NOT_LONG)
112          {          {
113            msg (SE, _("Fixed-length records were specified on /RECFORM, but "            msg (SE, _("Fixed-length records were specified on /RECFORM, but "
114                       "record length was not specified on /LRECL.  "                       "record length was not specified on /LRECL.  "
115                       "Assuming 1024-character records."));                       "Assuming 1024-character records."));
116            handle->length = 1024;            length = 1024;
117          }          }
118        else if (cmd.n_lrecl[0] < 1)        else if (cmd.n_lrecl[0] < 1)
119          {          {
120            msg (SE, _("Record length (%ld) must be at least one byte.  "            msg (SE, _("Record length (%ld) must be at least one byte.  "
121                       "1-character records will be assumed."), cmd.n_lrecl[0]);                       "1-character records will be assumed."), cmd.n_lrecl[0]);
122            handle->length = 1;            length = 1;
123          }          }
124        else        else
125          handle->length = cmd.n_lrecl[0];          length = cmd.n_lrecl[0];
126        break;        break;
127      default:      default:
128        assert (0);        assert (0);
129      }      }
130    
131      handle = create_file_handle (handle_name, cmd.s_name,
132                                   mode, length, tab_width);
133    
134    
135    return CMD_SUCCESS;    return CMD_SUCCESS;
136    
137   lossage:   lossage:
138    free_file_handle (&cmd);    free_file_handle (&cmd);
139    return CMD_FAILURE;    return CMD_FAILURE;
140  }  }
   
 /* File handle functions. */  
   
 /* Creates and returns a new file handle with the given values  
    and defaults for other values.  Adds the created file handle  
    to the global list. */  
 static struct file_handle *  
 create_file_handle (const char *handle_name, const char *filename)  
 {  
   struct file_handle *handle;  
   
   /* Create and initialize file handle. */  
   handle = xmalloc (sizeof *handle);  
   handle->next = file_handles;  
   handle->name = xstrdup (handle_name);  
   handle->filename = xstrdup (filename);  
   handle->identity = fn_get_identity (filename);  
   handle->where.filename = handle->filename;  
   handle->where.line_number = 0;  
   handle->mode = MODE_TEXT;  
   handle->length = 1024;  
   handle->tab_width = 4;  
   handle->open_cnt = 0;  
   handle->type = NULL;  
   handle->aux = NULL;  
   file_handles = handle;  
   
   return handle;  
 }  
   
 static void  
 destroy_file_handle(void *fh_, void *aux UNUSED)  
 {  
   struct file_handle *fh = fh_;  
   free (fh->name);  
   free (fh->filename);  
   fn_free_identity (fh->identity);  
   free (fh);  
 }  
   
 static const char *  
 mode_name (const char *mode)  
 {  
   assert (mode != NULL);  
   assert (mode[0] == 'r' || mode[0] == 'w');  
   
   return mode[0] == 'r' ? "reading" : "writing";  
 }  
   
141    
 /* Tries to open handle H with the given TYPE and MODE.  
   
    TYPE is the sort of file, e.g. "system file".  Only one given  
    type of access is allowed on a given file handle at once.  
   
    MODE combines the read or write mode with the sharing mode.  
    The first character is 'r' for read, 'w' for write.  The  
    second character is 's' to permit sharing, 'e' to require  
    exclusive access.  
   
    Returns the address of a void * that the caller can use for  
    data specific to the file handle if successful, or a null  
    pointer on failure.  For exclusive access modes the void *  
    will always be a null pointer at return.  In shared access  
    modes the void * will necessarily be null only if no other  
    sharers are active.  
   
    If successful, a reference to type is retained, so it should  
    probably be a string literal. */  
 void **  
 fh_open (struct file_handle *h, const char *type, const char *mode)  
 {  
   assert (h != NULL);  
   assert (type != NULL);  
   assert (mode != NULL);  
   assert (mode[0] == 'r' || mode[0] == 'w');  
   assert (mode[1] == 's' || mode[1] == 'e');  
   assert (mode[2] == '\0');  
   
   if (h->open_cnt != 0)  
     {  
       if (strcmp (h->type, type))  
         {  
           msg (SE, _("Can't open %s as a %s because it is "  
                      "already open as a %s"),  
                handle_get_name (h), type, h->type);  
           return NULL;  
         }  
       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"),  
                handle_get_name (h), type,  
                mode_name (mode), mode_name (h->open_mode));  
           return NULL;  
         }  
       else if (h->open_mode[1] == 'e')  
         {  
           msg (SE, _("Can't re-open %s as a %s for %s"),  
                handle_get_name (h), type, mode_name (mode));  
           return NULL;  
         }  
     }  
   else  
     {  
       h->type = type;  
       strcpy (h->open_mode, mode);  
       assert (h->aux == NULL);  
     }  
   h->open_cnt++;  
   
   return &h->aux;  
 }  
   
 /* Closes file handle H, which must have been open for the  
    specified TYPE and MODE of access provided to fh_open().  
    Returns zero if the file is now closed, nonzero if it is still  
    open due to another reference. */  
 int  
 fh_close (struct file_handle *h, const char *type, const char *mode)  
 {  
   assert (h != NULL);  
   assert (h->open_cnt > 0);  
   assert (type != NULL);  
   assert (!strcmp (type, h->type));  
   assert (mode != NULL);  
   assert (!strcmp (mode, h->open_mode));  
   
   h->open_cnt--;  
   if (h->open_cnt == 0)  
     {  
       h->type = NULL;  
       h->aux = NULL;  
     }  
   return h->open_cnt;  
 }  
142    
143    
144  static struct linked_list *handle_list;  static struct linked_list *handle_list;
# Line 354  fh_parse (void) Line 169  fh_parse (void)
169        char *filename = ds_c_str (&tokstr);        char *filename = ds_c_str (&tokstr);
170        char *handle_name = xmalloc (strlen (filename) + 3);        char *handle_name = xmalloc (strlen (filename) + 3);
171        sprintf (handle_name, "\"%s\"", filename);        sprintf (handle_name, "\"%s\"", filename);
172        handle = create_file_handle (handle_name, filename);        handle = create_file_handle_with_defaults (handle_name, filename);
173        ll_push_front(handle_list, handle);        ll_push_front(handle_list, handle);
174        free (handle_name);        free (handle_name);
175      }      }
# Line 365  fh_parse (void) Line 180  fh_parse (void)
180    return handle;    return handle;
181  }  }
182    
 /* 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.  
   
    Useful for printing error messages about use of file handles.  */  
 const char *  
 handle_get_name (const struct file_handle *handle)  
 {  
   assert (handle != NULL);  
   return handle->name;  
 }  
   
 /* Returns the name of the file associated with HANDLE. */  
 const char *  
 handle_get_filename (const struct file_handle *handle)  
 {  
   assert (handle != NULL);  
   return handle->filename;  
 }  
   
 /* Returns the mode of HANDLE. */  
 enum file_handle_mode  
 handle_get_mode (const struct file_handle *handle)  
 {  
   assert (handle != NULL);  
   return handle->mode;  
 }  
   
 /* Returns the width of a logical record on HANDLE. */  
 size_t  
 handle_get_record_width (const struct file_handle *handle)  
 {  
   assert (handle != NULL);  
   return handle->length;  
 }  
   
 /* Returns the number of characters per tab stop for HANDLE, or  
    zero if tabs are not to be expanded.  Applicable only to  
    MODE_TEXT files. */  
 size_t  
 handle_get_tab_width (const struct file_handle *handle)  
 {  
   assert (handle != NULL);  
   return handle->tab_width;  
 }  
183    
184    
185  void  void

Legend:
Removed from v.1.22  
changed lines
  Added in v.1.23

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26