📄 cut.c
字号:
int dash_found = 0; /* Nonzero if a '-' is found in this field. */
int value = 0; /* If nonzero, a number being accumulated. */
int fieldset = 0; /* Number of fields selected so far. */
/* If nonzero, index of first field in a range that goes to end of line. */
int eol_range_start = 0;
for (;;)
{
switch (*fieldstr)
{
case '-':
/* Starting a range. */
if (dash_found)
invalid_list ();
dash_found++;
fieldstr++;
if (value)
{
if (value >= line_size)
enlarge_line (value);
initial = value;
value = 0;
}
else
initial = 1;
break;
case ',':
case '\0':
/* Ending the string, or this field/byte sublist. */
if (dash_found)
{
dash_found = 0;
/* A range. Possibilites: -n, m-n, n-.
In any case, `initial' contains the start of the range. */
if (value == 0)
{
/* `n-'. From `initial' to end of line. */
eol_range_start = initial;
fieldset++;
}
else
{
/* `m-n' or `-n' (1-n). */
if (value < initial)
invalid_list ();
if (value >= line_size)
enlarge_line (value);
/* Is there already a range going to end of line? */
if (eol_range_start != 0)
{
/* Yes. Is the new sequence already contained
in the old one? If so, no processing is
necessary. */
if (initial < eol_range_start)
{
/* No, the new sequence starts before the
old. Does the old range going to end of line
extend into the new range? */
if (eol_range_start < value)
/* Yes. Simply move the end of line marker. */
eol_range_start = initial;
else
/* No. A simple range, before and disjoint from
the range going to end of line. Fill it. */
for (; initial <= value; initial++)
fields[initial] = field_output;
/* In any case, some fields were selected. */
fieldset++;
}
}
else
{
/* There is no range going to end of line. */
for (; initial <= value; initial++)
fields[initial] = field_output;
fieldset++;
}
value = 0;
}
}
else if (value != 0)
{
/* A simple field number, not a range. */
if (value >= line_size)
enlarge_line (value);
fields[value] = field_output;
value = 0;
fieldset++;
}
if (*fieldstr == '\0')
{
/* If there was a range going to end of line, fill the
array from the end of line point. */
if (eol_range_start)
for (initial = eol_range_start; initial < line_size; initial++)
fields[initial] = field_output;
return fieldset;
}
fieldstr++;
break;
default:
if (*fieldstr < '0' || *fieldstr > '9')
invalid_list ();
value = 10 * value + *fieldstr - '0';
fieldstr++;
break;
}
}
}
void
cut_file (stream)
FILE *stream;
{
if (operating_mode == byte_mode)
cut_file_bytes (stream);
else
cut_file_fields (stream);
}
/* Print the file open for reading on stream FNO
with the bytes specified in `fields' removed from each line. */
void
cut_file_bytes (fno)
FILE *fno;
{
register int c; /* Each character from the file. */
int doneflag = 0; /* Nonzero if EOF reached. */
int char_count; /* Number of chars in the line so far. */
char *outbufptr; /* Where to save next char to output. */
while (doneflag == 0)
{
/* Start processing a line. */
outbufptr = outbuf;
char_count = 0;
do
{
c = getc (fno);
if (c == EOF)
{
doneflag++;
break;
}
/* If this character is to be sent, stow it in the outbuffer. */
if (++char_count == line_size - 1)
enlarge_line (char_count);
if (fields[char_count] == field_output || c == '\n')
*outbufptr++ = c;
}
while (c != '\n');
if (char_count)
fwrite (outbuf, sizeof (char), outbufptr - outbuf, stdout);
}
}
/* Print the file open for reading on stream FNO
with the fields specified in `fields' removed from each line.
All characters are initially stowed in the raw input buffer, until
at least one field has been found. */
void
cut_file_fields (fno)
FILE *fno;
{
register int c; /* Each character from the file. */
int doneflag = 0; /* Nonzero if EOF reached. */
int char_count; /* Number of chars in line before any delim. */
int fieldfound; /* Nonzero if any fields to print found. */
int curr_field; /* Current index in `fields'. */
char *outbufptr; /* Where to save next char to output. */
char *inbufptr; /* Where to save next input char. */
while (doneflag == 0)
{
char_count = 0;
fieldfound = 0;
curr_field = 1;
outbufptr = outbuf;
inbufptr = inbuf;
do
{
c = getc (fno);
if (c == EOF)
{
doneflag++;
break;
}
if (fields[curr_field] == field_output && c != '\n')
{
/* Working on a field. It, and its terminating
delimiter, go only into the processed buffer. */
fieldfound = 1;
if (outbufptr - outbuf == line_size - 2)
enlarge_line (outbufptr - outbuf);
*outbufptr++ = c;
}
else if (fieldfound == 0)
{
if (++char_count == line_size - 1)
enlarge_line (char_count);
*inbufptr++ = c;
}
if (c == delim && ++curr_field == line_size - 1)
enlarge_line (curr_field);
}
while (c != '\n');
if (fieldfound)
{
/* Something was found. Print it. */
if (outbufptr[-1] == delim)
--outbufptr; /* Supress trailing delimiter. */
fwrite (outbuf, sizeof (char), outbufptr - outbuf, stdout);
if (c == '\n')
putc (c, stdout);
}
else if (!delimited_lines_only && char_count)
/* A line with some characters, no delimiters, and no
supression. Print it. */
fwrite (inbuf, sizeof (char), inbufptr - inbuf, stdout);
}
}
/* Extend the buffers to accomodate at least NEW_SIZE characters. */
void
enlarge_line (new_size)
int new_size;
{
int i;
new_size += 256; /* Leave some room to grow. */
fields = (enum field_action *)
xrealloc (fields, new_size * sizeof (enum field_action));
outbuf = (char *) xrealloc (outbuf, new_size);
inbuf = (char *) xrealloc (inbuf, new_size);
for (i = line_size; i < new_size; i++)
fields[i] = field_omit;
line_size = new_size;
}
#ifndef MSDOS /* We have it in gnulib */
/* Allocate N bytes of memory dynamically, with error checking. */
char *
xmalloc (n)
unsigned n;
{
char *p;
p = malloc (n);
if (p == 0)
error (2, 0, "virtual memory exhausted");
return p;
}
char *
xrealloc (p, n)
char *p;
unsigned n;
{
p = realloc (p, n);
if (p == 0)
error (2, 0, "virtual memory exhausted");
return p;
}
#endif /* not MSDOS */
void
invalid_list ()
{
error (2, 0, "invalid byte or field list");
}
void
usage ()
{
#ifdef MSDOS
fprintf (stderr, "\
Usage: %s {-b byte-list,+bytes byte-list} [-n] [+copying]\n\
[+version] [file...]\n\
%s {-c character-list,+characters character-list} [+copying]\n\
[+version] [file...]\n\
%s {-f field-list,+fields field-list} [-d delim] [-s]\n\
[+delimiter delim] [+only-delimited] [+copying] [+version] [file...]\n",
program_name, program_name, program_name);
#else /* not MSDOS */
fprintf (stderr, "\
Usage: %s {-b byte-list,+bytes byte-list} [-n] [file...]\n\
%s {-c character-list,+characters character-list} [file...]\n\
%s {-f field-list,+fields field-list} [-d delim] [-s]\n\
[+delimiter delim] [+only-delimited] [file...]\n",
program_name, program_name, program_name);
#endif /* not MSDOS */
exit (2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -