something like this would get you started on a set based solution:
with sp_lines(ObjectId, SPName, CRPos, [LineNo])
as (
select
o.id
,o.name
,t.n as CRPos
,ROW_NUMBER() over (partition by o.name order by t.n) as [LineNo]
from sys.syscomments c
inner join sys.sysobjects o on c.id = o.id
left join Tally t on substring(c.text, t.n, 1) = char(10)
where c.text like '%varchar%'
and o.xtype = 'P'
)
select
current_line.SPName
,substring(c.text, isnull(previous_line.CRPos+1, 1), current_line.CRPos - isnull(previous_line.CRPos+1, 1)) as LineText
--,isnull(previous_line.CRPos+1, 1) as LineStart
--,current_line.CRPos - isnull(previous_line.CRPos+1, 1) as Length
from sp_lines current_line
left join sp_lines previous_line on current_line.ObjectId = previous_line.ObjectId
and current_line.[LineNo] - 1 = previous_line.[LineNo]
inner join sys.syscomments c on current_line.ObjectId = c.id
where substring(c.text, isnull(previous_line.CRPos+1, 1), current_line.CRPos - isnull(previous_line.CRPos+1, 1)) like '%varchar%'