Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!rutgers!labrea!aurora!ames!sdcsvax!ucbvax!YALE.ARPA!LEICHTER-JERRY From: LEICHTER-JERRY@YALE.ARPA Newsgroups: comp.os.vms Subject: Re: Command input from a file continued, and maybe a bug in VMS Message-ID: <8708092055.AA19459@ucbvax.Berkeley.EDU> Date: Sun, 9-Aug-87 16:56:05 EDT Article-I.D.: ucbvax.8708092055.AA19459 Posted: Sun Aug 9 16:56:05 1987 Date-Received: Sun, 9-Aug-87 22:52:31 EDT Sender: daemon@ucbvax.BERKELEY.EDU Reply-To: Distribution: world Organization: The ARPA Internet Lines: 89 ... I want something like the DCL @ command: If the command is @filespec, the command interpreters should open this file, and present it (line by line) to CLI$DCL_PARSE and other routines, which read special input from a terminal. ... Several fellow netpeople pointed me towards the LIB$SET_LOGICAL routine, which seems to do what I want.... [I wrote a] short FORTRAN program [that] should read one line from the terminal, print it, and then redirect SYS$INPUT to the file INPUT.FILE, read one line from there, print it, and exit: [The program works as described, using LIB$GET_INPUT to read lines. It ends up reading entirely from the terminal, or entirely from the file.] [W]hat counts for LIB$INPUT is not the translation of SYS$INPUT at the time you call it, but AT THE TIME THE PROGRAM WAS INVOKED.... The only question is: Why is this so ? What use is LIB$SET_LOGICAL in this case ? Is this a bug ? Should i SPR it ? Am i stupid ? Is there something tricky (maybe using the right logical name table) i overlooked ? The logic of LIB$GET_INPUT is simple: declare statically-allocated CHANNEL declare statically-allocated FILE_OPEN = FALSE if (not FILE_OPEN) CHANNEL = OPEN("SYS$INPUT:") FILE_OPEN = TRUE read-line-from-CHANNEL return-line-so-read Thus, what matters to LIB$GET_INPUT is what SYS$INPUT pointed to at the time LIB$GET_INPUT was first called. The reason it does this is two-fold: - Opening a file is slow process, and not one you want to repeat for every line of input; - If SYS$INPUT were to point to a file on a disk, then re-opening each time would be not just slow, but WRONG: Each time you open the file, you are positioned to the first line! LIB$GET_INPUT has no way of tracking assignments you do to SYS$INPUT after the file is open, nor does RMS ever do that for an opened file. This kind of dynamic re-assignment works within DCL only as the result of a special-case hack, added in V4.0: Since user programs want to re-assign logicals in supervisor mode, they have to ask DCL to do it for them. That's what LIB$SET_LOGICAL does that using the VMS $CRELNM cannot do for you. Similarly, when you type ASSIGN or DEFINE to DCL, it obviously "has its hands on" the assignments. Hence, it's in a position to check for any logical names of special interest to it, and treat them accordingly. The names it watches for are, I think, SYS$INPUT and SYS$OUTPUT: DCL itself has channels open on those files, and will re-open them when it seems those logicals being changed. This special-case treatment as added to avoid some anomolies that could make VMS look very puzzling in earlier versions. (Not that it can't look very puzzling now!) This IS special-case treatment, however, and does NOT genere- lize. The correct general principle is: Logical names are used for FINDING files (at OPEN time), NOT for accessing them (at READ, WRITE time). As for your original problem: Sorry, there's no direct, doesn't-change-any- of-the-code solution I'm aware of. The "supported" approach is to write your own routine that reads lines from wherever you want them to come from, and pass its address to the routines you are using that are currently calling LIB$GET_INPUT by default. (I haven't by any means gone through the list, but I think all the RTL routines work that way: LIB$GET_INPUT is a default, not the only option.) Simply writing your own LIB$GET_INPUT doesn't work: While routines that YOU write would use it, the RTL routines are in pre-linked shareable images; their code is already tied to the "real" LIB$GET_INPUT, which is also in the shared image. In fact, since this would give you TWO LIB$GET_INPUT's, the Linker is going to get unhappy. A "hack" solution someone might suggest is to over-write the LIB$GET_INPUT vector to point to your replacement routine. Unfortunately, even this won't work: Calls within the same shareable image as LIB$GET_INPUT will have been resolved to the actual entry point, not the vector. (See the discussion of transfer vectors in either the Linker or MACRO books.) -- Jerry -------