From:	HENRY::IN%"NED%ymir.bitnet%wiscvm.wisc.edu%sri-kl.ARPA%relay.cs.net@rca.com" 24-FEB-1987 13:32
To:	info-vax@SRI-KL.ARPA
Subj:	Problems and solutions for VAX C standard I/O

I have been working on porting Nelson Beebe's family of TeX previewers
to VMS using VAX C (yes, they seem to be working, no, I have not tested them
enough to be sure they work correctly). I have encountered two problems
and solutions while using VAX C that I thought would be of interest to this
group.
 
The first problem is the use of standard I/O functions on non-streamlf
files. In particular, I wanted to use the fseek function on files with
fixed length 512 byte records. (My set of .PXL files for TeX are written
in this format. I cannot change the format without breaking all of my other
DVI programs, and I do not want to have to duplicate 100,000 blocks of files.)
 
VAXCRTL is very clever and uses block I/O on streamlf files. When it sees
another file type it uses a fancy sort of record I/O instead. The result
is that fseek doesn't go where you want it to when using record I/O. I wanted
to FORCE C to use block I/O on a non-streamlf file. I could not find a way to
do this in the documentation, so I started perusing the ufiche and I found a
really neat feature.
 
It turns out that if you include the special attribute "ctx=stm" in a call
to fopen the file will be opened for block I/O UNCONDITIONALLY. For example:
 
    fd = fopen(filename,mode,"ctx=stm");
 
This will work for ANY sort of sequential file. Of course, if you open
a regular variable length record file you're going to get the record
length fields and all the other junk that's in there, but its just the
ticket for reading fixed length record files in a reasonable fashion.
 
The actual effect of this file attribute is to set some bit in the CTX field
of the file's RAB. This "user" field is used by C to store all sorts of
status bits.
 
This feature was added in November 1985, and my C manual is dated April
1985 (V2.0), so its not suprising that is does not appear in the documentation.
However, the release notes do not mention it either (at least not that I
can find). I presume that it will be documented in some future release,
or perhaps I simply missed seeing it (although I don't think so). I certainly
hope it doesn't disappear in some future release!
 
On to the second problem. Beebe's DVI converters use the ungetc standard
I/O function in several places. However, a nasty bug showed up in ungetc --
it cannot "push back" a character with an ASCII value above 127. Such
characters are ALL interpreted as EOF characters, and you cannot unget
an EOF (I don't know why but you cannot). This behavior is not documented
as far as I can see, and it certainly does not correspond to ungetc in most
other C implementations.
 
I pondered this for a while and finally decided to write my own ungetc that
would work with any character.  A listing of this routine is given below.
I had to diddle an assortment of internal C data structures so the routine
may break in some future release, but it works fine with V2.2 of C.
 
                                Ned Freed
                                ned@ymir.bitnet
 
--------------------------------------------------------------------------
 
        .title  vmsungetc - Replacement for VAX C ungetc routine
 
        $FABDEF
 
        fcb_l_buffcnt = 0
        fcb_l_buffptr = 4
        fcb_l_buffadr = 8
 
        .entry  vmsungetc,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
 
        movl    8(ap),r7
        movl    (r7),r7
        movl    fcb_l_buffptr(r7),r1
        cmpl    r1,fcb_l_buffadr(r7)
        bleq    10$
        movb    4(ap),-(r1)
        movl    r1,fcb_l_buffptr(r7)
        incl    fcb_l_buffcnt(r7)
10$:    ret
 
        .end
