TheGNUGeneralPublicLicenseisoftenshippedwithGNUsoftware,and isgenerallykeptinafilecalledCOPYINGorLICENSE.Ifyoudonot haveacopyofthelicense,writetotheFreeSoftwareFoundation,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */
/* The goal is to make the implementation transparent, so that you don'thavetoknowwhatdatatypesareused,justwhatfunctions
you can call. I think I have done that. */
#define READLINE_LIBRARY
#ifdefined (__TANDEM) # include <floss.h> #endif
#ifdefined (HAVE_CONFIG_H) # include "config_readline.h" #endif
#include <stdio.h>
#include <sys/types.h> #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H) # include <sys/file.h> #endif #include"posixstat.h" #include <fcntl.h>
#ifdefined (HAVE_STDLIB_H) # include <stdlib.h> #else # include "ansi_stdlib.h" #endif/* HAVE_STDLIB_H */
#ifdefined (HAVE_UNISTD_H) # include <unistd.h> #endif
#ifdefined (__EMX__) || defined (__CYGWIN__) # undef HAVE_MMAP #endif
/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment onwin95/98/nt),wewanttoopenfileswithO_BINARYmodesothatthere isno\n->\r\nconversionperformed.Onothersystems,wedon'twantto
mess around with O_BINARY at all, so we ensure that it's defined to 0. */ #ifdefined (__EMX__) || defined (__CYGWIN__) # ifndef O_BINARY # define O_BINARY 0 # endif #else/* !__EMX__ && !__CYGWIN__ */ # undef O_BINARY # define O_BINARY 0 #endif/* !__EMX__ && !__CYGWIN__ */
/* If non-zero, we write timestamps to the history file in history_do_write() */ int history_write_timestamps = 0;
/* Does S look like the beginning of a history timestamp entry? Placeholder
for more extensive tests. */ #define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char)
/* Return the string that should be used in the place of this filename.Thisonlymatterswhenyoudon'tspecifythe
filename to read_history (), or write_history (). */ staticchar *
history_filename (filename) constchar *filename;
{ char *return_val; constchar *home; int home_len;
/* Add the contents of FILENAME to the history list, a line at a time. IfFILENAMEisNULL,thenreadfrom~/.history.Returns0if
successful, or errno if not. */ int
read_history (filename) constchar *filename;
{ return (read_history_range (filename, 0, -1));
}
/* Read a range of lines from FILENAME, adding them to the history list. StartreadingattheFROM'thlineandendattheTO'th.IfFROM iszero,startatthebeginning.IfTOislessthanFROM,read untiltheendofthefile.IfFILENAMEisNULL,thenreadfrom
~/.history. Returns 0 if successful, or errno if not. */ int
read_history_range (filename, from, to) constchar *filename; int from, to;
{ registerchar *line_start, *line_end, *p; char *input, *buffer, *bufend, *last_ts; int file, current_line, chars_read; struct stat finfo;
size_t file_size; #ifdefined (EFBIG) int overflow_errno = EFBIG; #elifdefined (EOVERFLOW) int overflow_errno = EOVERFLOW; #else int overflow_errno = EIO; #endif
/* Set TO to larger than end of file if negative. */ if (to < 0)
to = chars_read;
/* Start at beginning of file, work to end. */
bufend = buffer + chars_read;
current_line = 0;
/* Skip lines until we are at FROM. */ for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++) if (*line_end == '\n')
{
p = line_end + 1; /* If we see something we think is a timestamp, continue with this
line. We should check more extensively here... */ if (HIST_TIMESTAMP_START(p) == 0)
current_line++;
line_start = p;
}
/* If there are lines left to gobble, then gobble them now. */ for (line_end = line_start; line_end < bufend; line_end++) if (*line_end == '\n')
{ /* Change to allow Windows-like \r\n end of line delimiter. */ if (line_end > line_start && line_end[-1] == '\r')
line_end[-1] = '\0'; else
*line_end = '\0';
if (*line_start)
{ if (HIST_TIMESTAMP_START(line_start) == 0)
{
add_history (line_start); if (last_ts)
{
add_history_time (last_ts);
last_ts = NULL;
}
} else
{
last_ts = line_start;
current_line--;
}
}
/* Count backwards from the end of buffer until we have passed LINESlines.bp1issetfunnyinitially.Butsincebp[1]can't beacommentcharacter(sinceit'sofftheend)and*bpcan'tbe
both a newline and the history comment character, it should be OK. */ for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
{ if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
lines--;
bp1 = bp;
}
/* If this is the first line, then the file contains exactly the numberoflineswewanttotruncateto,sowedon'tneedtodo anything.It'sthefirstlineifwedon'tfindanewlinebetween thecurrentvalueofiand0.Otherwise,writefromthestartof
this line until the end of the buffer. */ for ( ; bp > buffer; bp--)
{ if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
{
bp++; break;
}
bp1 = bp;
}
/* Write only if there are more lines in the file than we want to
truncate to. */ if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
{
bytes_written= write (file, bp, chars_read - (bp - buffer));
(void) bytes_written;
if (nelements > history_length)
nelements = history_length;
/* Build a buffer of all the lines to write, and write them in one syscall.
Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
{
HIST_ENTRY **the_history; /* local */ registerint j; int buffer_size; char *buffer;
the_history = history_list (); /* Calculate the total number of bytes to write. */ for (buffer_size = 0, i = history_length - nelements; i < history_length; i++) #if0
buffer_size += 2 + HISTENT_BYTES (the_history[i]); #else
{ if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
buffer_size += strlen (the_history[i]->timestamp) + 1;
buffer_size += strlen (the_history[i]->line) + 1;
} #endif
/* Allocate the buffer, and fill it. */ #ifdef HISTORY_USE_MMAP if (ftruncate (file, buffer_size+cursize) == -1) goto mmap_error;
buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize); if ((void *)buffer == MAP_FAILED)
{
mmap_error:
rv = errno;
FREE (output);
close (file); return rv;
} #else
buffer = (char *)malloc (buffer_size); if (buffer == 0)
{
rv = errno;
FREE (output);
close (file); return rv;
} #endif
/* Append NELEMENT entries to FILENAME. The entries appended are from
the end of the list minus NELEMENTs up to the end of the list. */ int
append_history (nelements, filename) int nelements; constchar *filename;
{ return (history_do_write (filename, nelements, HISTORY_APPEND));
}
/* Overwrite FILENAME with the current history. If FILENAME is NULL, thenwritethehistorylistto~/.history.Valuesreturned
are as in read_history ().*/ int
write_history (filename) constchar *filename;
{ return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.