• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 364
  • Last Modified:

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

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
amankhan
Asked:
amankhan
1 Solution
 
amankhanAuthor Commented:
Whats the main usage of static variables in that program....

aman
0
 
grg99Commented:
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
 
Jaime OlivaresSoftware ArchitectCommented:
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
Creating Active Directory Users from a Text File

If your organization has a need to mass-create AD user accounts, watch this video to see how its done without the need for scripting or other unnecessary complexities.

 
brettmjohnsonCommented:
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
 
ssnkumarCommented:
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
 
brettmjohnsonCommented:
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
 
ssnkumarCommented:
I think that is correct.
I didn't read the code properly!:-(
Anyway, thanks for pointing out the mistake...

-ssnkumar
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Protect Your Employees from Wi-Fi Threats

As Wi-Fi growth and popularity continues to climb, not everyone understands the risks that come with connecting to public Wi-Fi or even offering Wi-Fi to employees, visitors and guests. Download the resource kit to make sure your safe wherever business takes you!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now