Alexey Maslov · Aug 17, 2017

Replacing all strings of special kind with macro calls

Hello everybody.

What I have is a criteria how to select "my" strings. What I need is to replace all of them with macro calls (using the same strings as arguments) in all classes of current namespace.

I was ready to write straightforward code, but at the last moment decided to ask the community: maybe I've overlooked a smarter option?

Any comments and advices would be great appreciated.

0 425
Discussion (6)2
Log in or sign up to continue

I think you could do the job with our RE/parser tool.

Disclosure: I work for George James Software.

Thank you, John.

Maybe we should look at RE/parser closer, while I'm not sure if it's able to cope with our great mixture of code (see my comment above). 

Honestly, string literals matching/replacing is only a small part of a bigger task of adding multi-language support to our HIS.

Thank you, Eduard,

This is a good example of regexp usage. At the meantime a colleague of mine is working on JS based solution outside of Caché (regexp replacement in .xml file). It's not clear enough if porting it to COS (class sources regexp replacement) would add any benefit.

Could you share your straightforward code? For searching all routines in a namespace in Cache ObjectScript, I have used Find in Files within Cache Studio (class is %SYS.%Studio.Project) but it looks like you are looking to programmatically replace what is returned as a result. The basic 'Find and Replace' only seems to only apply to the currently active window. I do not know if Atelier has more advanced Find in Files and & Replace feature to search the entire namespace but from the documentation I've read, I suspect not.

Other search facilities I have used include %GCHANGE routine and %RFIND. %GCHANGE has an option for changing the contents of a global - useful if you have XECUTE and indirection (@) statements that call executable code from a global reference. This practice was more common when the size of routines had to be very small and executing statements from within a global reference was one way getting round this limitation. If you have no executable code in globals then %GCHANGE probably doesn't apply.

Check out the ObjectScript function $TEXT to return source code from a routine. You could use ZINSERT and ZREMOVE commands to programmatically alter the contents of source code.  

UPDATE: If I was trying to solve this problem. I would do a find in files to get the routine references. Verify the output and copy the contents to a plain text file. Clean up the file if necessary removing data that is not required. Read the contents of the file to obtain the routine references. Use ZINSERT and ZREMOVE to replace the source code contents. You will probably need to re-compile for the changes to take effect.

Thank you, Stephen.

I should confess that you are quite write: our code resides in .cls, .inc, .int and also in globals. As to my straightforward code, it is not written yet. At the moment I have a simple "search-in-global engine", which matching ability should be improved (regexp?) and replacement functionality should be added. If speed will turn to be a problem, I will use it with ^ROUTINE, ^rINC and ^oddDEF globals as well, while I dislike this idea and prefer to start with official API (%Dictionary classes). 

Check out SystemMethodsRemover - it does automatic regexp replace on the codebase. It's configured for system methods replacing, but you can easily repurpose it.