/* Generated from "/Users/hww3/pikebuild/src/facetgroup.cmod" by precompile.pike
 *
 * Do NOT edit this file.
 */

#undef PRECOMPILE_API_VERSION
#define PRECOMPILE_API_VERSION 5



#undef cmod___CMOD__
#define cmod___CMOD__ 1
#line 1 "/Users/hww3/pikebuild/src/facetgroup.cmod"
#line 1 "/Users/hww3/pikebuild/src/facetgroup.cmod"
#line 1 "/Users/hww3/pikebuild/src/facetgroup.cmod"
#line 2816 "/usr/local/pike/8.0.1/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike"







#line 2823 "/usr/local/pike/8.0.1/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike"
#line 1 "/Users/hww3/pikebuild/src/facetgroup.cmod"
#line 1 "/Users/hww3/pikebuild/src/facetgroup.cmod"
/* -*- c -*- 
|| 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: 6e7d5948733854b6414a5d956bcf8c149cd044ea $
*/

#include "global.h"
#include "fdlib.h"
#include "main.h"
#include "object.h"
#include "mapping.h"
#include "multiset.h"
#include "svalue.h"
#include "stralloc.h"
#include "array.h"
#include "pike_macros.h"
#include "pike_error.h"
#include "pike_memory.h"
#include "dynamic_buffer.h"
#include "interpret.h"
#include "las.h"
#include "gc.h"
#include "stralloc.h"
#include "opcodes.h"
#include "pike_error.h"
#include "program.h"
#include "operators.h"
#include "builtin_functions.h"
#include "constants.h"
#include "program.h"
#include "block_alloc.h"



#ifndef TYPEOF
/* Compat with older Pikes. */
#define TYPEOF(SVAL)	((SVAL).type)
#define SUBTYPEOF(SVAL)	((SVAL).subtype)
#define SET_SVAL_TYPE(SVAL, TYPE)	(TYPEOF(SVAL) = TYPE)
#define SET_SVAL_SUBTYPE(SVAL, TYPE)	(SUBTYPEOF(SVAL) = TYPE)
#define SET_SVAL(SVAL, TYPE, SUBTYPE, FIELD, EXPR) do {	\
    /* Set the type afterwards to avoid a clobbered	\
     * svalue in case EXPR throws. */			\
    (SVAL).u.FIELD = (EXPR);				\
    SET_SVAL_TYPE((SVAL), (TYPE));			\
    SET_SVAL_SUBTYPE((SVAL), (SUBTYPE));		\
  } while(0)
#endif /* !TYPEOF */


#ifndef DEFAULT_CMOD_STORAGE
#define DEFAULT_CMOD_STORAGE
#endif
#line 36 "/Users/hww3/pikebuild/src/facetgroup.cmod"
#ifdef WITH_FACETS

/*! @class FacetGroup
 *! 
 *! This class is used to handle facets in the system. All facets 
 *! in the system have to belong to a facet group. A facet 
 *! group is a pike module that inherits from this class. For 
 *! example you can create a file MyFacetgroup.pmod with the following
 *! content:
 *!
 *! @code
 *!   inherit FacetGroup;
 *! @endcode
 *!
 *! You can then use the facet group MyFacetGroup in a facet-class 
 *! like this:
 *!
 *! @code
 *! class A
 *! {
 *!   facet NameOfMyFacet : .MyFacetGroup; 
 *!   // Rest of class A 
 *! }
 *! @endcode
 *!
 */

/* Linked list of facet-classes */
struct facet_class_struct { 
int id;
struct facet_class_struct *next;
};

/* Linked list of facets with their facet-classes */
struct facet_node_struct {
struct pike_string *name;
struct facet_class_struct *classes;
struct facet_node_struct *next;
};

/* Linked list of facets a product class is inheriting from */
struct facet_list_struct {
int facet_index;
int facet_class;
struct facet_list_struct *next;
};

/* Linked list of product classes with lists of what facets they use */
struct product_class_struct {
int id;
struct facet_list_struct *facets;
int num_used_facets;
struct product_class_struct *next;
};

BLOCK_ALLOC_FILL_PAGES(facet_class_struct, 2)
BLOCK_ALLOC_FILL_PAGES(facet_node_struct, 2)
BLOCK_ALLOC_FILL_PAGES(product_class_struct, 2)
BLOCK_ALLOC_FILL_PAGES(facet_list_struct, 2)

/* The actual facet_group class */

#undef class_facet_group_defined
#define class_facet_group_defined
DEFAULT_CMOD_STORAGE struct program *facet_group_program=NULL;
static int facet_group_program_fun_num=-1;

#undef var_facets_facet_group_defined
#define var_facets_facet_group_defined

#undef var_pclasses_facet_group_defined
#define var_pclasses_facet_group_defined

#undef var_num_facets_facet_group_defined
#define var_num_facets_facet_group_defined

#undef var_checked_product_classes_facet_group_defined
#define var_checked_product_classes_facet_group_defined

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

#undef THIS_FACET_GROUP
#define THIS_FACET_GROUP ((struct facet_group_struct *)(Pike_interpreter.frame_pointer->current_storage))

#undef OBJ2_FACET_GROUP
#define OBJ2_FACET_GROUP(o) ((struct facet_group_struct *)(o->storage+facet_group_storage_offset))

#undef GET_FACET_GROUP_STORAGE
#define GET_FACET_GROUP_STORAGE(o) ((struct facet_group_struct *)(o->storage+facet_group_storage_offset)
static ptrdiff_t facet_group_storage_offset;
struct facet_group_struct {

#ifdef var_facets_facet_group_defined
#line 99 "/Users/hww3/pikebuild/src/facetgroup.cmod"
struct facet_node_struct *facets;
#endif /* var_facets_facet_group_defined */

#ifdef var_pclasses_facet_group_defined
#line 100 "/Users/hww3/pikebuild/src/facetgroup.cmod"
struct product_class_struct *pclasses;
#endif /* var_pclasses_facet_group_defined */

#ifdef var_num_facets_facet_group_defined
#line 101 "/Users/hww3/pikebuild/src/facetgroup.cmod"
int num_facets;
#endif /* var_num_facets_facet_group_defined */

#ifdef var_checked_product_classes_facet_group_defined
#line 102 "/Users/hww3/pikebuild/src/facetgroup.cmod"
int checked_product_classes;
#endif /* var_checked_product_classes_facet_group_defined */
};
#ifdef PIKE_DEBUG
/* Ensure the struct is used in a variable declaration, or else gdb might not see it. */
static struct facet_group_struct *facet_group_gdb_dummy_ptr;
#endif
#line 104 "/Users/hww3/pikebuild/src/facetgroup.cmod"
/* Retruns 1 if product classes in this facet group have been checked,
   * 0 otherwise */
#define f_facet_group_product_classes_checked_defined
DEFAULT_CMOD_STORAGE ptrdiff_t f_facet_group_product_classes_checked_fun_num = 0;
DEFAULT_CMOD_STORAGE void f_facet_group_product_classes_checked(INT32 args) {
#line 106 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(args != 0) wrong_number_of_args_error("product_classes_checked",args,0);
#line 106 "/Users/hww3/pikebuild/src/facetgroup.cmod"
{
do { INT_TYPE ret_=(THIS->checked_product_classes);  push_int(ret_); return; }while(0);
#line 108 "/Users/hww3/pikebuild/src/facetgroup.cmod"
}

}
#line 110 "/Users/hww3/pikebuild/src/facetgroup.cmod"
/* Function to check that all product-classes inherits from all facet */
#define f_facet_group_check_product_classes_defined
DEFAULT_CMOD_STORAGE ptrdiff_t f_facet_group_check_product_classes_fun_num = 0;
DEFAULT_CMOD_STORAGE void f_facet_group_check_product_classes(INT32 args) {
#line 111 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(args != 0) wrong_number_of_args_error("check_product_classes",args,0);
#line 111 "/Users/hww3/pikebuild/src/facetgroup.cmod"
{
struct facet_list_struct *fl;
struct product_class_struct *pc;
int error = 0;
for(pc=THIS->pclasses; pc; pc = pc->next) {
if (pc->num_used_facets < THIS->num_facets) {
my_yyerror("Product class only inherits from %d out of %d facets.",
pc->num_used_facets, THIS->num_facets);
}
#ifdef PIKE_DEBUG
 else if (pc->num_used_facets > THIS->num_facets) {
/* It should be impossible to get here */
yyerror("Product class inherits more than once from some facet.");
}
#endif
 }
THIS->checked_product_classes = 1;
pop_n_elems(args);
}

}
#line 131 "/Users/hww3/pikebuild/src/facetgroup.cmod"
/* Add info that the class "class" inherits from the facet "facet_index" */
#define f_facet_group_add_product_class_defined
DEFAULT_CMOD_STORAGE ptrdiff_t f_facet_group_add_product_class_fun_num = 0;
DEFAULT_CMOD_STORAGE void f_facet_group_add_product_class(INT32 args) {
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
INT_TYPE class;
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
INT_TYPE facet_index;
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
INT_TYPE facet_class;
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(args != 3) wrong_number_of_args_error("add_product_class",args,3);
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(TYPEOF(Pike_sp[0-3]) != PIKE_T_INT) SIMPLE_ARG_TYPE_ERROR("add_product_class",1,"int");
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
class=Pike_sp[0-3].u.integer;
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(TYPEOF(Pike_sp[1-3]) != PIKE_T_INT) SIMPLE_ARG_TYPE_ERROR("add_product_class",2,"int");
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
facet_index=Pike_sp[1-3].u.integer;
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(TYPEOF(Pike_sp[2-3]) != PIKE_T_INT) SIMPLE_ARG_TYPE_ERROR("add_product_class",3,"int");
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
facet_class=Pike_sp[2-3].u.integer;
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
{
struct facet_list_struct *fl, *fltmp;
struct product_class_struct *pc, *pctmp;

/* Set checked_product_classes to 0 to indicate that not all
     * product classes have been checked */
THIS->checked_product_classes = 0;

/* Check whether the product class is allready in our list of
     * product classes */
for (pc=THIS->pclasses; pc; pc = pc->next) {
if (class == pc->id)
break;
}

if (!pc) { /* New product class */
pctmp = alloc_product_class_struct();
pctmp->id = class;
pctmp->facets = NULL;
pctmp->num_used_facets = 0;
pctmp->next = THIS->pclasses;
THIS->pclasses = pctmp;
pc = pctmp;
}

/* pc now points to the product class to modify */
for(fl=pc->facets; fl; fl = fl->next) {
if (fl->facet_index == facet_index)
break;
}
if (!fl) {
/*Add facet "facet_index" to product class "class"'s inherits */
fltmp = alloc_facet_list_struct();
fltmp->facet_index = facet_index;
fltmp->facet_class = facet_class;
pc->num_used_facets++;
fltmp->next = pc->facets;
pc->facets = fltmp;
}
else /* The product class already inherits from this facet */
if (fl->facet_class != facet_class)
yyerror("Product class can only inherit from one class in every facet.");
pop_n_elems(args);
}

}
#line 177 "/Users/hww3/pikebuild/src/facetgroup.cmod"
/* Add a facet class in the facet group */
#define f_facet_group_add_facet_class_defined
DEFAULT_CMOD_STORAGE ptrdiff_t f_facet_group_add_facet_class_fun_num = 0;
DEFAULT_CMOD_STORAGE void f_facet_group_add_facet_class(INT32 args) {
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
struct pike_string * facet;
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
INT_TYPE class;
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
INT_TYPE product_class;
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(args != 3) wrong_number_of_args_error("add_facet_class",args,3);
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(TYPEOF(Pike_sp[0-3]) != PIKE_T_STRING) SIMPLE_ARG_TYPE_ERROR("add_facet_class",1,"string");
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
debug_malloc_pass(facet=Pike_sp[0-3].u.string);
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(TYPEOF(Pike_sp[1-3]) != PIKE_T_INT) SIMPLE_ARG_TYPE_ERROR("add_facet_class",2,"int");
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
class=Pike_sp[1-3].u.integer;
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
if(TYPEOF(Pike_sp[2-3]) != PIKE_T_INT) SIMPLE_ARG_TYPE_ERROR("add_facet_class",3,"int");
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
product_class=Pike_sp[2-3].u.integer;
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
{
struct facet_class_struct *c, *ctmp;
struct facet_node_struct *f, *prevf, *ftmp;
struct product_class_struct *pc, *prevpc;
struct object *o;
int facet_index = 0;

/* Check if it is a new facet or not. */
prevf = NULL;
for(f=THIS->facets; f; f=f->next, facet_index++) {
if ( is_same_string(f->name,facet) )
break;
prevf=f;
}

if (product_class) {
/* This occurs if the inherit statement comes before the facet */
/* statement in the class */
for (prevpc=pc=THIS->pclasses; pc; pc = pc->next) {
if (pc->id == class)
break;
prevpc = pc;
}
if (!pc)
yyerror("Program marked as product class but not found in list of product classes.");
else {
if (pc->num_used_facets > 1 ||
facet_index != pc->facets->facet_index)
yyerror("Facet class can not inherit from a class in another facet.");
else {
if (prevpc->id == pc->id)
THIS->pclasses = pc->next;
else
prevpc->next = pc->next;
really_free_product_class_struct(pc);
}
}
}

if (!f) { /* A new facet */
THIS->num_facets++;
f = alloc_facet_node_struct();
add_ref(f->name = facet);
f->next = NULL;
if (!prevf)
THIS->facets = f;
else
prevf->next = f;
f->classes = NULL;
}

/* f now points to the facet 'facet' in 'facets' */
/* Check whether the class 'class' is already in the facet */
for (c=f->classes; c; c = c->next) {
if (class == c->id)
break;
}

if (c)
yyerror("Redundant facet statement.");
else {
ctmp = alloc_facet_class_struct();
ctmp->id = class;
ctmp->next = f->classes;
f->classes = ctmp;
}

do { INT_TYPE ret_=(facet_index); pop_n_elems(3); push_int(ret_); return; }while(0);
#line 246 "/Users/hww3/pikebuild/src/facetgroup.cmod"
}

}

#undef internal_init_facet_group_defined
#define internal_init_facet_group_defined

#undef facet_group_event_handler_defined
#define facet_group_event_handler_defined
static void init_facet_group_struct(void)
#line 248 "/Users/hww3/pikebuild/src/facetgroup.cmod"
{
THIS->facets = NULL;
THIS->pclasses = NULL;
THIS->num_facets = 0;
THIS->checked_product_classes = 0;
}


#undef facet_group_gc_live_obj
#define facet_group_gc_live_obj

#undef internal_exit_facet_group_defined
#define internal_exit_facet_group_defined

#undef facet_group_event_handler_defined
#define facet_group_event_handler_defined
static void exit_facet_group_struct(void)
#line 255 "/Users/hww3/pikebuild/src/facetgroup.cmod"
{
struct facet_node_struct *f, *fnext;
struct facet_class_struct *fc, *fcnext;
struct product_class_struct *p, *pnext;
struct facet_list_struct *fl, *flnext;
for (fnext=f=THIS->facets; fnext; f=fnext) {
fnext = f->next;
for (fcnext=fc=f->classes; fcnext; fc=fcnext) {
fcnext = fc->next;
really_free_facet_class_struct(fc);
}
free_string(f->name);
really_free_facet_node_struct(f);
}
for (pnext=p=THIS->pclasses; pnext; p=pnext) {
pnext = p->next;
for (flnext=fl=p->facets; flnext; fl=flnext) {
flnext = fl->next;
really_free_facet_list_struct(fl);
}
really_free_product_class_struct(p);
}
}

#ifdef facet_group_event_handler_defined
static void facet_group_event_handler(int ev) {
  switch(ev) {

#ifdef internal_init_facet_group_defined
  case PROG_EVENT_INIT: init_facet_group_struct(); break;

#endif /* internal_init_facet_group_defined */

#ifdef internal_exit_facet_group_defined
  case PROG_EVENT_EXIT: exit_facet_group_struct(); break;

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

#endif /* facet_group_event_handler_defined */
#line 278 "/Users/hww3/pikebuild/src/facetgroup.cmod"
;

void init_facetgroup(void)
{
init_facet_class_struct_blocks();
init_facet_node_struct_blocks();
init_facet_list_struct_blocks();
init_product_class_struct_blocks();

#ifdef class_facet_group_defined

#ifdef PROG_FACET_GROUP_ID
#line 97 "/Users/hww3/pikebuild/src/facetgroup.cmod"
  START_NEW_PROGRAM_ID(FACET_GROUP);
#else
#line 97 "/Users/hww3/pikebuild/src/facetgroup.cmod"
  start_new_program();

#endif /* PROG_FACET_GROUP_ID */

#ifndef tObjImpl_FACET_GROUP

#undef tObjImpl_FACET_GROUP
#define tObjImpl_FACET_GROUP tObj

#endif /* tObjImpl_FACET_GROUP */

#ifdef THIS_FACET_GROUP
  facet_group_storage_offset = ADD_STORAGE(struct facet_group_struct);
#endif /* THIS_FACET_GROUP */

#ifdef facet_group_event_handler_defined
  pike_set_prog_event_callback(facet_group_event_handler);

#ifndef facet_group_gc_live_obj
  Pike_compiler->new_program->flags &= ~PROGRAM_LIVE_OBJ;

#endif /* facet_group_gc_live_obj */

#endif /* facet_group_event_handler_defined */

#ifdef f_facet_group_product_classes_checked_defined
  f_facet_group_product_classes_checked_fun_num =
#line 106 "/Users/hww3/pikebuild/src/facetgroup.cmod"
    ADD_FUNCTION2("product_classes_checked", f_facet_group_product_classes_checked, tFunc(tNone,"\10\200\0\0\0\177\377\377\377"), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_facet_group_product_classes_checked_defined */

#ifdef f_facet_group_check_product_classes_defined
  f_facet_group_check_product_classes_fun_num =
#line 111 "/Users/hww3/pikebuild/src/facetgroup.cmod"
    ADD_FUNCTION2("check_product_classes", f_facet_group_check_product_classes, tFunc(tNone,tVoid), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_facet_group_check_product_classes_defined */

#ifdef f_facet_group_add_product_class_defined
  f_facet_group_add_product_class_fun_num =
#line 132 "/Users/hww3/pikebuild/src/facetgroup.cmod"
    ADD_FUNCTION2("add_product_class", f_facet_group_add_product_class, tFunc("\10\200\0\0\0\177\377\377\377" "\10\200\0\0\0\177\377\377\377" "\10\200\0\0\0\177\377\377\377",tVoid), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_facet_group_add_product_class_defined */

#ifdef f_facet_group_add_facet_class_defined
  f_facet_group_add_facet_class_fun_num =
#line 178 "/Users/hww3/pikebuild/src/facetgroup.cmod"
    ADD_FUNCTION2("add_facet_class", f_facet_group_add_facet_class, tFunc(tStr "\10\200\0\0\0\177\377\377\377" "\10\200\0\0\0\177\377\377\377","\10\200\0\0\0\177\377\377\377"), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_facet_group_add_facet_class_defined */
#line 97 "/Users/hww3/pikebuild/src/facetgroup.cmod"
  facet_group_program=end_program();
#line 97 "/Users/hww3/pikebuild/src/facetgroup.cmod"
  facet_group_program_fun_num=add_program_constant("facet_group",facet_group_program,0);

#endif /* class_facet_group_defined */
#line 286 "/Users/hww3/pikebuild/src/facetgroup.cmod"
;
add_global_program("FacetGroup", facet_group_program);
}

void exit_facetgroup(void)
{

#ifdef class_facet_group_defined
  if(facet_group_program) {
#line 97 "/Users/hww3/pikebuild/src/facetgroup.cmod"
    free_program(facet_group_program);
    facet_group_program=0;
  }

#endif /* class_facet_group_defined */
#line 293 "/Users/hww3/pikebuild/src/facetgroup.cmod"
}

/*! @endclass
 */

#endif

