niceprintf.c

Go to the documentation of this file.
00001 /****************************************************************
00002 Copyright 1990, 1991, 1993, 1994, 2000 by AT&T, Lucent Technologies and Bellcore.
00003 
00004 Permission to use, copy, modify, and distribute this software
00005 and its documentation for any purpose and without fee is hereby
00006 granted, provided that the above copyright notice appear in all
00007 copies and that both that the copyright notice and this
00008 permission notice and warranty disclaimer appear in supporting
00009 documentation, and that the names of AT&T, Bell Laboratories,
00010 Lucent or Bellcore or any of their entities not be used in
00011 advertising or publicity pertaining to distribution of the
00012 software without specific, written prior permission.
00013 
00014 AT&T, Lucent and Bellcore disclaim all warranties with regard to
00015 this software, including all implied warranties of
00016 merchantability and fitness.  In no event shall AT&T, Lucent or
00017 Bellcore be liable for any special, indirect or consequential
00018 damages or any damages whatsoever resulting from loss of use,
00019 data or profits, whether in an action of contract, negligence or
00020 other tortious action, arising out of or in connection with the
00021 use or performance of this software.
00022 ****************************************************************/
00023 
00024 #include "defs.h"
00025 #include "names.h"
00026 #include "output.h"
00027 #ifndef KR_headers
00028 #include "stdarg.h"
00029 #endif
00030 
00031 #define TOO_LONG_INDENT (2 * tab_size)
00032 #define MAX_INDENT 44
00033 #define MIN_INDENT 22
00034 static int last_was_newline = 0;
00035 int sharp_line = 0;
00036 int indent = 0;
00037 int in_comment = 0;
00038 int in_define = 0;
00039  extern int gflag1;
00040  extern char filename[];
00041 
00042  static void ind_printf Argdcl((int, FILE*, const char*, va_list));
00043 
00044  static void
00045 #ifdef KR_headers
00046 write_indent(fp, use_indent, extra_indent, start, end)
00047         FILE *fp;
00048         int use_indent;
00049         int extra_indent;
00050         char *start;
00051         char *end;
00052 #else
00053 write_indent(FILE *fp, int use_indent, int extra_indent, char *start, char *end)
00054 #endif
00055 {
00056     int ind, tab;
00057 
00058     if (sharp_line) {
00059         fprintf(fp, "#line %ld \"%s\"\n", lineno, filename);
00060         sharp_line = 0;
00061         }
00062     if (in_define == 1) {
00063         in_define = 2;
00064         use_indent = 0;
00065         }
00066     if (last_was_newline && use_indent) {
00067         if (*start == '\n') do {
00068                 putc('\n', fp);
00069                 if (++start > end)
00070                         return;
00071                 }
00072                 while(*start == '\n');
00073 
00074         ind = indent <= MAX_INDENT
00075                 ? indent
00076                 : MIN_INDENT + indent % (MAX_INDENT - MIN_INDENT);
00077 
00078         tab = ind + extra_indent;
00079 
00080         while (tab > 7) {
00081             putc ('\t', fp);
00082             tab -= 8;
00083         } /* while */
00084 
00085         while (tab-- > 0)
00086             putc (' ', fp);
00087     } /* if last_was_newline */
00088 
00089     while (start <= end)
00090         putc (*start++, fp);
00091 } /* write_indent */
00092 
00093 #ifdef KR_headers
00094 /*VARARGS2*/
00095   void
00096  margin_printf (fp, a, b, c, d, e, f, g)
00097   FILE *fp;
00098   char *a;
00099   long b, c, d, e, f, g;
00100 {
00101     ind_printf (0, fp, a, b, c, d, e, f, g);
00102 } /* margin_printf */
00103 
00104 /*VARARGS2*/
00105   void
00106  nice_printf (fp, a, b, c, d, e, f, g)
00107   FILE *fp;
00108   char *a;
00109   long b, c, d, e, f, g;
00110 {
00111     ind_printf (1, fp, a, b, c, d, e, f, g);
00112 } /* nice_printf */
00113 #define SPRINTF(x,a,b,c,d,e,f,g) sprintf(x,a,b,c,d,e,f,g)
00114 
00115 #else /* if (!defined(KR_HEADERS)) */
00116 
00117 #define SPRINTF(x,a,b,c,d,e,f,g) vsprintf(x,a,ap)
00118 
00119   void
00120  margin_printf(FILE *fp, const char *fmt, ...)
00121 {
00122         va_list ap;
00123         va_start(ap,fmt);
00124         ind_printf(0, fp, fmt, ap);
00125         va_end(ap);
00126         }
00127 
00128   void
00129  nice_printf(FILE *fp, const char *fmt, ...)
00130 {
00131         va_list ap;
00132         va_start(ap,fmt);
00133         ind_printf(1, fp, fmt, ap);
00134         va_end(ap);
00135         }
00136 #endif
00137 
00138 #define  max_line_len c_output_line_length
00139                 /* 74Number of characters allowed on an output
00140                                    line.  This assumes newlines are handled
00141                                    nicely, i.e. a newline after a full text
00142                                    line on a terminal is ignored */
00143 
00144 /* output_buf   holds the text of the next line to be printed.  It gets
00145    flushed when a newline is printed.   next_slot   points to the next
00146    available location in the output buffer, i.e. where the next call to
00147    nice_printf will have its output stored */
00148 
00149 static char *output_buf;
00150 static char *next_slot;
00151 static char *string_start;
00152 
00153 static char *word_start = NULL;
00154 static int cursor_pos = 0;
00155 static int In_string = 0;
00156 
00157  void
00158 np_init(Void)
00159 {
00160         next_slot = output_buf = Alloc(MAX_OUTPUT_SIZE);
00161         memset(output_buf, 0, MAX_OUTPUT_SIZE);
00162         }
00163 
00164  static char *
00165 #ifdef KR_headers
00166 adjust_pointer_in_string(pointer)
00167         register char *pointer;
00168 #else
00169 adjust_pointer_in_string(register char *pointer)
00170 #endif
00171 {
00172         register char *s, *s1, *se, *s0;
00173 
00174         /* arrange not to break \002 */
00175         s1 = string_start ? string_start : output_buf;
00176         for(s = s1; s < pointer; s++) {
00177                 s0 = s1;
00178                 s1 = s;
00179                 if (*s == '\\') {
00180                         se = s++ + 4;
00181                         if (se > pointer)
00182                                 break;
00183                         if (*s < '0' || *s > '7')
00184                                 continue;
00185                         while(++s < se)
00186                                 if (*s < '0' || *s > '7')
00187                                         break;
00188                         --s;
00189                         }
00190                 }
00191         return s0 - 1;
00192         }
00193 
00194 /* ANSI says strcpy's behavior is undefined for overlapping args,
00195  * so we roll our own fwd_strcpy: */
00196 
00197  static void
00198 #ifdef KR_headers
00199 fwd_strcpy(t, s)
00200         register char *t;
00201         register char *s;
00202 #else
00203 fwd_strcpy(register char *t, register char *s)
00204 #endif
00205 { while(*t++ = *s++); }
00206 
00207 /* isident -- true iff character could belong to a unit.  C allows
00208    letters, numbers and underscores in identifiers.  This also doubles as
00209    a check for numeric constants, since we include the decimal point and
00210    minus sign.  The minus has to be here, since the constant "10e-2"
00211    cannot be broken up.  The '.' also prevents structure references from
00212    being broken, which is a quite acceptable side effect */
00213 
00214 #define isident(x) (Tr[x] & 1)
00215 #define isntident(x) (!Tr[x])
00216 
00217   static void
00218 #ifdef KR_headers
00219  ind_printf (use_indent, fp, a, b, c, d, e, f, g)
00220   int use_indent;
00221   FILE *fp;
00222   char *a;
00223   long b, c, d, e, f, g;
00224 #else
00225  ind_printf (int use_indent, FILE *fp, const char *a, va_list ap)
00226 #endif
00227 {
00228     extern int max_line_len;
00229     extern FILEP c_file;
00230     extern char tr_tab[];       /* in output.c */
00231     register char *Tr = tr_tab;
00232     int ch, cmax, inc, ind;
00233     static int extra_indent, last_indent, set_cursor = 1;
00234 
00235     cursor_pos += indent - last_indent;
00236     last_indent = indent;
00237     SPRINTF (next_slot, a, b, c, d, e, f, g);
00238 
00239     if (fp != c_file) {
00240         fprintf (fp,"%s", next_slot);
00241         return;
00242     } /* if fp != c_file */
00243 
00244     do {
00245         char *pointer;
00246 
00247 /* The   for   loop will parse one output line */
00248 
00249         if (set_cursor) {
00250                 ind = indent <= MAX_INDENT
00251                         ? indent
00252                         : MIN_INDENT + indent % (MAX_INDENT - MIN_INDENT);
00253                 cursor_pos = extra_indent;
00254                 if (use_indent)
00255                         cursor_pos += ind;
00256                 set_cursor = 0;
00257                 }
00258         if (in_comment) {
00259                 cmax = max_line_len + 32;       /* let comments be wider */
00260                 for (pointer = next_slot; *pointer && *pointer != '\n' &&
00261                                 cursor_pos <= cmax; pointer++)
00262                         cursor_pos++;
00263                 }
00264         else
00265           for (pointer = next_slot; *pointer && *pointer != '\n' &&
00266                 cursor_pos <= max_line_len; pointer++) {
00267 
00268             /* Update state variables here */
00269 
00270             if (In_string) {
00271                 switch(*pointer) {
00272                         case '\\':
00273                                 if (++cursor_pos > max_line_len) {
00274                                         cursor_pos -= 2;
00275                                         --pointer;
00276                                         goto overflow;
00277                                         }
00278                                 ++pointer;
00279                                 break;
00280                         case '"':
00281                                 In_string = 0;
00282                                 word_start = 0;
00283                         }
00284                 }
00285             else switch (*pointer) {
00286                 case '"':
00287                         if (cursor_pos + 5 > max_line_len) {
00288                                 word_start = 0;
00289                                 --pointer;
00290                                 goto overflow;
00291                                 }
00292                         In_string = 1;
00293                         string_start = word_start = pointer;
00294                         break;
00295                 case '\'':
00296                         if (pointer[1] == '\\')
00297                                 if ((ch = pointer[2]) >= '0' && ch <= '7')
00298                                         for(inc = 3; pointer[inc] != '\''
00299                                                 && ++inc < 5;);
00300                                 else
00301                                         inc = 3;
00302                         else
00303                                 inc = 2;
00304                         /*debug*/ if (pointer[inc] != '\'')
00305                         /*debug*/  fatalstr("Bad character constant %.10s",
00306                                         pointer);
00307                         if ((cursor_pos += inc) > max_line_len) {
00308                                 cursor_pos -= inc;
00309                                 word_start = 0;
00310                                 --pointer;
00311                                 goto overflow;
00312                                 }
00313                         word_start = pointer;
00314                         pointer += inc;
00315                         break;
00316                 case '\t':
00317                     cursor_pos = 8 * ((cursor_pos + 8) / 8) - 1;
00318                     break;
00319                 default: {
00320 
00321 /* HACK  Assumes that all characters in an atomic C token will be written
00322    at the same time.  Must check for tokens first, since '-' is considered
00323    part of an identifier; checking isident first would mean breaking up "->" */
00324 
00325                     if (word_start) {
00326                         if (isntident(*(unsigned char *)pointer))
00327                                 word_start = NULL;
00328                         }
00329                     else if (isident(*(unsigned char *)pointer))
00330                         word_start = pointer;
00331                     break;
00332                 } /* default */
00333             } /* switch */
00334             cursor_pos++;
00335         } /* for pointer = next_slot */
00336  overflow:
00337         if (*pointer == '\0') {
00338 
00339 /* The output line is not complete, so break out and don't output
00340    anything.  The current line fragment will be stored in the buffer */
00341 
00342             next_slot = pointer;
00343             break;
00344         } else {
00345             char last_char;
00346             int in_string0 = In_string;
00347 
00348 /* If the line was too long, move   pointer   back to the character before
00349    the current word.  This allows line breaking on word boundaries.  Make
00350    sure that 80 character comment lines get broken up somehow.  We assume
00351    that any non-string 80 character identifier must be in a comment.
00352 */
00353 
00354             if (*pointer == '\n')
00355                 in_define = 0;
00356             else if (word_start && word_start > output_buf)
00357                 if (In_string)
00358                         if (string_start && pointer - string_start < 5)
00359                                 pointer = string_start - 1;
00360                         else {
00361                                 pointer = adjust_pointer_in_string(pointer);
00362                                 string_start = 0;
00363                                 }
00364                 else if (word_start == string_start
00365                                 && pointer - string_start >= 5) {
00366                         pointer = adjust_pointer_in_string(next_slot);
00367                         In_string = 1;
00368                         string_start = 0;
00369                         }
00370                 else
00371                         pointer = word_start - 1;
00372             else if (cursor_pos > max_line_len) {
00373 #ifndef ANSI_Libraries
00374                 extern char *strchr();
00375 #endif
00376                 if (In_string) {
00377                         pointer = adjust_pointer_in_string(pointer);
00378                         if (string_start && pointer > string_start)
00379                                 string_start = 0;
00380                         }
00381                 else if (strchr("&*+-/<=>|", *pointer)
00382                         && strchr("!%&*+-/<=>^|", pointer[-1])) {
00383                         pointer -= 2;
00384                         if (strchr("<>", *pointer)) /* <<=, >>= */
00385                                 pointer--;
00386                         }
00387                 else {
00388                         if (word_start)
00389                                 while(isident(*(unsigned char *)pointer))
00390                                         pointer++;
00391                         pointer--;
00392                         }
00393                 }
00394             last_char = *pointer;
00395             write_indent(fp, use_indent, extra_indent, output_buf, pointer);
00396             next_slot = output_buf;
00397             if (In_string && !string_start && Ansi == 1 && last_char != '\n')
00398                 *next_slot++ = '"';
00399             fwd_strcpy(next_slot, pointer + 1);
00400 
00401 /* insert a line break */
00402 
00403             if (last_char == '\n') {
00404                 if (In_string)
00405                         last_was_newline = 0;
00406                 else {
00407                         last_was_newline = 1;
00408                         extra_indent = 0;
00409                         sharp_line = gflag1;
00410                         }
00411                 }
00412             else {
00413                 extra_indent = TOO_LONG_INDENT;
00414                 if (In_string && !string_start) {
00415                         if (Ansi == 1) {
00416                                 fprintf(fp, gflag1 ? "\"\\\n" : "\"\n");
00417                                 use_indent = 1;
00418                                 last_was_newline = 1;
00419                                 }
00420                         else {
00421                                 fprintf(fp, "\\\n");
00422                                 last_was_newline = 0;
00423                                 }
00424                         In_string = in_string0;
00425                         }
00426                 else {
00427                         if (in_define/* | gflag1*/)
00428                                 putc('\\', fp);
00429                         putc ('\n', fp);
00430                         last_was_newline = 1;
00431                         }
00432             } /* if *pointer != '\n' */
00433 
00434             if (In_string && Ansi != 1 && !string_start)
00435                 cursor_pos = 0;
00436             else
00437                 set_cursor = 1;
00438 
00439             string_start = word_start = NULL;
00440 
00441         } /* else */
00442 
00443     } while (*next_slot);
00444 
00445 } /* ind_printf */

Generated on Sun Mar 4 15:03:44 2007 for Scilab [trunk] by  doxygen 1.5.1