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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [readline/] [histfile.c] - Blame information for rev 106

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

Line No. Rev Author Line
1 106 markom
/* 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 1, 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
   675 Mass Ave, Cambridge, MA 02139, 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 <sys/stat.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
#if defined (__EMX__)
58
#  ifndef O_BINARY
59
#    define O_BINARY 0
60
#  endif
61
#else /* !__EMX__ */
62
   /* If we're not compiling for __EMX__, we don't want this at all.  Ever. */
63
#  undef O_BINARY
64
#  define O_BINARY 0
65
#endif /* !__EMX__ */
66
 
67
#include <errno.h>
68
#if !defined (errno)
69
extern int errno;
70
#endif /* !errno */
71
 
72
#include "history.h"
73
#include "histlib.h"
74
 
75
/* Functions imported from shell.c */
76
extern char *get_env_value ();
77
 
78
extern char *xmalloc (), *xrealloc ();
79
 
80
/* Return the string that should be used in the place of this
81
   filename.  This only matters when you don't specify the
82
   filename to read_history (), or write_history (). */
83
static char *
84
history_filename (filename)
85
     char *filename;
86
{
87
  char *return_val, *home;
88
  int home_len;
89
 
90
  return_val = filename ? savestring (filename) : (char *)NULL;
91
 
92
  if (return_val)
93
    return (return_val);
94
 
95
  home = get_env_value ("HOME");
96
 
97
  if (home == 0)
98
    {
99
      home = ".";
100
      home_len = 1;
101
    }
102
  else
103
    home_len = strlen (home);
104
 
105
  return_val = xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
106
  strcpy (return_val, home);
107
  return_val[home_len] = '/';
108
  strcpy (return_val + home_len + 1, ".history");
109
 
110
  return (return_val);
111
}
112
 
113
/* Add the contents of FILENAME to the history list, a line at a time.
114
   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
115
   successful, or errno if not. */
116
int
117
read_history (filename)
118
     char *filename;
119
{
120
  return (read_history_range (filename, 0, -1));
121
}
122
 
123
/* Read a range of lines from FILENAME, adding them to the history list.
124
   Start reading at the FROM'th line and end at the TO'th.  If FROM
125
   is zero, start at the beginning.  If TO is less than FROM, read
126
   until the end of the file.  If FILENAME is NULL, then read from
127
   ~/.history.  Returns 0 if successful, or errno if not. */
128
int
129
read_history_range (filename, from, to)
130
     char *filename;
131
     int from, to;
132
{
133
  register int line_start, line_end;
134
  char *input, *buffer;
135
  int file, current_line;
136
  struct stat finfo;
137
  size_t file_size;
138
 
139
  buffer = (char *)NULL;
140
  input = history_filename (filename);
141
  file = open (input, O_RDONLY|O_BINARY, 0666);
142
 
143
 
144
#ifdef __MSDOS__
145
  /* MSDOS doesn't allow leading dots in file names.  Try again
146
     with the dot replaced by an underscore.  */
147
  if (file < 0 && !filename)
148
    {
149
      input[strlen (input) - 8] = '_';
150
      file = open (input, O_RDONLY|O_BINARY, 0666);
151
    }
152
#endif
153
  if ((file < 0) || (fstat (file, &finfo) == -1))
154
    goto error_and_exit;
155
 
156
  file_size = (size_t)finfo.st_size;
157
 
158
  /* check for overflow on very large files */
159
  if (file_size != finfo.st_size || file_size + 1 < file_size)
160
    {
161
#if defined (EFBIG)
162
      errno = EFBIG;
163
#endif
164
      goto error_and_exit;
165
    }
166
 
167
  buffer = xmalloc (file_size + 1);
168
#if 0
169
  if (read (file, buffer, file_size) != file_size)
170
#else
171
  if (read (file, buffer, file_size) < 0)
172
#endif
173
    {
174
  error_and_exit:
175
      if (file >= 0)
176
        close (file);
177
 
178
      FREE (input);
179
      FREE (buffer);
180
 
181
      return (errno);
182
    }
183
 
184
  close (file);
185
 
186
  /* Set TO to larger than end of file if negative. */
187
  if (to < 0)
188
    to = file_size;
189
 
190
  /* Start at beginning of file, work to end. */
191
  line_start = line_end = current_line = 0;
192
 
193
  /* Skip lines until we are at FROM. */
194
  while (line_start < file_size && current_line < from)
195
    {
196
      for (line_end = line_start; line_end < file_size; line_end++)
197
        if (buffer[line_end] == '\n')
198
          {
199
            current_line++;
200
            line_start = line_end + 1;
201
            if (current_line == from)
202
              break;
203
          }
204
    }
205
 
206
  /* If there are lines left to gobble, then gobble them now. */
207
  for (line_end = line_start; line_end < file_size; line_end++)
208
    if (buffer[line_end] == '\n')
209
      {
210
        buffer[line_end] = '\0';
211
 
212
        if (buffer[line_start])
213
          add_history (buffer + line_start);
214
 
215
        current_line++;
216
 
217
        if (current_line >= to)
218
          break;
219
 
220
        line_start = line_end + 1;
221
      }
222
 
223
  FREE (input);
224
  FREE (buffer);
225
 
226
  return (0);
227
}
228
 
229
/* Truncate the history file FNAME, leaving only LINES trailing lines.
230
   If FNAME is NULL, then use ~/.history. */
231
int
232
history_truncate_file (fname, lines)
233
     char *fname;
234
     int lines;
235
{
236
  register int i;
237
  int file, chars_read;
238
  char *buffer, *filename;
239
  struct stat finfo;
240
  size_t file_size;
241
 
242
  buffer = (char *)NULL;
243
  filename = history_filename (fname);
244
  file = open (filename, O_RDONLY|O_BINARY, 0666);
245
 
246
#ifdef __MSDOS__
247
  /* MSDOS doesn't allow leading dots in file names.  Try again
248
     with the dot replaced by an underscore.  */
249
  if (file < 0 && !fname)
250
    {
251
      filename[strlen (filename) - 8] = '_';
252
      file = open (filename, O_RDONLY|O_BINARY, 0666);
253
    }
254
#endif
255
 
256
  if (file == -1 || fstat (file, &finfo) == -1)
257
    goto truncate_exit;
258
 
259
  file_size = (size_t)finfo.st_size;
260
 
261
  /* check for overflow on very large files */
262
  if (file_size != finfo.st_size || file_size + 1 < file_size)
263
    {
264
      close (file);
265
#if defined (EFBIG)
266
      errno = EFBIG;
267
#endif
268
      goto truncate_exit;
269
    }
270
 
271
  buffer = xmalloc (file_size + 1);
272
  chars_read = read (file, buffer, file_size);
273
  close (file);
274
 
275
  if (chars_read <= 0)
276
    goto truncate_exit;
277
 
278
  /* Count backwards from the end of buffer until we have passed
279
     LINES lines. */
280
  for (i = chars_read - 1; lines && i; i--)
281
    {
282
      if (buffer[i] == '\n')
283
        lines--;
284
    }
285
 
286
  /* If this is the first line, then the file contains exactly the
287
     number of lines we want to truncate to, so we don't need to do
288
     anything.  It's the first line if we don't find a newline between
289
     the current value of i and 0.  Otherwise, write from the start of
290
     this line until the end of the buffer. */
291
  for ( ; i; i--)
292
    if (buffer[i] == '\n')
293
      {
294
        i++;
295
        break;
296
      }
297
 
298
  /* Write only if there are more lines in the file than we want to
299
     truncate to. */
300
  if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
301
    {
302
      write (file, buffer + i, file_size - i);
303
 
304
#if defined (__BEOS__)
305
      /* BeOS ignores O_TRUNC. */
306
      ftruncate (file, file_size - i);
307
#endif
308
 
309
      close (file);
310
    }
311
 
312
 truncate_exit:
313
 
314
  FREE (buffer);
315
 
316
  free (filename);
317
  return 0;
318
}
319
 
320
/* Workhorse function for writing history.  Writes NELEMENT entries
321
   from the history list to FILENAME.  OVERWRITE is non-zero if you
322
   wish to replace FILENAME with the entries. */
323
static int
324
history_do_write (filename, nelements, overwrite)
325
     char *filename;
326
     int nelements, overwrite;
327
{
328
  register int i;
329
  char *output;
330
  int file, mode;
331
 
332
  mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
333
  output = history_filename (filename);
334
 
335
  if ((file = open (output, mode, 0600)) == -1)
336
    {
337
#ifdef __MSDOS__
338
      /* MSDOS doesn't allow leading dots in file names.  If this is
339
         the default file name, try again with the dot replaced by an
340
         underscore.  */
341
      if (!filename)
342
        {
343
          output[strlen (output) - 8] = '_';
344
          if ((file = open (output, mode, 0600)) == -1)
345
            {
346
              FREE (output);
347
              return (errno);
348
            }
349
        }
350
#else
351
      FREE (output);
352
      return (errno);
353
#endif
354
    }
355
 
356
  if (nelements > history_length)
357
    nelements = history_length;
358
 
359
  /* Build a buffer of all the lines to write, and write them in one syscall.
360
     Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
361
  {
362
    HIST_ENTRY **the_history;   /* local */
363
    register int j;
364
    int buffer_size;
365
    char *buffer;
366
 
367
    the_history = history_list ();
368
    /* Calculate the total number of bytes to write. */
369
    for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
370
      buffer_size += 1 + strlen (the_history[i]->line);
371
 
372
    /* Allocate the buffer, and fill it. */
373
    buffer = xmalloc (buffer_size);
374
 
375
    for (j = 0, i = history_length - nelements; i < history_length; i++)
376
      {
377
        strcpy (buffer + j, the_history[i]->line);
378
        j += strlen (the_history[i]->line);
379
        buffer[j++] = '\n';
380
      }
381
 
382
    write (file, buffer, buffer_size);
383
    free (buffer);
384
  }
385
 
386
  close (file);
387
 
388
  FREE (output);
389
 
390
  return (0);
391
}
392
 
393
/* Append NELEMENT entries to FILENAME.  The entries appended are from
394
   the end of the list minus NELEMENTs up to the end of the list. */
395
int
396
append_history (nelements, filename)
397
     int nelements;
398
     char *filename;
399
{
400
  return (history_do_write (filename, nelements, HISTORY_APPEND));
401
}
402
 
403
/* Overwrite FILENAME with the current history.  If FILENAME is NULL,
404
   then write the history list to ~/.history.  Values returned
405
   are as in read_history ().*/
406
int
407
write_history (filename)
408
     char *filename;
409
{
410
  return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
411
}

powered by: WebSVN 2.1.0

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