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:
- 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).
- There may be a drive letter or not.
- There may be a path or not.
- There may be an extension or not.
- 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)
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))
let $drive = ''
! 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))
let $path = ''
let $filename = $fullname
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
when = 1
let $ext = ''
when = 2
let $ext = substr($filename, 2, length($filename))
let $filename = ''
let $ext = substr($filename, #start_pos, length($filename))
let $filename = substr($filename, 1, #start_pos - 2)
begin-procedure go_past_last_char($string, $char, :#after_last)
! Loop until the last occurrence of search character
let #new_pos = 0
let #after_last = #new_pos + 1
let #new_pos = instr($string, $char, #after_last)
if #new_pos = 0
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.
Next week, we will use the Parse_Filename procedure to help an SQR program determine whether another instance of itself is running.
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:
- Years that are evenly divisible by 400 are leap years.
- All other years that are evenly divisible by 100 are not leap years.
- 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?
There are also file names in Windows with the format \computernamesharenamepath.
Good point. In that case, the routine will return the following values:
(assuming $fullname = ‘\computernamesharenamepathfile.ext’)
$drive =” (null)
$path = ‘\computernamesharenamepath’
$filename = ‘file’
$ext = ‘ext’
Um, my first solution had the cond() value going into a variable…so what I posted works but probably didn’t make much sense! Try this instead…
if #year % 4 = 0 and (#year % 100 <> 0 or #year % 400 = 0)
if dateadd(strtodate(edit(#year, ‘0000’) || ‘0228’), ‘day’, 1) <> strtodate(edit(#year, ‘0000’) || ‘0301’)
Welcome, Kevin. Based on your comment, I didn’t publish your first solution. These solutions look good. But there is also a solution that you could use even if you didn’t know the rule about “every four years, except centuries, blah blah blah.”
Are you the author of SP Debugger for SQR? I’m honored to have you here. I plan to talk about your creation in a future post. People should check it out at:
Yes, I did write SP Debugger–thanks for the comment!
Ah, maybe you are thinking of this:
if datediff(strtodate(edit(#year + 1, ‘0000’) || ‘0101’), strtodate(edit(#year, ‘0000’) || ‘0101’), ‘day’) = 366
Ohhh, you are so close! Have you checked the edit() masks for dates?
Edit 12/31 using ‘DDD’? Oh, clever…
Good work! Thank you very much!
I always wanted to write in my blog something like that. Can I take part of your post to my site?
Of course, I will add backlink?
Sincerely, Timur Alhimenkov
Welcome to my blog, Timur. You flatter me and I’d be glad to contiribute something useful to your site. I look forward to visiting it.
I will not understand why so my posts delete or do not publish and do not answer questions.
I read every comment I get. I prefer to publish the comments that will be of interest to my readers. I get comments that seem very general like “Thank you,” or “Very interesting,” or “You stole that from another site,” that seem like they could apply to any blog or any topic. As for the accusation, I’d be delighted to find another active blog about SQR, but so far I haven’t. I am impressed that all these bloggers, who write so fluently in Russian on their websites, also read my technical-English essays so well. However, it is not at all flattering to contemplate someone (or something) going from one website to the next, robotically sprinkling the web with shallow praise.