[PHP-DEV] PHP 4.0 Bug #3607: Aspell .29 Compat and Fix From: ajr4 <email protected>
Date: 02/24/00

From: ajr4 <email protected>
Operating system: Linux 2.2.14
PHP version: 4.0 Beta 4 Patch Level 1
PHP Bug Type: Compile Failure
Bug description: Aspell .29 Compat and Fix

As you know current versions of aspell do not have c compatability. Unlike other bug reports in this one I simply offer a fix. I have written c wrappers around the c++ functions of aspell and slightly altered php4-bx/ext/aspell/aspell.c. Recompile aspell and php with the following files. Maybe you know better how to put these wrappers into php. I don't know enough about linking c++ objects to c ones to know if there would be issues.

-------==== begin: aspell-.29/lib/inc/aspell-c.h ====-------

#include <stdlib.h>

typedef struct Aspell {
  void *manager;
  void *options;
} Aspell;

typedef struct SC_Error aspellError;

typedef enum aspellProblem {
  as_none, as_nonexistent, as_bad_format,
  as_cant_write, as_duplicates,
  as_unknown_lang, as_mismatched_lang
} aspellProblem;

typedef const char * aspellString;

typedef struct aspellSuggestions {
  size_t size;
  aspellString * data; /* an array of size elements */
  void *internal_obj;
} aspellSuggestions;

typedef struct aspellWordList {
  size_t size;
  aspellString * data; /* an array of size elements */
  void *internal_obj;
} aspellWordList;

#ifdef __cplusplus
extern "C" {
#endif

  Aspell * aspell_new(const char *master, const char *personal);
  void aspell_free(Aspell *sc);
  const aspellError * aspell_error(Aspell *sc);
  const char * aspell_lang_name(Aspell *sc);
  aspellSuggestions * aspell_suggest(Aspell *sc, const char *word);
  int aspell_check(Aspell *sc, const char *word);
  int aspell_check_raw(Aspell *sc, const char *word);
  void aspell_add_personal(Aspell *sc, const char *word);
  void aspell_add_session(Aspell *sc, const char *word);
  void aspell_save_dicts(Aspell *sc);
  void aspell_clear_session(Aspell *sc);
  void aspell_change_personal(Aspell *sc, const char *base);
  aspellWordList * get_personal(Aspell *sc); /* not implemented yet */
  aspellWordList * get_session(Aspell *sc); /* not implemented yet */
  
  void aspell_free_suggestions(aspellSuggestions *wl);
  void aspell_free_word_list(aspellWordList *wl);
  
  const char * aspell_error_file(const aspellError *error);
  const char * aspell_error_addinfo(const aspellError *error);
  aspellProblem aspell_error_problem(const aspellError *error);
  const char * aspell_error_message(const aspellError *error);

#ifdef __cplusplus
};
#endif

-------==== end: aspell-.29/lib/inc/aspell-c.h ====-------

-------==== begin: aspell-.29/lib/aspell-c.cc ====-------

#include <cstring>
#include <aspell/manager.hh>
#include <aspell/check.hh>
#include <aspell/data.hh>
#include <aspell/suggest.hh>
#include <aspell/config.hh>
#include "aspell-c.h"

using namespace autil;
using namespace aspell;

Aspell * aspell_new( const char *master, const char *personal ) {
  char *lval, *eq, *rval;
  Aspell *ret = new Aspell;

  ret->options = new Config;

  if( master != NULL && (eq = strchr( master, '=' )) != NULL ) {
    lval = strndup( master, eq - master );
    rval = eq + 1;
    ((Config *)(ret->options))->replace( lval, rval );
    free( lval );
  }
  if( personal != NULL && (eq = strchr( personal, '=' )) != NULL ) {
    lval = strndup( personal, eq - personal );
    rval = eq + 1;
    ((Config *)(ret->options))->replace( lval, rval );
    free( lval );
  }

  ret->manager = new Manager( *((Config *)(ret->options)) );
  return( ret );
}

void aspell_free(Aspell *sc) {
  delete (Manager *)sc->manager;
  delete (Config *)sc->options;
  delete sc;
}

const aspellError * aspell_error(Aspell *sc) {
  return( NULL );
}

const char * aspell_lang_name(Aspell *sc){
  return( ((Manager *)sc->manager)->lang_name() );
}

aspellSuggestions * aspell_suggest(Aspell *sc, const char *word) {
  if( !sc )
    return( NULL );

  aspellSuggestions *ret = new aspellSuggestions;
  SuggestionList *suggestions;

  suggestions = &((Manager *)sc->manager)->suggest( word );

  ret->size = suggestions->size();
  ret->data = new aspellString[ret->size+1];

  int i = 0;
  autil::Emulation<const char *> els = suggestions->elements();
  while ( ( ret->data[i++] = els.next()) != 0 );

  return( ret );
}

int aspell_check(Aspell *sc, const char *word) {
  return( ((Manager *)sc->manager)->check( word ) ? 1 : 0 );
}

int aspell_check_raw(Aspell *sc, const char *word) {
  return( ((Manager *)sc->manager)->check_raw( word ) ? 1 : 0 );
}

void aspell_add_personal(Aspell *sc, const char *word) {
}

void aspell_add_session(Aspell *sc, const char *word) {
}

void aspell_save_dicts(Aspell *sc) {
}

void aspell_clear_session(Aspell *sc) {
}

void aspell_change_personal(Aspell *sc, const char *base) {
}

aspellWordList * get_personal(Aspell *sc) {
  return( NULL );
}
aspellWordList * get_session(Aspell *sc) {
  return( NULL );
}

void aspell_free_suggestions(aspellSuggestions *wl) {
  delete[] wl->data;
  delete wl;
}

void aspell_free_word_list(aspellWordList *wl) {
}

const char * aspell_error_file(const aspellError *error) {
  return( NULL );
}

const char * aspell_error_addinfo(const aspellError *error) {
  return( NULL );
}

aspellProblem aspell_error_problem(const aspellError *error) {
  return( as_none );
}

const char * aspell_error_message(const aspellError *error) {
  return( NULL );
}
-------==== end: aspell-.29/lib/aspell-c.cc ====-------

-------==== begin: aspell-.29/lib/Makefile.am ====-------

DEFS += -DDICTDIR=\"${dictdir}\" \
        -DDATADIR=\"${pkgdatadir}\" \
        -DCONFIGDIR=\"${sysconfdir}\"

INCLUDES += -I../ -I../util -I./inc -I../filter

lib_LTLIBRARIES = libaspell.la

libaspell_la_SOURCES = \
  config.cc language.cc phonetic.cc writable_repl.cc \
  data.cc language_exceps.cc readonly_ws.cc writable_ws.cc \
  manager.cc suggest.cc writable_base.cc\
  token.cc check.cc aspell-c.cc

libaspell_la_LIBADD = ../util/libaspell-util.la ../filter/libaspell-filter.la

libaspell_la_LDFLAGS = -version-info 4:0:0

SUBDIRS = inc

EXTRA_DIST = *.hh
-------==== end: aspell-.29/lib/Makefile.am ====-------

-------==== begin: php4-bx/ext/aspell.c ====-------
/*
   +----------------------------------------------------------------------+
   | PHP version 4.0 |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.01 of the PHP license, |
   | that is bundled with this package in the file LICENSE, and is |
   | available at through the world-wide-web at |
   | http://www.php.net/license/2_01.txt. |
   | If you did not receive a copy of the PHP license and are unable to |
   | obtain it through the world-wide-web, please send a note to |
   | license <email protected> so we can mail you a copy immediately. |
   +----------------------------------------------------------------------+
   | Authors: |
   +----------------------------------------------------------------------+
 */

/* $Id: aspell.c,v 1.14 2000/02/19 23:21:25 zeev Exp $ */

#include "php.h"
#if defined(COMPILE_DL)
#include "phpdl.h"
#endif
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>

#if HAVE_ASPELL

#include "php_aspell.h"
#include <aspell-c.h>

function_entry aspell_functions[] = {
        PHP_FE(aspell_new, NULL)
        PHP_FE(aspell_check, NULL)
        PHP_FE(aspell_check_raw, NULL)
        PHP_FE(aspell_suggest, NULL)
        {NULL, NULL, NULL}
};

static int le_aspell;

zend_module_entry aspell_module_entry = {
        "Aspell", aspell_functions, PHP_MINIT(aspell), NULL, NULL, NULL, PHP_MINFO(aspell), STANDARD_MODULE_PROPERTIES
};

#if COMPILE_DL
DLEXPORT zend_module_entry *get_module(void) { return &aspell_module_entry; }
#endif

static void php_aspell_close(Aspell *sc)
{
        aspell_free(sc);
}

PHP_MINIT_FUNCTION(aspell)
{
    le_aspell = register_list_destructors(php_aspell_close,NULL);
        return SUCCESS;

}

/* {{{ proto int aspell_new(string master[, string personal])
   Load a dictionary */
PHP_FUNCTION(aspell_new)
{
        pval **master,**personal;
        int argc;
        Aspell *sc;
        int ind;
        
        argc = ARG_COUNT(ht);
        if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc,&master,&personal) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        convert_to_string_ex(master);
        if(argc==2)
          {
                convert_to_string_ex(personal) ;
                sc=aspell_new((*master)->value.str.val,(*personal)->value.str.val);
          }
        else
          sc=aspell_new((*master)->value.str.val,"");

        ind = zend_list_insert(sc, le_aspell);
        RETURN_LONG(ind);
}
/* }}} */

/* {{{ proto array aspell_suggest(aspell int,string word)
   Return array of Suggestions */
PHP_FUNCTION(aspell_suggest)
{
        pval **scin, **word;
        int argc;
        Aspell *sc;
        int ind,type;
        aspellSuggestions *sug;
        size_t i;

        
        argc = ARG_COUNT(ht);
        if (argc != 2 || zend_get_parameters_ex(argc, &scin,&word) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        convert_to_long_ex(scin);
        convert_to_string_ex(word);
        sc = (Aspell *)zend_list_find((*scin)->value.lval, &type);
        if(!sc)
          {
                php_error(E_WARNING, "%d is not an ASPELL result index",(*scin)->value.lval);
                RETURN_FALSE;
          }

        if (array_init(return_value) == FAILURE) {
                RETURN_FALSE;
        }

        sug = aspell_suggest(sc, (*word)->value.str.val);
          for (i = 0; i != sug->size; ++i) {
                add_next_index_string(return_value,(char *)sug->data[i],1);
          }
          aspell_free_suggestions(sug);
}
/* }}} */

/* {{{ proto int aspell_check(aspell int,string word)
   Return if word is valid */
PHP_FUNCTION(aspell_check)
{
   int type;
   pval **scin,**word;
   Aspell *sc;

   int argc;
    argc = ARG_COUNT(ht);
    if (argc != 2 || zend_get_parameters_ex(argc, &scin,&word) == FAILURE) {
        WRONG_PARAM_COUNT;
    }
    convert_to_long_ex(scin);
    convert_to_string_ex(word);
    sc= (Aspell *) zend_list_find((*scin)->value.lval, &type);
    if(!sc)
      {
        php_error(E_WARNING, "%d is not an ASPELL result index",(*scin)->value.lval);
        RETURN_FALSE;
      }
    if (aspell_check(sc, (*word)->value.str.val))
      {
        RETURN_TRUE;
      }
    else
      {
  RETURN_FALSE;
      }
}
/* }}} */

/* {{{ proto int aspell_check_raw(aspell int,string word)
   Return if word is valid, ignoring case or trying to trim it in any way*/
PHP_FUNCTION(aspell_check_raw)
{
  pval **scin,**word;
  int type;
  int argc;
  Aspell *sc;

    argc = ARG_COUNT(ht);
    if (argc != 2 || zend_get_parameters_ex(argc, &scin,&word) == FAILURE) {
        WRONG_PARAM_COUNT;
    }
    convert_to_long_ex(scin);
    convert_to_string_ex(word);
    sc = (Aspell *)zend_list_find((*scin)->value.lval, &type);
    if(!sc)
      {
        php_error(E_WARNING, "%d is not an ASPELL result index",(*scin)->value.lval);
        RETURN_FALSE;
      }
        if (aspell_check_raw(sc, (*word)->value.str.val))
          {
            RETURN_TRUE;
          }
        else
          {
            RETURN_FALSE;
              }
}
/* }}} */

PHP_MINFO_FUNCTION(aspell)
{
        php_printf("ASpell support enabled");

}

#endif
-------==== end: php4-bx/ext/aspell/aspell.c ====-------

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: php-dev-unsubscribe <email protected>
For additional commands, e-mail: php-dev-help <email protected>
To contact the list administrators, e-mail: php-list-admin <email protected>