OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [readline/] [histfile.c] - Blame information for rev 1767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* histfile.c - functions to manipulate the history file. */
2
 
3
/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
4
 
5
   This file contains the GNU History Library (the Library), a set of
6
   routines for managing the text of previously typed lines.
7
 
8
   The Library 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 2, or (at your option)
11
   any later version.
12
 
13
   The Library is distributed in the hope that it will be useful, but
14
   WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
   General Public License for more details.
17
 
18
   The GNU General Public License is often shipped with GNU software, and
19
   is generally kept in a file called COPYING or LICENSE.  If you do not
20
   have a copy of the license, write to the Free Software Foundation,
21
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22
 
23
/* The goal is to make the implementation transparent, so that you
24
   don't have to know what data types are used, just what functions
25
   you can call.  I think I have done that. */
26
#define READLINE_LIBRARY
27
 
28
#if defined (HAVE_CONFIG_H)
29
#  include <config.h>
30
#endif
31
 
32
#include <stdio.h>
33
 
34
#include <sys/types.h>
35
#ifndef _MINIX
36
#  include <sys/file.h>
37
#endif
38
#include "posixstat.h"
39
#include <fcntl.h>
40
 
41
#if defined (HAVE_STDLIB_H)
42
#  include <stdlib.h>
43
#else
44
#  include "ansi_stdlib.h"
45
#endif /* HAVE_STDLIB_H */
46
 
47
#if defined (HAVE_UNISTD_H)
48
#  include <unistd.h>
49
#endif
50
 
51
#if defined (HAVE_STRING_H)
52
#  include <string.h>
53
#else
54
#  include <strings.h>
55
#endif /* !HAVE_STRING_H */
56
 
57
 
58
/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
59
   on win 95/98/nt), we want to open files with O_BINARY mode so that there
60
   is no \n -> \r\n conversion performed.  On other systems, we don't want to
61
   mess around with O_BINARY at all, so we ensure that it's defined to 0. */
62
#if defined (__EMX__) || defined (__CYGWIN__)
63
#  ifndef O_BINARY
64
#    define O_BINARY 0
65
#  endif
66
#else /* !__EMX__ && !__CYGWIN__ */
67
#  undef O_BINARY
68
#  define O_BINARY 0
69
#endif /* !__EMX__ && !__CYGWIN__ */
70
 
71
#include <errno.h>
72
#if !defined (errno)
73
extern int errno;
74
#endif /* !errno */
75
 
76
#include "history.h"
77
#include "histlib.h"
78
 
79
#include "rlshell.h"
80
#include "xmalloc.h"
81
 
82
/* Return the string that should be used in the place of this
83
   filename.  This only matters when you don't specify the
84
   filename to read_history (), or write_history (). */
85
static char *
86
history_filename (filename)
87
     char *filename;
88
{
89
  char *return_val, *home;
90
  int home_len;
91
 
92
  return_val = filename ? savestring (filename) : (char *)NULL;
93
 
94
  if (return_val)
95
    return (return_val);
96
 
97
  home = get_env_value ("HOME");
98
 
99
  if (home == 0)
100
    {
101
      home = ".";
102
      home_len = 1;
103
    }
104
  else
105
    home_len = strlen (home);
106
 
107
  return_val = xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
108
  strcpy (return_val, home);
109
  return_val[home_len] = '/';
110
#if defined (__MSDOS__)
111
  strcpy (return_val + home_len + 1, "_history");
112
#else
113
  strcpy (return_val + home_len + 1, ".history");
114
#endif
115
 
116
  return (return_val);
117
}
118
 
119
/* Add the contents of FILENAME to the history list, a line at a time.
120
   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
121
   successful, or errno if not. */
122
int
123
read_history (filename)
124
     char *filename;
125
{
126
  return (read_history_range (filename, 0, -1));
127
}
128
 
129
/* Read a range of lines from FILENAME, adding them to the history list.
130
   Start reading at the FROM'th line and end at the TO'th.  If FROM
131
   is zero, start at the beginning.  If TO is less than FROM, read
132
   until the end of the file.  If FILENAME is NULL, then read from
133
   ~/.history.  Returns 0 if successful, or errno if not. */
134
int
135
read_history_range (filename, from, to)
136
     char *filename;
137
     int from, to;
138
{
139
  register int line_start, line_end;
140
  char *input, *buffer;
141
  int file, current_line, chars_read;
142
  struct stat finfo;
143
  size_t file_size;
144
 
145
  buffer = (char *)NULL;
146
  input = history_filename (filename);
147
  file = open (input, O_RDONLY|O_BINARY, 0666);
148
 
149
  if ((file < 0) || (fstat (file, &finfo) == -1))
150
    goto error_and_exit;
151
 
152
  file_size = (size_t)finfo.st_size;
153
 
154
  /* check for overflow on very large files */
155
  if (file_size != finfo.st_size || file_size + 1 < file_size)
156
    {
157
#if defined (EFBIG)
158
      errno = EFBIG;
159
#endif
160
      goto error_and_exit;
161
    }
162
 
163
  buffer = xmalloc (file_size + 1);
164
 
165
  chars_read = read (file, buffer, file_size);
166
  if (chars_read < 0)
167
    {
168
  error_and_exit:
169
      if (file >= 0)
170
        close (file);
171
 
172
      FREE (input);
173
      FREE (buffer);
174
 
175
      return (errno);
176
    }
177
 
178
  close (file);
179
 
180
  /* Set TO to larger than end of file if negative. */
181
  if (to < 0)
182
    to = chars_read;
183
 
184
  /* Start at beginning of file, work to end. */
185
  line_start = line_end = current_line = 0;
186
 
187
  /* Skip lines until we are at FROM. */
188
  while (line_start < chars_read && current_line < from)
189
    {
190
      for (line_end = line_start; line_end < chars_read; line_end++)
191
        if (buffer[line_end] == '\n')
192
          {
193
            current_line++;
194
            line_start = line_end + 1;
195
            if (current_line == from)
196
              break;
197
          }
198
    }
199
 
200
  /* If there are lines left to gobble, then gobble them now. */
201
  for (line_end = line_start; line_end < chars_read; line_end++)
202
    if (buffer[line_end] == '\n')
203
      {
204
        buffer[line_end] = '\0';
205
 
206
        if (buffer[line_start])
207
          add_history (buffer + line_start);
208
 
209
        current_line++;
210
 
211
        if (current_line >= to)
212
          break;
213
 
214
        line_start = line_end + 1;
215
      }
216
 
217
  FREE (input);
218
  FREE (buffer);
219
 
220
  return (0);
221
}
222
 
223
/* Truncate the history file FNAME, leaving only LINES trailing lines.
224
   If FNAME is NULL, then use ~/.history. */
225
int
226
history_truncate_file (fname, lines)
227
     char *fname;
228
     int lines;
229
{
230
  register int i;
231
  int file, chars_read;
232
  char *buffer, *filename;
233
  struct stat finfo;
234
  size_t file_size;
235
 
236
  buffer = (char *)NULL;
237
  filename = history_filename (fname);
238
  file = open (filename, O_RDONLY|O_BINARY, 0666);
239
 
240
  if (file == -1 || fstat (file, &finfo) == -1)
241
    goto truncate_exit;
242
 
243
  /* Don't try to truncate non-regular files. */
244
  if (S_ISREG(finfo.st_mode) == 0)
245
    goto truncate_exit;
246
 
247
  file_size = (size_t)finfo.st_size;
248
 
249
  /* check for overflow on very large files */
250
  if (file_size != finfo.st_size || file_size + 1 < file_size)
251
    {
252
      close (file);
253
#if defined (EFBIG)
254
      errno = EFBIG;
255
#endif
256
      goto truncate_exit;
257
    }
258
 
259
  buffer = xmalloc (file_size + 1);
260
  chars_read = read (file, buffer, file_size);
261
  close (file);
262
 
263
  if (chars_read <= 0)
264
    goto truncate_exit;
265
 
266
  /* Count backwards from the end of buffer until we have passed
267
     LINES lines. */
268
  for (i = chars_read - 1; lines && i; i--)
269
    {
270
      if (buffer[i] == '\n')
271
        lines--;
272
    }
273
 
274
  /* If this is the first line, then the file contains exactly the
275
     number of lines we want to truncate to, so we don't need to do
276
     anything.  It's the first line if we don't find a newline between
277
     the current value of i and 0.  Otherwise, write from the start of
278
     this line until the end of the buffer. */
279
  for ( ; i; i--)
280
    if (buffer[i] == '\n')
281
      {
282
        i++;
283
        break;
284
      }
285
 
286
  /* Write only if there are more lines in the file than we want to
287
     truncate to. */
288
  if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
289
    {
290
      write (file, buffer + i, chars_read - i);
291
 
292
#if defined (__BEOS__)
293
      /* BeOS ignores O_TRUNC. */
294
      ftruncate (file, chars_read - i);
295
#endif
296
 
297
      close (file);
298
    }
299
 
300
 truncate_exit:
301
 
302
  FREE (buffer);
303
 
304
  free (filename);
305
  return 0;
306
}
307
 
308
/* Workhorse function for writing history.  Writes NELEMENT entries
309
   from the history list to FILENAME.  OVERWRITE is non-zero if you
310
   wish to replace FILENAME with the entries. */
311
static int
312
history_do_write (filename, nelements, overwrite)
313
     char *filename;
314
     int nelements, overwrite;
315
{
316
  register int i;
317
  char *output;
318
  int file, mode;
319
 
320
  mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
321
  output = history_filename (filename);
322
 
323
  if ((file = open (output, mode, 0600)) == -1)
324
    {
325
      FREE (output);
326
      return (errno);
327
    }
328
 
329
  if (nelements > history_length)
330
    nelements = history_length;
331
 
332
  /* Build a buffer of all the lines to write, and write them in one syscall.
333
     Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
334
  {
335
    HIST_ENTRY **the_history;   /* local */
336
    register int j;
337
    int buffer_size;
338
    char *buffer;
339
 
340
    the_history = history_list ();
341
    /* Calculate the total number of bytes to write. */
342
    for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
343
      buffer_size += 1 + strlen (the_history[i]->line);
344
 
345
    /* Allocate the buffer, and fill it. */
346
    buffer = xmalloc (buffer_size);
347
 
348
    for (j = 0, i = history_length - nelements; i < history_length; i++)
349
      {
350
        strcpy (buffer + j, the_history[i]->line);
351
        j += strlen (the_history[i]->line);
352
        buffer[j++] = '\n';
353
      }
354
 
355
    write (file, buffer, buffer_size);
356
    free (buffer);
357
  }
358
 
359
  close (file);
360
 
361
  FREE (output);
362
 
363
  return (0);
364
}
365
 
366
/* Append NELEMENT entries to FILENAME.  The entries appended are from
367
   the end of the list minus NELEMENTs up to the end of the list. */
368
int
369
append_history (nelements, filename)
370
     int nelements;
371
     char *filename;
372
{
373
  return (history_do_write (filename, nelements, HISTORY_APPEND));
374
}
375
 
376
/* Overwrite FILENAME with the current history.  If FILENAME is NULL,
377
   then write the history list to ~/.history.  Values returned
378
   are as in read_history ().*/
379
int
380
write_history (filename)
381
     char *filename;
382
{
383
  return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
384
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.