[Info-vax] OpenVMS - DCL - Data entry filtering
Bob Gezelter
gezelter at rlgsc.com
Thu Mar 26 08:01:32 EDT 2015
On Wednesday, March 25, 2015 at 5:09:45 AM UTC-4, IanD wrote:
> I am wanting to write a small bit of DCL that will filter a users input to ensure that the following characters are voided in any input
>
> ban_these_characters = "~`!@#$%^&*()-+={}[]\|;:',.<>/?"""
>
> The OS version is 7.3-2 if that helps
>
> I tried things like the following:
>
> ban_these_characters = "~`!@#$%^&*()-+={}[]\|;:',.<>/?"""
> data_entry = "~~test~~"
> data_entry = data_entry - ban_these_characters
>
> But that only removes the banned characters if they exactly match the entered string in the exact order, obviously this is not what I want
>
> I have for years mistakenly thought DCL performed a string removal of ALL the characters in the subtraction operation irrespective of their position in the string needing to be filtered! Silly me for making an assumption!
>
> I can remove one character at a time by using:
>
> data_entry = data_entry - "~"
>
> and then performing the same operation again to again, removing one character at a time in a recursive call
>
> i.e.
> data_entry = "~~test~~"
> data_entry = data_entry - "~"
>
> result: data_entry = "~test~~"
>
> data_entry = data_entry - "~"
>
> result: data_entry = "test~~"
>
> and so on, all rather tedious
>
> Using this technique, to effectively remove ALL occurrences of a banned character I have to loop around performing the string subtraction until the given banned character being tested is no longer in the accepted string
>
> If I then want to remove a string of banded characters irrespective of their order in any input string then I need to perform this recursively in a multiple recursive loop, an n x m comparison test *sigh* (of course a while loop here would make life a lot easier)
>
> By my rough calculations this will typically take around 650 comparisons and over 1500 comparisons worst case for the given input validation I am wanting to do. Sure, I can reduce it slightly by scanning and keeping only accepted characters in a positive test but the number of comparisons is very similar to the above negative test
>
> I don't want to resort to writing this in C, so DCL is the poison of choice here
>
> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
> >>>> Question: Is there a smarter / easier way of doing this in DCL? <<<<<
> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>
> I thought maybe pipe might be able to do it but attempts to redirect sys$command to sys$pipe died in a puff of illogic and near brain haemorrhaging
>
> Input from the VMS brains trust would be greatly appreciated :-)
>
> To those who are working on or contemplating modernising DCL (even though my preference is to replace it), the above would be nice to have in DCL if it's not already available natively
>
> Something like an f$fao directive, for arguments sake, lets call it !RC (for Remove Character(s) as in:
>
> result = f$fao("!AS!RC","string","remove_all_of_these_characters")
>
> While we are it, we could add a whole swag of string checks and string manipulation components to DCL, such as String reversal, Character occurrence counting, pretty much most things that a string library in C would have and they probably wouldn't take much doing as the C libraries already exist anyhow
>
> Oh and PLEASE add the ability to right justify and pad an output, there's a left justify but why no direct right justify?
Ian,
I would certainly implement Hoff's suggestion, namely "allow only those known to be valid".
I would extract one character at a time, and check it against the list of known good characters using F$EXTRACT and F$LOCATE, to wit:
$ TOBETESTED = F$EXTRACT(0, 1, STRING)
$ STRING = F$EXTRACT(1, F$LENGTH(STRING) - 1, STRING)
$ IF (F$LOCATE(STRINGOFVALIDCHARACTERS, TOBETESTED) .EQ. 1) THEN TOBETESTED = ""
$ VALIDSTRING = VALIDSTRING + TOBETESTED
The above needs to execute once for each character in the subject string.
With a small change, one can further reduce the iteration count by replicating the code in a vector, and inserting a line after each instantiation checking if the source string is exhausted.
- Bob Gezelter, http://www.rlgsc.com
More information about the Info-vax
mailing list