@@ -92,11 +92,14 @@ int count_newlines( char * s ) {
9292 return count ;
9393}
9494
95+ /** true if last char through exp_output was a space */
96+ static bool printedSpaceLast = false;
97+
9598void exp_output ( char * buf , int len ) {
9699 FILE * fp = ( exppp_fp ? exppp_fp : stdout );
97100
98101 error_sym .line += count_newlines ( buf );
99-
102+ printedSpaceLast = ( * ( buf + len - 1 ) == ' ' );
100103 if ( exppp_buf ) {
101104 /* output to string */
102105 if ( len > exppp_buflen ) {
@@ -114,8 +117,8 @@ void exp_output( char * buf, int len ) {
114117}
115118
116119void wrap ( const char * fmt , ... ) {
117- char * p ;
118120 char buf [10000 ];
121+ char * p , * start = buf ;
119122 int len ;
120123 va_list args ;
121124
@@ -125,6 +128,12 @@ void wrap( const char * fmt, ... ) {
125128
126129 len = strlen ( buf );
127130
131+ /* eliminate leading whitespace */
132+ while ( ( * start == ' ' ) && ( ( printedSpaceLast ) || ( * ( start + 1 ) == ' ' ) ) ){
133+ start ++ ;
134+ len -- ;
135+ }
136+
128137 /* 1st condition checks if string cant fit into current line */
129138 /* 2nd condition checks if string cant fit into any line */
130139 /* I.e., if we still can't fit after indenting, don't bother to */
@@ -139,14 +148,14 @@ void wrap( const char * fmt, ... ) {
139148 curpos = indent2 ; /* reset current position */
140149 }
141150
142- exp_output ( buf , len );
151+ exp_output ( start , len );
143152
144153 if ( len ) {
145154 /* reset cur position based on last newline seen */
146- if ( 0 == ( p = strrchr ( buf , '\n' ) ) ) {
155+ if ( 0 == ( p = strrchr ( start , '\n' ) ) ) {
147156 curpos += len ;
148157 } else {
149- curpos = len + buf - p ;
158+ curpos = len + start - p ;
150159 }
151160 }
152161}
@@ -322,111 +331,73 @@ const char * real2exp( double r ) {
322331 #undef PP_SMALL_BUF_SZ
323332}
324333
325- /** write delimiter, newline, indent spaces, '+', and delimiter to str
326- * \param str pointer to pointer to char
327- * \param indent number of spaces for indentation
328- * \param first true if first call - skips delimiter before newline
329- * \return count of chars added to str
330- *
331- * *str is assumed to have enough space
332- *
333- * Will not work with encoded strings
334+ /** Find next '.' in null-terminated string, return number of chars
335+ * If no '.' found, returns length of string
334336 */
335- unsigned int insertStrBrk ( char * * const str , unsigned int indent , bool first ) {
336- unsigned int i = 0 ;
337- if ( ! first ) {
338- * * str = '\'' ;
339- ( * str ) ++ ;
337+ int nextBreakpoint ( const char * pos , const char * end ) {
338+ int i = 0 ;
339+ while ( ( * pos != '.' ) && ( * pos != '\0' ) && ( pos < end ) ) {
340+ i ++ ;
341+ pos ++ ;
340342 }
341- * * str = '\n' ;
342- ( * str )++ ;
343- while ( i < indent ) {
344- * * str = ' ' ;
345- ( * str )++ ;
343+ if ( * pos == '.' ) {
346344 i ++ ;
347345 }
348- if ( !first ) {
349- * * str = '+' ;
350- ( * str )++ ;
351- * * str = ' ' ;
352- ( * str )++ ;
346+ return i ;
347+ }
348+
349+ /** true if it makes sense to break before printing next part of the string */
350+ bool shouldBreak ( int len ) {
351+ if ( ( curpos > indent2 ) &&
352+ ( ( curpos + len ) > exppp_linelength ) ) {
353+ return true;
354+ }
355+ return false;
356+ }
357+
358+ /** Insert newline if it makes sense. */
359+ void maybeBreak ( int len , bool first ) {
360+ if ( shouldBreak ( len ) ) {
361+ if ( first ) {
362+ raw ( "\n%*s'" , indent2 , "" );
363+ } else {
364+ raw ( "'\n%*s+ '" , indent2 , "" );
365+ }
366+ } else if ( first ) {
367+ /* staying on same line */
368+ raw ( "%s" , ( printedSpaceLast ? "'" : " '" ) );
353369 }
354- * * str = '\'' ;
355- ( * str )++ ;
356- return 2 + indent + ( first ? 3 : 0 ); /* 2 for \n' , +3 if first */
357370}
358371
359372/** Break a long un-encoded string up for output and enclose in ''
360- * if it is too long, error
361- * if too short, enclose in '' but don't insert line breaks
373+ * if short, enclose in '' but don't insert line breaks
362374 * \param in the input string
363375 *
364- * use globals indent2 and curpos
376+ * side effects: output via raw()
377+ * reads globals indent2 and curpos
365378 */
366- const char * breakLongStr ( const char * in ) {
367- const unsigned int minbreak = 50 ; /* if line is longer than this, try to break it */
368- static char buf [8192 ] = { 0 }, * optr ;
369- const char * iptr = in ;
370-
371- /* error message to print when we can't return `in` because it is too long and needs wrapped in '' */
372- const char * errmsg = "ERROR: Cannot break long string of len %d:\n%s\n" ;
373-
374- unsigned int inlen = strlen ( in ), linelen = 0 ;
375-
376- /* used to ensure that we don't overflow the buffer */
377- int extrachars = 8191 - inlen ;
378- optr = buf ;
379-
380- if ( inlen < minbreak ) {
381- * optr = '\'' ;
382- optr ++ ;
383- strcpy ( optr , in );
384- optr += inlen ;
385- * optr = '\'' ;
386- optr ++ ;
387- * optr = '\0' ;
388- return buf ;
389- }
390- if ( inlen > 8000 ) {
391- /* 8000 gives us 191 extra chars for '\n + ' */
392- fprintf ( stderr , errmsg , inlen , in );
393- abort ();
394- }
395- if ( indent2 < curpos ) {
396- /* start with a newline, indent, and delimiter */
397- extrachars -= insertStrBrk ( & optr , indent2 , true );
398- if ( extrachars <= ( int ) indent2 + 7 ) {
399- fprintf ( stderr , errmsg , inlen , in );
400- abort ();
401- }
402- } else {
403- * optr = ' ' ;
404- optr ++ ;
405- * optr = '\'' ;
406- optr ++ ;
379+ void breakLongStr ( const char * in ) {
380+ const char * iptr = in , * end ;
381+ unsigned int inlen = strlen ( in );
382+ bool first = true;
383+ /* used to ensure that we don't overrun the input buffer */
384+ end = in + inlen ;
385+
386+ if ( ( ( int ) inlen + curpos ) < exppp_linelength ) {
387+ /* short enough to fit on current line */
388+ raw ( "%s%s'" , ( printedSpaceLast ? "'" : " '" ), in );
389+ return ;
407390 }
408391
409- /* copy */
410- while ( * iptr ) {
411- * optr = * iptr ;
412- optr ++ ;
413- iptr ++ ;
414- linelen ++ ;
415- /* look for '.' to break after, as long as there is something after it and the line is reasonably long */
416- if ( ( * ( iptr - 1 ) == '.' ) && ( * iptr != '\0' ) && ( linelen >= minbreak ) ) {
417- extrachars -= insertStrBrk ( & optr , indent2 , false );
418- if ( extrachars <= ( int ) indent2 + 7 ) {
419- fprintf ( stderr , errmsg , inlen , in );
420- abort ();
421- }
422- linelen = 0 ;
423- }
392+ /* insert newlines at dots as necessary */
393+ while ( ( iptr < end ) && ( * iptr ) ) {
394+ int i = nextBreakpoint ( iptr , end );
395+ maybeBreak ( i , first );
396+ first = false;
397+ raw ( "%.*s" , i , iptr );
398+ iptr += i ;
424399 }
425- * optr = '\'' ;
426- optr ++ ;
427- * optr = '\0' ;
428- optr ++ ;
429- return buf ;
400+ raw ( "' " );
430401}
431402
432403/* Interfacing Definitions */
0 commit comments