Is there a list of Special characters to be avoided in JCL/MVS Script variables - printing

I have a program that generates random pin codes. These pins are generated in Java, then stored in the mainframe, via a NATURAL program. From there, they are eventually physically printed by a batch JCL job that calls an MVS SCRIPT to print the form, with the pin code on it.
I've come across some issues with special characters before such as: |{}![]^~<>; that for one reason or another do not print properly. I've also removed 0OQ1l for OCR reasons.
Recently, an error came to my attention with another character that doesn't print properly, . but the . character only fails when it is the first character of the PIN Code.
So since I've run into this issue I thought I would see if I could find other special jcl, Natural or MVS Script characters that might interfere with my programs operation so that I can test them now and hopefully not run into this issue later or have to fallback to only using OCR'ed AlphaNumeric characters.
EDIT
Java - Web Application Runs Under Tomcat 6.x on a Solaris Server.
Natural - The Natural Program is called using webmethods Broker generated classes (POJOs).
My understanding is it uses RPC for actual communication.
The program verifies some data and stores the Pin in combination with a GUID on a record, in ADABAS.
There is a batch job that runs to print the forms. The Batch job is written in JCL.
My Understanding from the maintainer of the Batch Job, and the Forms stuff is the actual language to describe the forms themselves and how they get printed is an outdated/unsupported language called MVS SCRIPT.
the Bottom section of the script looks like this:
//**********************************************************************
//* PRINT SORTED FORMS TO #### USING MVS SCRIPT
//**********************************************************************
PRINTALL EXEC PGM=DSMSPEXEC,PARM='LIST'
//* less 'interesting' lines omitted
SYSPRINT DD SYSOUT=*
PRINT1 DD SYSOUT=A, OUTPUT=*.C####,
RECFM=VBM,LRECL=####,BLKSIZE=####
//* less 'interesting' lines omitted
//SYSIN DD *
AUTH /* redacted */
SCRIPT FROM(MYFORMS) (MESSAGE(ID TRACE) CONT -
FILE(PRINT1) PROFILE(redacted) -
NOSEGLIB DEVICE(PG4A) CHARS(X0A055BC))
.C#### is an actual number and is a variable that points to the chosen printer.
NOTE: I'm a Web Programmer, I don't speak mainframe, JCL, MVS, etc.

I think you will find the program (pgm=) is DSMSPEXC and not DSMSPEXEC.
I am guessing (could be wrong) we are talking about Script/DCF (which later became IBM Bookmaster / Bookmanager on other platforms).
Script/DCF is basically a GML based language. It was from GML that SGML was derived (HTML and XML are prominent examples of SGML languages).
In Script : starts a tag, . ends a tag. There are also macro's which have a . in column 1
.* ".*" in column 1 starts a line comment
.* .fo off is Format off (like <pre> in html)
.fo off
.* Starting an ordered list
:ol.
:li.Item in orded list
:eol.
i.e.
Script HTML
: < - Starts tag
. > - end of tag Script/DCF is generally pretty tolerant of .
& & - Starts a variable
There are variables (&gml. = :) for most of the special characters.
Characters to worry about are
: - always
& - always
. - in column one or after a :.
Other characters should be ok provided there are no translation errors. There charset X0A055BC (Mainframe SONORAN SANS SERIF ??) might not have all the special chars in it.
There are manuals around for Script/DCF tags.

Your data is not going to affect the JCL in any way.
I don't know about ADABAS or NATURAL. If you ask here, http://www.ibmmainframeforum.com/viewforum.php?f=25, specifically about that part, with as much detail as you can provide, there is a very expert guy, RDZbrog, who can probably answer that for you.
For the SCRIPT/VS itself, as Bruce Martin has pointed out, there may be some issues. With .xx and :xx there is not a clash with normal text. But you don't have normal text. With the &, which indicates a SCRIPT variable, it is more likely to be problematic and at any location.
I would fire some test data through: Your PINs with position one being all available punctuation preceding "fo" and "ol", and the same with those sequences "embedded" in your PINs. Also include a double & and a triple &.
Your query should be resolved in your specification. It is not, but I'm sure you'll get all the documentation updated when you get a resolution.

Related

Informix 4GL report to screen - Reverse

I have a generated report in Informix 4GL that prints to the screen.
I need to have one column displayed in reverse format.
I tried the following:
print line_image attribute(reverse)
But that doesn't work. Is this possible at all?
Adding on to the previous answer, you can try the following
print "\033[7mHello \033[0mWorld"
\033[7m means to print in reverse. And, \033[0m means to go back to standard.
If you mean "is there any way at all to do it", the answer's "yes". If you mean "is there a nice easy built-in way to do it", the answer's "no".
What you'll need to do is:
Determine the character sequence that switches to 'reverse' video — store the characters in a string variable brv (begin reverse video; choose your own name if you don't like mine).
Determine the character sequence that switches to 'normal' video — store the characters in a string variable erv (end reverse video).
Arrange for your printing to use:
PRINT COLUMN 1, first_lot_of_data,
COLUMN 37, brv, reverse_data,
COLUMN 52, erv,
COLUMN 56, next_lot_of_data
There'll probably be 3 or 4 characters needed to switch. Those characters will be counted by the column-counting code in the report.
Different terminal types will have different sequences. These days, the chances are your not dealing with the huge variety of actual green-screen terminals that were prevalent in the mid-80s, so you may be able to hardwire your findings for the brv and erv strings. OTOH, you may have to do some fancy footwork to find the correct sequences for different terminals at runtime. Shout if you need more information on this.
A simple way which might allow you to discover the relevant sequences is to run a program such as (this hasn't been anywhere near an I4GL compiler — there are probably syntax errors in it):
MAIN
DISPLAY "HI" AT 1,1
DISPLAY "REVERSE" AT 1,4 ATTRIBUTE(REVERSE)
DISPLAY "LO" AT 1, 12
SLEEP 2
END MAIN
Compile that into terminfo.4ge and run:
./terminfo.4ge # So you know what the screen looks like
./terminfo.4ge > out.file
There's a chance that won't use the display attributes. You'd see that if you run cat out.file and don't see the reverse flash up, then we have to work harder.
You could also look at the terminal entry in the termcap file or from the terminfo entry. Use infocmp $TERM (with the correct terminal type set in the environment variable) and look for the smso (enter standout mode) and rmso (exit standout mode) capabilities. Decipher those (I have rmso=\E[27m and smso=\E[7m for an xterm-256color terminal; the \E is ASCII ESC or \033) and use them in the brv and erv strings. Note that rmso is 5 characters long.

Is there a solution for transpiling Lua labels to ECMAScript3?

I'm re-building a Lua to ES3 transpiler (a tool for converting Lua to cross-browser JavaScript). Before I start to spend my ideas on this transpiler, I want to ask if it's possible to convert Lua labels to ECMAScript 3. For example:
goto label;
:: label ::
print "skipped";
My first idea was to separate each body of statements in parts, e.g, when there's a label, its next statements must be stored as a entire next part:
some body
label (& statements)
other label (& statements)
and so on. Every statement that has a body (or the program chunk) gets a list of parts like this. Each part of a label should have its name stored in somewhere (e.g, in its own part object, inside a property).
Each part would be a function or would store a function on itself to be executed sequentially in relation to the others.
A goto statement would lookup its specific label to run its statement and invoke a ES return statement to stop the current statements execution.
The limitations of separating the body statements in this way is to access the variables and functions defined in different parts... So, is there a idea or answer for this? Is it impossible to have stable labels if converting them to ECMAScript?
I can't quite follow your idea, but it seems someone already solved the problem: JavaScript allows labelled continues, which, combined with dummy while loops, permit emulating goto within a function. (And unless I forgot something, that should be all you need for Lua.)
Compare pages 72-74 of the ECMAScript spec ed. #3 of 2000-03-24 to see that it should work in ES3, or just look at e.g. this answer to a question about goto in JS. As usual on the 'net, the URLs referenced there are dead but you can get summerofgoto.com [archived] at the awesome Internet Archive. (Outgoing GitHub link is also dead, but the scripts are also archived: parseScripts.js, goto.min.js or goto.js.)
I hope that's enough to get things running, good luck!

How to get the current paragraph name?

I would like to know how to get the current paragraph name in COBOL (using MVS Enterprise COBOL V4.2 here).
Let's say I have this code in the PROCEDURE DIVISION :
MAIN-LOGIC.
MOVE SPACE TO ABT-MSG
PERFORM PARAGRAPH-1
PERFORM PARAGRAPH-2
GO TO CLOSE-PROGRAM.
*
* SEARCH FOR A VALUE IN AN ARRAY AND GET THE RELATED INDEX
*
PARAGRAPH-1.
MOVE 42 TO SEARCH-VALUE
PERFORM VARYING I-SEARCH FROM 1 BY 1
UNTIL SOME-ARRAY(I-SEARCH) = SEARCH-VALUE
IF (I-SEARCH = MAX-ARRAY-POSITION)
MOVE SEARCH-ABORT TO ABT-MSG
MOVE 'PARAGRAPH-1' TO ABT-LOC
GO TO CLOSE-PROGRAM
END-IF
END-PERFORM
DISPLAY 'VALUE WAS FOUND AT POSITION ' I-SEARCH '.'.
*
* STORE A NEW VALUE AT THE END OF AN ARRAY
*
PARAGRAPH-2.
MOVE 42 TO STORAGE-VALUE
ADD 1 TO I-STORAGE
IF (I-STORAGE > MAX-ARRAY-POSITION)
MOVE STORAGE-ABORT TO ABT-MSG
MOVE 'PARAGRAPH-2' TO ABT-LOC
GO TO CLOSE-PROGRAM
END-IF
MOVE STORAGE-VALUE TO SOME-ARRAY(I-STORAGE).
*
* CLOSE THE PROGRAM
*
CLOSE-PROGRAM.
IF ABT-MSG > SPACE
DISPLAY ABT-MSG
DISPLAY '(FOUND IN ' ABT-LOC ')'
MOVE 20 TO RETURN-CODE
ELSE
DISPLAY SUCCESS-MESSAGE
END-IF
STOP RUN.
I would like to be able to access the current paragraph name (and store it in ABT-LOC) instead of having to write it.
Is there a COBOL system variable to do so, like 'CURR-PARA-NAME' or something ?
Thank you.
------ UPDATE 1 -------
I have updated my code example to make it more specific.
Know that, in my real COBOL program, there are various occurences of SEARCH-ABORT and STORAGE-ABORT possibilities (I am working with many arrays).
I want to make my code as good as possible, hence my will to access the current paragraph name instead of having to write it.
Thank you again.
------- UPDATE 2 ------
Well then. It seems I cannot do it (the users of my program will probably reject any debug messages they are not used to get - For your information, I am rewriting a 50 years old program with very, very bad programming practices such as upward GO TOs, fall-through logic and the godforsaken ALTER, and I want to get the same output at the end).
Don't worry, I will not cry tonight. This was just an esthetical improvement to my code, and I can live without it (my code is already a lot prettier than what I based myself on).
I thank all of you for your time, and wish you a good... Stack Overday !
As Simon Sobisch has correctly indicated in his answer, the only way to do exactly what you want is to use the "debugging declaratives". See later in the answer for making that work, but no-one should allow you to do this to a Production program.
COBOL is a compiled language so there is no no automatic access to any data-name or procedure name (paragraph or SECTION) unless the compiler makes something available. Which, excluding the case above, it doesn't.
That leaves three approaches: doing it manually (which you correctly want to avoid, as sure as peaches someone is going to copy or relocate code without changing the literal); pre-processing (with a program or the editor) to automatically populate your field with the correct label; doing something else.
Since you are implicitly discounting the first, again I believe correctly, let's consider the second. What if you have two, three or eight things in the same paragraph/SECTION which are all "business errors" (although usually these types of things are more "integrity errors", a state which should not exist, so don't continue)?
Since you will get those, a "pre-processing" solution starts to get more ugly.
What else can be done?
Well, it's something we've faced for many, many years. The answer is, unique (within the program) error numbers. The individual errors can be named, well, and given a number. The well-named error reference is difficult to use "incorrectly". When adding a new error, it is difficult to duplicate an existing number. Or, to put it another way, it is easy to duplicate but horribly easy to spot in testing - "hey, that's produced 1234, that's wrong".
It's in no way bullet-proof, but the data-name (and any associated text) give better indication of the problem than a paragraph-name (which is not going to be, except artificially, any indication of what the error is, just the location of it). The error references are very easy to find in the program, and from that it is easy to locate the procedure name, except you don't actually need it any more.
Whether the program with error-numbers outweigh the dross of manually maintained MOVE 'literal' TO some-standard-name programs is unknown. But you can guess which I favour and recommend.
Now, how to do it for Enterprise COBOL with DECLARATIVES.
IDENTIFICATION DIVISION.
PROGRAM-ID. STAB39.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. FRED DEBUGGING MODE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 W-WHEN-COMPILED PIC X(8)BX(8).
01 ABT-LOC PIC X(30).
PROCEDURE DIVISION.
DDECLARATIVES.
DSOME-SECTION SECTION.
D USE FOR DEBUGGING ON ALL PROCEDURES
D .
DSOME-PARA.
D MOVE DEBUG-NAME TO ABT-LOC
D .
DEND DECLARATIVES.
STARTING-UP SECTION.
DISPLAY
ABT-LOC
D DISPLAY
D "IT IS STARTING UP"
MOVE WHEN-COMPILED TO W-WHEN-COMPILED
DISPLAY
"STAB39 "
W-WHEN-COMPILED
.
A-PARA.
DISPLAY
ABT-LOC
PERFORM
10 TIMES
D DISPLAY
"ITERATING"
END-PERFORM
.
ANOTHER-PARA.
DISPLAY
ABT-LOC
PERFORM THE-PARA
10 TIMES
PERFORM THE-SECOND-PARA
GOBACK
.
THE-PARA.
DISPLAY
ABT-LOC
.
THE-SECOND-PARA.
DISPLAY
ABT-LOC
.
Some notes:
The SOURCE-COMPUTER paragraph is required to use COBOLs in-built debugging features, to turn them on. So the ENVIRONMENT DIVISION and CONFIGURATION SECTION are also required. The "computer name", FRED in the example, is required, but it is irrelevant. You can "name" your computer after your favourite pet or relative if you like, or put anything there, there just has to be something.
DECLARATIVES can only be specified at the start of the PROCEDURE DIVISION. They must be within a SECTION and all actions must be within a paragraph belonging to a SECTION. The names of the SECTION and paragraph are irrelevant, but make them meaningful anyway.
Because the DECLARATIVES must contain a SECTION, you will be subject to an informational diagnostic message if your first procedure label is not also a SECTION. This does not require using SECTIONS over paragraphs in your program, it has no further effect.
The D in column seven indicates a "debugging line". These lines only get code generated when you turn debugging on with the SOURCE-COMPUTER paragraph.
The program exercises all use of a paragraph (and use of a SECTION is no different for this example) except GO TO. Paragraphs which are GO TO'd will produce the same results as any other reference, but you won't see GO TOs in my programs :-)
It is possible to name the procedure or procedures you want to "trap" with the DECLARATIVES instead of using "ALL PROCEDURES".
You may have multiple DEBUGGING procedures, and you can include extensive code within them if you wish (setting up conditions for testing, for instance).
Although this feature has existed in COBOL for a long time, it is probably fair to say that it is not widely used, especially as specific "debugging products" became available.
It is not enough just to have this program, the "run time" needs to have DEBUG turned on, if it is not the default. The run-time on z/OS is called Language Environment and is shared by multiple languages (allowing easy inter-language communication). Languages include C/C++, PL/I and Java as well as COBOL. There are Language Environment routines and macros available to make HLASM/Assembler programs "LE Compliant" to also provide ready interfacing.
To see what run-time options your site has as default, the easiest thing to do is to include a CEEOPTS DD statement in your run JCL.
//CEEOPTS DD *
RPTOPTS(ON)
This will list out all the options used for your "Enclave" (your run environment) and indicate where each option is sourced from.
If, in the OPTION column, you see NODEBUG, then COBOL debugging is turned off by default. To turn it on for a particular run:
//CEEOPTS DD *
DEBUG
This will allow all the D-labelled debugging lines and the debugging DECLARATIVES to execute.
This will do what you want, but no-one will allow a program with debugging on into Production, so you can't use it for what you want.
In order of preference, I advise error-numbers (and testing), automation, hand-coded procedure-name literals.
IBM fully documents all its products, and you can find the documentation (Language Reference and Programming Guide amongst others) for Enterprise COBOL V4.2 and also Language Environment (several) for your release of z/OS.
One final point. Don't use GO TO to "break out" of your normal processing flow. Use PERFORM. Even when, logically, the PERFORM cannot return. Using GO TO will turn off compiler optimisation for paragraphs/SECTIONs containing the GO TO which can easily cause a noticeable impact on execution. This is the reverse of the advice from before IBM COBOL ensured that the state of PERFORMed paragraphs/SECTIONs is not preserved between CALLs. At that time the correct advice was to use GO TO. It is no longer the correct advice.
As you have the pseudo-code "something bad happened here" I assume an exception. In this case the standard (COBOL 2002, COBOL 2014) function EXCEPTION-LOCATION may help (although the actual string is implementor-defined I assume the paragraph may be in there [GnuCOBOL for example has the format: program-id; paragraph [or paragraph OF section or section, depending on your program]; source-line]).
If your COBOL compiler provides this information in this function and there is no exception in the offending part already: create one via subtract 1 from unsigned-var or similar.
As Bill already said (or implied): this is a question where the actual COBOL compiler used will be the most important part if you must have the names in as identifier and as label or not.
Edit (after the actual COBOL compiler is known):
IBM MVS Enterprise COBOL doesn't have the EXCEPTION-LOCATION function. Therefore I see only one built-in solution:
DECLARATIVES.
debug-declaratives SECTION.
USE FOR DEBUGGING ON ALL PROCEDURES.
debug-par.
MOVE debug-name TO current-procedure.
END DECLARATIVES.
But as this is only active if your program runs in debugging-mode (which may causes a lot of debugging messages to occur) I don't suggest to actual use this.
Try to use an Editor providing macros (or run a shell script on your actual source) to create the source you pass to the compiler afterwards.

Create a user assistant using NLP

I am following a course titled Natural Language Processing on Coursera, and while the course is informative, I wonder if the contents given cater to what am I looking for.Basically I want to implement a textual version of Cortana, or Siri for now as a project, i.e. where the user can enter commands for the computer in natural language and they will be processed and translated into appropriate OS commands. My question is
What is generally sequence of steps for the above applications, after processing the speech? Do they tag the text and then parse it, or do they have any other approach?
Under which application of NLP does it fall? Can someone cite me some good resources for same? My only doubt is that what I follow now, shall that serve any important part towards my goal or not?
What you want to create can be thought of as a carefully constrained chat-bot, except you are not attempting to hold a general conversation with the user, but to process specific natural language input and map it to specific commands or actions.
In essence, you need a tool that can pattern match various user input, with the extraction or at least recognition of various important topic or subject elements, and then decide what to do with that data.
Rather than get into an abstract discussion of natural language processing, I'm going to make a recommendation instead. Use ChatScript. It is a free open source tool for creating chat-bots that recently took first place in the Loebner chat-bot competition, as it has done so several times in the past:
http://chatscript.sourceforge.net/
The tool is written in C++, but you don't need to touch the source code to create NLP apps; just use the scripting language provided by the tool. Although initially written for chat-bots, it has expanded into an extremely programmer friendly tool for doing any kind of NLP app.
Most importantly, you are not boxed in by the philosophy of the tool or limited by the framework provided by the tool. It has all the power of most scripting languages so you won't find yourself going most of the distance towards your completing your app, only to find some crushing limitation during the last mile that defeats your app or at least cripples it severely.
It also includes a large number of ontologies that can jump-start significantly your development efforts, and it's built-in pre-processor does parts-of-speech parsing, input conformance, and many other tasks crucial to writing script that can easily be generalized to handle large variations in user input. It also has a full interface to the WordNet synset database. There are many other important features in ChatScript that make NLP development much easier, too many to list here. It can run on Linux or Windows as a server that can be accessed using a TCP-IP socket connection.
Here's a tiny and overly simplistic example of some ChatScript script code:
# Define the list of available devices in the user's household.
concept: ~available_devices( green_kitchen_lamp stove radio )
#! Turn on the green kitchen lamp.
#! Turn off that damn radio!
u: ( turn _[ on off ] *~2 _~available_devices )
# Save off the desired action found in the user's input. ON or OFF.
$action = _0
# Save off the name of the device the user wants to turn on or off.
$target_device = _1
# Launch the utility that turns devices on and off.
^system( devicemanager $action $target_device )
Above is a typical ChatScript rule. Your app will have many such rules. This rule is looking for commands from the user to turn various devices in the house on and off. The # character indicates a line is a comment. Here's a breakdown of the rule's head:
It consists of the prefix u:. This tells ChatScript a rule that the rule accepts user input in statement or question format.
It consists of the match pattern, which is the content between the parentheses. This match pattern looks for the word turn anywhere in the sentence. Next it looks for the desired user action. The square brackets tell ChatScript to match the word on or the word off. The underscore preceding the square brackets tell ChatScript to capture the matched text, the same way parentheses do in a regular expression. The ~2 token is a range restricted wildcard. It tells ChatScript to allow up to 2 intervening words between the word turn and the concept set named ~available_devices.
~available_devices is a concept set. It is defined above the rule and contains the set of known devices the user can turn on and off. The underscore preceding the concept set name tells ChatScript to capture the name of the device the user specified in their input.
If the rule pattern matches the current user input, it "fires" and then the rule's body executes. The contents of this rule's body is fairly obvious, and the comments above each line should help you understand what the rule does if fired. It saves off the desired action and the desired target device captured from the user's input to variables. (ChatScript variable names are preceded by a single or double dollar-sign.) Then it shells to the operating system to execute a program named devicemanager that will actually turn on or off the desired device.
I wanted to point out one of ChatScript's many features that make it a robust and industrial strength NLP tool. If you look above the rule you will see two sentences prefixed by a string consisting of the characters #!. These are not comments but are validation sentences instead. You can run ChatScript in verify mode. In verify mode it will find all the validation sentences in your scripts. It will then apply each validation sentence to the rule immediately following it/them. If the rule pattern does not match the validation sentence, an error message will be written to a log file. This makes each validation sentence a tiny, easy to implement unit test. So later when you make changes to your script, you can run ChatScript in verify mode and see if you broke anything.

Tex command which affects the next complete word

Is it possible to have a TeX command which will take the whole next word (or the next letters up to but not including the next punctuation symbol) as an argument and not only the next letter or {} group?
I’d like to have a \caps command on certain acronyms but don’t want to type curly brackets over and over.
First of all create your command, for example
\def\capsimpl#1{{\sc #1}}% Your main macro
The solution to catch a space or punctuation:
\catcode`\#=11
\def\addtopunct#1{\expandafter\let\csname punct#\meaning#1\endcsname\let}
\addtopunct{ }
\addtopunct{.} \addtopunct{,} \addtopunct{?}
\addtopunct{!} \addtopunct{;} \addtopunct{:}
\newtoks\capsarg
\def\caps{\capsarg{}\futurelet\punctlet\capsx}
\def\capsx{\expandafter\ifx\csname punct#\meaning\punctlet\endcsname\let
\expandafter\capsend
\else \expandafter\continuecaps\fi}
\def\capsend{\expandafter\capsimpl\expandafter{\the\capsarg}}
\def\continuecaps#1{\capsarg=\expandafter{\the\capsarg#1}\futurelet\punctlet\capsx}
\catcode`\#=12
#Debilski - I wrote something similar to your active * code for the acronyms in my thesis. I activated < and then \def<#1> to print the acronym, as well as the expansion if it's the first time it's encountered. I also went a bit off the deep end by allowing defining the expansions in-line and using the .aux files to send the expansions "back in time" if they're used before they're declared, or to report errors if an acronym is never declared.
Overall, it seemed like it would be a good idea at the time - I rarely needed < to be catcode 12 in my actual text (since all my macros were in a separate .sty file), and I made it behave in math mode, so I couldn't foresee any difficulties. But boy was it brittle... I don't know how many times I accidentally broke my build by changing something seemingly unrelated. So all that to say, be very careful activating characters that are even remotely commonly-used.
On the other hand, with XeTeX and higher unicode characters, it's probably a lot safer, and there are generally easy ways to type these extra characters, such as making a multi (or compose) key (I usually map either numlock or one of the windows keys to this), so that e.g. multi-!-! produces ¡). Or if you're running in emacs, you can use C-\ to switch into TeX input mode briefly to insert unicode by typing the TeX command for it (though this is a pain for actually typing TeX documents, since it intercepts your actual \'s, and please please don't try defining your own escape character!)
Regarding whitespace after commands: see package xspace, and TeX FAQ item Commands gobble following space.
Now why this is very difficult: as you noted yourself, things like that can only be done by changing catcodes, it seems. Catcodes are assigned to characters when TeX reads them, and TeX reads one line at a time, so you can not do anything with other spaces on the same line, IMHO. There might be a way around this, but I do not see it.
Dangerous code below!
This code will do what you want only at the end of the line, so if what you want is more "fluent" typing without brackets, but you are willing to hit 'return' after each acronym (and not run any auto-indent later), you can use this:
\def\caps{\begingroup\catcode`^^20 =11\mcaps}
\def\mcaps#1{\def\next##1 {\sc #1##1\catcode`^^20 =10\endgroup\ }\next}
One solution might be setting another character as active and using this one for escaping. This does not remove the need for a closing character but avoids typing the \caps macro, thus making it overall easier to type.
Therefore under very special circumstances, the following works.
\catcode`\*=\active
\def*#1*{\textsc{\MakeTextLowercase{#1}}}
Now follows an *Acronym*.
Unfortunately, this makes uses of \section*{} impossible without additional macro definitions.
In Xetex, it seems to be possible to exploit unicode characters for this, so one could define
\catcode`\•=\active
\def•#1•{\textsc{\MakeTextLowercase{#1}}}
Now follows an •Acronym•.
Which should reduce the effects on other commands but of course needs to have the character ‘•’ mapped to the keyboard somewhere to be of use.

Resources