Sometimes we have a fully qualified filename (drive letter, path, filename, and extension) and we need to parse it.  There are a few challenges to this:

  1. The same SQR source code needs to work under Windows, Unix, and maybe other operating systems. Directories may be delimited by slashes (Unix) or backslashes (Windows).
  2. There may be a drive letter or not.
  3. There may be a path or not.
  4. There may be an extension or not.
  5. There may be periods in the directory names and filename before the extension.

Admittedly, this isn’t rocket science or even information theory.  But we aren’t born knowing the code, and it can take time to sketch out and debug.  So here is one approach.

! Call this procedure with a string variable or literal that contains:
! 1. (Optional) A drive letter followed by a colon.
! 2. (Optional) A directory path delimited by slash or backslash.
! 3. (Required) A filename that does not contain a slash or backslash.
! 4. (Optional) An extension preceded by a period.
! This procedure will return four values (which can include null) for
! the drive, path, filename, and extension.


begin-procedure parse_filename($fullname, :$drive, :$path, :$filename, :$ext)


let #pos = instr($fullname, ':', 1)
if #pos
  let $drive = substr($fullname, 1, #pos)
! don't worry - the change in $fullname won't be passed back to the calling procedure
  let $fullname = substr($fullname, #pos + 1, length($fullname))
else
  let $drive = ''
end-if


! Should we use slash (Unix) or backslash (Windows)?
let $slash   = cond(instr($fullname, '/', 1) = 0, '\', '/')


do go_past_last_char($fullname, $slash, #start_pos)


! The path is everything up to and including the last slash
! The filename is everything after the last slash
if #start_pos > 1
  let $path = substr($fullname, 1, #start_pos - 1)
  let $filename = substr($fullname, #start_pos, length($fullname))
else
  let $path = ''
  let $filename = $fullname
end-if


do go_past_last_char($filename, '.', #start_pos)


! The filename is everything up to but not including the last period
! The extension is everything after the last period
evaluate #start_pos
  when = 1
    let $ext = ''
  when = 2
    let $ext = substr($filename, 2, length($filename))
    let $filename = ''
  when-other
    let $ext = substr($filename, #start_pos, length($filename))
    let $filename = substr($filename, 1, #start_pos - 2)
end-evaluate


end-procedure parse_filename


begin-procedure go_past_last_char($string, $char, :#after_last)


! Loop until the last occurrence of search character
let #new_pos = 0
while 1
  let #after_last = #new_pos + 1
  let #new_pos = instr($string, $char, #after_last)
  if #new_pos = 0
    break
  end-if
end-while


end-procedure go_past_last_char

We can apply this routine to built-in variable $sqr-program (the name of the SQR program file) to determine where our source file is stored and what is the name of its process in the Peoplesoft Process Scheduler. We can apply it to built-in variable $sqr-report (the name of the SQR print file) to determine where our output is going and where to put other files we want to view in the Peoplesoft Process Monitor.

Looking Ahead

Next week, we will use the Parse_Filename procedure to help an SQR program determine whether another instance of itself is running.

Brain Teaser

Meanwhile, here is a brain teaser.  Please post solutions as comments.

Most years have 365 days.  Leap years have 366 days. The extra day is February 29.  Leap years are determined by their number (2008, 2012, etc.).  The rules for leap years are as follows:

  1. Years that are evenly divisible by 400 are leap years.
  2. All other years that are evenly divisible by 100 are not leap years.
  3. All other years that are divisible by 4 are leap years.

Given #year is a variable containing the integer value of a year or $year is a variable containing the string of a four digit year, what are some ways to determine in SQR whether it is a leap year?  How many ways can you find?  What is the simplest way?