Logo Search packages:      
Sourcecode: yorick-yeti version File versions  Download package

yeti_new.c

/*
 * yeti_new.c --
 *
 *    Various built-in functions using the ney Yorick API defined in
 *    'yapi.h'.
 *
 *-----------------------------------------------------------------------------
 *
 *      Copyright (C) 2005-2006, Eric Thiébaut.
 *
 *    This file is part of Yeti.
 *
 *    Yeti is  free software;  you can redistribute  it and/or  modify it
 *    under  the terms of  the GNU  General Public  License version  2 as
 *    published by the Free Software Foundation.
 *
 *    Yeti is distributed in the hope that it will be useful, but WITHOUT
 *    ANY WARRANTY; without even  the implied warranty of MERCHANTABILITY
 *    or FITNESS  FOR A PARTICULAR  PURPOSE.  See the GNU  General Public
 *    License for more details.
 *
 *    You should have  received a copy of the  GNU General Public License
 *    along with  Yeti (file "COPYING"  in the top source  directory); if
 *    not, write to  the Free Software Foundation, Inc.,  51 Franklin St,
 *    Fifth Floor, Boston, MA 02110-1301 USA
 *
 *-----------------------------------------------------------------------------
 *
 * History:
 *    $Id: yeti_new.c,v 1.2 2007/04/19 17:05:20 eric Exp $
 *    $Log: yeti_new.c,v $
 *    Revision 1.2  2007/04/19 17:05:20  eric
 *    Bug in make_dimlist fixed.
 *
 *    Revision 1.1  2006/07/19 14:52:26  eric
 *    Initial revision
 *
 */

#ifndef _YETI_NEW_C
#define _YETI_NEW_C 1

#include <string.h>
#include <stdarg.h>
#include <stdio.h>

#include <unistd.h>

#include <pstdlib.h>
#include "yapi.h"


#define type_t     unsigned char
#define CHECK_DIMS check_dims_c
#include __FILE__

#define type_t     short
#define CHECK_DIMS check_dims_s
#include __FILE__

#define type_t     int
#define CHECK_DIMS check_dims_i
#include __FILE__

#define type_t     long
#define CHECK_DIMS check_dims_l
#include __FILE__


#if 0
void Y_tmpfile(int argc)
{
  const char *tail = "XXXXXX";
  ystring_t src, dst, *arr;
  long len, size;
  int pad, fd;

  if (argc != 1) y_error("tmpfile takes exaclty one argument");
  src = ygets_q(0);
  len = (src && src[0] ? strlen(src) : 0);
  if (len < 6 || strcmp(src + (len - 6), tail)) {
    pad = 1;
    size = len + 7;
  } else {
    pad = 0;
    size = len + 1;
  }
  arr = ypush_q(0);
  dst = p_malloc(size);
  dst[size - 1] = '\0'; /* mark end of string */
  arr[0] = dst; /* then store string pointer */
  if (len > 0) memcpy(dst, src, len);
  if (pad) memcpy(dst + len, tail, 6);
  fprintf(stderr, "template=\"%s\"\n", dst);
  fd = mkstemp(dst);
  if (fd < 0) {
    y_error("tmpfile failed to create a unique temporary file");
  } else {
    close(fd);
  }
}
#endif

#if 0
void Y_is_dimlist(int argc)
{
}
#endif

/* n  or [l, n1, n2, .., nl] */
void Y_make_dimlist(int argc)
{
  long *dimlist, dims[Y_DIMSIZE], ref, ndims, j, n;
  int iarg;            /* argument index */
  int nvoids;          /* number of void arguments */
  int iarg_of_result;  /* index of potentially valid result */

  if (argc < 1) y_error("make_dimlist takes at least one argument");
  if (yarg_subroutine()) {
    ref = yget_ref(argc - 1);
    if (ref < 0L) y_error("expecting a simple reference for first argument");
  } else {
    ref = -1L;
  }

  /* First pass: count total number of dimensions. */
  nvoids = 0;
  iarg_of_result = -1;
  ndims = 0L;
  for (iarg = argc - 1; iarg >= 0; --iarg) {
    switch (yarg_typeid(iarg)) {
    case Y_CHAR:
      ndims += check_dims_c(ygeta_c(iarg, NULL, dims), dims);
      break;
    case Y_SHORT:
      ndims += check_dims_s(ygeta_s(iarg, NULL, dims), dims);
      break;
    case Y_INT:
      ndims += check_dims_i(ygeta_i(iarg, NULL, dims), dims);
      break;
    case Y_LONG:
      ndims += check_dims_l(ygeta_l(iarg, NULL, dims), dims);
      if (iarg_of_result < 0 && dims[0] == 1L) {
      /* First argument which is elligible as the resulting
         dimension list. */
      iarg_of_result = iarg;
      }
      break;
    case Y_VOID:
      ++nvoids;
      break;
    default:
      y_error("unexpected data type in dimension list");
    }
  }
  if (argc - nvoids == 1 && iarg_of_result >= 0) {
    /* Exactly one non void argument and which is elligible
       as the resulting dimension list. */
    if (ref < 0L) {
      /* Called as a function; nothing to do except dropping the
       void arguments above the result if any. */
      if (iarg_of_result > 0) {
      yarg_drop(iarg_of_result);
      }
      return;
    }

    /* Called as a subroutine: elligible result must be the first
       argument. */
    if (iarg_of_result == argc -1) {
      return;
    }
  }

  /* Second pass: build up new dimension list. */
  dims[0] = 1;
  dims[1] = ndims + 1;
  dimlist = ypush_l(dims);
  *dimlist = ndims;
  for (iarg = argc; iarg >= 1; --iarg) {
#define GET_DIMS(type_t, x)                           \
      {                                               \
      type_t *ptr = (type_t *)ygeta_##x(iarg, &n, dims);    \
      if (dims[0]) {                                  \
        for (j=1L ; j<n ; ++j) {                      \
          *++dimlist = ptr[j];                        \
        }                                       \
      } else {                                  \
        *++dimlist = ptr[0];                          \
      }                                         \
      }                                               \
      break
    switch (yarg_typeid(iarg)) {
    case Y_CHAR:  GET_DIMS(unsigned char, c);
    case Y_SHORT: GET_DIMS(short,         s);
    case Y_INT:   GET_DIMS(int,           i);
    case Y_LONG:  GET_DIMS(long,          l);
    }
#undef GET_DIMS
  }

  if (ref >= 0L) {
    /* replace reference by topmost stack element */
    yput_global(ref, 0);
  }
}

#else /* _YETI_NEW_C defined */

#ifdef CHECK_DIMS
static long CHECK_DIMS(const void *array, const long dims[])
{
  const type_t *value = array;
  long j, n;

  n = value[0];
  if (! dims[0] && n > 0L) return 1L;
  if (dims[0] == 1L && dims[1] == n + 1L) {
    for (j=1L ; j<=n ; ++j) {
      if (value[j] <= 0) {
      goto bad_dimlist;
      }
    }
    return n;
  }
 bad_dimlist:
  y_error("bad dimension list @");
  return -1L; /* avoid compiler warnings */
}
#endif /* CHECK_DIMS */

#undef type_t
#undef CHECK_DIMS
#endif /* _YETI_NEW_C defined */

Generated by  Doxygen 1.6.0   Back to index