Solved

Can Anyone Explain This Program line by line if you have patience .....

Posted on 2004-08-04
7
317 Views
Last Modified: 2010-04-15
Hi Guys

 This Code IS from Richard Stevens Book......




/* include readline */
#include        "unp.h"

static ssize_t
my_read(int fd, char *ptr)
{
        static int      read_cnt = 0;
        static char     *read_ptr;
        static char     read_buf[MAXLINE];

        if (read_cnt <= 0) {
again:
                if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
                        if (errno == EINTR)
                                goto again;
                        return(-1);
                } else if (read_cnt == 0)
                        return(0);
                read_ptr = read_buf;
        }

        read_cnt--;
        *ptr = *read_ptr++;
        return(1);
}

ssize_t
readline(int fd, void *vptr, size_t maxlen)
{
        int             n, rc;
        char    c, *ptr;

        ptr = vptr;
        for (n = 1; n < maxlen; n++) {
                if ( (rc = my_read(fd, &c)) == 1) {
                        *ptr++ = c;
                        if (c == '\n')
                                break;  /* newline is stored, like fgets() */
                } else if (rc == 0) {
                        if (n == 1)
                                return(0);      /* EOF, no data read */
                        else
                                break;          /* EOF, some data was read */
                } else
                        return(-1);             /* error, errno set by read() */
        }

        *ptr = 0;       /* null terminate like fgets() */
        return(n);
}
/* end readline */

ssize_t
Readline(int fd, void *ptr, size_t maxlen)
{
        ssize_t         n;

        if ( (n = readline(fd, ptr, maxlen)) < 0)
                err_sys("readline error");
        return(n);
}


help me

aman

0
Comment
Question by:amankhan
7 Comments
 

Author Comment

by:amankhan
ID: 11719109
Whats the main usage of static variables in that program....

aman
0
 
LVL 22

Expert Comment

by:grg99
ID: 11719234
Two, er THREE  probs:

(1)  I don't see ANY static vars in the code.

(2)  I don't see a program.

(2)  Sure sounds like homework.....

0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 11719956
When you invoke a function, any local variable (function local) is created on the fly, if this function is invoked many times, then this can make your program slower.
A static variable is like a global variable (never is destroyed until program ends) but in a local scope (the function, in this case)

So static variables can be used for 2 main purposes:
1.- To remember the previous value of the variable when function was invoked
2.- To avoid the variables to be created and destroyed every time the function is invoked

I think in your sample code static variables are used for both purposes:
- read_cnt will remember last value, so it keep count of last value the previous time my_read was invoked
- read_buf will be not created again and again when my_read is invoked, gaining some performance
 
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 23

Accepted Solution

by:
brettmjohnson earned 500 total points
ID: 11720512
It might be easier to read this program from the bottom up:

Readline() is little more than a very thin wrapper over readline(), adding
error reporting.  There is not much more to say about it.

readline() reads a line of text from the file opened on the file descriptor 'fd'
into the memory specified by 'ptr'.  At most 'maxlen' bytes will be read into
the buffer.  A 'line' is defined as a sequence of bytes terminated by the
ASCII NEWLINE character ('\n') or reaching 'maxlen' in length.  If the on-disk
line is physically longer than 'maxlen' then it will be read in 'maxlen'-sized chunks
on each subsequent call to readline().  The newline character, if found, is returned
in the buffer, so the caller knows if it read a full or partial line.  The returned
buffer of bytes is always terminated with a NUL byte ('\0').  readline returns the
number of bytes read into the buffer (not including the NUL terminator).

To assemble the line, readline() reads one byte at a time from the file by
calling my_read().  If it gets a byte back from my_read(), readline() places
that byte into its supplied buffer, then checks it to see if it was a newline,
allowing it to finish.  If no data was read, it returns 0 bytes read, indicating
an End-Of-File (EOF) condition.  As a comment in the code mentions, readline()
is behaving much like the system library function fgets(), so you can read
the documentation for fgets() for more details.

my_read() does 'buffered' file input from the file opened on descriptor 'fd'.
The function my_read() is declared static, so it is not visible outside of the C file
in which is is implemented (it's 'scope' is limited to the file).

Although my_read() one byte at a time from the files contents, for efficiency it
reads the file in larger chunks and caches the data in a internal buffer 'read_buf[]'.
Although not mentioned in the code snippet supplied, the sizeof read_buf[]
is probably a multiple of the disk block size (512, 1024, or 4096 bytes,
depending on OS and filesystem).  my_read() will read a buffer full of data from
the file, the return the buffer contents one byte at a time for each successive
call to my_read().  When the bytes in the read_buff[] are exhausted, my_read()
reads another chunk of the file in to its cache.

Note that between calls to my_read(), it needs to remember the cache of data it
has read in from the file, the next byte in that cache to return, and the number
of bytes left in the cache.  This information is stored in the variables, read_buf[],
read_ptr, and read_cnt, respectively.  However if these variables were local variables
to the my_read() function as follows, their values would not persist across successive
calls to my_read(), since the storage space for local variables is allocated from the stack
at function entry time:

static ssize_t
my_read(int fd, char *ptr)
{
       int      read_cnt = 0;
       char     *read_ptr;
       char     read_buf[MAXLINE];
      ...
}

To correct that problem, we could move the variables outside the scope of the
function, making them global.  This forces their storage to be allocated at compile
time, rather than function entry time, so their values persist.

int      read_cnt = 0;
char  *read_ptr;
char    read_buf[MAXLINE];

static ssize_t
my_read(int fd, char *ptr)
{
      ...
}

Unfortunately, although making the variables global allows their values to
persist between calls to my_read(), it also exposes the private workings of
my_read() to the outside world.  We could make the variables static, but
their placement still exposes the inner workings of my_read() to all the
other functions in the C file (only slightly better than exposing to the whole
world):

static int      read_cnt = 0;
static char  *read_ptr;
static char    read_buf[MAXLINE];

static ssize_t
my_read(int fd, char *ptr)
{
      ...
}

Using the 'static' keyword with a variable declared within the scope of a function
allows the function create storage that is allocated at compile time and is persistent
across calls like a global variable, but its 'scope' (ability to reference by name) is
limited to the confines of the function:

static ssize_t
my_read(int fd, char *ptr)
{
       static int      read_cnt = 0;
       static char  *read_ptr;
       static char    read_buf[MAXLINE];
      ...
}



BTW.  Use of a static buffer in this particular way is not particularly good
programming practice.  The function is not 're-entrant'.  Consider the case
where you want to read lines from two separate files (perhaps you are
comparing the two files).  Since my_read() only has a single buffer of
cached data, it doesn't know from which file the data was read.  So even
if you call my_read(fd2, ...), if there was cached bytes previously read from
fd1, my_read() will cheerfully return them.

A better choice is to attach the cached read buffer to each file descriptor
rather than using a single static buffer.  That is exactly what the FILE structure
in stdio.h does.

0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 11723199
read_cnt need not be a static variable.
read_buf is a local array, where the data read is getting stored. It's address will be given to pointer ptr, which will be used by the called function.
If read_buf is not a static variable, then once the function returns, the address stored in ptr will become invalid! To avoid this danger, read_buf is declared as static array.
The static pointer read_ptr is not at all needed. The address of read_buf can be directly assigned to ptr.

-ssnkumar
0
 
LVL 23

Expert Comment

by:brettmjohnson
ID: 11723267
ssnkumar,

You did not read the code carefully.  read_cnt and read_ptr MUST be static in this
implementation since they maintain the current read position and number of valid
bytes remaining within read_buf[] between calls to my_read().  See my explanation above.
Note that my_read() returns a single char read from the input stream, albeit in an
awkward manner compared to fgetc().

0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 11723317
I think that is correct.
I didn't read the code properly!:-(
Anyway, thanks for pointing out the mistake...

-ssnkumar
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now