Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is this implementation of fread in Chromium OS made of?

Tags:

c

libc

I was looking at the source code of fread in chromium-os / glibc and became increasingly puzzled about it.

NB: I am talking about the source code and NOT the use of fread or other related questions


Function prototype as a macro

First I was surprised about the way that fread is declared as a macro with its function name, followed by its arguments and finally its arguments' type:

/* Read NMEMB chunks of SIZE bytes each from STREAM into P.  */

size_t
DEFUN(fread, (p, size, nmemb, stream),
      PTR p AND size_t size AND size_t nmemb AND register FILE *stream)

What is the rationale behind this and why not

size_t fread(PTR p, size_t size, size_t nmemb, register FILE * stream)

which is much more readable?


What is __fillbf(register FILE *stream)

I was especially puzzled about this line:

int c = __fillbf(stream);

and could not find this function anywhere. I thought that it could be a system call that I don't already know about but it is not part of the table

So what is the real code behind __fill_bf(register FILE *) ?

Edit: Thanks to dyp for macro definition, Crowman for __fillbf and Ray for the nice synthesis of explanation!

ps: any answer with some extra explanations about the tricky parts of fread are also welcome!

like image 565
Antonin GAVREL Avatar asked Mar 01 '21 16:03

Antonin GAVREL


1 Answers

DEFUN

Before ANSI-standardization, function declaration had a different syntax:

ANSI-declaration:

int f(int x, double y) {
...
}

Pre-ANSI (K&R1) declaration:

f(x, y)
int x;
double y;
{
...
}

Macros like DEFUN are often defined for programs that may need to be compiled by very old compilers. (It's less common now, since ANSI standardization happened back in 1989.) There will be a file that defines macros one way if using ANSI/ISO C, and another way if using pre-ANSI C. (For chromiumos, that would be ansidecl.h.) DEFUN calls will thus expand into the appropriate decl format for the compiler being used.

__fillbf

As Crowman mentioned in the comments, the definition for __fillbf is in internals.c. It appears that it reads a block of characters into an internal buffer, so that fgetc can read one character at a time without needing to make a disk access each time.

like image 102
Ray Avatar answered Oct 24 '22 01:10

Ray