This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2 2/5] Clean pthread functions namespaces for C11 threads


PIng.

2015-08-26 0:07 GMT+09:00 Juan Manuel Torres Palma <j.m.torrespalma@gmail.com>:
> This patch creates weak aliases for all conflicting functions with
> C11 threads.h functions, allowing user to redefine them. Some
> functions do not need aliases as they have already been defined as
> versioned symbols.
>
> 2015-08-25  Juan Manuel Torres Palma  <jmtorrespalma@gmail.com>
>
>         Clean pthread functions namespaces for C11 threads
>
>         This patch creates weak aliases for all conflicting functions with
>         C11 threads.h functions, allowing user to redefine them. Some functions
>         do not need aliases as they have already been defined as versioned
>         symbols.
>
>         * misc/Versions (__mmap, __munmap, __mprotect): Export private
>         symbols for calls from libpthread.
>         * nptl/allocatestack.c: Modify calls to mmap, munmap and mprotect
>         to namespace safe versions __mmap, __munmap and __mprotect.
>         * nptl/pthreadP.h (__pthread_mutex_timedlock, __pthread_key_delete)
>         (__pthread_detach, __pthread_join, __pthread_cancel): Add functions
>         prototypes.
>         * nptl/pthread_cancel.c (__pthread_cancel): Change static
>         requirements.
>         (pthread_cancel): Declare as weak alias.
>         * nptl/pthread_create.c: Change static requirements.
>         * nptl/pthread_detach.c (pthread_detach): Declare as weak alias.
>         (__pthread_detach): Rename pthread_detach function.
>         * nptl/pthread_equal.c (pthread_equal): Declare as weak alias.
>         * nptl/pthread_exit.c (pthread_exit): Likewise.
>         (__pthread_exit): Change static requirements.
>         * nptl/pthread_getspecific.c (pthread_getspecific): Declare as weak
>         alias.
>         * nptl/pthread_join.c (pthread_join): Declare as weak alias.
>         (__pthread_join): Rename pthread_join function.
>         * nptl/pthread_key_create.c (pthread_key_create):
>         Declare as weak alias.
>         * nptl/pthread_key_delete.c (pthread_key_delete):
>         Declare as weak alias.
>         (__pthread_key_delete): Rename pthread_key_delete function.
>         * nptl/pthread_mutex_destroy.c (pthread_mutex_destroy):
>         Declare as weak alias.
>         * nptl/pthread_mutex_init.c (pthread_mutex_init): Likewise.
>         * nptl/pthread_mutex_lock.c (pthread_mutex_lock): Likewise.
>         * nptl/pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise.
>         (__pthread_mutex_timedlock): Rename pthread_mutex_timedlock function.
>         * nptl/pthread_mutex_trylock.c (pthread_mutex_trylock):
>         Declare as weak alias.
>         * nptl/pthread_mutex_unlock.c (pthread_mutex_unlock): Likewise.
>         * nptl/pthread_mutexattr_init.c (pthread_mutexattr_init): Likewise.
>         * nptl/pthread_mutexattr_settype.c
>         (pthread_mutexattr_init): Likewise.
>         * nptl/pthread_self.c (pthread_self): Likewise.
>         * nptl/pthread_setspecific.c (pthread_setspecific): Likewise.
>         * nptl/tpp.c: Modify calls to sched_get_priority_max and
>         sched_get_priority_min to namespace safe versions.
>         * sysdeps/posix/gethostname.c: Modyfy call to uname, to
>         __uname.
>
> diff --git a/misc/Versions b/misc/Versions
> index 671f487..e535682 100644
> --- a/misc/Versions
> +++ b/misc/Versions
> @@ -157,5 +157,6 @@ libc {
>      __mktemp;
>      __libc_ifunc_impl_list;
>      __tdelete; __tfind; __tsearch; __twalk;
> +    __mmap; __munmap; __mprotect;
>    }
>  }
> diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
> index 753da61..c2f61a0 100644
> --- a/nptl/allocatestack.c
> +++ b/nptl/allocatestack.c
> @@ -285,7 +285,7 @@ __free_stacks (size_t limit)
>
>           /* Remove this block.  This should never fail.  If it does
>              something is really wrong.  */
> -         if (munmap (curr->stackblock, curr->stackblock_size) != 0)
> +         if (__munmap (curr->stackblock, curr->stackblock_size) != 0)
>             abort ();
>
>           /* Maybe we have freed enough.  */
> @@ -335,7 +335,7 @@ change_stack_perm (struct pthread *pd
>  #else
>  # error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
>  #endif
> -  if (mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
> +  if (__mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
>      return errno;
>
>    return 0;
> @@ -501,8 +501,8 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
>             size += pagesize_m1 + 1;
>  #endif
>
> -         mem = mmap (NULL, size, prot,
> -                     MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
> +         mem = __mmap (NULL, size, prot,
> +                       MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
>
>           if (__glibc_unlikely (mem == MAP_FAILED))
>             return errno;
> @@ -582,7 +582,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
>               assert (errno == ENOMEM);
>
>               /* Free the stack memory we just allocated.  */
> -             (void) munmap (mem, size);
> +             (void) __munmap (mem, size);
>
>               return errno;
>             }
> @@ -612,7 +612,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
>               if (err != 0)
>                 {
>                   /* Free the stack memory we just allocated.  */
> -                 (void) munmap (mem, size);
> +                 (void) __munmap (mem, size);
>
>                   return err;
>                 }
> @@ -637,7 +637,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
>  # elif _STACK_GROWS_UP
>           char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1);
>  #endif
> -         if (mprotect (guard, guardsize, PROT_NONE) != 0)
> +         if (__mprotect (guard, guardsize, PROT_NONE) != 0)
>             {
>             mprot_error:
>               lll_lock (stack_cache_lock, LLL_PRIVATE);
> @@ -655,7 +655,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
>                  of memory caused problems we better do not use it
>                  anymore.  Uh, and we ignore possible errors.  There
>                  is nothing we could do.  */
> -             (void) munmap (mem, size);
> +             (void) __munmap (mem, size);
>
>               return errno;
>             }
> @@ -672,19 +672,19 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
>           char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1);
>
>           if (oldguard < guard
> -             && mprotect (oldguard, guard - oldguard, prot) != 0)
> +             && __mprotect (oldguard, guard - oldguard, prot) != 0)
>             goto mprot_error;
>
> -         if (mprotect (guard + guardsize,
> +         if (__mprotect (guard + guardsize,
>                         oldguard + pd->guardsize - guard - guardsize,
>                         prot) != 0)
>             goto mprot_error;
>  #elif _STACK_GROWS_DOWN
> -         if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
> +         if (__mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
>                         prot) != 0)
>             goto mprot_error;
>  #elif _STACK_GROWS_UP
> -         if (mprotect ((char *) pd - pd->guardsize,
> +         if (__mprotect ((char *) pd - pd->guardsize,
>                         pd->guardsize - guardsize, prot) != 0)
>             goto mprot_error;
>  #endif
> diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
> index 8cd51c6..a1ae39d 100644
> --- a/nptl/pthreadP.h
> +++ b/nptl/pthreadP.h
> @@ -414,6 +414,8 @@ extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
>  extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
>  extern int __pthread_mutex_trylock (pthread_mutex_t *_mutex);
>  extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
> +extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex,
> +     const struct timespec *__abstime);
>  extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex)
>       attribute_hidden internal_function;
>  extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex)
> @@ -477,6 +479,7 @@ extern int __pthread_cond_timedwait (pthread_cond_t *cond,
>  extern int __pthread_condattr_destroy (pthread_condattr_t *attr);
>  extern int __pthread_condattr_init (pthread_condattr_t *attr);
>  extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *));
> +extern int __pthread_key_delete (pthread_key_t key);
>  extern void *__pthread_getspecific (pthread_key_t key);
>  extern int __pthread_setspecific (pthread_key_t key, const void *value);
>  extern int __pthread_once (pthread_once_t *once_control,
> @@ -485,8 +488,11 @@ extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void),
>                              void (*child) (void));
>  extern pthread_t __pthread_self (void);
>  extern int __pthread_equal (pthread_t thread1, pthread_t thread2);
> +extern int __pthread_detach (pthread_t th);
> +extern int __pthread_cancel (pthread_t th);
>  extern int __pthread_kill (pthread_t threadid, int signo);
>  extern void __pthread_exit (void *value) __attribute__ ((__noreturn__));
> +extern int __pthread_join (pthread_t threadid, void **thread_return);
>  extern int __pthread_setcanceltype (int type, int *oldtype);
>  extern int __pthread_enable_asynccancel (void) attribute_hidden;
>  extern void __pthread_disable_asynccancel (int oldtype)
> diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
> index 981e4bc..f8cd33d 100644
> --- a/nptl/pthread_cancel.c
> +++ b/nptl/pthread_cancel.c
> @@ -25,7 +25,7 @@
>
>
>  int
> -pthread_cancel (pthread_t th)
> +__pthread_cancel (pthread_t th)
>  {
>    volatile struct pthread *pd = (volatile struct pthread *) th;
>
> @@ -108,4 +108,5 @@ pthread_cancel (pthread_t th)
>    return result;
>  }
>
> -PTHREAD_STATIC_FN_REQUIRE (pthread_create)
> +weak_alias (__pthread_cancel, pthread_cancel);
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_create_2_1)
> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
> index d10f4ea..16317c7 100644
> --- a/nptl/pthread_create.c
> +++ b/nptl/pthread_create.c
> @@ -768,14 +768,14 @@ compat_symbol (libpthread, __pthread_create_2_0, pthread_create,
>
>  /* If pthread_create is present, libgcc_eh.a and libsupc++.a expects some other POSIX thread
>     functions to be present as well.  */
> -PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_lock)
> -PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_trylock)
> -PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_unlock)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_mutex_lock)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_mutex_trylock)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_mutex_unlock)
>
> -PTHREAD_STATIC_FN_REQUIRE (pthread_once)
> -PTHREAD_STATIC_FN_REQUIRE (pthread_cancel)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_once)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_cancel)
>
> -PTHREAD_STATIC_FN_REQUIRE (pthread_key_create)
> -PTHREAD_STATIC_FN_REQUIRE (pthread_key_delete)
> -PTHREAD_STATIC_FN_REQUIRE (pthread_setspecific)
> -PTHREAD_STATIC_FN_REQUIRE (pthread_getspecific)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_key_create)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_key_delete)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_setspecific)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_getspecific)
> diff --git a/nptl/pthread_detach.c b/nptl/pthread_detach.c
> index aa735f6..c7628f1 100644
> --- a/nptl/pthread_detach.c
> +++ b/nptl/pthread_detach.c
> @@ -22,7 +22,7 @@
>
>
>  int
> -pthread_detach (th)
> +__pthread_detach (th)
>       pthread_t th;
>  {
>    struct pthread *pd = (struct pthread *) th;
> @@ -54,3 +54,4 @@ pthread_detach (th)
>
>    return result;
>  }
> +weak_alias (__pthread_detach, pthread_detach)
> diff --git a/nptl/pthread_equal.c b/nptl/pthread_equal.c
> index 69f4c1b..2e730df 100644
> --- a/nptl/pthread_equal.c
> +++ b/nptl/pthread_equal.c
> @@ -26,4 +26,4 @@ __pthread_equal (thread1, thread2)
>  {
>    return thread1 == thread2;
>  }
> -strong_alias (__pthread_equal, pthread_equal)
> +weak_alias (__pthread_equal, pthread_equal)
> diff --git a/nptl/pthread_exit.c b/nptl/pthread_exit.c
> index a60adbd..f80e6a5 100644
> --- a/nptl/pthread_exit.c
> +++ b/nptl/pthread_exit.c
> @@ -27,8 +27,8 @@ __pthread_exit (void *value)
>
>    __do_cancel ();
>  }
> -strong_alias (__pthread_exit, pthread_exit)
> +weak_alias (__pthread_exit, pthread_exit)
>
>  /* After a thread terminates, __libc_start_main decrements
>     __nptl_nthreads defined in pthread_create.c.  */
> -PTHREAD_STATIC_FN_REQUIRE (pthread_create)
> +PTHREAD_STATIC_FN_REQUIRE (__pthread_create_2_1)
> diff --git a/nptl/pthread_getspecific.c b/nptl/pthread_getspecific.c
> index 0bee354..a5e5f45 100644
> --- a/nptl/pthread_getspecific.c
> +++ b/nptl/pthread_getspecific.c
> @@ -64,5 +64,5 @@ __pthread_getspecific (key)
>
>    return result;
>  }
> -strong_alias (__pthread_getspecific, pthread_getspecific)
> +weak_alias (__pthread_getspecific, pthread_getspecific)
>  hidden_def (__pthread_getspecific)
> diff --git a/nptl/pthread_join.c b/nptl/pthread_join.c
> index c841ff9..9635b08 100644
> --- a/nptl/pthread_join.c
> +++ b/nptl/pthread_join.c
> @@ -37,7 +37,7 @@ cleanup (void *arg)
>
>
>  int
> -pthread_join (pthread_t threadid, void **thread_return)
> +__pthread_join (pthread_t threadid, void **thread_return)
>  {
>    struct pthread *pd = (struct pthread *) threadid;
>
> @@ -115,3 +115,4 @@ pthread_join (pthread_t threadid, void **thread_return)
>
>    return result;
>  }
> +weak_alias (__pthread_join, pthread_join)
> diff --git a/nptl/pthread_key_create.c b/nptl/pthread_key_create.c
> index a642c69..9beec6b 100644
> --- a/nptl/pthread_key_create.c
> +++ b/nptl/pthread_key_create.c
> @@ -49,5 +49,5 @@ __pthread_key_create (key, destr)
>
>    return EAGAIN;
>  }
> -strong_alias (__pthread_key_create, pthread_key_create)
> +weak_alias (__pthread_key_create, pthread_key_create)
>  hidden_def (__pthread_key_create)
> diff --git a/nptl/pthread_key_delete.c b/nptl/pthread_key_delete.c
> index bd9b4a2..f201b71 100644
> --- a/nptl/pthread_key_delete.c
> +++ b/nptl/pthread_key_delete.c
> @@ -22,7 +22,7 @@
>
>
>  int
> -pthread_key_delete (key)
> +__pthread_key_delete (key)
>       pthread_key_t key;
>  {
>    int result = EINVAL;
> @@ -40,3 +40,4 @@ pthread_key_delete (key)
>
>    return result;
>  }
> +weak_alias (__pthread_key_delete, pthread_key_delete)
> diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c
> index f6089df..3d40205 100644
> --- a/nptl/pthread_mutex_destroy.c
> +++ b/nptl/pthread_mutex_destroy.c
> @@ -37,5 +37,5 @@ __pthread_mutex_destroy (mutex)
>
>    return 0;
>  }
> -strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy)
> +weak_alias (__pthread_mutex_destroy, pthread_mutex_destroy)
>  hidden_def (__pthread_mutex_destroy)
> diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
> index d71cfef..6b9ab16 100644
> --- a/nptl/pthread_mutex_init.c
> +++ b/nptl/pthread_mutex_init.c
> @@ -148,5 +148,5 @@ __pthread_mutex_init (mutex, mutexattr)
>
>    return 0;
>  }
> -strong_alias (__pthread_mutex_init, pthread_mutex_init)
> +weak_alias (__pthread_mutex_init, pthread_mutex_init)
>  hidden_def (__pthread_mutex_init)
> diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
> index 9a3b466..af20011 100644
> --- a/nptl/pthread_mutex_lock.c
> +++ b/nptl/pthread_mutex_lock.c
> @@ -514,7 +514,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
>    return 0;
>  }
>  #ifndef __pthread_mutex_lock
> -strong_alias (__pthread_mutex_lock, pthread_mutex_lock)
> +weak_alias (__pthread_mutex_lock, pthread_mutex_lock)
>  hidden_def (__pthread_mutex_lock)
>  #endif
>
> diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
> index f0fb03e..c74bff1 100644
> --- a/nptl/pthread_mutex_timedlock.c
> +++ b/nptl/pthread_mutex_timedlock.c
> @@ -41,7 +41,7 @@
>  #endif
>
>  int
> -pthread_mutex_timedlock (mutex, abstime)
> +__pthread_mutex_timedlock (mutex, abstime)
>       pthread_mutex_t *mutex;
>       const struct timespec *abstime;
>  {
> @@ -520,3 +520,4 @@ pthread_mutex_timedlock (mutex, abstime)
>   out:
>    return result;
>  }
> +weak_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock)
> diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
> index 33df384..229afdf 100644
> --- a/nptl/pthread_mutex_trylock.c
> +++ b/nptl/pthread_mutex_trylock.c
> @@ -404,6 +404,6 @@ __pthread_mutex_trylock (mutex)
>
>  #ifndef __pthread_mutex_trylock
>  #ifndef pthread_mutex_trylock
> -strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
> +weak_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
>  #endif
>  #endif
> diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
> index 80939ba..d9ff351 100644
> --- a/nptl/pthread_mutex_unlock.c
> +++ b/nptl/pthread_mutex_unlock.c
> @@ -314,5 +314,5 @@ __pthread_mutex_unlock (mutex)
>  {
>    return __pthread_mutex_unlock_usercnt (mutex, 1);
>  }
> -strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
> +weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
>  hidden_def (__pthread_mutex_unlock)
> diff --git a/nptl/pthread_mutexattr_init.c b/nptl/pthread_mutexattr_init.c
> index 92206b0..ef92f47 100644
> --- a/nptl/pthread_mutexattr_init.c
> +++ b/nptl/pthread_mutexattr_init.c
> @@ -34,4 +34,4 @@ __pthread_mutexattr_init (attr)
>
>    return 0;
>  }
> -strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init)
> +weak_alias (__pthread_mutexattr_init, pthread_mutexattr_init)
> diff --git a/nptl/pthread_mutexattr_settype.c b/nptl/pthread_mutexattr_settype.c
> index c6bd5a6..5651ad1 100644
> --- a/nptl/pthread_mutexattr_settype.c
> +++ b/nptl/pthread_mutexattr_settype.c
> @@ -42,4 +42,4 @@ __pthread_mutexattr_settype (attr, kind)
>    return 0;
>  }
>  weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_setkind_np)
> -strong_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype)
> +weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype)
> diff --git a/nptl/pthread_self.c b/nptl/pthread_self.c
> index d6ba45c..422151e 100644
> --- a/nptl/pthread_self.c
> +++ b/nptl/pthread_self.c
> @@ -25,4 +25,4 @@ __pthread_self (void)
>  {
>    return (pthread_t) THREAD_SELF;
>  }
> -strong_alias (__pthread_self, pthread_self)
> +weak_alias (__pthread_self, pthread_self)
> diff --git a/nptl/pthread_setspecific.c b/nptl/pthread_setspecific.c
> index a9cf26c..36b42f8 100644
> --- a/nptl/pthread_setspecific.c
> +++ b/nptl/pthread_setspecific.c
> @@ -91,5 +91,5 @@ __pthread_setspecific (key, value)
>
>    return 0;
>  }
> -strong_alias (__pthread_setspecific, pthread_setspecific)
> +weak_alias (__pthread_setspecific, pthread_setspecific)
>  hidden_def (__pthread_setspecific)
> diff --git a/nptl/tpp.c b/nptl/tpp.c
> index 142c618..a754ab6 100644
> --- a/nptl/tpp.c
> +++ b/nptl/tpp.c
> @@ -43,9 +43,9 @@ void
>  __init_sched_fifo_prio (void)
>  {
>    atomic_store_relaxed (&__sched_fifo_max_prio,
> -                       sched_get_priority_max (SCHED_FIFO));
> +                       __sched_get_priority_max (SCHED_FIFO));
>    atomic_store_relaxed (&__sched_fifo_min_prio,
> -                       sched_get_priority_min (SCHED_FIFO));
> +                       __sched_get_priority_min (SCHED_FIFO));
>  }
>
>  int
> diff --git a/sysdeps/posix/gethostname.c b/sysdeps/posix/gethostname.c
> index 4917705..f0bf75f 100644
> --- a/sysdeps/posix/gethostname.c
> +++ b/sysdeps/posix/gethostname.c
> @@ -31,7 +31,7 @@ __gethostname (name, len)
>    struct utsname buf;
>    size_t node_len;
>
> -  if (uname (&buf))
> +  if (__uname (&buf))
>      return -1;
>
>    node_len = strlen (buf.nodename) + 1;
> --
> 2.4.3



-- 
Juan Manuel Torres Palma.
Computer Science Student at Universidad de Granada.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]