pike.git / src / modules / Pipe / pipe.c

version» Context lines:

pike.git/src/modules/Pipe/pipe.c:1: + /* + || This file is part of Pike. For copyright information see COPYRIGHT. + || Pike is distributed under GPL, LGPL and MPL. See the file COPYING + || for more information. + || This module has been deprecated. + */ +    #include "global.h"   #include "config.h" - #include "machine.h" + #include "module.h" + #include "threads.h" + #include "stralloc.h" + #include "pike_macros.h" + #include "object.h" + #include "constants.h" + #include "interpret.h" + #include "svalue.h" + #include "pike_error.h" + #include "builtin_functions.h" + #include "fdlib.h"      #include <sys/types.h>   #include <sys/stat.h>      #ifdef HAVE_SYS_FILE_H   #include <sys/file.h>   #endif /* HAVE_SYS_FILE_H */      #include <errno.h>    -  + /* Some <sys/mman.h>'s (eg AIX 5L/ia64) contain a #define of MAP_VARIABLE +  * for use as the opposite of MAP_FIXED. +  * +  * "program.h" above has a conflicting definition of MAP_VARIABLE. +  */ + #undef MAP_VARIABLE +    #ifdef HAVE_SYS_MMAN_H   #include <sys/mman.h>   #else   #ifdef HAVE_LINUX_MMAN_H   #include <linux/mman.h>   #else   #ifdef HAVE_MMAP   /* sys/mman.h is _probably_ there anyway. */   #include <sys/mman.h>   #endif   #endif   #endif      #ifdef HAVE_SYS_ID_H   #include <sys/id.h>   #endif /* HAVE_SYS_ID_H */      #include <fcntl.h>    - RCSID("$Id: pipe.c,v 1.46 2001/09/24 11:58:28 grubba Exp $"); +     - #include "threads.h" - #include "stralloc.h" - #include "pike_macros.h" - #include "object.h" - #include "constants.h" - #include "interpret.h" - #include "svalue.h" - #include "pike_error.h" - #include "builtin_functions.h" - #include "fdlib.h" -  +    #ifndef S_ISREG   #ifdef S_IFREG   #define S_ISREG(mode) (((mode) & (S_IFMT)) == (S_IFREG))   #else   #define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))   #endif   #endif    - /* must be included last */ - #include "module_magic.h" +     -  + #define sp Pike_sp      /*   #define PIPE_STRING_DEBUG   #define PIPE_MMAP_DEBUG   #define PIPE_FILE_DEBUG   #define BLOCKING_CLOSE   */      #ifndef SEEK_SET   #ifdef L_SET
pike.git/src/modules/Pipe/pipe.c:89:   #define INSISTANT_WRITE   #endif      #ifndef MAP_FILE   # define MAP_FILE 0   #endif      #define READ_BUFFER_SIZE 65536   #define MAX_BYTES_IN_BUFFER 65536    - /* -  * usage: -  * single socket output -  * or regular file output and (multiple, adding) socket output -  * with no mmap input -  * -  * multiple socket output without regular file output illegal + /*! @module Pipe +  *! +  *! Single socket output. +  *! +  *! Regular file output and (multiple, adding) socket output +  *! with no mmap input. +  *! +  *! Multiple socket output without regular file output illegal.    */      static struct program *pipe_program, *output_program;      #ifdef THIS   #undef THIS   #endif   #define THIS ((struct pipe *)(Pike_fp->current_storage))   #define THISOBJ (Pike_fp->current_object)   
pike.git/src/modules/Pipe/pipe.c:143:    struct object *next;    struct pipe *the_pipe;   };      struct buffer   {    struct pike_string *s;    struct buffer *next;   };    + /*! @class pipe +  *! +  *! Concatenation pipe. +  */ +    struct pipe   {    int living_outputs; /* number of output objects */       struct svalue done_callback;    struct svalue output_closed_callback;    struct svalue id;       /*    * if fd is -1: use fd
pike.git/src/modules/Pipe/pipe.c:188:   void close_and_free_everything(struct object *o,struct pipe *);   static INLINE void output_finish(struct object *obj);   static INLINE void output_try_write_some(struct object *obj);      /********** internal ********************************************************/      /* Push a callback to this object given the internal function number.    */   static void push_callback(ptrdiff_t no)   { -  add_ref(Pike_sp->u.object=THISOBJ); -  Pike_sp->subtype = DO_NOT_WARN(no + Pike_fp->context.identifier_level); -  Pike_sp->type = T_FUNCTION; +  SET_SVAL(*Pike_sp, T_FUNCTION, +  DO_NOT_WARN(no + Pike_fp->context->identifier_level), +  object, THISOBJ); +  add_ref(THISOBJ);    Pike_sp++;   }      /* Allocate a new struct input, link it last in the linked list */   static INLINE struct input *new_input(void)   {    struct input *i;    ninputs++;    i=ALLOC_STRUCT(input);    i->type=I_NONE;
pike.git/src/modules/Pipe/pipe.c:252: Inside #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
  #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)    munmap(i->u.mmap,i->len);    mmapped -= i->len;   #else    Pike_error("I_MMAP input when MMAP is diabled!");   #endif    break;       case I_NONE: break;    } -  free((char *)i); +  free(i);   }      /* do the done_callback, then close and free everything */   static INLINE void pipe_done(void)   { -  if (THIS->done_callback.type!=T_INT) +  if (TYPEOF(THIS->done_callback) != T_INT)    {    assign_svalue_no_free(sp++,&THIS->id);    apply_svalue(&(THIS->done_callback),1);    pop_stack();       if(!THISOBJ->prog) /* We will not free anything in this case. */    return;    /* Pike_error("Pipe done callback destructed pipe.\n"); */    }    close_and_free_everything(THISOBJ,THIS);
pike.git/src/modules/Pipe/pipe.c:299:    */   static INLINE int append_buffer(struct pike_string *s)    /* 1=buffer full */   {    struct buffer *b;       debug_malloc_touch(s);       if(THIS->fd!= -1)    { -  fd_lseek(THIS->fd, THIS->pos, SEEK_SET); -  fd_write(THIS->fd, s->str, s->len); +  ptrdiff_t len = s->len; +  char *data = s->str; +  ptrdiff_t bytes; +  +  while ((fd_lseek(THIS->fd, THIS->pos, SEEK_SET) < 0) && (errno == EINTR)) +  ; +  while (len > 0) { +  do { +  bytes = fd_write(THIS->fd, data, len); +  } while ((bytes < 0) && (errno == EINTR)); +  if (bytes < 0) break; +  data += bytes; +  len -= bytes; +  }    THIS->pos+=s->len;    return 0;    }    else    {    nbuffers++;    b=ALLOC_STRUCT(buffer);    b->next=NULL;    b->s=s;    sbuffers += s->len;
pike.git/src/modules/Pipe/pipe.c:370:      /* Read some data from the blocking object.    *    */   static int read_some_data(void)   {    struct pipe *this = THIS;    struct input * i = this->firstinput;       if (!i || i->type != I_BLOCKING_OBJ) { -  fatal("PIPE: read_some_data(): Bad input type!\n"); +  Pike_fatal("PIPE: read_some_data(): Bad input type!\n");    return -1;    }    push_int(8192);    push_int(1); /* We don't care if we don't get all 8192 bytes. */    apply(i->u.obj, "read", 2); -  if ((sp[-1].type == T_STRING) && (sp[-1].u.string->len > 0)) { +  if ((TYPEOF(sp[-1]) == T_STRING) && (sp[-1].u.string->len > 0)) {    append_buffer(sp[-1].u.string);    pop_stack();    THIS->sleeping = 1;    return(1); /* Success */    }       /* FIXME: Should we check the return value here? */    pop_stack();    /* EOF */    return(0); /* EOF */
pike.git/src/modules/Pipe/pipe.c:450:   static INLINE struct pike_string* gimme_some_data(size_t pos)   {    struct buffer *b;    ptrdiff_t len;    struct pipe *this = THIS;       /* We have a file cache, read from it */    if (this->fd!=-1)    {    char buffer[READ_BUFFER_SIZE]; +  ptrdiff_t sz = this->pos-pos;    -  if (this->pos<=pos) return NULL; /* no data */ -  len=this->pos-pos; -  if (len>READ_BUFFER_SIZE) len=READ_BUFFER_SIZE; +  if (sz <= 0) return NULL; /* no data */ +  if (sz > READ_BUFFER_SIZE) sz = READ_BUFFER_SIZE;    THREADS_ALLOW(); -  fd_lseek(this->fd, pos, SEEK_SET); +  while ((fd_lseek(this->fd, pos, SEEK_SET) < 0) && (errno == EINTR)) +  ;    THREADS_DISALLOW();    do {    THREADS_ALLOW(); -  len = fd_read(this->fd, buffer, len); +  len = fd_read(this->fd, buffer, sz);    THREADS_DISALLOW();    if (len < 0) {    if (errno != EINTR) {    return(NULL);    } -  +  check_threads_etc();    }    } while(len < 0);    /*    * FIXME: What if len is 0?    */    return make_shared_binary_string(buffer,len);    }       if (pos<this->pos)    return make_shared_string("buffer underflow"); /* shit */
pike.git/src/modules/Pipe/pipe.c:489:    /* Free the first buffer, and update THIS->pos */    b=this->firstbuffer;    this->pos+=b->s->len;    this->bytes_in_buffer-=b->s->len;    this->firstbuffer=b->next;    if (!b->next)    this->lastbuffer=NULL;    sbuffers-=b->s->len;    nbuffers--;    free_string(b->s); -  free((char *)b); +  free(b);       /* Wake up first input if it was sleeping and we    * have room for more in the buffer.    */    if (this->sleeping &&    this->firstinput &&    this->bytes_in_buffer<MAX_BYTES_IN_BUFFER)    {    if (this->firstinput->type == I_BLOCKING_OBJ) {    if (!read_some_data()) {
pike.git/src/modules/Pipe/pipe.c:659:    out->mode=O_SLEEP;    }    return;    }    len=s->len;    push_string(s);    apply_low(out->obj,out->write_offset,1);    out->mode=O_RUN;       ret=-1; -  if(sp[-1].type == T_INT) ret=sp[-1].u.integer; +  if(TYPEOF(sp[-1]) == T_INT) ret=sp[-1].u.integer;    pop_stack();       if (ret==-1) /* error, byebye */    {    output_finish(obj);    return;    }    out->pos+=ret;    THIS->sent+=ret;      #ifdef INSISTANT_WRITE    } while(ret == len);   #endif   }      /********** methods *********************************************************/    - /* Add an input to this pipe */ + /*! @decl void input(object obj) +  *! +  *! Add an input file to this pipe. +  */   static void pipe_input(INT32 args)   {    struct input *i;    int fd=-1; /* Per, one less warning to worry about... */    struct object *obj;    -  if (args<1 || sp[-args].type != T_OBJECT) +  if (args<1 || TYPEOF(sp[-args]) != T_OBJECT)    Pike_error("Bad/missing argument 1 to pipe->input().\n");       obj=sp[-args].u.object;    if(!obj || !obj->prog)    Pike_error("pipe->input() on destructed object.\n");       push_int(0);    apply(sp[-args-1].u.object,"set_id", 1);    pop_stack();   
pike.git/src/modules/Pipe/pipe.c:706: Inside #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
     #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)       /* We do not handle mmaps if we have a buffer */    if(THIS->fd == -1)    {    char *m;    struct stat s;       apply(obj, "query_fd", 0); -  if(sp[-1].type == T_INT) fd=sp[-1].u.integer; +  if(TYPEOF(sp[-1]) == T_INT) fd=sp[-1].u.integer;    pop_stack();       if (fd != -1 && fstat(fd,&s)==0)    { -  int filep=fd_lseek(fd, 0L, SEEK_CUR); /* keep the file pointer */ +  off_t filep=fd_lseek(fd, 0L, SEEK_CUR); /* keep the file pointer */ +  size_t len = s.st_size - filep;    if(S_ISREG(s.st_mode) /* regular file */ -  && ((long)(m=(char *)mmap(0,s.st_size - filep,PROT_READ, -  MAP_FILE|MAP_SHARED,fd,filep))!=-1)) +  && ((m=(char *)mmap(0, len, PROT_READ, +  MAP_FILE|MAP_SHARED,fd,filep))+1))    { - #ifdef HAVE_GETEUID -  int ou = 0; - #endif -  mmapped += s.st_size; +  mmapped += len;       i->type=I_MMAP; -  i->len=s.st_size; +  i->len = len;    i->u.mmap=m;   #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL)    /* Mark the pages as sequential read only access... */ -  -  /* NOTE: -  * -  * Potential race-condition with other threads -  */ -  - #ifdef HAVE_GETEUID -  if((ou=geteuid()) && !getuid()) { - #ifdef HAVE_SETEUID -  seteuid(0); - #else /* ! HAVE_SETEUID */ - #ifdef HAVE_SETRESUID -  setresuid(-1, 0, -1); - #endif /* HAVE_SETRESUID */ - #endif /* HAVE_SETEUID */ -  } +  madvise(m, len, MADV_SEQUENTIAL);   #endif -  madvise(m, s.st_size, MADV_SEQUENTIAL); - #ifdef HAVE_GETEUID -  if(ou) { - #ifdef HAVE_SETEUID -  seteuid(ou); - #else /* ! HAVE_SETEUID */ - #ifdef HAVE_SETRESUID -  setresuid(-1, ou, -1); - #endif /* HAVE_SETRESUID */ - #endif /* HAVE_SETEUID */ -  } - #endif - #endif +     pop_n_elems(args);    push_int(0);    return;    }    }    }   #endif       i->u.obj=obj;    nobjects++;
pike.git/src/modules/Pipe/pipe.c:819:    push_int(0);    push_callback(offset_input_close_callback);    apply_low(i->u.obj,i->set_nonblocking_offset,3);    pop_stack();    }       pop_n_elems(args);    push_int(0);   }    + /*! @decl void write(string bytes) +  *! +  *! Add an input string to this pipe. +  */   static void pipe_write(INT32 args)   {    struct input *i;    -  if (args<1 || sp[-args].type!=T_STRING) +  if (args<1 || TYPEOF(sp[-args]) != T_STRING)    Pike_error("illegal argument to pipe->write()\n");       if (!THIS->firstinput)    {    append_buffer(sp[-args].u.string);    pop_n_elems(args);    push_int(0);    return;    }       i=new_input();    i->type=I_STRING;    nstrings++;    add_ref(i->u.str=sp[-args].u.string);    pop_n_elems(args-1);   }      void f_mark_fd(INT32 args);    -  + /*! @decl void output(object obj, int|void start_pos) +  *! +  *! Add an output file object. +  */   static void pipe_output(INT32 args)   {    struct object *obj;    struct output *o;    int fd;    struct stat s;    struct buffer *b;       if (args<1 || -  sp[-args].type != T_OBJECT || +  TYPEOF(sp[-args]) != T_OBJECT ||    !sp[-args].u.object ||    !sp[-args].u.object->prog)    Pike_error("Bad/missing argument 1 to pipe->output().\n");       if (args==2 && -  sp[1-args].type != T_INT) +  TYPEOF(sp[1-args]) != T_INT)    Pike_error("Bad argument 2 to pipe->output().\n");       if (THIS->fd==-1) /* no buffer */    {    /* test if usable as buffer */    apply(sp[-args].u.object,"query_fd",0);    -  if ((sp[-1].type==T_INT) +  if ((TYPEOF(sp[-1]) == T_INT)    && (fd=sp[-1].u.integer)>=0    && (fstat(fd,&s)==0)    && S_ISREG(s.st_mode)    && (THIS->fd=fd_dup(fd))!=-1 )    {    /* keep the file pointer of the duped fd */    THIS->pos=fd_lseek(fd, 0L, SEEK_CUR);    - #if 0 -  /* This won't work if the spider-module is dynamically linked. */ -  push_int(THIS->fd); -  push_string(make_shared_string("pipe.c: file buffer")); -  f_mark_fd(2); -  pop_stack(); - #endif /* 0 */ -  +     THIS->living_outputs++;       while (THIS->firstbuffer)    { -  +  ptrdiff_t len; +  char *data;    b=THIS->firstbuffer;    THIS->firstbuffer=b->next; -  fd_lseek(THIS->fd, THIS->pos, SEEK_SET); -  fd_write(THIS->fd,b->s->str,b->s->len); +  while ((fd_lseek(THIS->fd, THIS->pos, SEEK_SET) < 0) && +  (errno == EINTR)) +  ; +  +  len = b->s->len; +  data = b->s->str; +  while (len > 0) { +  ptrdiff_t bytes; +  do { +  bytes = fd_write(THIS->fd, data, len); +  } while((bytes < 0) && (errno == EINTR)); +  if (bytes < 0) break; +  len -= bytes; +  data += bytes; +  } +     sbuffers-=b->s->len;    nbuffers--;    free_string(b->s); -  free((char *)b); +  free(b);    }    THIS->lastbuffer=NULL;       /* keep the file pointer of the duped fd    THIS->pos=0; */    push_int(0);    apply(sp[-args-2].u.object,"set_id", 1);    pop_n_elems(args+2); /* ... and from apply x 2 */    return;    }
pike.git/src/modules/Pipe/pipe.c:959:       push_int(0);    push_callback(offset_output_write_callback);    push_callback(offset_output_close_callback);    apply_low(o->obj,o->set_nonblocking_offset,3);    pop_stack();       pop_n_elems(args-1);   }    + /*! @decl void set_done_callback(void|function(mixed:mixed) done_cb, @ +  *! void|mixed id) +  *! +  *! Set the callback function to be called when all the outputs +  *! have been sent. +  */   static void pipe_set_done_callback(INT32 args)   {    if (args==0)    {    free_svalue(&THIS->done_callback); -  THIS->done_callback.type=T_INT; +  SET_SVAL_TYPE(THIS->done_callback, T_INT);    return;    } -  if (args<1 || (sp[-args].type!=T_FUNCTION && sp[-args].type!=T_ARRAY)) +  if (args<1 || (TYPEOF(sp[-args]) != T_FUNCTION && +  TYPEOF(sp[-args]) != T_ARRAY))    Pike_error("Illegal argument to set_done_callback()\n");       if (args>1)    {    free_svalue(&THIS->id);    assign_svalue_no_free(&(THIS->id),sp-args+1);    }       free_svalue(&THIS->done_callback);    assign_svalue_no_free(&(THIS->done_callback),sp-args);    pop_n_elems(args-1);   }    -  + /*! @decl void set_output_closed_callback(void|function(mixed, object:mixed) close_cb, @ +  *! void|mixed id) +  *! +  *! Set the callback function to be called when one of the outputs has +  *! been closed from the other side. +  */   static void pipe_set_output_closed_callback(INT32 args)   {    if (args==0)    {    free_svalue(&THIS->output_closed_callback); -  THIS->output_closed_callback.type=T_INT; +  SET_SVAL_TYPE(THIS->output_closed_callback, T_INT);    return;    } -  if (args<1 || (sp[-args].type!=T_FUNCTION && sp[-args].type!=T_ARRAY)) +  if (args<1 || (TYPEOF(sp[-args]) != T_FUNCTION && +  TYPEOF(sp[-args]) != T_ARRAY))    Pike_error("Illegal argument to set_output_closed_callback()\n");       if (args>1)    {    free_svalue(&THIS->id);    assign_svalue_no_free(&(THIS->id),sp-args+1);    }    free_svalue(&THIS->output_closed_callback);    assign_svalue_no_free(&(THIS->output_closed_callback),sp-args);    pop_n_elems(args-1);   }    -  + /*! @decl void finish() +  *! +  *! Terminate and reinitialize the pipe. +  */   static void pipe_finish(INT32 args)   {    pop_n_elems(args);    push_int(0);    pipe_done();   }    -  + /*! @decl void start() +  *! +  *! Start sending the input(s) to the output(s). +  */   static void pipe_start(INT32 args) /* force start */   {    low_start();    if(args)    pop_n_elems(args-1);   }    -  + /*! @decl int bytes_sent() +  *! +  *! Return the number of bytes sent. +  */   static void f_bytes_sent(INT32 args)   {    pop_n_elems(args);    push_int(THIS->sent);   }      /********** callbacks *******************************************************/      static void pipe_write_output_callback(INT32 args)   { -  if (args<1 || sp[-args].type!=T_OBJECT) +  if (args<1 || TYPEOF(sp[-args]) != T_OBJECT)    Pike_error("Illegal argument to pipe->write_output_callback\n");       if(!sp[-args].u.object->prog) return;       if(sp[-args].u.object->prog != output_program)    Pike_error("Illegal argument to pipe->write_output_callback\n");       debug_malloc_touch(sp[-args].u.object);    output_try_write_some(sp[-args].u.object);    pop_n_elems(args-1);   }      static void pipe_close_output_callback(INT32 args)   {    struct output *o; -  if (args<1 || sp[-args].type!=T_OBJECT) +  if (args<1 || TYPEOF(sp[-args]) != T_OBJECT)       if(!sp[-args].u.object->prog) return;       if(sp[-args].u.object->prog != output_program)    Pike_error("Illegal argument to pipe->close_output_callback\n");       o=(struct output *)(sp[-args].u.object->storage);    -  if (THIS->output_closed_callback.type!=T_INT) +  if (TYPEOF(THIS->output_closed_callback) != T_INT)    {    assign_svalue_no_free(sp++,&THIS->id);    push_object(o->obj);    apply_svalue(&(THIS->output_closed_callback),2);    pop_stack();    }       output_finish(sp[-args].u.object);    pop_n_elems(args-1);   }      static void pipe_read_input_callback(INT32 args)   {    struct input *i;    struct pike_string *s;    -  if (args<2 || sp[1-args].type!=T_STRING) +  if (args<2 || TYPEOF(sp[1-args]) != T_STRING)    Pike_error("Illegal argument to pipe->read_input_callback\n");       i=THIS->firstinput;       if (!i)    Pike_error("Pipe read callback without any inputs left.\n");       s=sp[1-args].u.string;       if(append_buffer(s))
pike.git/src/modules/Pipe/pipe.c:1122:    }    nobjects--;    free_object(i->u.obj);    i->type=I_NONE;       input_finish();    if(args)    pop_n_elems(args-1);   }    + /*! @decl string version() +  *! +  *! Return the version of the module. +  */   static void pipe_version(INT32 args)   {    pop_n_elems(args); -  push_string(make_shared_string("PIPE ver 2.0")); +  push_text("PIPE ver 2.0");   }      /********** init/exit *******************************************************/      void close_and_free_everything(struct object *thisobj,struct pipe *p)   {    struct buffer *b;    struct input *i;    struct output *o;    struct object *obj;
pike.git/src/modules/Pipe/pipe.c:1156:    add_ref(thisobj); /* don't kill object during this */       while (p->firstbuffer)    {    b=p->firstbuffer;    p->firstbuffer=b->next;    sbuffers-=b->s->len;    nbuffers--;    free_string(b->s);    b->next=NULL; -  free((char *)b); /* Hubbe */ +  free(b); /* Hubbe */    }    p->lastbuffer=NULL;          while (p->firstinput)    {    i=p->firstinput;    p->firstinput=i->next;    free_input(i);    }
pike.git/src/modules/Pipe/pipe.c:1192:       p->living_outputs=0;       if (thisobj)    free_object(thisobj);       free_svalue(& p->done_callback);    free_svalue(& p->output_closed_callback);    free_svalue(& p->id);    -  p->done_callback.type=T_INT; -  p->output_closed_callback.type=T_INT; -  p->id.type=T_INT; +  SET_SVAL_TYPE(p->done_callback, T_INT); +  SET_SVAL_TYPE(p->output_closed_callback, T_INT); +  SET_SVAL_TYPE(p->id, T_INT);       /* p->done=0; */   }    - static void init_pipe_struct(struct object *o) + static void init_pipe_struct(struct object *DEBUGUSED(o))   {    debug_malloc_touch(o);       THIS->firstbuffer=THIS->lastbuffer=NULL;    THIS->firstinput=THIS->lastinput=NULL;    THIS->firstoutput=NULL;    THIS->bytes_in_buffer=0;    THIS->pos=0;    THIS->sleeping=0;    THIS->done=0;    THIS->fd=-1; -  THIS->done_callback.type=T_INT; -  THIS->output_closed_callback.type=T_INT; -  THIS->id.type=T_INT; +  SET_SVAL_TYPE(THIS->done_callback, T_INT); +  SET_SVAL_TYPE(THIS->output_closed_callback, T_INT); +  SET_SVAL_TYPE(THIS->id, T_INT);    THIS->id.u.integer=0;    THIS->living_outputs=0;    THIS->sent=0;   }    - static void exit_pipe_struct(struct object *o) + static void exit_pipe_struct(struct object *UNUSED(o))   {    close_and_free_everything(NULL,THIS);   }    - static void exit_output_struct(struct object *obj) + static void exit_output_struct(struct object *DEBUGUSED(obj))   {    struct output *o;       debug_malloc_touch(obj);    o=(struct output *)(Pike_fp->current_storage);       if (o->obj)    {    if(o->obj->prog)    {
pike.git/src/modules/Pipe/pipe.c:1256:    if(!THISOBJ->prog)    Pike_error("Pipe done callback destructed pipe.\n");    }    free_object(o->obj);    noutputs--;    o->obj=0;    o->fd=-1;    }   }    - static void init_output_struct(struct object *ob) + static void init_output_struct(struct object *DEBUGUSED(ob))   {    struct output *o;    debug_malloc_touch(ob);    o=(struct output *)(Pike_fp->current_storage);    o->obj=0;   }         /********** Pike init *******************************************************/   
pike.git/src/modules/Pipe/pipe.c:1282:    push_int(DO_NOT_WARN(noutputs));    push_int(DO_NOT_WARN(ninputs));    push_int(DO_NOT_WARN(nstrings));    push_int(DO_NOT_WARN(nobjects));    push_int(DO_NOT_WARN(mmapped));    push_int(DO_NOT_WARN(nbuffers));    push_int(DO_NOT_WARN(sbuffers));    f_aggregate(7);   }    - void pike_module_init(void) + /*! @endclass +  */ +  + /*! @endmodule +  */ +  + PIKE_MODULE_INIT   {    start_new_program();    ADD_STORAGE(struct pipe);    - /* function(:array) */ -  ADD_EFUN("_pipe_debug", f__pipe_debug,tFunc(tNone,tArray), 0); +     /* function(object:void) */    ADD_FUNCTION("input",pipe_input,tFunc(tObj,tVoid),0);    /* function(object,void|int:void) */    ADD_FUNCTION("output",pipe_output,tFunc(tObj tOr(tVoid,tInt),tVoid),0);    /* function(string:void) */    ADD_FUNCTION("write",pipe_write,tFunc(tStr,tVoid),0);       /* function(:void) */    ADD_FUNCTION("start",pipe_start,tFunc(tNone,tVoid),0);    /* function(:void) */
pike.git/src/modules/Pipe/pipe.c:1343:    offset_input_read_callback=find_identifier("_input_read_callback",    pipe_program);          start_new_program();    ADD_STORAGE(struct output);    set_init_callback(init_output_struct);    set_exit_callback(exit_output_struct);    output_program=end_program();    add_program_constant("__output",output_program, 0); +  +  /* function(:array) */ +  ADD_FUNCTION("_pipe_debug", f__pipe_debug,tFunc(tNone,tArray), 0);   }    - void pike_module_exit(void) + PIKE_MODULE_EXIT   {    if(pipe_program) free_program(pipe_program);    pipe_program=0;    if(output_program) free_program(output_program);    output_program=0;   } -  -  -  -  -  -  -  +