Fix for PR1654 - implement "movstrsi" pattern to copy simple blocks of memory.
[official-gcc.git] / libchill / basicio.c
blob7b71a084c1dcf8fd1dbbff4e11576838c407ecb7
1 /* Implement Input/Output runtime actions for CHILL.
2 Copyright (C) 1992,1993 Free Software Foundation, Inc.
3 Author: Wilfried Moser, et al
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* As a special exception, if you link this library with other files,
22 some of which are compiled with GCC, to produce an executable,
23 this library does not by itself cause the resulting executable
24 to be covered by the GNU General Public License.
25 This exception does not however invalidate any other reasons why
26 the executable file might be covered by the GNU General Public License. */
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <limits.h>
33 #include <errno.h>
35 #include <string.h>
36 #include <stdlib.h>
38 #include "fileio.h"
40 #ifndef PATH_MAX
41 #define PATH_MAX _POSIX_PATH_MAX
42 #endif
44 static
45 void
46 GetSetAttributes( Association_Mode* the_assoc )
48 struct stat statbuf;
49 int retco;
51 if( (retco = stat( the_assoc->pathname, &statbuf )) )
52 return;
54 if( S_ISREG(statbuf.st_mode) )
56 SET_FLAG( the_assoc, IO_EXISTING );
57 if( !TEST_FLAG( the_assoc, IO_VARIABLE ) )
58 SET_FLAG( the_assoc, IO_INDEXABLE );
60 else
61 if( S_ISCHR(statbuf.st_mode) || S_ISFIFO(statbuf.st_mode) )
63 SET_FLAG( the_assoc, IO_EXISTING );
64 CLR_FLAG( the_assoc, IO_INDEXABLE );
66 SET_FLAG( the_assoc, IO_SEQUENCIBLE );
68 /* FIXME: File size and computation of number of records for outoffile ? */
70 if( !access( the_assoc->pathname, R_OK ) )
71 SET_FLAG( the_assoc, IO_READABLE );
72 if( !access( the_assoc->pathname, W_OK ) )
73 SET_FLAG( the_assoc, IO_WRITEABLE );
76 static
77 void
78 makeName( Association_Mode* the_assoc, char* the_path, int the_path_len,
79 char* file, int line)
81 int namlen;
82 if( ! the_assoc->pathname &&
83 ! (the_assoc->pathname = (char*)malloc( PATH_MAX )) )
84 CHILLEXCEPTION( file, line, SPACEFAIL, PATHNAME_ALLOC );
86 if( the_path[0] != DIRSEP )
88 if( !getcwd( the_assoc->pathname, PATH_MAX ) )
90 the_assoc->syserrno = errno;
91 CHILLEXCEPTION( file, line, ASSOCIATEFAIL, GETCWD_FAILS );
93 namlen = strlen( the_assoc->pathname );
94 the_assoc->pathname[namlen++] = DIRSEP;
96 else
97 namlen = 0;
99 strncpy( the_assoc->pathname + namlen, the_path, the_path_len );
100 the_assoc->pathname[namlen+the_path_len] = '\0';
104 * ASSOCIATE
106 /* Caution: returns an Association mode location (!) */
107 Association_Mode*
108 __associate( Association_Mode* the_assoc,
109 char* the_path,
110 int the_path_len,
111 char* the_mode,
112 int the_mode_len,
113 char* file,
114 int line )
116 if( !the_assoc )
117 CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
119 if( TEST_FLAG(the_assoc, IO_ISASSOCIATED) )
120 CHILLEXCEPTION( file, line, ASSOCIATEFAIL, IS_ASSOCIATED );
122 /* clear all flags */
123 the_assoc->flags = 0;
125 if( ! the_path_len )
126 CHILLEXCEPTION( file, line, ASSOCIATEFAIL, NO_PATH_NAME );
128 makeName( the_assoc, the_path, the_path_len, file, line );
129 GetSetAttributes( the_assoc );
131 CLR_FLAG( the_assoc, IO_VARIABLE );
132 if ( the_mode )
134 if( !strncmp( the_mode, "VARIABLE", 8 ) )
136 SET_FLAG( the_assoc, IO_VARIABLE );
137 CLR_FLAG( the_assoc, IO_INDEXABLE );
139 else
140 if( strlen( the_mode ) )
141 CHILLEXCEPTION( file, line, ASSOCIATEFAIL, INVALID_ASSOCIATION_MODE );
144 SET_FLAG( the_assoc, IO_ISASSOCIATED );
145 return the_assoc;
149 * DISSOCIATE
151 void
152 __dissociate( Association_Mode* the_assoc, char* file, int line )
154 if( !the_assoc )
155 CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
157 if( !TEST_FLAG( the_assoc, IO_ISASSOCIATED ) )
158 CHILLEXCEPTION( file, line, NOTASSOCIATED, IS_NOT_ASSOCIATED );
160 if( the_assoc->access )
161 __disconnect( the_assoc->access, file, line );
163 the_assoc->access = NULL;
164 CLR_FLAG( the_assoc, IO_ISASSOCIATED );
166 /* free allocated memory */
167 if (the_assoc->pathname)
169 free (the_assoc->pathname);
170 the_assoc->pathname = 0;
172 if (the_assoc->bufptr)
174 free (the_assoc->bufptr);
175 the_assoc->bufptr = 0;
180 * CREATE
182 void __create( Association_Mode* the_assoc, char* file, int line )
184 if( !the_assoc )
185 CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
187 if( !TEST_FLAG( the_assoc, IO_ISASSOCIATED ) )
188 CHILLEXCEPTION( file, line, NOTASSOCIATED, IS_NOT_ASSOCIATED );
190 if( TEST_FLAG( the_assoc, IO_EXISTING ) )
191 CHILLEXCEPTION( file, line, CREATEFAIL, FILE_EXISTING );
193 if( (the_assoc->handle = open( the_assoc->pathname, O_CREAT+O_TRUNC+O_WRONLY, 0666 ))
194 == -1 )
195 CHILLEXCEPTION( file, line, CREATEFAIL, CREATE_FAILS );
197 the_assoc->usage = ReadWrite;
198 GetSetAttributes( the_assoc );
200 close( the_assoc->handle );
204 * MODIFY
206 void
207 __modify( Association_Mode* the_assoc,
208 char* the_path,
209 int the_path_len,
210 char* the_mode,
211 int the_mode_len,
212 char* file,
213 int line )
215 if( !the_assoc )
216 CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
218 if( !TEST_FLAG( the_assoc, IO_ISASSOCIATED ) )
219 CHILLEXCEPTION( file, line, NOTASSOCIATED, IS_NOT_ASSOCIATED );
221 if( the_path_len )
223 char* oldname;
225 if( ! (oldname = (char*)malloc( PATH_MAX )) )
226 CHILLEXCEPTION( file, line, SPACEFAIL, PATHNAME_ALLOC );
227 strcpy( oldname, the_assoc->pathname );
229 makeName( the_assoc, the_path, the_path_len, file, line );
231 if( rename( oldname, the_assoc->pathname ) )
233 free( oldname );
234 CHILLEXCEPTION( file, line, MODIFYFAIL, RENAME_FAILS );
236 free( oldname );
238 else
240 /* FIXME: other options? */
244 static
245 /*** char* DirMode[] = { "rb", "r+b", "r+b" }; ***/
246 int DirMode[] = { O_RDONLY, O_RDWR, O_RDWR };
248 static
249 /*** char* SeqMode [] = { "rb", "r+b", "r+b" }; ***/
250 int SeqMode[] = { O_RDONLY, O_RDWR, O_RDWR };
253 * CONNECT
255 void
256 __connect( void* the_transfer,
257 Association_Mode* the_assoc,
258 Usage_Mode the_usage,
259 Where_Mode the_where,
260 Boolean with_index,
261 signed long the_index,
262 char* file,
263 int line )
265 Access_Mode* the_access;
266 off_t filepos;
267 off_t savepos;
268 char dummy;
269 unsigned long nbytes;
270 int oflag;
272 if( !the_transfer )
273 CHILLEXCEPTION( file, line, EMPTY, NULL_ACCESS );
274 if( !the_assoc )
275 CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
277 if( TEST_FLAG((Text_Mode*)the_transfer, IO_TEXTLOCATION ))
279 if( ! ((Text_Mode*)the_transfer)->access_sub )
280 CHILLEXCEPTION( file, line, EMPTY, NO_ACCESS_SUBLOCATION );
281 the_access = ((Text_Mode*)the_transfer)->access_sub;
282 SET_FLAG( the_access, IO_TEXTIO );
284 else
286 the_access = (Access_Mode*)the_transfer;
287 CLR_FLAG( the_access, IO_TEXTIO );
290 /* FIXME: This should be an (implementation-dependent) static check
291 if( with_index && the_access->rectype > Fixed )
292 CHILLEXCEPTION( file, line, CONNECTFAIL, IMPL_RESTRICTION );
295 if( ! TEST_FLAG(the_assoc, IO_ISASSOCIATED) )
296 CHILLEXCEPTION( file, line, NOTASSOCIATED, IS_NOT_ASSOCIATED );
298 if( ! TEST_FLAG( the_assoc, IO_EXISTING ) )
299 CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_EXISTING );
301 if( ! TEST_FLAG( the_assoc, IO_READABLE ) &&
302 ( the_usage = ReadOnly || the_usage == ReadWrite ) )
303 CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_READABLE );
305 if( ! TEST_FLAG( the_assoc, IO_WRITEABLE ) &&
306 ( the_usage = WriteOnly || the_usage == ReadWrite ) )
307 CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_WRITEABLE );
309 if( ! TEST_FLAG( the_assoc, IO_INDEXABLE )
310 && TEST_FLAG( the_access, IO_INDEXED ) )
311 CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_INDEXABLE );
313 if( ! TEST_FLAG( the_assoc, IO_SEQUENCIBLE )
314 && ! TEST_FLAG( the_access, IO_INDEXED ) )
315 CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_SEQUENCIBLE );
317 if( the_where == Same && the_assoc->access == NULL )
318 CHILLEXCEPTION( file, line, CONNECTFAIL, NO_CURRENT_POS );
320 /* This dynamic condition is not checked for text connections. */
321 if( ! TEST_FLAG( the_access, IO_TEXTIO ) )
322 if( ! TEST_FLAG( the_assoc, IO_VARIABLE )
323 && the_access->rectype > Fixed
324 && ( the_usage == WriteOnly || the_usage == ReadWrite ) )
325 CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_VARIABLE );
327 if( TEST_FLAG( the_assoc, IO_VARIABLE )
328 && the_access->rectype == Fixed
329 && ( the_usage == ReadOnly || the_usage == ReadWrite ) )
330 CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_FIXED );
332 if( ! TEST_FLAG( the_access, IO_INDEXED ) && the_usage == ReadWrite )
333 CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_INDEXED );
335 /* Access location may be connected to a different association. */
336 if( the_access->association && the_access->association != the_assoc )
337 __disconnect( the_access, file, line );
339 /* Is the association location already connected? */
340 if( the_assoc->access )
342 /* save position just in case we need it for the_where == Same */
343 if( (savepos = lseek( the_assoc->handle, 0L, SEEK_CUR )) == -1L )
344 CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
346 /* text: read correction, flush buffer */
347 if( the_assoc->bufptr ){
348 savepos -= the_assoc->bufptr->len - the_assoc->bufptr->cur;
349 the_assoc->bufptr->len = the_assoc->bufptr->cur = 0;
352 /* implicit disconnect */
353 __disconnect( the_assoc->access, file, line );
356 the_assoc->usage = the_usage;
357 CLR_FLAG( the_access, IO_OUTOFFILE );
359 if( TEST_FLAG( the_access, IO_INDEXED ) )
361 if( (the_assoc->handle = open( the_assoc->pathname, DirMode[the_usage] )) == -1 )
362 CHILLEXCEPTION( file, line, CONNECTFAIL, OPEN_FAILS );
364 /* Set base index. */
365 switch( the_where )
367 case First:
368 filepos = 0;
369 break;
370 case Same:
371 filepos = savepos;
372 break;
373 case Last:
374 if( lseek( the_assoc->handle, 0L, SEEK_END ) == -1L )
375 CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
376 filepos = lseek( the_assoc->handle, 0L, SEEK_CUR );
377 break;
380 /* Set current index */
381 if( with_index )
383 if( the_index < the_access->lowindex
384 || the_access->highindex < the_index )
385 CHILLEXCEPTION( file, line, RANGEFAIL, BAD_INDEX );
386 filepos += (the_index - the_access->lowindex) * the_access->reclength;
388 if( lseek( the_assoc->handle, filepos, SEEK_SET ) == -1L )
389 CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
390 the_access->base = filepos;
392 else
394 /* for association to text for reading: allocate buffer */
395 if( TEST_FLAG((Text_Mode*)the_transfer, IO_TEXTLOCATION ) &&
396 the_usage == ReadOnly &&
397 !the_assoc->bufptr )
399 if( ! (the_assoc->bufptr = (readbuf_t*)malloc( sizeof(readbuf_t) )) )
400 CHILLEXCEPTION( file, line, CONNECTFAIL, BUFFER_ALLOC );
401 memset (the_assoc->bufptr, 0, sizeof (readbuf_t));
403 if( (the_assoc->handle = open( the_assoc->pathname, SeqMode[the_usage] )) == -1 )
404 CHILLEXCEPTION( file, line, CONNECTFAIL, OPEN_FAILS );
406 /* Set base index. */
407 switch( the_where )
409 case First:
410 filepos = 0;
411 break;
412 case Same:
413 filepos = savepos;
414 break;
415 case Last:
416 if( lseek( the_assoc->handle, 0L, SEEK_END ) == -1L )
417 CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
418 filepos = lseek( the_assoc->handle, 0L, SEEK_CUR );
419 break;
422 /* file truncation for sequential, Write Only */
423 /***************************** FIXME: cannot truncate at Same
424 if( the_usage == WriteOnly )
426 if( fseek( the_assoc->file_ptr, filepos, SEEK_SET ) == -1L )
427 CHILLEXCEPTION( file, line, CONNECTFAIL, FSEEK_FAILS );
428 fclose( the_assoc->file_ptr );
429 if( !(the_assoc->file_ptr = fopen( the_assoc->pathname, "ab" )) )
430 CHILLEXCEPTION( file, line, CONNECTFAIL, OPEN_FAILS );
432 else
433 ***************************/
434 if( (filepos = lseek( the_assoc->handle, filepos, SEEK_SET )) == -1L )
435 CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
438 the_access->association = the_assoc;
439 the_assoc->access = the_access;
440 /* for text: set carriage control default */
441 if( TEST_FLAG((Text_Mode*)the_transfer, IO_TEXTLOCATION ) ){
442 the_assoc->ctl_pre = '\0';
443 the_assoc->ctl_post = '\n';
447 void
448 __disconnect( void* the_transfer, char* file, int line )
450 Access_Mode* the_access;
452 if( !the_transfer )
453 CHILLEXCEPTION( file, line, EMPTY, NULL_ACCESS );
455 if( TEST_FLAG((Text_Mode*)the_transfer, IO_TEXTLOCATION ))
457 the_access = ((Text_Mode*)the_transfer)->access_sub;
458 CLR_FLAG( the_access, IO_TEXTIO );
460 else
461 the_access = (Access_Mode*)the_transfer;
463 if( !the_access->association )
464 CHILLEXCEPTION( file, line, NOTCONNECTED, IS_NOT_CONNECTED );
466 close( the_access->association->handle );
467 /* FIXME: check result */
469 if( the_access->store_loc )
470 free( the_access->store_loc );
471 the_access->store_loc = NULL;
472 the_access->association->access = NULL;
473 the_access->association = NULL;