%{ /* * $Id: aux-item-def-parse.y,v 1.25 2005/12/18 22:18:12 ceder Exp $ * Copyright (C) 1994-1996, 1999, 2001-2005 Lysator Academic Computer Association. * * This file is part of the LysKOM server. * * LysKOM is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * LysKOM 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 LysKOM; see the file COPYING. If not, write to * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, * MA 02139, USA. * * Please report bugs at http://bugzilla.lysator.liu.se/. */ /* Rename hack from the automake 1.4 manual. */ #define yymaxdepth aid_maxdepth #define yyparse aid_parse #define yylex aid_lex #define yyerror aid_error #define yylval aid_lval #define yychar aid_char #define yydebug aid_debug #define yypact aid_pact #define yyr1 aid_r1 #define yyr2 aid_r2 #define yydef aid_def #define yychk aid_chk #define yypgo aid_pgo #define yyact aid_act #define yyexca aid_exca #define yyerrflag aid_errflag #define yynerrs aid_nerrs #define yyps aid_ps #define yypv aid_pv #define yys aid_s #define yy_yys aid_yys #define yystate aid_state #define yytmp aid_tmp #define yyv aid_v #define yy_yyv aid_yyv #define yyval aid_val #define yylloc aid_lloc #define yyreds aid_reds #define yytoks aid_toks #define yylhs aid_yylhs #define yylen aid_yylen #define yydefred aid_yydefred #define yydgoto aid_yydgoto #define yysindex aid_yysindex #define yyrindex aid_yyrindex #define yygindex aid_yygindex #define yytable aid_yytable #define yycheck aid_yycheck #define yyname aid_yyname #define yyrule aid_yyrule #ifdef HAVE_CONFIG_H # include #endif #if STDC_HEADERS || HAVE_STRING_H # include #else # include #endif #ifdef HAVE_STDARG_H # include #endif #include #include #include "timewrap.h" #include "kom-types.h" #include "com.h" #include "async.h" #include "connections.h" #include "aux-items.h" #include "s-string.h" #include "server/smalloc.h" #include "lyskomd.h" #include "debug.h" #include "log.h" #include "string-malloc.h" #include "eintr.h" BUGDECL; #define YYDEBUG 1 static Aux_item_definition def; static Bool errorFlag = FALSE; extern int yylex(void); static char *inputFile; int aux_item_def_error_line; extern int yylineno; #if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H) void yyerror(const char * format, ...) # if HAVE_ATTRIBUTE_FORMAT_PRINTF __attribute__ ((format (printf, 1, 2))) # endif ; #else void yyerror(); #endif struct aux_item_def_value_type; static void chk_assign(int *, int *, const char *, void *, int, String, struct aux_item_def_value_type *, int); static Aux_item_flags * chk_flag_a(int *found, int *good, const char *id, String data, struct aux_item_def_value_type *val, int lineno); static const char *aux_item_def_typename(int); static void aux_item_def_check_trigger(int *found, int *good, const char *check_name, int type, String trigger_name, String function_name, unsigned long *counter, Aux_item_trigger **triggers); static void aux_item_def_check_validate(int *found, int *good, const char *check_name, String field_name, int type, String data, Aux_item_definition *def); #define YYERROR_VERBOSE %} %union { String str; unsigned long num; struct aux_item_def_value_type { int type; union { String str; unsigned long num; } val; } value; } %token NUMBER BOOLEAN %token ID STRING %token DISABLED TEXT CONFERENCE LETTERBOX TOK_SERVER TOK_ANY %token VOID CREATE MODIFY %type value %type action %% items : items item | /* Empty */ ; item : head '{' body '}' { if (def.tag != 0) { aux_item_definition_add(&def); } def = empty_aux_item_definition; } ; head : NUMBER ':' ID '(' targets ')' { def.tag = $1; def.name = s_crea_c_str($3); if (buglevel) { kom_log("Parsing definition of aux-item %ld (%s)\n", def.tag, def.name); } s_clear(&($3)); $3 = EMPTY_STRING; yylval.str = EMPTY_STRING; } | NUMBER ':' ID '(' targets ')' DISABLED { def.tag = $1; def.name = s_crea_c_str($3); def.disabled = TRUE; s_clear(&($3)); $3 = EMPTY_STRING; yylval.str = EMPTY_STRING; } ; targets : targets ',' target | target ; target : action TEXT { def.texts = TRUE; def.text_a = $1; } | action CONFERENCE { def.confs = TRUE; def.conf_a = $1; } | action LETTERBOX { def.letterboxes = TRUE; def.conf_a = $1; } | TOK_SERVER { def.system = TRUE; } | action TOK_ANY { def.texts = TRUE; def.text_a = $1; def.confs = TRUE; def.conf_a = $1; def.letterboxes = TRUE; def.system = TRUE; } ; action : action CREATE { $$ = $1 | AUX_ITEM_ADD_ON_CREATE; } | action MODIFY { $$ = $1 | AUX_ITEM_ADD_ON_MODIFY; } | /* Empty */ { $$ = 0; } ; body : body assign | body error | /* Empty */ ; assign : ID '=' value ';' { int found = 0; int good = 0; Aux_item_flags *f; chk_assign(&found, &good, "author-only", &def.author_only, BOOLEAN, $1, &$3, @3.first_line); chk_assign(&found, &good, "supervisor-only", &def.supervisor_only, BOOLEAN, $1, &$3, @3.first_line); chk_assign(&found, &good, "system-only", &def.system_only, BOOLEAN, $1, &$3, @3.first_line); chk_assign(&found, &good, "inherit-limit", &def.inherit_limit, NUMBER, $1, &$3, @3.first_line); chk_assign(&found, &good, "unique", &def.one_per_person, BOOLEAN, $1, &$3, @3.first_line); chk_assign(&found, &good, "unique-data", &def.unique_data, BOOLEAN, $1, &$3, @3.first_line); chk_assign(&found, &good, "permanent", &def.may_not_delete, BOOLEAN, $1, &$3, @3.first_line); chk_assign(&found, &good, "owner-delete", &def.owner_delete, BOOLEAN, $1, &$3, @3.first_line); if ((f = chk_flag_a(&found, &good, "inherit", $1, &$3, @3.first_line)) != NULL) f->inherit = 1; if ((f = chk_flag_a(&found, &good, "secret", $1, &$3, @3.first_line)) != NULL) f->secret = 1; if ((f = chk_flag_a(&found, &good, "hide-creator", $1, &$3, @3.first_line)) != NULL) f->hide_creator = 1; if ((f = chk_flag_a(&found, &good, "dont-garb", $1, &$3, @3.first_line)) != NULL) f->dont_garb = 1; if ((f = chk_flag_a(&found, &good, "reserved-2", $1, &$3, @3.first_line)) != NULL) f->reserved3 = 1; if ((f = chk_flag_a(&found, &good, "reserved-3", $1, &$3, @3.first_line)) != NULL) f->reserved4 = 1; if ((f = chk_flag_a(&found, &good, "reserved-4", $1, &$3, @3.first_line)) != NULL) f->reserved5 = 1; aux_item_def_check_validate(&found, &good, "validate", $1, $3.type, $3.val.str, &def); aux_item_def_check_trigger(&found, &good, "delete-trigger", $3.type, $1, $3.val.str, &def.num_delete_triggers, &def.delete_triggers); aux_item_def_check_trigger(&found, &good, "undelete-trigger", $3.type, $1, $3.val.str, &def.num_undelete_triggers, &def.undelete_triggers); aux_item_def_check_trigger(&found, &good, "add-trigger", $3.type, $1, $3.val.str, &def.num_add_triggers, &def.add_triggers); if (found == 0) { char *tmp; tmp = s_crea_c_str($1); aux_item_def_error_line = @1.first_line; yyerror("invalid field name: %s", tmp); string_free(tmp); } if ($3.type == STRING || $3.type == ID) { s_clear(&($3).val.str); $3.val.str = EMPTY_STRING; yylval.value.val.str = EMPTY_STRING; } s_clear(&($1)); $1 = EMPTY_STRING; yylval.str = EMPTY_STRING; } ; value : BOOLEAN { $$.val.num = $1; $$.type = BOOLEAN; } | STRING { $$.val.str = $1; $$.type = STRING; } | NUMBER { $$.val.num = $1; $$.type = NUMBER; } | ID '(' ')' { $$.val.str = $1; $$.type = ID;} | VOID { YYERROR; } ; %% extern FILE *yyin; #if defined(HAVE_VFPRINTF) && defined(HAVE_STDARG_H) void yyerror(const char *format, ...) { va_list AP; va_start(AP, format); fprintf(stderr, "%s: %d: ", inputFile, aux_item_def_error_line); vfprintf(stderr, format, AP); fprintf(stderr, "\n"); fflush(stderr); errorFlag = TRUE; va_end(AP); } #else void yyerror(const char *s, int a, int b, int c, int d, int e, int f, int g) { fprintf(stderr, "%s: %d: ", inputFile, aux_item_def_error_line); fprintf(stderr, format, a, b, c, d, e, f, g); fprintf(stderr, "\n"); fflush(stderr); errorFlag = TRUE; } #endif static const char *aux_item_def_typename(int type) { switch (type) { case STRING: return "string"; case NUMBER: return "number"; case BOOLEAN: return "boolean"; case ID: return "identifier"; default: return "unknown"; } } static void chk_assign(int *found, int *good, const char *id, void *data, int type, String field, struct aux_item_def_value_type *val, int lineno) { if (*found) return; if (!s_strcmp(s_fcrea_str(id), field)) { *found = 1; if (type != val->type) { aux_item_def_error_line = lineno; yyerror("invalid type: expected %s, got %s", aux_item_def_typename(type), aux_item_def_typename(val->type)); *good = 0; return; } else if (type == STRING) { *((char **)data) = s_crea_c_str(val->val.str); } else if (type == NUMBER) { *((unsigned long *)data) = val->val.num; } else if (type == BOOLEAN) { *((Bool *)data) = val->val.num ? TRUE : FALSE; } else { restart_kom("Internal error: bad type in aux-item definition " "assignment (can't happen.)\n"); } *good = 1; } } static Aux_item_flags * chk_flag_a(int *found, int *good, const char *id, String field, struct aux_item_def_value_type *val, int lineno) { if (*found) return NULL; if (!s_strcmp(s_fcrea_str(id), field)) { *found = 1; if (val->type != BOOLEAN ) { aux_item_def_error_line = lineno; yyerror("invalid type: expected %s, got %s", aux_item_def_typename(BOOLEAN), aux_item_def_typename(val->type)); *good = 0; } else { *good = 1; if (val->val.num) return &def.set_flags; else return &def.clear_flags; } } return NULL; } static void aux_item_def_check_trigger(int *found, int *good, const char *check_name, int type, String trigger_name, String function_name, unsigned long *counter, Aux_item_trigger **triggers) { Aux_item_trigger trigger; char *tmp_string; if (*found) return; if (s_strcmp(s_fcrea_str(check_name), trigger_name) == 0) { *found = 1; if (type != ID) { yyerror("invalid type: expected %s, got %s", aux_item_def_typename(ID), aux_item_def_typename(type)); return; } tmp_string = s_crea_c_str(function_name); trigger = aux_item_find_trigger(tmp_string); if (trigger == NULL) { yyerror("undefined function: %s", tmp_string); string_free(tmp_string); return; } string_free(tmp_string); *counter += 1; *triggers = srealloc(*triggers, *counter * sizeof(Aux_item_trigger)); *triggers[*counter-1] = trigger; *good = 1; } } void parse_aux_item_definitions(char *file) { inputFile = file; yyin = i_fopen(file, "r"); if (yyin == NULL) { perror(file); restart_kom("Unable to open aux-item definition file\n"); } def = empty_aux_item_definition; yyparse(); i_fclose(yyin); if (errorFlag == TRUE) { restart_kom("Errors reading aux-item definition file\n"); } /* { extern Aux_item_definition *aux_item_definition_list; extern unsigned long num_aux_item_definitions; Aux_item_definition *def; fprintf(stderr, "Number of defs: %ld\n", num_aux_item_definitions); def = aux_item_definition_list; while (def != NULL) { fprintf(stderr, "Name: '%s'\n", def->name); fprintf(stderr, "Tag: %ld\n", def->tag); fprintf(stderr, "Clear flags: "); if (def->clear_flags.deleted) fprintf(stderr, "deleted "); if (def->clear_flags.inherit) fprintf(stderr, "inherit "); if (def->clear_flags.secret) fprintf(stderr, "secret "); if (def->clear_flags.hide_creator) fprintf(stderr,"hide_creator "); if (def->clear_flags.reserved2) fprintf(stderr, "reserved2 "); if (def->clear_flags.reserved3) fprintf(stderr, "reserved3 "); if (def->clear_flags.reserved4) fprintf(stderr, "reserved4 "); if (def->clear_flags.reserved5) fprintf(stderr, "reserved5 "); fprintf(stderr, "\n"); fprintf(stderr, "Set flags: "); if (def->set_flags.deleted) fprintf(stderr, "deleted "); if (def->set_flags.inherit) fprintf(stderr, "inherit "); if (def->set_flags.secret) fprintf(stderr, "secret "); if (def->set_flags.hide_creator) fprintf(stderr,"hide_creator "); if (def->set_flags.reserved2) fprintf(stderr, "reserved2 "); if (def->set_flags.reserved3) fprintf(stderr, "reserved3 "); if (def->set_flags.reserved4) fprintf(stderr, "reserved4 "); if (def->set_flags.reserved5) fprintf(stderr, "reserved5 "); fprintf(stderr, "\n"); fprintf(stderr, "Author only: %d\n", def->author_only); fprintf(stderr, "Supervisor only: %d\n", def->supervisor_only); fprintf(stderr, "Unique: %d\n", def->one_per_person); fprintf(stderr, "Unique-data: %d\n", def->unique_data); fprintf(stderr, "Permanent: %d\n", def->may_not_delete); fprintf(stderr, "Inherit limit: %ld\n", def->inherit_limit); fprintf(stderr, "Texts: %d\n", def->texts); fprintf(stderr, "Conferences: %d\n", def->confs); fprintf(stderr, "Letterboxes: %d\n", def->letterboxes); fprintf(stderr, "Validate regexp: '%s'\n", def->validate_regexp?def->validate_regexp:"0x0"); def = def->next; } } */ } static void aux_item_def_check_validate(int *found, int *good, const char *check_name, String field_name, int type, String data, Aux_item_definition *def) { Aux_item_validation_function validator; char *tmp_string; if (*found) return; if (s_strcmp(s_fcrea_str(check_name), field_name) == 0) { *found = 1; /* * Validator is a function */ if (type == ID) { tmp_string = s_crea_c_str(data); validator = aux_item_find_validator(tmp_string); if (validator == NULL) { yyerror("undefined function: %s", tmp_string); string_free(tmp_string); return; } string_free(tmp_string); def->num_validators += 1; def->validators = srealloc(def->validators, def->num_validators * sizeof(*def->validators)); def->validators[def->num_validators-1].type = AUX_VALIDATE_FUNCTION; def->validators[def->num_validators-1].v.fn.function = validator; *good = 1; } else if (type == STRING) { /* * Validator is a string (regexp) */ def->num_validators += 1; def->validators = srealloc(def->validators, def->num_validators * sizeof(*def->validators)); def->validators[def->num_validators-1].type = AUX_VALIDATE_REGEXP; def->validators[def->num_validators-1].v.re.regexp = s_crea_c_str(data); def->validators[def->num_validators-1].v.re.cached_re_buf = NULL; *good = 1; } else { yyerror("invalid type: expected %s or %s, got %s", aux_item_def_typename(ID), aux_item_def_typename(STRING), aux_item_def_typename(type)); } } }