Arm: Add read_description read funcs and use in GDB
[external/binutils.git] / readline / histfile.c
1 /* histfile.c - functions to manipulate the history file. */
2
3 /* Copyright (C) 1989-2010 Free Software Foundation, Inc.
4
5    This file contains the GNU History Library (History), a set of
6    routines for managing the text of previously typed lines.
7
8    History is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation, either version 3 of the License, or
11    (at your option) any later version.
12
13    History is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with History.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /* The goal is to make the implementation transparent, so that you
23    don't have to know what data types are used, just what functions
24    you can call.  I think I have done that. */
25
26 #define READLINE_LIBRARY
27
28 #if defined (__TANDEM)
29 #  include <floss.h>
30 #endif
31
32 #if defined (HAVE_CONFIG_H)
33 #  include <config.h>
34 #endif
35
36 #include <stdio.h>
37
38 #include <sys/types.h>
39 #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
40 #  include <sys/file.h>
41 #endif
42 #include "posixstat.h"
43 #include <fcntl.h>
44
45 #if defined (HAVE_STDLIB_H)
46 #  include <stdlib.h>
47 #else
48 #  include "ansi_stdlib.h"
49 #endif /* HAVE_STDLIB_H */
50
51 #if defined (HAVE_UNISTD_H)
52 #  include <unistd.h>
53 #endif
54
55 #include <ctype.h>
56
57 #if defined (__EMX__)
58 #  undef HAVE_MMAP
59 #endif
60
61 #ifdef HISTORY_USE_MMAP
62 #  include <sys/mman.h>
63
64 #  ifdef MAP_FILE
65 #    define MAP_RFLAGS  (MAP_FILE|MAP_PRIVATE)
66 #    define MAP_WFLAGS  (MAP_FILE|MAP_SHARED)
67 #  else
68 #    define MAP_RFLAGS  MAP_PRIVATE
69 #    define MAP_WFLAGS  MAP_SHARED
70 #  endif
71
72 #  ifndef MAP_FAILED
73 #    define MAP_FAILED  ((void *)-1)
74 #  endif
75
76 #endif /* HISTORY_USE_MMAP */
77
78 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
79    on win 95/98/nt), we want to open files with O_BINARY mode so that there
80    is no \n -> \r\n conversion performed.  On other systems, we don't want to
81    mess around with O_BINARY at all, so we ensure that it's defined to 0. */
82 #if defined (__EMX__) || defined (__CYGWIN__)
83 #  ifndef O_BINARY
84 #    define O_BINARY 0
85 #  endif
86 #else /* !__EMX__ && !__CYGWIN__ */
87 #  undef O_BINARY
88 #  define O_BINARY 0
89 #endif /* !__EMX__ && !__CYGWIN__ */
90
91 #include <errno.h>
92 #if !defined (errno)
93 extern int errno;
94 #endif /* !errno */
95
96 #include "history.h"
97 #include "histlib.h"
98
99 #include "rlshell.h"
100 #include "xmalloc.h"
101
102 /* If non-zero, we write timestamps to the history file in history_do_write() */
103 int history_write_timestamps = 0;
104
105 /* Does S look like the beginning of a history timestamp entry?  Placeholder
106    for more extensive tests. */
107 #define HIST_TIMESTAMP_START(s)         (*(s) == history_comment_char && isdigit ((s)[1]) )
108
109 /* Return the string that should be used in the place of this
110    filename.  This only matters when you don't specify the
111    filename to read_history (), or write_history (). */
112 static char *
113 history_filename (filename)
114      const char *filename;
115 {
116   char *return_val;
117   const char *home;
118   int home_len;
119
120   return_val = filename ? savestring (filename) : (char *)NULL;
121
122   if (return_val)
123     return (return_val);
124   
125   home = sh_get_env_value ("HOME");
126 #ifdef _WIN32
127   if (!home)
128     home = sh_get_env_value ("APPDATA");
129 #endif
130
131   if (home == 0)
132     {
133 #if 0
134       home = ".";
135       home_len = 1;
136 #else
137       return (NULL);
138 #endif
139     }
140   else
141     home_len = strlen (home);
142
143   return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
144   strcpy (return_val, home);
145   return_val[home_len] = '/';
146 #if defined (__MSDOS__)
147   strcpy (return_val + home_len + 1, "_history");
148 #else
149   strcpy (return_val + home_len + 1, ".history");
150 #endif
151
152   return (return_val);
153 }
154
155 /* Add the contents of FILENAME to the history list, a line at a time.
156    If FILENAME is NULL, then read from ~/.history.  Returns 0 if
157    successful, or errno if not. */
158 int
159 read_history (filename)
160      const char *filename;
161 {
162   return (read_history_range (filename, 0, -1));
163 }
164
165 /* Read a range of lines from FILENAME, adding them to the history list.
166    Start reading at the FROM'th line and end at the TO'th.  If FROM
167    is zero, start at the beginning.  If TO is less than FROM, read
168    until the end of the file.  If FILENAME is NULL, then read from
169    ~/.history.  Returns 0 if successful, or errno if not. */
170 int
171 read_history_range (filename, from, to)
172      const char *filename;
173      int from, to;
174 {
175   register char *line_start, *line_end, *p;
176   char *input, *buffer, *bufend, *last_ts;
177   int file, current_line, chars_read;
178   struct stat finfo;
179   size_t file_size;
180 #if defined (EFBIG)
181   int overflow_errno = EFBIG;
182 #elif defined (EOVERFLOW)
183   int overflow_errno = EOVERFLOW;
184 #else
185   int overflow_errno = EIO;
186 #endif
187
188   buffer = last_ts = (char *)NULL;
189   input = history_filename (filename);
190   file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
191
192   if ((file < 0) || (fstat (file, &finfo) == -1))
193     goto error_and_exit;
194
195   file_size = (size_t)finfo.st_size;
196
197   /* check for overflow on very large files */
198   if (file_size != finfo.st_size || file_size + 1 < file_size)
199     {
200       errno = overflow_errno;
201       goto error_and_exit;
202     }
203
204 #ifdef HISTORY_USE_MMAP
205   /* We map read/write and private so we can change newlines to NULs without
206      affecting the underlying object. */
207   buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
208   if ((void *)buffer == MAP_FAILED)
209     {
210       errno = overflow_errno;
211       goto error_and_exit;
212     }
213   chars_read = file_size;
214 #else
215   buffer = (char *)malloc (file_size + 1);
216   if (buffer == 0)
217     {
218       errno = overflow_errno;
219       goto error_and_exit;
220     }
221
222   chars_read = read (file, buffer, file_size);
223 #endif
224   if (chars_read < 0)
225     {
226   error_and_exit:
227       if (errno != 0)
228         chars_read = errno;
229       else
230         chars_read = EIO;
231       if (file >= 0)
232         close (file);
233
234       FREE (input);
235 #ifndef HISTORY_USE_MMAP
236       FREE (buffer);
237 #endif
238
239       return (chars_read);
240     }
241
242   close (file);
243
244   /* Set TO to larger than end of file if negative. */
245   if (to < 0)
246     to = chars_read;
247
248   /* Start at beginning of file, work to end. */
249   bufend = buffer + chars_read;
250   current_line = 0;
251
252   /* Skip lines until we are at FROM. */
253   for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
254     if (*line_end == '\n')
255       {
256         p = line_end + 1;
257         /* If we see something we think is a timestamp, continue with this
258            line.  We should check more extensively here... */
259         if (HIST_TIMESTAMP_START(p) == 0)
260           current_line++;
261         line_start = p;
262       }
263
264   /* If there are lines left to gobble, then gobble them now. */
265   for (line_end = line_start; line_end < bufend; line_end++)
266     if (*line_end == '\n')
267       {
268         /* Change to allow Windows-like \r\n end of line delimiter. */
269         if (line_end > line_start && line_end[-1] == '\r')
270           line_end[-1] = '\0';
271         else
272           *line_end = '\0';
273
274         if (*line_start)
275           {
276             if (HIST_TIMESTAMP_START(line_start) == 0)
277               {
278                 add_history (line_start);
279                 if (last_ts)
280                   {
281                     add_history_time (last_ts);
282                     last_ts = NULL;
283                   }
284               }
285             else
286               {
287                 last_ts = line_start;
288                 current_line--;
289               }
290           }
291
292         current_line++;
293
294         if (current_line >= to)
295           break;
296
297         line_start = line_end + 1;
298       }
299
300   FREE (input);
301 #ifndef HISTORY_USE_MMAP
302   FREE (buffer);
303 #else
304   munmap (buffer, file_size);
305 #endif
306
307   return (0);
308 }
309
310 /* Truncate the history file FNAME, leaving only LINES trailing lines.
311    If FNAME is NULL, then use ~/.history.  Returns 0 on success, errno
312    on failure. */
313 int
314 history_truncate_file (fname, lines)
315      const char *fname;
316      int lines;
317 {
318   char *buffer, *filename, *bp, *bp1;           /* bp1 == bp+1 */
319   int file, chars_read, rv;
320   struct stat finfo;
321   size_t file_size;
322
323   buffer = (char *)NULL;
324   filename = history_filename (fname);
325   file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
326   rv = 0;
327
328   /* Don't try to truncate non-regular files. */
329   if (file == -1 || fstat (file, &finfo) == -1)
330     {
331       rv = errno;
332       if (file != -1)
333         close (file);
334       goto truncate_exit;
335     }
336
337   if (S_ISREG (finfo.st_mode) == 0)
338     {
339       close (file);
340 #ifdef EFTYPE
341       rv = EFTYPE;
342 #else
343       rv = EINVAL;
344 #endif
345       goto truncate_exit;
346     }
347
348   file_size = (size_t)finfo.st_size;
349
350   /* check for overflow on very large files */
351   if (file_size != finfo.st_size || file_size + 1 < file_size)
352     {
353       close (file);
354 #if defined (EFBIG)
355       rv = errno = EFBIG;
356 #elif defined (EOVERFLOW)
357       rv = errno = EOVERFLOW;
358 #else
359       rv = errno = EINVAL;
360 #endif
361       goto truncate_exit;
362     }
363
364   buffer = (char *)malloc (file_size + 1);
365   if (buffer == 0)
366     {
367       close (file);
368       goto truncate_exit;
369     }
370
371   chars_read = read (file, buffer, file_size);
372   close (file);
373
374   if (chars_read <= 0)
375     {
376       rv = (chars_read < 0) ? errno : 0;
377       goto truncate_exit;
378     }
379
380   /* Count backwards from the end of buffer until we have passed
381      LINES lines.  bp1 is set funny initially.  But since bp[1] can't
382      be a comment character (since it's off the end) and *bp can't be
383      both a newline and the history comment character, it should be OK. */
384   for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
385     {
386       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
387         lines--;
388       bp1 = bp;
389     }
390
391   /* If this is the first line, then the file contains exactly the
392      number of lines we want to truncate to, so we don't need to do
393      anything.  It's the first line if we don't find a newline between
394      the current value of i and 0.  Otherwise, write from the start of
395      this line until the end of the buffer. */
396   for ( ; bp > buffer; bp--)
397     {
398       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
399         {
400           bp++;
401           break;
402         }
403       bp1 = bp;
404     }
405
406   /* Write only if there are more lines in the file than we want to
407      truncate to. */
408   if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
409     {
410       if (write (file, bp, chars_read - (bp - buffer)) < 0)
411         rv = errno;
412
413 #if defined (__BEOS__)
414       /* BeOS ignores O_TRUNC. */
415       ftruncate (file, chars_read - (bp - buffer));
416 #endif
417
418       close (file);
419     }
420
421  truncate_exit:
422
423   FREE (buffer);
424
425   xfree (filename);
426   return rv;
427 }
428
429 /* Workhorse function for writing history.  Writes NELEMENT entries
430    from the history list to FILENAME.  OVERWRITE is non-zero if you
431    wish to replace FILENAME with the entries. */
432 static int
433 history_do_write (filename, nelements, overwrite)
434      const char *filename;
435      int nelements, overwrite;
436 {
437   register int i;
438   char *output;
439   int file, mode, rv;
440 #ifdef HISTORY_USE_MMAP
441   size_t cursize;
442
443   mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
444 #else
445   mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
446 #endif
447   output = history_filename (filename);
448   file = output ? open (output, mode, 0600) : -1;
449   rv = 0;
450
451   if (file == -1)
452     {
453       FREE (output);
454       return (errno);
455     }
456
457 #ifdef HISTORY_USE_MMAP
458   cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
459 #endif
460
461   if (nelements > history_length)
462     nelements = history_length;
463
464   /* Build a buffer of all the lines to write, and write them in one syscall.
465      Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
466   {
467     HIST_ENTRY **the_history;   /* local */
468     register int j;
469     int buffer_size;
470     char *buffer;
471
472     the_history = history_list ();
473     /* Calculate the total number of bytes to write. */
474     for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
475 #if 0
476       buffer_size += 2 + HISTENT_BYTES (the_history[i]);
477 #else
478       {
479         if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
480           buffer_size += strlen (the_history[i]->timestamp) + 1;
481         buffer_size += strlen (the_history[i]->line) + 1;
482       }
483 #endif
484
485     /* Allocate the buffer, and fill it. */
486 #ifdef HISTORY_USE_MMAP
487     if (ftruncate (file, buffer_size+cursize) == -1)
488       goto mmap_error;
489     buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
490     if ((void *)buffer == MAP_FAILED)
491       {
492 mmap_error:
493         rv = errno;
494         FREE (output);
495         close (file);
496         return rv;
497       }
498 #else    
499     buffer = (char *)malloc (buffer_size);
500     if (buffer == 0)
501       {
502         rv = errno;
503         FREE (output);
504         close (file);
505         return rv;
506       }
507 #endif
508
509     for (j = 0, i = history_length - nelements; i < history_length; i++)
510       {
511         if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
512           {
513             strcpy (buffer + j, the_history[i]->timestamp);
514             j += strlen (the_history[i]->timestamp);
515             buffer[j++] = '\n';
516           }
517         strcpy (buffer + j, the_history[i]->line);
518         j += strlen (the_history[i]->line);
519         buffer[j++] = '\n';
520       }
521
522 #ifdef HISTORY_USE_MMAP
523     if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
524       rv = errno;
525 #else
526     if (write (file, buffer, buffer_size) < 0)
527       rv = errno;
528     xfree (buffer);
529 #endif
530   }
531
532   close (file);
533
534   FREE (output);
535
536   return (rv);
537 }
538
539 /* Append NELEMENT entries to FILENAME.  The entries appended are from
540    the end of the list minus NELEMENTs up to the end of the list. */
541 int
542 append_history (nelements, filename)
543      int nelements;
544      const char *filename;
545 {
546   return (history_do_write (filename, nelements, HISTORY_APPEND));
547 }
548
549 /* Overwrite FILENAME with the current history.  If FILENAME is NULL,
550    then write the history list to ~/.history.  Values returned
551    are as in read_history ().*/
552 int
553 write_history (filename)
554      const char *filename;
555 {
556   return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
557 }