#line 1 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
/*
|| 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.
|| $Id: pcre_glue.cmod,v 1.17 2004/06/28 00:23:52 aldem Exp $
|| (original author: mirar)
*/

#include "global.h"
RCSID("$Id: pcre_glue.cmod,v 1.17 2004/06/28 00:23:52 aldem Exp $");
#include "pcre_machine.h"

#include "pike_macros.h"
#include "object.h"
#include "constants.h"
#include "interpret.h"
#include "svalue.h"
#include "threads.h"
#include "array.h"
#include "mapping.h"
#include "pike_error.h"
#include "stralloc.h"
#include "threads.h"
#include "builtin_functions.h"
#include "module_support.h"
#include "operators.h"

/*! @module Regexp
 */

/*! @module PCRE
 */

#ifdef HAVE_LIBPCRE

#include <pcre.h>

/*** _pcre the regexp object ***********************************/

/*! @class _pcre
 */


#undef class_cq__pcre_defined
#define class_cq__pcre_defined
struct program *cq__pcre_program=0;
int cq__pcre_program_fun_num=-1;

#undef var_re_cq__pcre_defined
#define var_re_cq__pcre_defined

#undef var_extra_cq__pcre_defined
#define var_extra_cq__pcre_defined

#undef var_pattern_cq__pcre_defined
#define var_pattern_cq__pcre_defined

#undef THIS
#define THIS ((struct cq__pcre_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef THIS_CQ__PCRE
#define THIS_CQ__PCRE ((struct cq__pcre_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef OBJ2_CQ__PCRE
#define OBJ2_CQ__PCRE(o) ((struct cq__pcre_struct *)(o->storage+cq__pcre_storage_offset))

#undef GET_CQ__PCRE_STORAGE
#define GET_CQ__PCRE_STORAGE ((struct cq__pcre_struct *)(o->storage+cq__pcre_storage_offset)
static ptrdiff_t cq__pcre_storage_offset;
struct cq__pcre_struct {

#ifdef var_pattern_cq__pcre_defined
  struct pike_string * pattern;

#endif /* var_pattern_cq__pcre_defined */

#ifdef var_re_cq__pcre_defined
#line 45 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
pcre *re;
#endif /* var_re_cq__pcre_defined */

#ifdef var_extra_cq__pcre_defined
#line 46 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
pcre_extra *extra;
#endif /* var_extra_cq__pcre_defined */
};
/*! @decl void create(string pattern, void|int options, void|object table)
 *!
 *! The option bits are:
 *! @int
 *!   @value  OPTION.ANCHORED
 *!     Force pattern anchoring
 *!   @value  OPTION.CASELESS
 *!     Do caseless matching
 *!   @value  OPTION.DOLLAR_ENDONLY
 *!     $ not to match newline at end
 *!   @value  OPTION.DOTALL
 *!     . matches anything including NL
 *!   @value  OPTION.EXTENDED
 *!     Ignore whitespace and # comments
 *!   @value  OPTION.EXTRA
 *!     PCRE extra features (not much use currently)
 *!   @value  OPTION.MULTILINE
 *!     ^ and $ match newlines within data
 *!   @value  OPTION.NO_AUTO_CAPTURE
 *!     Disable numbered capturing parentheses (named ones available)
 *!   @value  OPTION.UNGREEDY
 *!     Invert greediness of quantifiers
 *!   @value  OPTION.UTF8
 *!     Run in UTF-8 mode
 *! @endint
 */

   #define f_cq__pcre_create_defined
ptrdiff_t f_cq__pcre_create_fun_num = 0;
void f_cq__pcre_create(INT32 args) {
#line 76 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
struct pike_string * pattern;
struct svalue * options;
struct svalue * table;
#line 76 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args < 1) wrong_number_of_args_error("create",args,1);
#line 76 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args > 3) wrong_number_of_args_error("create",args,3);
#line 76 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(Pike_sp[0-args].type != PIKE_T_STRING) SIMPLE_BAD_ARG_ERROR("create",1,"string");
#line 76 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
debug_malloc_pass(pattern=Pike_sp[0-args].u.string);
if (args > 1) {options=Pike_sp+1-args; dmalloc_touch_svalue(Pike_sp+1-args);
} else options=0;
if ((args > 2) && 
    ((Pike_sp[2-args].type != PIKE_T_INT) ||
     (Pike_sp[2-args].u.integer))) {
#line 78 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(Pike_sp[2-args].type != PIKE_T_OBJECT) SIMPLE_BAD_ARG_ERROR("create",3,"void|object");
#line 78 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
table=Pike_sp+2-args; dmalloc_touch_svalue(Pike_sp+2-args);
} else table=0;
#line 79 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
{
	 INT32 options=0;
	 struct object *table=NULL;
	 const char *errptr;
	 int erroffset;

	 if (THIS->pattern) { free_string(THIS->pattern); THIS->pattern=NULL; }
 
         /* get stuff as ints and check the string at the same time */
	 switch (args)
	 {
	    default:
	       if (Pike_sp[2-args].type!=T_INT) /* allow NULL table */
	       {
		  get_all_args("pcre->create",args,"%S%d%o",
			       &(THIS->pattern),&options,&table);
		  break;
	       }
	    case 2:
	       get_all_args("pcre->create",args,"%S%d",
			    &(THIS->pattern),&options);
	       break;
	    case 1:
	    case 0:
	       get_all_args("pcre->create",args,"%S",&(THIS->pattern));
	       break;
	 }
	 add_ref(THIS->pattern);

	 if (THIS->re) (*pcre_free)(THIS->re); /* -> free() usually */
	 if (THIS->extra) (*pcre_free)(THIS->extra); /* -> free() usually */
	 THIS->extra=NULL;

	 THIS->re=pcre_compile(
	    THIS->pattern->str,options,
	    &errptr,&erroffset,
	    NULL /* table */ );

	 if (!THIS->re)
	    Pike_error("error calling pcre_compile [%d]: %s\n",
		       erroffset,errptr);
      }

}
/*! @decl object study()
 *!
 *!  (from the pcreapi man-page)
 *!  "When  a pattern is going to be used several times, it is worth spending
 *!  more time analyzing it in order to speed up the time taken  for  match-
 *!  ing."
 */

   #define f_cq__pcre_study_defined
ptrdiff_t f_cq__pcre_study_fun_num = 0;
void f_cq__pcre_study(INT32 args) {
#line 130 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args != 0) wrong_number_of_args_error("study",args,0);
{
	 const char *errmsg=NULL;
	 if (!THIS->re)
	    Pike_error("need to initialize before study() is called\n");

	 if (THIS->extra) (*pcre_free)(THIS->extra); /* -> free() usually */

         THIS->extra=pcre_study(THIS->re,0,&errmsg);

	 if (errmsg)
	    Pike_error("error calling pcre_study: %s\n",errmsg);

	 do { struct object * ret_=(this_object());  push_object(ret_); return; }while(0);
#line 144 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
}

}
/*! @decl static string _sprintf(int c, mapping flags)
 */
   #define f_cq__pcre_cq__sprintf_defined
ptrdiff_t f_cq__pcre_cq__sprintf_fun_num = 0;
void f_cq__pcre_cq__sprintf(INT32 args) {
#line 148 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
INT_TYPE c;
#line 148 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
struct mapping * flags;
#line 148 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args != 2) wrong_number_of_args_error("_sprintf",args,2);
#line 148 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(Pike_sp[0-2].type != PIKE_T_INT) SIMPLE_BAD_ARG_ERROR("_sprintf",1,"int");
c=Pike_sp[0-2].u.integer;
#line 148 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(Pike_sp[1-2].type != PIKE_T_MAPPING) SIMPLE_BAD_ARG_ERROR("_sprintf",2,"mapping(mixed:mixed)");
#line 148 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
debug_malloc_pass(flags=Pike_sp[1-2].u.mapping);
#line 150 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
{
      switch(c)
      {
	 default:
	    push_undefined();
	    return;

	 case 'O':
	    push_constant_text ("%t(%O)");
	    ref_push_object(Pike_fp->current_object);
	    if (THIS->pattern)
	       ref_push_string(THIS->pattern);
	    else
	       push_undefined();
	    f_sprintf(3);
	    return;

	 case 's':
	    if (THIS->pattern)
	       ref_push_string(THIS->pattern);
	    else
	       push_undefined();
	    return;

	 case 't':
	    push_text("Regexp.PCRE._pcre");
	    return;
      }
   }

}
#line 180 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
#ifdef HAVE_PCRE_FULLINFO

   /*! @decl mapping info()
    *!
    *! Returns additional information about a compiled pattern. Only
    *! available if PCRE was compiled with Fullinfo.
    *!
    *! @returns
    *! @mapping
    *!   @member int "backrefmax"
    *!     Return the number of the highest back reference in the
    *!     pattern. The fourth argument should point to an int
    *!     variable. Zero is returned if there are no back references.
    *!   @member int "capturecount"
    *!     Return the number of capturing subpatterns in the pattern.
    *!     The fourth argument should point to an int variable.
    *!   @member int "firstbyte"
    *!     Return information about the first byte of any matched
    *!     string, for a non-anchored pattern. (This option used to be
    *!     called PCRE_INFO_FIRSTCHAR; the old name is still
    *!     recognized for backwards compatibility.)
    *!
    *!     If there is a fixed first byte, e.g. from a pattern such as
    *!     (cat|cow|coyote), it is returned in the integer pointed to
    *!     by where. Otherwise, if either
    *!
    *!     (a) the pattern was compiled with the PCRE_MULTILINE
    *!     option, and every branch starts with @expr{"^"@}, or
    *!
    *!     (b) every branch of the pattern starts with @expr{".*"@}
    *!     and PCRE_DOTALL is not set (if it were set, the pattern
    *!     would be anchored),
    *!
    *!     @expr{-1@} is returned, indicating that the pattern matches
    *!     only at the start of a subject string or after any newline
    *!     within the string. Otherwise @expr{-2@} is returned. For
    *!     anchored patterns, @expr{-2@} is returned.
    *!   @member int "lastliteral"
    *!     Return the value of the rightmost literal byte that must
    *!     exist in any matched string, other than at its start, if
    *!     such a byte has been recorded. The fourth argument should
    *!     point to an int variable. If there is no such byte,
    *!     @expr{-1@} is returned. For anchored patterns, a last
    *!     literal byte is recorded only if it follows something of
    *!     variable length. For example, for the pattern /^a\d+z\d+/
    *!     the returned value is @expr{"z"@}, but for /^a\dz\d/ the
    *!     returned value is @expr{-1@}.
    *!   @member int "namecount"
    *!   @member int "nameentrysize"
    *!
    *!   @member int "options"
    *!     Return a copy of the options with which the pattern was
    *!     compiled. The fourth argument should point to an unsigned
    *!     long int variable. These option bits are those specified in
    *!     the call to pcre_compile(), modified by any top-level
    *!     option settings within the pattern itself.
    *!
    *!     A pattern is automatically anchored by PCRE if all of its
    *!     top-level alternatives begin with one of the following:
    *!
    *! @xml{<matrix>
    *! <r><c>^</c><c>unless PCRE_MULTILINE is set</c></r>
    *! <r><c>\A</c><c>always</c></r>
    *! <r><c>\G</c><c>always</c></r>
    *! <r><c>.*</c><c>if PCRE_DOTALL is set and there are no back
    *! references to the subpattern in which .* appears</c></r>
    *! </matrix>@}
    *!
    *!     For such patterns, the PCRE_ANCHORED bit is set in the
    *!     options returned.
    *!   @member int "size"
    *!      Return the size of the compiled pattern, that is, the
    *!      value that was passed as the argument to pcre_malloc()
    *!      when PCRE was getting memory in which to place the
    *!      compiled data. The fourth argument should point to a
    *!      size_t variable.
    *!   @member int "studysize"
    *!      Returns the size of the data block pointed to by the
    *!      study_data field in a pcre_extra block. That is, it is the
    *!      value that was passed to pcre_malloc() when PCRE was
    *!      getting memory into which to place the data created by
    *!      pcre_study(). The fourth argument should point to a size_t
    *!      variable.
    *! @endmapping
    */
   #define f_cq__pcre_info_defined
ptrdiff_t f_cq__pcre_info_fun_num = 0;
void f_cq__pcre_info(INT32 args) {
#line 265 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args != 0) wrong_number_of_args_error("info",args,0);
{
	 int backrefmax,firstbyte,lastliteral,capturecount;
	 void *firsttable,*nametable;
	 int namecount,nameentrysize,options;
	 size_t size,studysize;
	 struct svalue *save_sp;

	 if (!THIS->re)
	    Pike_error("need to initialize before info() is called\n");

	 if (pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_BACKREFMAX,&backrefmax) ||
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_CAPTURECOUNT,&capturecount) ||
#ifdef PCRE_INFO_FIRSTBYTE
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_FIRSTBYTE,&firstbyte) ||
#endif /* PCRE_INFO_FIRSTBYTE */
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_FIRSTTABLE,&firsttable) ||
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_LASTLITERAL,&lastliteral) ||
#ifdef PCRE_INFO_NAMECOUNT
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_NAMECOUNT,&namecount) ||
#endif /* PCRE_INFO_NAMECOUNT */
#ifdef PCRE_INFO_NAMEENTRYSIZE
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_NAMEENTRYSIZE,&nameentrysize) ||
#endif /* PCRE_INFO_NAMEENTRYSIZE */
#ifdef PCRE_INFO_NAMETABLE
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_NAMETABLE,&nametable) ||
#endif /* PCRE_INFO_NAMETABLE */
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_OPTIONS,&options) ||
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_SIZE,&size) ||
#ifdef PCRE_INFO_STUDYSIZE
	     pcre_fullinfo(THIS->re,THIS->extra,
			   PCRE_INFO_STUDYSIZE,&studysize) ||
#endif /* PCRE_INFO_STUDYSIZE */
	     0)
	    Pike_error("pcre_fullinfo gave errors (unexpected)\n");

	 pop_n_elems(args);
	 save_sp = Pike_sp;
	  
	 push_text("backrefmax");   	push_int(backrefmax);
	 push_text("capturecount"); 	push_int(capturecount);
#ifdef PCRE_INFO_FIRSTBYTE
	 push_text("firstbyte"); 	push_int(firstbyte);
#endif /* PCRE_INFO_FIRSTBYTE */
	 push_text("firsttable"); 	push_int(0); /* FIXME: table */
	 push_text("lastliteral"); 	push_int(lastliteral);
#ifdef PCRE_INFO_NAMECOUNT
	 push_text("namecount"); 	push_int(namecount);
#endif /* PCRE_INFO_NAMECOUNT */
#ifdef PCRE_INFO_NAMEENTRYSIZE
	 push_text("nameentrysize"); 	push_int(nameentrysize);
#endif /* PCRE_INFO_NAMEENTRYSIZE */
#ifdef PCRE_INFO_NAMETABLE
	 push_text("nametable"); 	push_int(0); /* FIXME: table */
#endif /* PCRE_INFO_NAMETABLE */
	 push_text("options");		push_int(options);
	 push_text("size"); 		push_int(size);
#ifdef PCRE_INFO_STUDYSIZE
	 push_text("studysize"); 	push_int(studysize);
#endif /* PCRE_INFO_STUDYSIZE */
	 f_aggregate_mapping(Pike_sp - save_sp);
      }

}
#line 338 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
#endif /* HAVE_PCRE_FULLINFO */

/*! @decl int|array exec(string subject,void|int startoffset)
 *!     match a regexp; will return an array of 2*n integers
 *!	where n is the number of hits;
 *!	returns an int upon failure
 *!
 *!	Error codes:
 *!  @int
 *!     @value ERROR.NOMATCH
 *!
 *!   The subject string did not match the pattern.
 *!
 *!     @value ERROR.NULL
 *!
 *!   Either code or subject was passed as NULL, or ovector was NULL
 *!   and oversize was not zero.
 *!
 *!     @value ERROR.BADOPTION
 *!
 *!   An unrecognized bit was set in the options argument.
 *!
 *!     @value ERROR.BADMAGIC
 *!
 *!   PCRE stores a 4-byte "magic number" at the start of the compiled
 *!   code, to catch the case when it is passed a junk pointer. This
 *!   is the error it gives when the magic number isn't present.
 *!
 *!     @value ERROR.UNKNOWN_NODE
 *!
 *!   While running the pattern match, an unknown item was encountered
 *!   in the compiled pattern. This error could be caused by a bug in
 *!   PCRE or by overwriting of the compiled pattern.
 *!
 *!     @value ERROR.NOMEMORY
 *!
 *!   If a pattern contains back references, but the ovector that is
 *!   passed to pcre_exec() is not big enough to remember the
 *!   referenced substrings, PCRE gets a block of memory at the start
 *!   of matching to use for this purpose. If the call via
 *!   pcre_malloc() fails, this error is given. The memory is freed at
 *!   the end of matching.
 *!
 *!     @value ERROR.NOSUBSTRING
 *!
 *!   This error is used by the pcre_copy_substring(),
 *!   pcre_get_substring(), and pcre_get_substring_list() functions
 *!   (see below). It is never returned by pcre_exec().
 *!
 *!     @value ERROR.MATCHLIMIT
 *!
 *!   The recursion and backtracking limit, as specified by the
 *!   match_limit field in a pcre_extra structure (or defaulted) was
 *!   reached. See the description above.
 *!
 *!     @value ERROR.CALLOUT
 *!
 *!   This error is never generated by pcre_exec() itself. It is
 *!   provided for use by callout functions that want to yield a
 *!   distinctive error code. See the pcrecallout documentation for
 *!   details.
 *! @endint
 */

#define OVECTOR_SIZE 3000 /* multiple of three; possible hits*3 */

   #define f_cq__pcre_exec_defined
ptrdiff_t f_cq__pcre_exec_fun_num = 0;
void f_cq__pcre_exec(INT32 args) {
#line 404 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
struct pike_string * subject;
struct svalue * startoffset;
#line 404 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args < 1) wrong_number_of_args_error("exec",args,1);
#line 404 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args > 2) wrong_number_of_args_error("exec",args,2);
#line 404 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(Pike_sp[0-args].type != PIKE_T_STRING) SIMPLE_BAD_ARG_ERROR("exec",1,"string");
#line 404 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
debug_malloc_pass(subject=Pike_sp[0-args].u.string);
if (args > 1) {startoffset=Pike_sp+1-args; dmalloc_touch_svalue(Pike_sp+1-args);
} else startoffset=0;
#line 406 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
{
	 struct array *res;

	 int rc;
	 int ovector[OVECTOR_SIZE];
	 INT32 off=0;
	 char *dummy_s;
	 int opts=0;

	 if (!THIS->re)
	    Pike_error("need to initialize before exec() is called\n");

         /* FIXME: also MATCH_LIMIT and CALLOUT_DATA ... later */

	 switch (args) /* get ints and check 8 bit compliancy */
	 {
	    case 2: get_all_args("exec",args,"%s%d",&dummy_s,&off); break;
	    case 1: get_all_args("exec",args,"%s",&dummy_s); break;
	 }
	 
	 rc=pcre_exec(THIS->re,THIS->extra,
		      subject->str,subject->len,
		      off,opts,
		      ovector,OVECTOR_SIZE);

	 if (rc<0)
	 {
	    push_int(rc);
	 }
	 else
	 {
	    int i;
	    rc*=2;
	    res=allocate_array(rc);
	    for (i=0; i<rc; i++)
	    {
	       ITEM(res)[i].type=T_INT;
	       ITEM(res)[i].subtype=0;
	       ITEM(res)[i].u.integer=ovector[i];
	    }
	    push_array(res);
	 }
      }

}
/*! @decl int get_stringnumber(string stringname)
 *!    returns the number of a named subpattern
 */

#line 454 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
#ifdef HAVE_PCRE_GET_STRINGNUMBER
   #define f_cq__pcre_get_stringnumber_defined
ptrdiff_t f_cq__pcre_get_stringnumber_fun_num = 0;
void f_cq__pcre_get_stringnumber(INT32 args) {
#line 455 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
struct pike_string * stringname;
#line 455 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args != 1) wrong_number_of_args_error("get_stringnumber",args,1);
#line 455 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(Pike_sp[0-1].type != PIKE_T_STRING) SIMPLE_BAD_ARG_ERROR("get_stringnumber",1,"string");
#line 455 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
debug_malloc_pass(stringname=Pike_sp[0-1].u.string);
{
	 if (stringname->size_shift)
	    SIMPLE_BAD_ARG_ERROR("get_stringnumber",1,"string (8bit)");
	 do { INT_TYPE ret_=(pcre_get_stringnumber(THIS->re,stringname->str)); pop_stack(); push_int(ret_); return; }while(0);
#line 460 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
}
}
#line 461 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
#endif /* HAVE_PCRE_GET_STRINGNUMBER */

/* init and exit */

   
#undef internal_init_cq__pcre_defined
#define internal_init_cq__pcre_defined

#undef cq__pcre_event_handler_defined
#define cq__pcre_event_handler_defined
static void init_cq__pcre_struct(void)
#line 466 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
{
	 THIS->re=NULL;
	 THIS->extra=NULL;
	 THIS->pattern=NULL;
      }

   
#undef internal_exit_cq__pcre_defined
#define internal_exit_cq__pcre_defined

#undef cq__pcre_event_handler_defined
#define cq__pcre_event_handler_defined
static void exit_cq__pcre_struct(void)
#line 473 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
{
	 if (THIS->re) (*pcre_free)(THIS->re); /* -> free() usually */
	 if (THIS->extra) (*pcre_free)(THIS->extra); /* -> free() usually */
      }


#ifdef cq__pcre_event_handler_defined
static void cq__pcre_event_handler(int ev) {
  switch(ev) {

#ifdef internal_init_cq__pcre_defined
  case PROG_EVENT_INIT: init_cq__pcre_struct(); break;

#endif /* internal_init_cq__pcre_defined */

#ifdef internal_exit_cq__pcre_defined
  case PROG_EVENT_EXIT: exit_cq__pcre_struct(); break;

#endif /* internal_exit_cq__pcre_defined */
  default: break; 
  }
}

#endif /* cq__pcre_event_handler_defined */
/*! @endclass
 */

#line 483 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
#endif /* HAVE_LIBPCRE */

/*! @decl array(string) split_subject(string subject, @
 *!                        array(int) previous_result)
 *! Convenience function that
 *! splits a subject string on the result from _pcre->exec()
 *! 
 *! equal to
 *! map(previous_result/2,
 *!     lambda(array v) { return subject[v[0]..v[1]-1]; })
 */

#define f_split_subject_defined
ptrdiff_t f_split_subject_fun_num = 0;
void f_split_subject(INT32 args) {
#line 495 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
struct pike_string * subject;
#line 495 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
struct array * previous_result;
#line 495 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(args != 2) wrong_number_of_args_error("split_subject",args,2);
#line 495 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(Pike_sp[0-2].type != PIKE_T_STRING) SIMPLE_BAD_ARG_ERROR("split_subject",1,"string");
#line 495 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
debug_malloc_pass(subject=Pike_sp[0-2].u.string);
#line 495 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
if(Pike_sp[1-2].type != PIKE_T_ARRAY) SIMPLE_BAD_ARG_ERROR("split_subject",2,"array(int)");
#line 495 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
debug_malloc_pass(previous_result=Pike_sp[1-2].u.array);
{
   int i,j;
   int sz=previous_result->size/2;
   struct array *res;

   for (i=0; i<sz*2; i++)
      if (ITEM(previous_result)[i].type!=T_INT)
	 SIMPLE_BAD_ARG_ERROR("split_subjects",2,"array(int)");

   res=allocate_array(sz);   
   for (i=j=0; j<sz; i+=2,j++)
   {
      ITEM(res)[j].type=T_STRING;
      ITEM(res)[j].subtype=0;
      ITEM(res)[j].u.string=
	 string_slice(subject,
		      ITEM(previous_result)[i].u.integer,
		      ITEM(previous_result)[i+1].u.integer-
		      ITEM(previous_result)[i].u.integer);
   }

   do { struct array * ret_=(res); pop_n_elems(2); push_array(ret_); return; }while(0);
#line 518 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
}

}
#line 520 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
/*** module init & exit & stuff *****************************************/

PIKE_MODULE_EXIT
{
   
#ifdef class_cq__pcre_defined
  if(cq__pcre_program) {
    free_program(cq__pcre_program);
    cq__pcre_program=0;
  }

#endif /* class_cq__pcre_defined */
#line 525 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
}

PIKE_MODULE_INIT
{
#ifdef HAVE_LIBPCRE

/*! @decl constant buildconfig_UTF8
 *!	(from the pcreapi man-page)
 *!     "The output is an integer that is set to one if UTF-8 support
 *!     is available; otherwise it is set to zero."
 *!	This constant is calculated when the module is initiated
 *!	by using pcre_config(3).
 *!
 *! @decl constant buildconfig_NEWLINE
 *!	(from the pcreapi man-page)
 *!     "The output is an integer that is set to  the  value  of  the
 *!     code  that  is  used for the newline character. It is either
 *!     linefeed (10) or carriage return (13), and  should  normally
 *!     be the standard character for your operating system."
 *!	This constant is calculated when the module is initiated
 *!	by using pcre_config(3).
 *!
 *! @decl constant buildconfig_LINK_SIZE
 *!	(from the pcreapi man-page)
 *!     "The output is an integer that contains the number  of  bytes
 *!     used  for  internal linkage in compiled regular expressions.
 *!     The value is 2, 3, or 4. Larger values allow larger  regular
 *!     expressions  to be compiled, at the expense of slower match-
 *!     ing. The default value of 2 is sufficient for  all  but  the
 *!     most  massive patterns, since it allows the compiled pattern
 *!     to be up to 64K in size."
 *!	This constant is calculated when the module is initiated
 *!	by using pcre_config(3).
 *!
 *! @decl constant buildconfig_POSIX_MALLOC_THRESHOLD
 *!	(from the pcreapi man-page)
 *!     "The output is an integer that contains the  threshold  above
 *!     which  the POSIX interface uses malloc() for output vectors.
 *!     Further details are given in the pcreposix documentation."
 *!	This constant is calculated when the module is initiated
 *!	by using pcre_config(3).
 *!
 *! @decl constant buildconfig_MATCH_LIMIT
 *!	(from the pcreapi man-page)
 *!     "The output is an integer that gives the  default  limit  for
 *!     the   number  of  internal  matching  function  calls  in  a
 *!     pcre_exec()  execution.  Further  details  are  given   with
 *!     pcre_exec() below."
 *!	This constant is calculated when the module is initiated
 *!	by using pcre_config(3).
 *!
 */

/* we need a constant that *isn't there* if we don't have UTF8 support */
#ifdef PCRE_CONFIG_UTF8
   {
      int outcome;
      if (pcre_config(PCRE_CONFIG_UTF8,&outcome)==0 && outcome)
         add_integer_constant("UTF8_SUPPORTED",1,0);
   }
#endif

#define FIGURE_BUILD_TIME_OPTION(X)					\
   do									\
   {									\
      int outcome;							\
      if (pcre_config(PCRE_CONFIG_##X,&outcome)==0)			\
         add_integer_constant("buildconfig_"#X,outcome,0);		\
   }									\
   while (0)

#ifdef PCRE_CONFIG_UTF8
   FIGURE_BUILD_TIME_OPTION(UTF8);
#endif
#ifdef PCRE_CONFIG_NEWLINE
   FIGURE_BUILD_TIME_OPTION(NEWLINE);
#endif
#ifdef PCRE_CONFIG_LINK_SIZE
   FIGURE_BUILD_TIME_OPTION(LINK_SIZE);
#endif
#ifdef PCRE_CONFIG_POSIX_MALLOC_THRESHOLD
   FIGURE_BUILD_TIME_OPTION(POSIX_MALLOC_THRESHOLD);
#endif
#ifdef PCRE_CONFIG_MATCH_LIMIT
   FIGURE_BUILD_TIME_OPTION(MATCH_LIMIT);
#endif

/*! @module OPTION
 *!  contains all option constants
 */

   start_new_program();

/*! @decl constant ANCHORED
 *!  (from the pcreapi manpage)
 *!  If this bit is set, the pattern is forced to be "anchored", that is, it
 *!  is constrained to match only at the first matching point in the  string
 *!  which is being searched (the "subject string"). This effect can also be
 *!  achieved by appropriate constructs in the pattern itself, which is  the
 *!  only way to do it in Perl.
 */
   add_integer_constant("ANCHORED",PCRE_ANCHORED,0);

/*! @decl constant CASELESS
 *!  (from the pcreapi manpage)
 *!  If  this  bit is set, letters in the pattern match both upper and lower
 *!  case letters. It is equivalent to Perl's  /i  option,  and  it  can  be
 *!  changed within a pattern by a (?i) option setting.
 */
   add_integer_constant("CASELESS",PCRE_CASELESS,0);

/*! @decl constant DOLLAR_ENDONLY
 *!  (from the pcreapi manpage)
 *!  If  this bit is set, a dollar metacharacter in the pattern matches only
 *!  at the end of the subject string. Without this option,  a  dollar  also
 *!  matches  immediately before the final character if it is a newline (but
 *!  not before any  other  newlines).  The  PCRE_DOLLAR_ENDONLY  option  is
 *!  ignored if PCRE_MULTILINE is set. There is no equivalent to this option
 *!  in Perl, and no way to set it within a pattern.
 */
   add_integer_constant("DOLLAR_ENDONLY",PCRE_DOLLAR_ENDONLY,0);

/*! @decl constant DOTALL
 *!  (from the pcreapi manpage)
 *!  If this bit is set, a dot  metacharater  in  the  pattern  matches  all
 *!  characters, including newlines. Without it, newlines are excluded. This
 *!  option is equivalent to Perl's /s option, and it can be changed  within
 *!  a  pattern  by  a  (?s)  option  setting. A negative class such as [^a]
 *!  always matches a newline character, independent of the setting of  this
 *!  option.
 */
   add_integer_constant("DOTALL",PCRE_DOTALL,0);

/*! @decl constant EXTENDED
 *!  (from the pcreapi manpage)
 *!  If  this  bit  is  set,  whitespace  data characters in the pattern are
 *!  totally ignored except  when  escaped  or  inside  a  character  class.
 *!  Whitespace  does  not  include the VT character (code 11). In addition,
 *!  characters between an unescaped # outside a  character  class  and  the
 *!  next newline character, inclusive, are also ignored. This is equivalent
 *!  to Perl's /x option, and it can be changed within a pattern by  a  (?x)
 *!  option setting.
 *!
 *!  This  option  makes  it possible to include comments inside complicated
 *!  patterns.  Note, however, that this applies only  to  data  characters.
 *!  Whitespace   characters  may  never  appear  within  special  character
 *!  sequences in a pattern, for  example  within  the  sequence  (?(  which
 *!  introduces a conditional subpattern.
 */
   add_integer_constant("EXTENDED",PCRE_EXTENDED,0);

/*! @decl constant EXTRA
 *!  (from the pcreapi manpage)
 *!  This  option  was invented in order to turn on additional functionality
 *!  of PCRE that is incompatible with Perl, but it  is  currently  of  very
 *!  little  use. When set, any backslash in a pattern that is followed by a
 *!  letter that has no special meaning  causes  an  error,  thus  reserving
 *!  these  combinations  for  future  expansion.  By default, as in Perl, a
 *!  backslash followed by a letter with no special meaning is treated as  a
 *!  literal.  There  are  at  present  no other features controlled by this
 *!  option. It can also be set by a (?X) option setting within a pattern.
 */
   add_integer_constant("EXTRA",PCRE_EXTRA,0);

/*! @decl constant MULTILINE
 *!  (from the pcreapi manpage)
 *!  By default, PCRE treats the subject string as consisting  of  a  single
 *!  "line"  of  characters (even if it actually contains several newlines).
 *!  The "start of line" metacharacter (^) matches only at the start of  the
 *!  string,  while  the "end of line" metacharacter ($) matches only at the
 *!  end of the string, or before a terminating  newline  (unless  PCRE_DOL-
 *!  LAR_ENDONLY is set). This is the same as Perl.
 *!
 *!  When  PCRE_MULTILINE  it  is set, the "start of line" and "end of line"
 *!  constructs match immediately following or immediately before  any  new-
 *!  line  in the subject string, respectively, as well as at the very start
 *!  and end. This is equivalent to Perl's /m option, and it can be  changed
 *!  within a pattern by a (?m) option setting. If there are no "\n" charac-
 *!  ters in a subject string, or no occurrences of ^ or  $  in  a  pattern,
 *!  setting PCRE_MULTILINE has no effect.
 *!
 */
   add_integer_constant("MULTILINE",PCRE_MULTILINE,0);

#ifdef PCRE_NO_AUTO_CAPTURE
/*! @decl constant NO_AUTO_CAPTURE
 *!  (from the pcreapi manpage)
 *!  If this option is set, it disables the use of numbered capturing paren-
 *!  theses in the pattern. Any opening parenthesis that is not followed  by
 *!  ?  behaves as if it were followed by ?: but named parentheses can still
 *!  be used for capturing (and they acquire  numbers  in  the  usual  way).
 *!  There is no equivalent of this option in Perl.
 */
   add_integer_constant("NO_AUTO_CAPTURE",PCRE_NO_AUTO_CAPTURE,0);
#endif

/*! @decl constant UNGREEDY
 *!  (from the pcreapi manpage)
 *!  This  option  inverts  the "greediness" of the quantifiers so that they
 *!  are not greedy by default, but become greedy if followed by "?". It  is
 *!  not  compatible  with Perl. It can also be set by a (?U) option setting
 *!  within the pattern.
 */
   add_integer_constant("UNGREEDY",PCRE_UNGREEDY,0);

#ifdef PCRE_UTF8
/*! @decl constant UTF8
 *!  (from the pcreapi manpage)
 *!  This option causes PCRE to regard both the pattern and the  subject  as
 *!  strings  of  UTF-8 characters instead of single-byte character strings.
 *!  However, it is available only if PCRE has been built to  include  UTF-8
 *!  support.  If  not, the use of this option provokes an error. Details of
 *!  how this option changes the behaviour of PCRE are given in the  section
 *!  on UTF-8 support in the main pcre page.
 */
   add_integer_constant("UTF8",PCRE_UTF8,0);
#endif

#define END_PROGRAM_MAKE_SUBMODULE(X)					\
   do									\
   { 									\
      struct program *p=end_program();					\
      struct object *obj=clone_object(p,0);				\
      add_object_constant(X,obj,0);					\
      free_object(obj);							\
      free_program(p);							\
   }									\
   while (0)

   END_PROGRAM_MAKE_SUBMODULE("OPTION");

/*! @endmodule OPTION
 */

/*! @module ERROR
 */

/*! @decl constant NOMATCH
 *! @decl constant NULL
 *! @decl constant BADOPTION
 *! @decl constant BADMAGIC
 *! @decl constant UNKNOWN_NODE
 *! @decl constant NOMEMORY
 *! @decl constant NOSUBSTRING
 *! @decl constant MATCHLIMIT
 *! @decl constant CALLOUT
 *!   Documented in @[exec].
 */

   start_new_program();
/* documented in exec() */
   add_integer_constant("NOMATCH",PCRE_ERROR_NOMATCH,0);
   add_integer_constant("NULL",PCRE_ERROR_NULL,0);
   add_integer_constant("BADOPTION",PCRE_ERROR_BADOPTION,0);
   add_integer_constant("BADMAGIC",PCRE_ERROR_BADMAGIC,0);
   add_integer_constant("UNKNOWN_NODE",PCRE_ERROR_UNKNOWN_NODE,0);
   add_integer_constant("NOMEMORY",PCRE_ERROR_NOMEMORY,0);
   add_integer_constant("NOSUBSTRING",PCRE_ERROR_NOSUBSTRING,0);
#ifdef PCRE_ERROR_MATCHLIMIT
   add_integer_constant("MATCHLIMIT",PCRE_ERROR_MATCHLIMIT,0);
#endif
#ifdef PCRE_ERROR_CALLOUT
   add_integer_constant("CALLOUT",PCRE_ERROR_CALLOUT,0);
#endif

   END_PROGRAM_MAKE_SUBMODULE("ERROR");

/*! @endmodule ERROR
 */

/*! @endmodule PCRE
 */

/*! @endmodule Regexp
 */

   
#ifdef class_cq__pcre_defined

#ifdef PROG_CQ__PCRE_ID
  START_NEW_PROGRAM_ID(CQ__PCRE);
#else
  start_new_program();

#endif /* PROG_CQ__PCRE_ID */

#ifndef tObjImpl_CQ__PCRE

#undef tObjImpl_CQ__PCRE
#define tObjImpl_CQ__PCRE tObj

#endif /* tObjImpl_CQ__PCRE */

#ifdef THIS_CQ__PCRE

  cq__pcre_storage_offset=ADD_STORAGE(struct cq__pcre_struct);

#endif /* THIS_CQ__PCRE */

#ifdef var_pattern_cq__pcre_defined
  PIKE_MAP_VARIABLE("pattern", cq__pcre_storage_offset + OFFSETOF(cq__pcre_struct, pattern),
                    tString, PIKE_T_STRING, 0);
#endif /* var_pattern_cq__pcre_defined */

#ifdef cq__pcre_event_handler_defined
  pike_set_prog_event_callback(cq__pcre_event_handler);

#endif /* cq__pcre_event_handler_defined */

#ifdef f_cq__pcre_create_defined
#line 76 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
  f_cq__pcre_create_fun_num =
    ADD_FUNCTION2("create", f_cq__pcre_create, tFunc(tString tOr(tVoid,"\10\200\0\0\0\177\377\377\377") tOr(tVoid,tObj),tVoid), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_cq__pcre_create_defined */

#ifdef f_cq__pcre_study_defined
#line 130 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
  f_cq__pcre_study_fun_num =
    ADD_FUNCTION2("study", f_cq__pcre_study, tFunc(tNone,tObj), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_cq__pcre_study_defined */

#ifdef f_cq__pcre_cq__sprintf_defined
#line 148 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
  f_cq__pcre_cq__sprintf_fun_num =
    ADD_FUNCTION2("_sprintf", f_cq__pcre_cq__sprintf, tFunc("\10\200\0\0\0\177\377\377\377" tMapping,tString), ID_STATIC, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_cq__pcre_cq__sprintf_defined */

#ifdef f_cq__pcre_info_defined
#line 265 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
  f_cq__pcre_info_fun_num =
    ADD_FUNCTION2("info", f_cq__pcre_info, tFunc(tNone,tMapping), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_cq__pcre_info_defined */

#ifdef f_cq__pcre_exec_defined
#line 404 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
  f_cq__pcre_exec_fun_num =
    ADD_FUNCTION2("exec", f_cq__pcre_exec, tFunc(tString tOr(tVoid,"\10\200\0\0\0\177\377\377\377"),tOr("\10\200\0\0\0\177\377\377\377",tArr("\10\200\0\0\0\177\377\377\377"))), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_cq__pcre_exec_defined */

#ifdef f_cq__pcre_get_stringnumber_defined
#line 455 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
  f_cq__pcre_get_stringnumber_fun_num =
    ADD_FUNCTION2("get_stringnumber", f_cq__pcre_get_stringnumber, tFunc(tString,"\10\200\0\0\0\177\377\377\377"), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_cq__pcre_get_stringnumber_defined */
  cq__pcre_program=end_program();
  cq__pcre_program_fun_num=add_program_constant("_pcre",cq__pcre_program,0);

#endif /* class_cq__pcre_defined */

#ifdef f_split_subject_defined
#line 495 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
  f_split_subject_fun_num =
    ADD_FUNCTION2("split_subject", f_split_subject, tFunc(tString tArr("\10\200\0\0\0\177\377\377\377"),tArr(tString)), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_split_subject_defined */
#line 803 "/export/aphraelraid/home/peter/hack/Pike/7.6/src/modules/_Regexp_PCRE/pcre_glue.cmod"
#endif /* HAVE_LIBPCRE */
}

