367 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			367 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************
 | 
						|
Copyright 1990, 1991 by AT&T Bell Laboratories and Bellcore.
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software
 | 
						|
and its documentation for any purpose and without fee is hereby
 | 
						|
granted, provided that the above copyright notice appear in all
 | 
						|
copies and that both that the copyright notice and this
 | 
						|
permission notice and warranty disclaimer appear in supporting
 | 
						|
documentation, and that the names of AT&T Bell Laboratories or
 | 
						|
Bellcore or any of their entities not be used in advertising or
 | 
						|
publicity pertaining to distribution of the software without
 | 
						|
specific, written prior permission.
 | 
						|
 | 
						|
AT&T and Bellcore disclaim all warranties with regard to this
 | 
						|
software, including all implied warranties of merchantability
 | 
						|
and fitness.  In no event shall AT&T or Bellcore be liable for
 | 
						|
any special, indirect or consequential damages or any damages
 | 
						|
whatsoever resulting from loss of use, data or profits, whether
 | 
						|
in an action of contract, negligence or other tortious action,
 | 
						|
arising out of or in connection with the use or performance of
 | 
						|
this software.
 | 
						|
****************************************************************/
 | 
						|
 | 
						|
#include "defs.h"
 | 
						|
#include "names.h"
 | 
						|
#include "output.h"
 | 
						|
 | 
						|
#define TOO_LONG_INDENT (2 * tab_size)
 | 
						|
#define MAX_INDENT 44
 | 
						|
#define MIN_INDENT 22
 | 
						|
static int last_was_newline = 0;
 | 
						|
int indent = 0;
 | 
						|
int in_comment = 0;
 | 
						|
 | 
						|
 static int
 | 
						|
write_indent(fp, use_indent, extra_indent, start, end)
 | 
						|
 FILE *fp;
 | 
						|
 int use_indent, extra_indent;
 | 
						|
 char *start, *end;
 | 
						|
{
 | 
						|
    int ind, tab;
 | 
						|
 | 
						|
    if (last_was_newline && use_indent) {
 | 
						|
	if (*start == '\n') do {
 | 
						|
		putc('\n', fp);
 | 
						|
		if (++start > end)
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		while(*start == '\n');
 | 
						|
 | 
						|
	ind = indent <= MAX_INDENT
 | 
						|
		? indent
 | 
						|
		: MIN_INDENT + indent % (MAX_INDENT - MIN_INDENT);
 | 
						|
 | 
						|
	tab = ind + extra_indent;
 | 
						|
 | 
						|
	while (tab > 7) {
 | 
						|
	    putc ('\t', fp);
 | 
						|
	    tab -= 8;
 | 
						|
	} /* while */
 | 
						|
 | 
						|
	while (tab-- > 0)
 | 
						|
	    putc (' ', fp);
 | 
						|
    } /* if last_was_newline */
 | 
						|
 | 
						|
    while (start <= end)
 | 
						|
	putc (*start++, fp);
 | 
						|
} /* write_indent */
 | 
						|
 | 
						|
 | 
						|
/*VARARGS2*/
 | 
						|
int margin_printf (fp, a, b, c, d, e, f, g)
 | 
						|
FILE *fp;
 | 
						|
char *a;
 | 
						|
long b, c, d, e, f, g;
 | 
						|
{
 | 
						|
    ind_printf (0, fp, a, b, c, d, e, f, g);
 | 
						|
} /* margin_printf */
 | 
						|
 | 
						|
/*VARARGS2*/
 | 
						|
int nice_printf (fp, a, b, c, d, e, f, g)
 | 
						|
FILE *fp;
 | 
						|
char *a;
 | 
						|
long b, c, d, e, f, g;
 | 
						|
{
 | 
						|
    ind_printf (1, fp, a, b, c, d, e, f, g);
 | 
						|
} /* nice_printf */
 | 
						|
 | 
						|
 | 
						|
#define  max_line_len c_output_line_length
 | 
						|
 		/* 74Number of characters allowed on an output
 | 
						|
			           line.  This assumes newlines are handled
 | 
						|
			           nicely, i.e. a newline after a full text
 | 
						|
			           line on a terminal is ignored */
 | 
						|
 | 
						|
/* output_buf   holds the text of the next line to be printed.  It gets
 | 
						|
   flushed when a newline is printed.   next_slot   points to the next
 | 
						|
   available location in the output buffer, i.e. where the next call to
 | 
						|
   nice_printf will have its output stored */
 | 
						|
 | 
						|
static char *output_buf;
 | 
						|
static char *next_slot;
 | 
						|
static char *string_start;
 | 
						|
 | 
						|
static char *word_start = NULL;
 | 
						|
static int cursor_pos = 0;
 | 
						|
static int In_string = 0;
 | 
						|
 | 
						|
 void
 | 
						|
np_init()
 | 
						|
{
 | 
						|
	next_slot = output_buf = Alloc(MAX_OUTPUT_SIZE);
 | 
						|
	memset(output_buf, 0, MAX_OUTPUT_SIZE);
 | 
						|
	}
 | 
						|
 | 
						|
 static char *
 | 
						|
adjust_pointer_in_string(pointer)
 | 
						|
 register char *pointer;
 | 
						|
{
 | 
						|
	register char *s, *s1, *se, *s0;
 | 
						|
 | 
						|
	/* arrange not to break \002 */
 | 
						|
	s1 = string_start ? string_start : output_buf;
 | 
						|
	for(s = s1; s < pointer; s++) {
 | 
						|
		s0 = s1;
 | 
						|
		s1 = s;
 | 
						|
		if (*s == '\\') {
 | 
						|
			se = s++ + 4;
 | 
						|
			if (se > pointer)
 | 
						|
				break;
 | 
						|
			if (*s < '0' || *s > '7')
 | 
						|
				continue;
 | 
						|
			while(++s < se)
 | 
						|
				if (*s < '0' || *s > '7')
 | 
						|
					break;
 | 
						|
			--s;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	return s0 - 1;
 | 
						|
	}
 | 
						|
 | 
						|
/* ANSI says strcpy's behavior is undefined for overlapping args,
 | 
						|
 * so we roll our own fwd_strcpy: */
 | 
						|
 | 
						|
 static void
 | 
						|
fwd_strcpy(t, s)
 | 
						|
 register char *t, *s;
 | 
						|
{ while(*t++ = *s++); }
 | 
						|
 | 
						|
/* isident -- true iff character could belong to a unit.  C allows
 | 
						|
   letters, numbers and underscores in identifiers.  This also doubles as
 | 
						|
   a check for numeric constants, since we include the decimal point and
 | 
						|
   minus sign.  The minus has to be here, since the constant "10e-2"
 | 
						|
   cannot be broken up.  The '.' also prevents structure references from
 | 
						|
   being broken, which is a quite acceptable side effect */
 | 
						|
 | 
						|
#define isident(x) (Tr[x] & 1)
 | 
						|
#define isntident(x) (!Tr[x])
 | 
						|
 | 
						|
int ind_printf (use_indent, fp, a, b, c, d, e, f, g)
 | 
						|
int use_indent;
 | 
						|
FILE *fp;
 | 
						|
char *a;
 | 
						|
long b, c, d, e, f, g;
 | 
						|
{
 | 
						|
    extern int max_line_len;
 | 
						|
    extern FILEP c_file;
 | 
						|
    extern char tr_tab[];	/* in output.c */
 | 
						|
    register char *Tr = tr_tab;
 | 
						|
    int ch, inc, ind;
 | 
						|
    static int extra_indent, last_indent, set_cursor = 1;
 | 
						|
 | 
						|
    cursor_pos += indent - last_indent;
 | 
						|
    last_indent = indent;
 | 
						|
    sprintf (next_slot, a, b, c, d, e, f, g);
 | 
						|
 | 
						|
    if (fp != c_file) {
 | 
						|
	fprintf (fp,"%s", next_slot);
 | 
						|
	return 1;
 | 
						|
    } /* if fp != c_file */
 | 
						|
 | 
						|
    do {
 | 
						|
	char *pointer;
 | 
						|
 | 
						|
/* The   for   loop will parse one output line */
 | 
						|
 | 
						|
	if (set_cursor) {
 | 
						|
		ind = indent <= MAX_INDENT
 | 
						|
			? indent
 | 
						|
			: MIN_INDENT + indent % (MAX_INDENT - MIN_INDENT);
 | 
						|
		cursor_pos = ind + extra_indent;
 | 
						|
		set_cursor = 0;
 | 
						|
		}
 | 
						|
	if (in_comment)
 | 
						|
        	for (pointer = next_slot; *pointer && *pointer != '\n' &&
 | 
						|
				cursor_pos <= max_line_len; pointer++)
 | 
						|
			cursor_pos++;
 | 
						|
	else
 | 
						|
          for (pointer = next_slot; *pointer && *pointer != '\n' &&
 | 
						|
		cursor_pos <= max_line_len; pointer++) {
 | 
						|
 | 
						|
	    /* Update state variables here */
 | 
						|
 | 
						|
	    if (In_string) {
 | 
						|
		switch(*pointer) {
 | 
						|
			case '\\':
 | 
						|
				if (++cursor_pos > max_line_len) {
 | 
						|
					cursor_pos -= 2;
 | 
						|
					--pointer;
 | 
						|
					goto overflow;
 | 
						|
					}
 | 
						|
				++pointer;
 | 
						|
				break;
 | 
						|
			case '"':
 | 
						|
				In_string = 0;
 | 
						|
				word_start = 0;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	    else switch (*pointer) {
 | 
						|
	        case '"':
 | 
						|
			if (cursor_pos + 5 > max_line_len) {
 | 
						|
				word_start = 0;
 | 
						|
				--pointer;
 | 
						|
				goto overflow;
 | 
						|
				}
 | 
						|
			In_string = 1;
 | 
						|
			string_start = word_start = pointer;
 | 
						|
		    	break;
 | 
						|
	        case '\'':
 | 
						|
			if (pointer[1] == '\\')
 | 
						|
				if ((ch = pointer[2]) >= '0' && ch <= '7')
 | 
						|
					for(inc = 3; pointer[inc] != '\''
 | 
						|
						&& ++inc < 5;);
 | 
						|
				else
 | 
						|
					inc = 3;
 | 
						|
			else
 | 
						|
				inc = 2;
 | 
						|
			/*debug*/ if (pointer[inc] != '\'')
 | 
						|
			/*debug*/  fatalstr("Bad character constant %.10s",
 | 
						|
					pointer);
 | 
						|
			if ((cursor_pos += inc) > max_line_len) {
 | 
						|
				cursor_pos -= inc;
 | 
						|
				word_start = 0;
 | 
						|
				--pointer;
 | 
						|
				goto overflow;
 | 
						|
				}
 | 
						|
			word_start = pointer;
 | 
						|
			pointer += inc;
 | 
						|
			break;
 | 
						|
		case '\t':
 | 
						|
		    cursor_pos = 8 * ((cursor_pos + 8) / 8) - 1;
 | 
						|
		    break;
 | 
						|
		default: {
 | 
						|
 | 
						|
/* HACK  Assumes that all characters in an atomic C token will be written
 | 
						|
   at the same time.  Must check for tokens first, since '-' is considered
 | 
						|
   part of an identifier; checking isident first would mean breaking up "->" */
 | 
						|
 | 
						|
		    if (!word_start && isident(*(unsigned char *)pointer))
 | 
						|
			word_start = pointer;
 | 
						|
		    else if (word_start && isntident(*(unsigned char *)pointer))
 | 
						|
			word_start = NULL;
 | 
						|
		    break;
 | 
						|
		} /* default */
 | 
						|
	    } /* switch */
 | 
						|
	    cursor_pos++;
 | 
						|
	} /* for pointer = next_slot */
 | 
						|
 overflow:
 | 
						|
	if (*pointer == '\0') {
 | 
						|
 | 
						|
/* The output line is not complete, so break out and don't output
 | 
						|
   anything.  The current line fragment will be stored in the buffer */
 | 
						|
 | 
						|
	    next_slot = pointer;
 | 
						|
	    break;
 | 
						|
	} else {
 | 
						|
	    char last_char;
 | 
						|
	    int in_string0 = In_string;
 | 
						|
 | 
						|
/* If the line was too long, move   pointer   back to the character before
 | 
						|
   the current word.  This allows line breaking on word boundaries.  Make
 | 
						|
   sure that 80 character comment lines get broken up somehow.  We assume
 | 
						|
   that any non-string 80 character identifier must be in a comment.
 | 
						|
*/
 | 
						|
 | 
						|
	    if (word_start && *pointer != '\n' && word_start > output_buf)
 | 
						|
		if (In_string)
 | 
						|
			if (string_start && pointer - string_start < 5)
 | 
						|
				pointer = string_start - 1;
 | 
						|
			else {
 | 
						|
				pointer = adjust_pointer_in_string(pointer);
 | 
						|
				string_start = 0;
 | 
						|
				}
 | 
						|
		else if (word_start == string_start
 | 
						|
				&& pointer - string_start >= 5) {
 | 
						|
			pointer = adjust_pointer_in_string(next_slot);
 | 
						|
			In_string = 1;
 | 
						|
			string_start = 0;
 | 
						|
			}
 | 
						|
		else
 | 
						|
			pointer = word_start - 1;
 | 
						|
	    else if (cursor_pos > max_line_len) {
 | 
						|
		extern char *strchr();
 | 
						|
		if (In_string) {
 | 
						|
			pointer = adjust_pointer_in_string(pointer);
 | 
						|
			if (string_start && pointer > string_start)
 | 
						|
				string_start = 0;
 | 
						|
			}
 | 
						|
		else if (strchr("&*+-/<=>|", *pointer)
 | 
						|
			&& strchr("!%&*+-/<=>^|", pointer[-1])) {
 | 
						|
			pointer -= 2;
 | 
						|
			if (strchr("<>", *pointer)) /* <<=, >>= */
 | 
						|
				pointer--;
 | 
						|
			}
 | 
						|
		else
 | 
						|
			pointer--;
 | 
						|
		}
 | 
						|
	    last_char = *pointer;
 | 
						|
	    write_indent(fp, use_indent, extra_indent, output_buf, pointer);
 | 
						|
	    next_slot = output_buf;
 | 
						|
	    if (In_string && !string_start && Ansi == 1 && last_char != '\n')
 | 
						|
		*next_slot++ = '"';
 | 
						|
	    fwd_strcpy(next_slot, pointer + 1);
 | 
						|
 | 
						|
/* insert a line break */
 | 
						|
 | 
						|
	    if (last_char == '\n') {
 | 
						|
		if (In_string)
 | 
						|
			last_was_newline = 0;
 | 
						|
		else {
 | 
						|
			last_was_newline = 1;
 | 
						|
			extra_indent = 0;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	    else {
 | 
						|
		extra_indent = TOO_LONG_INDENT;
 | 
						|
		if (In_string && !string_start) {
 | 
						|
			if (Ansi == 1) {
 | 
						|
				fprintf(fp, "\"\n");
 | 
						|
				use_indent = 1;
 | 
						|
				last_was_newline = 1;
 | 
						|
				}
 | 
						|
			else {
 | 
						|
				fprintf(fp, "\\\n");
 | 
						|
				last_was_newline = 0;
 | 
						|
				}
 | 
						|
			In_string = in_string0;
 | 
						|
			}
 | 
						|
		else {
 | 
						|
			putc ('\n', fp);
 | 
						|
			last_was_newline = 1;
 | 
						|
			}
 | 
						|
	    } /* if *pointer != '\n' */
 | 
						|
 | 
						|
	    if (In_string && Ansi != 1 && !string_start)
 | 
						|
		cursor_pos = 0;
 | 
						|
	    else
 | 
						|
		set_cursor = 1;
 | 
						|
 | 
						|
	    string_start = word_start = NULL;
 | 
						|
 | 
						|
	} /* else */
 | 
						|
 | 
						|
    } while (*next_slot);
 | 
						|
 | 
						|
    return 0;
 | 
						|
} /* ind_printf */
 |