diff options
author | Jim Meyering <jim@meyering.net> | 1993-12-22 22:41:00 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 1993-12-22 22:41:00 +0000 |
commit | 797585985fffbf0f6e6ef09113051d2ebc976193 (patch) | |
tree | 2582e1dea3547e9d6a60f40bdd299823ce649bfc /src | |
parent | 9883bf72802226d20c4de97b217e343725aded9c (diff) | |
download | coreutils-797585985fffbf0f6e6ef09113051d2ebc976193.tar.xz |
.
Diffstat (limited to 'src')
-rw-r--r-- | src/cut.c | 788 |
1 files changed, 449 insertions, 339 deletions
@@ -72,6 +72,11 @@ #define _GNU_SOURCE #include <stdio.h> + +/* FIXME */ +/* #define NDEBUG */ +#include <assert.h> + #include <getopt.h> #include <sys/types.h> #include "system.h" @@ -85,47 +90,55 @@ } \ while (0) +struct range_pair + { + int lo; + int hi; + }; + +#define ADD_RANGE_PAIR(rp, low, high) \ + do \ + { \ + if (n_rp >= n_rp_allocated) \ + { \ + n_rp_allocated *= 2; \ + (rp) = (struct range_pair *) xrealloc ((rp), \ + n_rp_allocated * sizeof (*(rp))); \ + } \ + rp[n_rp].lo = (low); \ + rp[n_rp].hi = (high); \ + ++n_rp; \ + } \ + while (0) + char *xmalloc (); char *xrealloc (); void error (); -static int set_fields (); -static int cut_file (); -static void cut_stream (); -static void cut_bytes (); -static void cut_fields (); -static void enlarge_line (); -static void usage (); - -/* The number of elements allocated for the input line - and the byte or field number. - Enlarged as necessary. */ -static int line_size; - -/* Processed output buffer. */ -static char *outbuf; - -/* Where to save next char to output. */ -static char *outbufptr; +/* FIXME: Comment. */ +static char *field_1_buffer; -/* Raw line buffer for field mode. */ -static char *inbuf; +/* FIXME: Comment. */ +static int field_1_bufsize; -/* Where to save next input char. */ -static char *inbufptr; +/* The largest field or byte index used as an endpoint of a closed + or degenerate range specification; this doesn't include the starting + index of right-open-ended ranges. For example, with either range spec + `2-5,9-', `2-3,5,9-' this variable would be set to 5. */ +static int max_range_endpoint; -/* What can be done about a byte or field. */ -enum field_action - { - FIELD_OMIT, - FIELD_OUTPUT - }; +/* If nonzero, this is the index of the first field in a range that goes + to end of line. */ +static int eol_range_start; /* In byte mode, which bytes to output. - In field mode, which `delim'-separated fields to output. + In field mode, which DELIM-separated fields to output. Both bytes and fields are numbered starting with 1, - so the first element of `fields' is unused. */ -static enum field_action *fields; + so the zeroth element of this array is unused. + A field or byte K has been selected if + (K <= MAX_RANGE_ENDPOINT and PRINTABLE_FIELD[K]) + || (EOL_RANGE_START > 0 && K >= EOL_RANGE_START). */ +static int *printable_field; enum operating_mode { @@ -143,9 +156,10 @@ char *program_name; static enum operating_mode operating_mode; -/* If nonzero, - for field mode, do not output lines containing no delimeter characters. */ -static int delimited_lines_only; +/* If non-zero do not output lines containing no delimeter characters. + Otherwise, all such lines are printed. This option is valid only + with field mode. */ +static int suppress_non_delimited; /* The delimeter character for field mode. */ static unsigned char delim; @@ -153,10 +167,6 @@ static unsigned char delim; /* Nonzero if we have ever read standard input. */ static int have_read_stdin; -/* If nonzero, this is the index of the first field in a range that goes - to end of line. */ -static int eol_range_start; - /* If non-zero, display usage information and exit. */ static int show_help; @@ -175,128 +185,164 @@ static struct option const longopts[] = {0, 0, 0, 0} }; -void -main (argc, argv) - int argc; - char **argv; +static void +usage (status) + int status; { - int optc, exit_status = 0; - - program_name = argv[0]; - - line_size = 512; - operating_mode = undefined_mode; - delimited_lines_only = 0; - delim = '\0'; - have_read_stdin = 0; - - fields = (enum field_action *) - xmalloc (line_size * sizeof (enum field_action)); - outbuf = (char *) xmalloc (line_size); - inbuf = (char *) xmalloc (line_size); - - for (optc = 0; optc < line_size; optc++) - fields[optc] = FIELD_OMIT; - - while ((optc = getopt_long (argc, argv, "b:c:d:f:ns", longopts, (int *) 0)) - != EOF) + if (status != 0) + fprintf (stderr, "Try `%s --help' for more information.\n", + program_name); + else { - switch (optc) - { - case 0: - break; - - case 'b': - case 'c': - /* Build the byte list. */ - if (operating_mode != undefined_mode) - FATAL_ERROR ("only one type of list may be specified"); - operating_mode = byte_mode; - if (set_fields (optarg) == 0) - FATAL_ERROR ("missing list of positions"); - break; - - case 'f': - /* Build the field list. */ - if (operating_mode != undefined_mode) - FATAL_ERROR ("only one type of list may be specified"); - operating_mode = field_mode; - if (set_fields (optarg) == 0) - FATAL_ERROR ("missing list of fields"); - break; + printf ("\ +Usage: %s [OPTION]... [FILE]...\n\ +", + program_name); + printf ("\ +\n\ + -b, --bytes=LIST output only these bytes\n\ + -c, --characters=LIST output only these characters\n\ + -d, --delimiter=DELIM use DELIM instead of TAB for field delimiter\n\ + -f, --fields=LIST output only these fields\n\ + -n (ignored)\n\ + -s, --only-delimited do not print lines not containing delimiters\n\ + --help display this help and exit\n\ + --version output version information and exit\n\ +\n\ +Use one, and only one of -b, -c or -f. Each LIST is made up of one\n\ +range, or many ranges separated by commas. Each range is one of:\n\ +\n\ + N N'th byte, character or field, counted from 1\n\ + N- from N'th byte, character or field, to end of line\n\ + N-M from N'th to M'th (included) byte, character or field\n\ + -M from first to M'th (included) byte, character or field\n\ +\n\ +With no FILE, or when FILE is -, read standard input.\n\ +"); + } + exit (status); +} - case 'd': - /* New delimiter. */ - if (optarg[0] == '\0') - FATAL_ERROR ("missing delimiter argument"); - if (optarg[1] != '\0') - FATAL_ERROR ("the delimiter must be a single character"); - delim = optarg[0]; - break; +/* Begin ------------ from getline.c */ +/* Always add at least this many bytes when extending the buffer. */ +#define MIN_CHUNK 64 - case 'n': - break; +/* Read up to (and including) a newline or TERMINATOR from STREAM into + *LINEPTR (and null-terminate it). *LINEPTR is a pointer returned from + xmalloc (or NULL), pointing to *N characters of space. It is + xrealloc'd as necessary. Return the number of characters read (not + including the null terminator), or -1 on error or EOF. */ - case 's': - delimited_lines_only++; - break; +int +getstr (lineptr, n, stream, terminator) + char **lineptr; + int *n; + FILE *stream; + char terminator; +{ + int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ + char *read_pos; /* Where we're reading into *LINEPTR. */ - default: - usage (2); - } - } + if (!lineptr || !n || !stream) + return -1; - if (show_version) + if (!*lineptr) { - printf ("%s\n", version_string); - exit (0); + *n = MIN_CHUNK; + *lineptr = xmalloc (*n); + if (!*lineptr) + return -1; } - if (show_help) - usage (0); + nchars_avail = *n; + read_pos = *lineptr; - if (operating_mode == undefined_mode) - FATAL_ERROR ("you must specify a list of bytes, characters, or fields"); + for (;;) + { + register int c = getc (stream); - if ((delimited_lines_only || delim != '\0') && operating_mode != field_mode) - FATAL_ERROR ("a delimiter may be specified only when operating on fields"); + /* We always want at least one char left in the buffer, since we + always (unless we get an error while reading the first char) + NUL-terminate the line buffer. */ - if (delim == '\0') - delim = '\t'; + assert (*n - nchars_avail == read_pos - *lineptr); + if (nchars_avail < 1) + { + if (*n > MIN_CHUNK) + *n *= 2; + else + *n += MIN_CHUNK; + + nchars_avail = *n + *lineptr - read_pos; + *lineptr = xrealloc (*lineptr, *n); + if (!*lineptr) + return -1; + read_pos = *n - nchars_avail + *lineptr; + assert (*n - nchars_avail == read_pos - *lineptr); + } - if (optind == argc) - exit_status |= cut_file ("-"); - else - for (; optind < argc; optind++) - exit_status |= cut_file (argv[optind]); + if (feof (stream) || ferror (stream)) + { + /* Return partial line, if any. */ + if (read_pos == *lineptr) + return -1; + else + break; + } - if (have_read_stdin && fclose (stdin) == EOF) - { - error (0, errno, "-"); - exit_status = 1; + *read_pos++ = c; + nchars_avail--; + + if (c == terminator || c == '\n') + /* Return the line. */ + break; } - if (ferror (stdout) || fclose (stdout) == EOF) - error (1, errno, "write error"); - exit (exit_status); + /* Done - NUL terminate and return the number of chars read. */ + *read_pos = '\0'; + + return read_pos - *lineptr; } -/* Select for printing the positions in `fields' that are listed in - byte or field specification FIELDSTR. FIELDSTR should be - composed of one or more numbers or ranges of numbers, separated by - blanks or commas. Incomplete ranges may be given: `-m' means - `1-m'; `n-' means `n' through end of line or last field. +static int +print_kth (k) + int k; +{ + return ((eol_range_start > 0 && eol_range_start <= k) + || (k <= max_range_endpoint && printable_field[k])); +} - Return the number of fields selected. */ +/* Given the list of field or byte range specifications FIELDSTR, set + MAX_RANGE_ENDPOINT and allocate and initialize the PRINTABLE_FIELD + array. If there is a right-open-ended range, set EOL_RANGE_START + to its starting index. FIELDSTR should be composed of one or more + numbers or ranges of numbers, separated by blanks or commas. + Incomplete ranges may be given: `-m' means `1-m'; `n-' means `n' + through end of line or last field. Return non-zero if FIELDSTR + contains at least one field specification, zero otherwise. */ static int set_fields (fieldstr) char *fieldstr; { - int initial = 1; /* Value of first number in a range. */ - int dash_found = 0; /* Nonzero if a '-' is found in this field. */ - int value = 0; /* If nonzero, a number being accumulated. */ - int fields_selected = 0; /* Number of fields selected so far. */ + int initial = 1; /* Value of first number in a range. */ + int dash_found = 0; /* Nonzero if a '-' is found in this field. */ + int value = 0; /* If nonzero, a number being accumulated. */ + int field_found = 0; /* Non-zero if at least one field spec + has been processed. */ + + struct range_pair *rp; + unsigned int n_rp; + unsigned int n_rp_allocated; + int i; + + n_rp = 0; + /* FIXME: use 1 only for testing. */ + n_rp_allocated = 1; + rp = (struct range_pair *) xmalloc (n_rp_allocated * sizeof (*rp)); + + /* Collect and store in RP the range end points. + It also sets EOL_RANGE_START if appropriate. */ for (;;) { @@ -310,8 +356,6 @@ set_fields (fieldstr) if (value) { - if (value >= line_size) - enlarge_line (value); initial = value; value = 0; } @@ -331,7 +375,7 @@ set_fields (fieldstr) { /* `n-'. From `initial' to end of line. */ eol_range_start = initial; - fields_selected++; + field_found = 1; } else { @@ -339,9 +383,6 @@ set_fields (fieldstr) if (value < initial) FATAL_ERROR ("invalid byte or field list"); - if (value >= line_size) - enlarge_line (value); - /* Is there already a range going to end of line? */ if (eol_range_start != 0) { @@ -355,27 +396,25 @@ set_fields (fieldstr) extend into the new range? */ if (value >= eol_range_start - 1) { - /* Yes. Simply move the end of line marker. */ - eol_range_start = initial; + /* 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; + ADD_RANGE_PAIR (rp, initial, value); } /* In any case, some fields were selected. */ - fields_selected++; + field_found = 1; } } else { /* There is no range going to end of line. */ - for (; initial <= value; initial++) - fields[initial] = FIELD_OUTPUT; - fields_selected++; + ADD_RANGE_PAIR (rp, initial, value); + field_found = 1; } value = 0; } @@ -383,35 +422,210 @@ set_fields (fieldstr) else if (value != 0) { /* A simple field number, not a range. */ - if (value >= line_size) - enlarge_line (value); - - fields[value] = FIELD_OUTPUT; + ADD_RANGE_PAIR (rp, value, value); value = 0; - fields_selected++; + field_found = 1; } 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 fields_selected; + break; } fieldstr++; } else if (ISDIGIT (*fieldstr)) { + /* FIXME: detect overflow? */ value = 10 * value + *fieldstr - '0'; fieldstr++; } else FATAL_ERROR ("invalid byte or field list"); } + + max_range_endpoint = 0; + for (i = 0; i < n_rp; i++) + { + if (rp[i].hi > max_range_endpoint) + max_range_endpoint = rp[i].hi; + } + + /* Allocate an array large enough so that it may be indexed by + the field numbers corresponding to all finite ranges + (i.e. `2-6' or `-4', but not `5-') in FIELDSTR. */ + + printable_field = (int *) xmalloc ((max_range_endpoint + 1) * sizeof (int)); + for (i = 1; i <= max_range_endpoint; i++) + printable_field[i] = 0; + + /* Set the array entries corresponding to integers in the ranges of RP. */ + for (i = 0; i < n_rp; i++) + { + int j; + for (j = rp[i].lo; j <= rp[i].hi; j++) + { + printable_field[j] = 1; + } + } + + free (rp); + + return field_found; +} + +/* Print the file open for reading on stream STREAM + with the bytes marked `FIELD_OMIT' in `fields' removed from each line. */ + +static void +cut_bytes (stream) + FILE *stream; +{ + int n_bytes; /* Number of chars in the line so far. */ + int printed_from_curr_line; + + printed_from_curr_line = 0; + n_bytes = 0; + while (1) + { + register int c; /* Each character from the file. */ + + c = getc (stream); + + if (c == '\n' || c == EOF) + { + if (printed_from_curr_line) + putchar ('\n'); + if (c == EOF) + break; + printed_from_curr_line = 0; + n_bytes = 0; + } + else + { + ++n_bytes; + if (print_kth (n_bytes)) + { + printed_from_curr_line = 1; + putchar (c); + } + } + /* WORKING */ + } +} + +/* Read from stream STREAM, printing to standard output any selected fields. + FIXME: comment. */ + +static void +cut_fields (FILE *stream) +{ + int c; + int field_idx; + int found_any_selected_field; + int first_field_special; + + found_any_selected_field = 0; + field_idx = 1; + + /* To support the semantics of the -s flag, we may have to buffer + all of the first field to determine whether it is `delimited.' + But that is unnecessary if all non-delimited lines must be printed + and the first field has been selected, or if non-delimited lines + must be suppressed and the first field has *not* been selected. + That is because a non-delimited line has exactly one field. */ + first_field_special = (suppress_non_delimited ^ !print_kth (1)); + + while (1) + { + if (field_idx == 1 && first_field_special) + { + int len; + + len = getstr (&field_1_buffer, &field_1_bufsize, stream, delim); + if (len < 0) + break; + + assert (len != 0); + + /* If the first field extends to the end of line (it is not + delimited) and we are printing all non-delimited lines, + print this one. */ + if (field_1_buffer[len - 1] != delim) + { + if (suppress_non_delimited) + { + /* Empty. */ + } + else + { + fwrite (field_1_buffer, sizeof (char), len, stdout); + /* Make sure the output line is newline terminated. */ + if (field_1_buffer[len - 1] != '\n') + putchar ('\n'); + } + continue; + } + if (print_kth (1)) + { + /* Print the field, but not the trailing delimiter. */ + fwrite (field_1_buffer, sizeof (char), len - 1, stdout); + found_any_selected_field = 1; + } + ++field_idx; + } + + if (print_kth (field_idx)) + { + if (found_any_selected_field) + putchar (delim); + found_any_selected_field = 1; + + while ((c = getc (stream)) != delim && c != '\n' && c != EOF) + { + putchar (c); + } + } + else + { + while ((c = getc (stream)) != delim && c != '\n' && c != EOF) + { + /* Empty. */ + } + } + + if (c == '\n') + { + c = getc (stream); + if (c != EOF) + { + ungetc (c, stream); + c = '\n'; + } + } + + if (c == delim) + ++field_idx; + else if (c == '\n' || c == EOF) + { + if (found_any_selected_field) + putchar ('\n'); + if (c == EOF) + break; + field_idx = 1; + found_any_selected_field = 0; + } + } +} + +static void +cut_stream (stream) + FILE *stream; +{ + if (operating_mode == byte_mode) + cut_bytes (stream); + else + cut_fields (stream); } /* Process file FILE to standard output. @@ -455,207 +669,103 @@ cut_file (file) return 0; } -static void -cut_stream (stream) - FILE *stream; -{ - if (operating_mode == byte_mode) - cut_bytes (stream); - else - cut_fields (stream); -} - -/* Print the file open for reading on stream STREAM - with the bytes marked `FIELD_OMIT' in `fields' removed from each line. */ - -static void -cut_bytes (stream) - FILE *stream; +void +main (argc, argv) + int argc; + char **argv; { - 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. */ - - while (doneflag == 0) - { - /* Start processing a line. */ - outbufptr = outbuf; - char_count = 0; - - do - { - c = getc (stream); - 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'); + int optc, exit_status = 0; - if (char_count) - fwrite (outbuf, sizeof (char), outbufptr - outbuf, stdout); - } -} + program_name = argv[0]; -/* Print the file open for reading on stream STREAM - with the fields marked `FIELD_OMIT' in `fields' removed from each line. - All characters are initially stowed in the raw input buffer, until - at least one field has been found. */ + operating_mode = undefined_mode; -static void -cut_fields (stream) - FILE *stream; -{ - register int c; /* Each character from the file. */ - int last_c; /* The previous character. */ - 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'. */ + /* By default, all non-delimited lines are printed. */ + suppress_non_delimited = 0; - c = EOF; + delim = '\0'; + have_read_stdin = 0; - while (doneflag == 0) + while ((optc = getopt_long (argc, argv, "b:c:d:f:ns", longopts, (int *) 0)) + != EOF) { - char_count = 0; - fieldfound = 0; - curr_field = 1; - outbufptr = outbuf; - inbufptr = inbuf; - - do + switch (optc) { - last_c = c; - c = getc (stream); - if (c == EOF) - { - doneflag++; - if (last_c == '\n' || last_c == EOF) - break; + case 0: + break; - /* The last character from the input stream is not a - newline. Pretend that the input was NL terminated. - But do that only if the file is not completely empty. */ - c = '\n'; - } + case 'b': + case 'c': + /* Build the byte list. */ + if (operating_mode != undefined_mode) + FATAL_ERROR ("only one type of list may be specified"); + operating_mode = byte_mode; + if (set_fields (optarg) == 0) + FATAL_ERROR ("missing list of positions"); + 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; - } + case 'f': + /* Build the field list. */ + if (operating_mode != undefined_mode) + FATAL_ERROR ("only one type of list may be specified"); + operating_mode = field_mode; + if (set_fields (optarg) == 0) + FATAL_ERROR ("missing list of fields"); + break; - if (c == delim) - { - ++curr_field; - if (curr_field == line_size - 1) - enlarge_line (curr_field); - } - } - while (c != '\n' && !doneflag); + case 'd': + /* New delimiter. */ + if (optarg[0] == '\0') + FATAL_ERROR ("missing delimiter argument"); + if (optarg[1] != '\0') + FATAL_ERROR ("the delimiter must be a single character"); + delim = optarg[0]; + break; - if (fieldfound) - { - /* Something was found. Print it. */ + case 'n': + break; - if ((unsigned char) outbufptr[-1] == delim && eol_range_start == 0) - { - /* Suppress the trailing delimiter unless there is a range - extending to end of line. */ - --outbufptr; - } + case 's': + suppress_non_delimited = 1; + break; - fwrite (outbuf, sizeof (char), outbufptr - outbuf, stdout); - if (c == '\n') - putc (c, stdout); + default: + usage (2); } - else if (!delimited_lines_only && char_count) - /* A line with some characters, no delimiters, and no - suppression. Print it. */ - fwrite (inbuf, sizeof (char), inbufptr - inbuf, stdout); } -} - -/* Extend the buffers to accomodate at least NEW_SIZE characters. */ -static void -enlarge_line (new_size) - int new_size; -{ - char *newp; - int i; - - new_size += 256; /* Leave some room to grow. */ + if (show_version) + { + printf ("%s\n", version_string); + exit (0); + } - fields = (enum field_action *) - xrealloc (fields, new_size * sizeof (enum field_action)); + if (show_help) + usage (0); - newp = (char *) xrealloc (outbuf, new_size); - outbufptr += newp - outbuf; - outbuf = newp; + if (operating_mode == undefined_mode) + FATAL_ERROR ("you must specify a list of bytes, characters, or fields"); - newp = (char *) xrealloc (inbuf, new_size); - inbufptr += newp - inbuf; - inbuf = newp; + /* FIXME: what is this? */ + if ((suppress_non_delimited || delim != '\0') && operating_mode != field_mode) + FATAL_ERROR ("a delimiter may be specified only when operating on fields"); - for (i = line_size; i < new_size; i++) - fields[i] = FIELD_OMIT; - line_size = new_size; -} + if (delim == '\0') + delim = '\t'; -static void -usage (status) - int status; -{ - if (status != 0) - fprintf (stderr, "Try `%s --help' for more information.\n", - program_name); + if (optind == argc) + exit_status |= cut_file ("-"); else + for (; optind < argc; optind++) + exit_status |= cut_file (argv[optind]); + + if (have_read_stdin && fclose (stdin) == EOF) { - printf ("\ -Usage: %s [OPTION]... [FILE]...\n\ -", - program_name); - printf ("\ -\n\ - -b, --bytes=LIST output only these bytes\n\ - -c, --characters=LIST output only these characters\n\ - -d, --delimiter=DELIM use DELIM instead of TAB for field delimiter\n\ - -f, --fields=LIST output only these fields\n\ - -n (ignored)\n\ - -s, --only-delimited do not print lines not containing delimiters\n\ - --help display this help and exit\n\ - --version output version information and exit\n\ -\n\ -Use one, and only one of -b, -c or -f. Each LIST is made up of one\n\ -range, or many ranges separated by commas. Each range is one of:\n\ -\n\ - N N'th byte, character or field, counted from 1\n\ - N- from N'th byte, character or field, to end of line\n\ - N-M from N'th to M'th (included) byte, character or field\n\ - -M from first to M'th (included) byte, character or field\n\ -\n\ -With no FILE, or when FILE is -, read standard input.\n\ -"); + error (0, errno, "-"); + exit_status = 1; } - exit (status); + if (ferror (stdout) || fclose (stdout) == EOF) + error (1, errno, "write error"); + + exit (exit_status); } |