#!/usr/bin/env awk function shift( array, \ junk, elm0, l ) { elm0 = array[0] for ( l = 0; l < asorti( array, junk ) - 1; l++ ) array[l] = array[l+1]; delete array[l] return elm0 } function init_cpp_src_line() { logical_line = "" delete break_pos } function shift_valid_bp( array, \ junk, elm ) { elm = -1 if ( 0 < asorti( array, junk ) ) do { elm = shift( array ) } while ( 0 > elm ); return elm } function check_cpp_src_line_break_pos( \ i, junk ) { printf( "break_pos:" ) for ( i = 0; i < asorti( break_pos, junk ); i++ ) printf( " %d", break_pos[i] ); printf( "\n" ) } function check_cpp_src_line() { printf( "logical_line[%s]\n", logical_line ) check_cpp_src_line_break_pos() } function append_line( phys_line, \ filt_line, bp_len ) { filt_line = phys_line sub( /\\$/, " ", filt_line ) logical_line = logical_line filt_line bp_len = asorti( break_pos, junk ) break_pos[bp_len] = length( logical_line ) - 1 } function print_line( \ c0, c1, i, junk, part_str ) { c0 = 0 while( asorti( break_pos, junk ) > 1 ) { if ( ( c1 = shift_valid_bp( break_pos ) ) < 1 ) { part_str = substr( logical_line, c0 + 1 ) printf( "%s\n", part_str ) return } part_str = substr( logical_line, c0 + 1, c1 - c0 + 1 ) gsub( / $/, "\\", part_str ) printf( "%s\n", part_str ) c0 = c1 + 1 } part_str = substr( logical_line, c0 + 1 ) printf( "%s\n", part_str ) } function shrink_spaces( pos, \ tail, removed_length, k ) { tail = substr( logical_line, pos ) sub( /^[ \t]+/, " ", tail ) removed_length = length( logical_line ) - pos - length( tail ) + 1 logical_line = substr( logical_line, 0, pos - 1 ) tail for ( k = 0; k < asorti( break_pos, junk ); k++ ) if ( ( pos + removed_length ) <= break_pos[k] ) break_pos[k] = break_pos[k] - removed_length; else if ( pos <= break_pos[k] ) break_pos[k] = -1; return removed_length } function shrink_spaces_to_linebreak( pos, \ junk, part_str, removed_length, i ) { for ( i = 0; i < asorti( break_pos, junk ) && break_pos[i] < pos ; i++ ) ; if ( break_pos[i] < 1 ) return; part_str = substr( logical_line, pos, break_pos[i] - pos + 1 ) sub( /^[ \t]+/, " ", part_str ) removed_length = ( break_pos[i] - pos + 1 ) - length( part_str ) tail = substr( logical_line, pos + removed_length ) logical_line = substr( logical_line, 0, pos - 1 ) tail for ( ; i < asorti( break_pos, junk ); i++ ) break_pos[i] -= removed_length; return removed_length } function delete_linebreaks_in_2nd_token( \ tail, paren_depth, junk, i, j, k, l ) { if ( logical_line ~ /^[ \t]*#[ \t]*define[ \t]+[0-9A-Za-z_]+\(/ ) { tail = logical_line sub( /^[ \t]*#[ \t]*define[ \t]+[0-9A-Za-z_]+/, "", tail ) paren_depth = 0 l = 0 i = length( logical_line ) - length( tail ) + 1 # seek to the 1st op paren j = i do { if ( substr( logical_line, j, 2 ) ~ /[ \t][ \t]/ ) l = shrink_spaces( j ); else if ( substr( logical_line, j, 1 ) == "(" ) paren_depth += 1; else if ( substr( logical_line, j, 1 ) == ")" ) paren_depth -= 1; j += 1 } while ( j < length( logical_line ) && paren_depth != 0 ) for ( k = 0; k < asorti( break_pos, junk ); k++ ) if ( i <= break_pos[k] && break_pos[k] < j ) break_pos[k] = -1; if ( l > 0 ) shrink_spaces_to_linebreak( j ); } } BEGIN{ init_cpp_src_line() } { append_line( $0 ) if ( $0 !~ /\\$/ ) { delete_linebreaks_in_2nd_token() print_line() init_cpp_src_line() } } END{ if ( 0 < length( logical_line ) ) { delete_linebreaks_in_2nd_token() print_line() } }