scanf(str,&b)
  public
  
    
    
The trick here is doing a match where you grab one line of input at
a time.  The linebreak may or may not occur at the boundary where the
string matches a format specifier. And if it does, some rule about
whitespace may or may not be in effect…
That’s why this is much more elaborate than the string version.
For each line: Match succeeds (non-emptily) and
the last attempted spec/string sub-match succeeded:
could the last spec keep matching?
  yes: save interim results and continue (next line)
The last attempted spec/string did not match:
are we on the next-to-last spec in the string?
yes:
  is fmt_string.string_left all spaces?
    yes: does current spec care about input space?
      yes: fatal failure
      no: save interim results and continue
no: continue  [this state could be analyzed further]
   
  
    Show source    
    
      
  def scanf(str,&b)
    return block_scanf(str,&b) if b
    return [] unless str.size > 0
    start_position = pos rescue 0
    matched_so_far = 0
    source_buffer = ""
    result_buffer = []
    final_result = []
    fstr = Scanf::FormatString.new(str)
    loop do
      if eof || (tty? &&! fstr.match(source_buffer))
        final_result.concat(result_buffer)
        break
      end
      source_buffer << gets
      current_match = fstr.match(source_buffer)
      spec = fstr.last_spec_tried
      if spec.matched
        if spec.mid_match?
          result_buffer.replace(current_match)
          next
        end
      elsif (fstr.matched_count == fstr.spec_count - 1)
        if /\A\s*\z/.match(fstr.string_left)
          break if spec.count_space?
          result_buffer.replace(current_match)
          next
        end
      end
      final_result.concat(current_match)
      matched_so_far += source_buffer.size
      source_buffer.replace(fstr.string_left)
      matched_so_far -= source_buffer.size
      break if fstr.last_spec
      fstr.prune
    end
    seek(start_position + matched_so_far, IO::SEEK_SET) rescue Errno::ESPIPE
    soak_up_spaces if fstr.last_spec && fstr.space
    return final_result
  end