Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

file handles and fcbs

4 views
Skip to first unread message

jhking

unread,
Apr 8, 2005, 10:20:24 PM4/8/05
to
A normal c library uses file handles. CP/M uses FCBs instead. From
looking at the Aztec C runtime it appeared they allocated some memory
for FCBs and when the program ended they went through those FCBs and
closed them all. Should we adopt a similar strategy?
My suspicion is that mapping FCBs to file handles and treating CON: and
KBD: like files will probably be our 2 biggest translation hurdles.
If you've got ideas on file handling speak up!

CBFalconer

unread,
Apr 9, 2005, 3:05:12 AM4/9/05
to

The only logical difference between FCBs and handle mechanisms is
where are the actual FCBs stored. A handle mechanism assigns space
in the OS for them, which facilitates keeping track of their
status, but eats up memory and limits the number of files that can
be open. The cost of an FCB system is basically that any FCB must
be initialized properly. With handles that is done at the time of
the creation of the space in the OS.

With the memory protection levels of CP/M (and MsDos) there is
never any guarantee that the status defining bits in an FCB are
valid.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson

s_dub...@yahoo.com

unread,
Apr 10, 2005, 10:45:53 PM4/10/05
to

jhking wrote:
> A normal c library uses file handles. CP/M uses FCBs instead. From

> looking at the Aztec C runtime it appeared they allocated some memory

> for FCBs and when the program ended they went through those FCBs and
> closed them all. Should we adopt a similar strategy?

Probably. Definitely the open modified files must be closed to flush
the writes to disk.

DRI C allocates the FILES structues at compile time. See STDIO.H

#include <portab.h> /* Portability Definitions */
/* */
/****************************************************************************
* Stream I/O File Definitions
*****************************************************************************/
#define BUFSIZ 512 /* Standard (ascii) buf size */
#define MAXFILES 16 /* Max # open files ( < 32 ) */
struct _iobuf { /* */
WORD _fd; /* file descriptor for low level io */
WORD _flag; /* stream info flags */
BYTE *_base; /* base of buffer */
BYTE *_ptr; /* current r/w pointer */
WORD _cnt; /* # chars to be read/have been wrt */
}; /* */
#ifndef FILE /* conditionally include: */
extern struct _iobuf _iob[MAXFILES]; /* an array of this info */
#define FILE struct _iobuf /* stream definition */
#endif /************************************/
/* flag byte definition */
#define _IOREAD 0x01 /* readable file */
#define _IOWRT 0x02 /* writeable file */
#define _IOABUF 0x04 /* alloc'd buffer */
#define _IONBUF 0x08 /* no buffer */
#define _IOERR 0x10 /* error has occurred */
#define _IOEOF 0x20 /* EOF has occurred */
#define _IOLBUF 0x40 /* handle as line buffer */
#define _IOSTRI 0x80 /* this stream is really a string */
#define _IOASCI 0x100 /* this was opened as an ascii file */
/************************************/
#define stdin (&_iob[0]) /* standard input stream */
#define stdout (&_iob[1]) /* " output " */
#define stderr (&_iob[2]) /* " error " */
/************************************/
#define clearerr(p) ((p)->_flag &= ~_IOERR) /* clear error flag */
#define feof(p) ((p)->_flag & _IOEOF) /* EOF encountered on stream
*/
#define ferror(p) ((p)->_flag & _IOERR) /* error encountered on stream
*/
#define fileno(p) ((p)->_fd) /* get stream's file descriptor */
#define getchar() getc(stdin) /* get char from stdin */
#define putchar(c) putc(c,stdout) /* put char to stdout */
#define putc fputc
#define getc fgetc


The FILE handle is an index number into an array of _iobuf structure.
The implementing code is locked up in the library, but looks guessable
since the functions mostly resolve to getc & putc.

> My suspicion is that mapping FCBs to file handles and treating CON:
and
> KBD: like files will probably be our 2 biggest translation hurdles.
> If you've got ideas on file handling speak up!

I think this file handling seems reasonable, perhaps adding a

#define _MUSTFLUSH 0x200 /* record changed must update */

to check .ATEXIT. I don't know if this functionality is already
covered
in the library, it should be.

Steve

CBFalconer

unread,
Apr 11, 2005, 12:24:40 AM4/11/05
to
s_dub...@yahoo.com wrote:
> jhking wrote:
>
>> A normal c library uses file handles. CP/M uses FCBs instead.
>> From looking at the Aztec C runtime it appeared they allocated
>> some memory for FCBs and when the program ended they went through
>> those FCBs and closed them all. Should we adopt a similar strategy?
>
> Probably. Definitely the open modified files must be closed to
> flush the writes to disk.
>
> DRI C allocates the FILES structues at compile time. See STDIO.H

IIRC my PascalP, when installed under CP/M, used the disk field of
the FCB to identify the device. After allowing for user values in
the upper 3 bits (0 to 7) there could be 32 device ids. 0 was
reserved for the null file, while 1 through a small number
described devices (con, kbd, aux, lst, etc.) conin and conout
could be redirected on the command line. The result was a small
set of tables in the system:

devnames
fopentbl
fclosetbl
fwritetbl
freadtbl
fstatustbl

where everything except the names table pointed to routines to
handle the calls. The system included a fileinit function, which
was automatically called when a file type was declared, and
initialized the FCB (and some auxiliary fields added to it). Since
the compiler knew when a file type was declared it could generate
the call to fileinit, and it could also call the fclose operation
when the file (and thus the FCB storage) went out of scope.

The kbd device file was used for non-echoing input. A different
device could use the interrupt system, and fileopen started it up.

The exception to this simplicity was when arrays of files were
declared, or files were components of records (struct in C).

It all worked cleanly. My embedded systems included such devices
as LANs, AtoD and DtoA converters, etc. I suspect I have omitted
some critical details above.

s_dub...@yahoo.com

unread,
Apr 11, 2005, 6:13:24 PM4/11/05
to
That does look like a clean design, each device is treated naturally as
a file. Roughly, how long was the development time for your PascalP
for cp/m? And, also, roughly, how long did the EXE version take to do?

CBFalconer

unread,
Apr 11, 2005, 9:36:24 PM4/11/05
to

It was all done by about 1981, but some improvements were made in
the next few years. Things started about 1977 or so. The primary
purpose was embedded machinery in the medical world. Unfortunately
almost everything go lost in a disk crash a few years ago. You can
find remnants on my site (see the organization header of this
message) including a compiler port, and enough to run things on
CP/M emulators. The source of the three back ends is gone, which
created code for the 8080, for a P-machine, or for the HP3000. The
port to the 8086 was never finished. I still have printouts of the
source to the 8080 p-machine interpreter, which includes the file
system.

0 new messages