Retrieving strings from r-code

dreed

New Member
I am trying to view the CVS version of r-code. In the source code I define a variable, that is auto-expanded by CVS. For example:
def var cvs{&sequence} as char no-undo init
"$Id: ds-clog1.p,v 1.7 2005/08/15 14:12:57 dan Exp $".

And when I look at the r-code with a text editior, I can see these values in the r-code for the main program and all include files. However, I would like to pull them out programmatically and display them in a window when I'm working at customer sites and debugging problems.

Does anyone know how to pull these strings out of the r-code? I'm running Progress v9.1D on MS Windows. I looked at "input from ... binary", and I figured out how to load the r-code into memory, but I have no idea how to identify and extract the CVS strings.

Thanks.

Dan
 
it's 5 in the morning, got back from a party and saw your question
so i didn't get to add any comments

if something isn't clear leave a message
and i'll get to it when i have the time

i hope it's what you're looking for, cool idea by the way !



/* test.p */

define var cvs as char no-undo init "<cvs>Hello World</cvs>".

/* remember to compile the file into .r */



/* main.p */

function getCVS returns char ( input pcFileName as char ):

define var str as char no-undo.
define frame a str view-as editor large size 10 by 10.

hide frame a.
str:read-file( pcFileName ).

define var i as int no-undo.
define var j as int no-undo.

i = index( str:screen-value, "<cvs>" ).
if i = 0 then return "".
i = i + length( "<cvs>" ).

j = index( str:screen-value, "</cvs>", i + 1 ).
if j = 0 then return "".
j = j - 1.

return substr( str:screen-value, i, j - i + 1 ).

end function. /* getCVS */

display getCVS( "test.r" ) format "x(35)".



degrassi forever !!!
 
Cool solution by the way! It never even occurred to me that something like that would work. It required some tweaking, but I did get it to work.

The "index" function can search only 32767 bytes, so right off the bat I had to use the "delete-line()" method to delete lines in the editor until "index" found the string I was searching for. (I also increased the width of the editor to 319 chars to get the max line width)


I noticed that all the variables and litteral values were stored in a section of the r-code following the string "TXS" (in addition to being scattered throughout the code), so I deleted lines until I found "TXS", and then I deleted all characters up to the "TXS" string with the following:
Code:
str:set-selection(1, index(str:screen-value, "TXS")). 

str:replace-selection-text("").

Because there can be any number of include files, each with their own CVS variable, I deleted the text as I found each string and reiterated the search. However, I found that on some programs, there were gaps larger than 32767 bytes between consequtive CVS variables, so on each iteration of my loop, if "$Id:" wasn't found, I deleted more lines until I found another instance, and then I deleted all text preceeding the instance to make sure "index" could get the full text string without surpassing the 32767 limit.

In the end I got exactly what I wanted. Thanks for finding the solution!

Here's my actual code:

Code:
&SCOPED-DEFINE BEG-STR "$Id:"
&SCOPED-DEFINE END-STR "$"
 
def temp-table zt-cvs
  field seq  as inte format ">>9"   label "Seq"
  field prog as char format "x(22)" label "Program"
  field ver  as char format "x(7)"  label "Version"
  field dt   as char format "x(19)" label "Date/Time"
  field dev  as char format "x(8)"  label "Dev"
  index seq as primary unique
    seq
  index prog as unique
    prog.

procedure cvs-scan:
  define input parameter ps-file as char no-undo.
 
  define var ys-text  as char no-undo.
  define var ys-cvs   as char no-undo.
  define var ys-prog  as char no-undo.
  define var ys-id    as char no-undo.
  define var yi-line  as inte no-undo.
  define var yi-lines as inte no-undo.
  define var yi-seq   as inte no-undo.
  define var yi-beg   as inte no-undo.
  define var yi-end   as inte no-undo.
  define var yi-len   as inte no-undo.
 
  for each zt-cvs:
    delete zt-cvs.
  end.
 
  if not file-found(r-code(ps-file)) then
    RETURN.
 
  /* store the r-code in an editor in a hidden frame */
  define frame yf-text
    ys-text view-as editor large size 319 by 10
    with width 320.
  hide frame yf-text.
  ys-text:read-file(r-code(ps-file)).

  yi-lines = ys-text:num-lines.
  /* Delete lines until "index" finds "TXS", which marks the variable section */
  do yi-line = 1 to yi-lines:
    if index(ys-text:screen-value, "TXS") = 0 then
          ys-text:delete-line().
    else
      LEAVE.
  end.  /* do yi-line = 1 to yi-lines: */
 
  /* Remove all garbage preceeding the "TXS" for maximum "index" reach */
  ys-text:set-selection(1, index(ys-text:screen-value, "TXS")).
  ys-text:replace-selection-text("").
 
  yi-seq = -1.  /* start with 0 */
  repeat:
    /* Sometimes there are gaps exceeding 32767 bytes - skip gaps here */
    if index(ys-text:screen-value, {&BEG-STR}) = 0 then do:
      yi-lines = ys-text:num-lines.
      /* Delete lines until "index" finds &BEG-STR */
      do yi-line = 1 to yi-lines:
        if index(ys-text:screen-value, {&BEG-STR}) = 0 then
              ys-text:delete-line().
        else
          LEAVE.
      end.  /* do yi-line = 1 to yi-lines: */
 
      /* Remove all garbage preceeding the &BEG-STR for maximum "index" reach */
      ys-text:set-selection(1, index(ys-text:screen-value, {&BEG-STR})).
      ys-text:replace-selection-text("").
    end.  /* if index(ys-text:screen-value, {&BEG-STR}) = 0 */
 
    assign
      yi-seq = yi-seq + 1
      yi-beg = index(ys-text:screen-value, {&BEG-STR})
      yi-end = index( ys-text:screen-value, {&END-STR}, yi-beg + 1)
      no-error.
 
    if yi-end = 0 then
      LEAVE.
 
    assign
      yi-beg = yi-beg + length({&BEG-STR}) + 1
      yi-len = yi-end - yi-beg - 1
 
      ys-cvs  = substring(ys-text:screen-value, yi-beg, yi-len)
      ys-prog = entry(1, entry(1, ys-cvs, " "), ",")
      .
 
    /* If record exists, then we've scanned past the main variable section */
    find zt-cvs where zt-cvs.prog = ys-prog no-error.
    if available zt-cvs then
      LEAVE.
 
    create zt-cvs.
    assign
      zt-cvs.seq  = yi-seq
      zt-cvs.prog = ys-prog
      zt-cvs.ver  = entry(2, ys-cvs, " ")
      zt-cvs.dt   = entry(3, ys-cvs, " ") + " " + entry(4, ys-cvs, " ")
      zt-cvs.dev  = entry(5, ys-cvs, " ")
      .
 
    /* Delete as we go to avoid the 32767 byte limit on the "index" function */
    ys-text:set-selection(1, yi-end).
    ys-text:replace-selection-text("").
  end.  /* repeat */
end procedure.  /* cvs-scan */
 
yes you are right, haven't thought about it,
it would be a problem with larger files
hey it was 5 in the morning

another option, maybe, would be to load the file into memory
as you first suggested

and then build a memptrindex equivalent to the index function
that searches the memptr using get-byte function
and other memptr manipulation statements

as you already know remember to free up the memory at the end
not to cause memory leaks

i think, that would be better
tell me if i can help in any way


it's been alot of time since i've looked at the r-code structure
but i think, in this case, it would show up
in the text and initial value segments

you can look it up in your edocs
managing 4gl applications \ appendices \ r-code features and functions

anybody knows how to get into the text segment directly ?
in the r-code not through compile string-xref

commands, utilities, undocumented features ?
maybe bring up the question over at peg


looks great ! good luck !
 
had another look at it
you can use the editor object search( ) method

that way everything stays simple
maybe not the most efficient, but not a big difference either

i tried it on a 150k .r and placed a "cvs" text close to the end
the cursor-offset was around 148k

try it out, tell me if it works



function getCVS returns char ( input pcFileName as char ):

define var str as char no-undo.
define frame a str view-as editor large size 10 by 10.

hide frame a.
str:read-file( pcFileName ).



define var i as int no-undo.
define var j as int no-undo.
define var ret as logi no-undo.

ret = str:search( "<cvs>", 1 ).
if not ret then return "".
i = str:cursor-offset.

ret = str:search( "</cvs>", 1 ).
if not ret then return "".
j = str:cursor-offset - length( "/<cvs>" ).



str:set-selection( i, j ).
str:edit-copy( ).

str:screen-value = "".
str:edit-paste( ).

return substr( str:screen-value, 1 ).

end function. /* getCVS */
 
oops, typo

instead of return substr at the end of the function
just use return str:screen-value.
or assign str. return str.

by the way, anybody here know what's degrassi ?
 
Back
Top