home *** CD-ROM | disk | FTP | other *** search
- static char * sccsid = "@(#) output.c (v6.5 5/19/89)";
- /*
- * Output routines for 'strings'.
- * We roll our own here, because stdio either expects NUL terminated
- * strings, which we don't have, or tests for buffer overflow at each
- * character. But we know how much characters will be added to the
- * output block, so we can make do with two or three tests per sequence
- * of printable characters.
- *
- * Sequences are stuffed into the output buffer, even temporarily when
- * we could not decide what to do with them, yet had to remember the
- * characters. When a temporary sequence is made permanent or a
- * permanent sequence added, and the new length of data in the output
- * buffer exceeds a threshold, it is output.
- * If the buffer overflows in between it is extended with a call to
- * realloc. This rarely ever happens, but if it happens, then
- * you will rather have strings to be slowing down than dump core.
- */
-
- # include "strings.h"
-
- /*
- * The characters in out_buf until num_out_buf are already accepted.
- * level points at the end of all characters in out_buf, even the
- * temporarily saved ones.
- * saved is the number of characters temporarily saved.
- * Note that level and saved are not the same. If there are number before
- * the sequences, then buf+num_out_buf+saved != level !!
- * Note that sometimes I have to compute the number of characters between
- * out_buf and level. I do this by subtracting the two pointers. I assume
- * that the result is int or convertible to int, but I don't have the
- * authority at hand to prove this.
- */
- CHAR_TYPE * out_buf;
- int num_out_buf = 0; /* numbers of chars in out_buf */
- CHAR_TYPE * level;
- int buf_len;
- int saved = 0;
-
- extern int ind_offset;
- extern int ind_prefix;
- extern CHAR_TYPE buf[];
- extern LSEEK_TYPE offset;
- extern char * cur_file_name;
-
- extern char * malloc ();
- extern char * realloc ();
-
- init_output ()
- {
- out_buf = (CHAR_TYPE *) malloc (sizeof (CHAR_TYPE) * OUT_BUF_LEN);
- level = out_buf;
- num_out_buf = 0;
- buf_len = OUT_BUF_LEN;
- }
-
- flush_output ()
- /*
- * Num_out_buf characters from the buffer are written.
- */
- {
- if (num_out_buf > 0) {
- # ifdef DEBUG
- fprintf (prot, "flush_output : write %d chars\n", num_out_buf);
- # endif
- if (write (1, out_buf, num_out_buf) != num_out_buf) {
- out ("PANIC : write error\n");
- exit (1);
- }
- num_out_buf = 0;
- }
- level = out_buf;
- }
-
- static
- make_room (n)
- register int n;
- /*
- * Must reallocate.
- * Buffer is enlarged by at least IN_BUF_LEN characters. The largest
- * piece which has to be put into the buffer will be at most IN_BUF_LEN
- * characters. If there is a sequence of puts, the buffer will be enlarged
- * each time. This should happen very rarely.
- */
- {
- register int i;
- # ifdef DEBUG
- fprintf (prot, "make_room :: REALLOC realloc called.\n");
- fflush (prot);
- # endif
- /*
- * Level is a pointer into out_buf. We have to save it here and
- * restore it later, because realloc might cause a copying of the
- * contents of out_buf to a new address.
- */
- i = level - out_buf;
- buf_len += n>IN_BUF_LEN?n:IN_BUF_LEN;
- # ifdef DEBUG
- fprintf (prot, "make_room :: output buffer will be enlarged to %d\n", buf_len);
- # endif
- out_buf = (CHAR_TYPE *) realloc (out_buf, (unsigned int)buf_len);
- if (out_buf == NULL) { /* panic */
- (void)write (2, "REALLOC ERROR.\n", 15);
- exit (1);
- }
- level = out_buf + i;
- }
-
- void
- add_cur_file_name ()
- /*
- * Only called if command line flag '-p' was specified.
- * Add the name of the current input file to the output stream.
- */
- {
- register int i;
-
- if (cur_file_name == NULL)
- return;
- i = strlen (cur_file_name);
- /*
- * Is there space for (i+1) characters at the end of the output buffer?
- * If not, flush it.
- */
- if ((int)(level - out_buf) + i + 1 > buf_len)
- make_room (i+1);
- FAST_COPY (cur_file_name, level, i);
- level += i;
- *level++ = ':';
- }
-
- append (b1, b2, ind_perm)
- register CHAR_TYPE * b1, * b2;
- int ind_perm;
- /*
- * Append a sequence permanently. Set the pointers.
- * If there are more than THRESHOLD characters then write them.
- */
- {
- register int n;
-
- /*
- * If the user wants it and this is the first part of a sequence,
- * add name of current file as prefix.
- */
- if (ind_prefix && saved == 0)
- add_cur_file_name ();
- /*
- * If there are no saved characters and the user wants offsets,
- * then we have to add an offset first.
- */
- if (ind_offset && saved == 0)
- output_offset (b1);
- /*
- * Is there enough space in out outbuf ?
- */
- n = b2 - b1;
- if ((int)(level - out_buf) + n + 1 > buf_len)
- make_room (n);
- /*
- * Copy the sequence. It may be empty, so don't forget to add a LF here.
- */
- if (n > 0) {
- FAST_COPY (b1, level, n);
- level += n;
- }
- if (ind_perm == 1) {
- *level++ = '\n';
- /*
- * There may be some temporarily saved characters in out_buf. Make
- * them permanent.
- */
- num_out_buf = level - out_buf;
- /*
- * If necessary, write.
- */
- if (num_out_buf > THRESHOLD)
- flush_output ();
- saved = 0;
- } else
- saved = n;
- }
-
- output_offset (b1)
- CHAR_TYPE * b1;
- /*
- * Convert n to its character representation in decimal and append this
- * at the end of the output buffer.
- * Normally we output 7 characters. If the number needs more we expand.
- */
- {
- register int i;
- register long j;
- register LSEEK_TYPE l;
- CHAR_TYPE * b;
-
- l = offset + (int)(b1 - buf);
- /*
- * How many characters must we output ?
- */
- for (i = 7, j = 10000000L; l >= j; j *= 10, i++);
-
- /*
- * Is there space for (i+1) characters at the end of the output buffer?
- * If not, flush it.
- */
- if ((int)(level - out_buf) + i+1 > buf_len)
- make_room (i+1);
-
- b = level;
- level += i+1;
-
- b[i--] = ' ';
- /*
- * Convert the number.
- */
- do {
- b[i--] = '0' + l % 10;
- l /= 10;
- } while (l != 0);
- /*
- * Add some blanks in front of number
- */
- for (; i >= 0; i--)
- b [i] = ' ';
- }
-
- # ifdef DEBUG
- out (s)
- {
- fputc (s, stderr);
- }
- # else DEBUG
- /*
- * The main program calls a routine called 'out'.
- */
- out (s)
- register char * s;
- {
- (void)write (2, s, strlen(s));
- }
- # endif DEBUG
-