Given that some entire config file has been loaded into $buffer, it would seem easiest to split that into lines, and then behave pretty much the same way as reading from a file, except that "local $/" is of no use in this case. The following is untested:

It's a little grotty, in the sense that you have to put the "within a HERE doc" behavior first in the "if...elsif..." series, because who knows whether/when the contents of a here-doc might trigger a false-alarm match on one of the other conditions. Also, as written above, there's nothing to warn about a here-doc that is not terminated at the last line in $buffer -- but that should be easy to figure out.

Which just means: split the content of the file on the zero-width positive lookbehind assertion of $/ (the input record separator). This is subtley different from just splitting on $/ (or, more safely, splitting on \Q$/\E), in that splitting on $/, itself, removes $/ from the output of the split... whereas splitting on the zero-width positive lookbehind assertion leaves it in. (This is because what is being splitted on is the empty string following each occurence of $/, so that is the thing that gets removed).

Anyway, this may not be the best way to deal with the situation of your problem, but it is the most general solution for dropping in a replacement of a <FILE> loop with some sort of loop over the contents of FILE.

When putting a smiley right before a closing parenthesis, do you:

Use two parentheses: (Like this: :) )
Use one parenthesis: (Like this: :)
Reverse direction of the smiley: (Like this: (: )
Use angle/square brackets instead of parentheses
Use C-style commenting to set the smiley off from the closing parenthesis
Make the smiley a dunce: (:>
I disapprove of emoticons
Other