Plan 9 from Bell Labs’s /usr/web/sources/contrib/de0u/root/sys/src/cmd/divergefs/config.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <String.h>
#include "common.h"
#include "debug.h"
#include "string.h"
#include "collection.h"
#include "function.h"
#include "array.h"
#include "rule.h"
#include "namerule.h"
#include "logicalrule.h"
#include "regexrule.h"
#include "moderule.h"
#include "allrule.h"
#include "filepath.h"
#include "file.h"
#include "holemanager.h"
#include "filehandle.h"
#include "fiddata.h"
#include "qidgenerator.h"
#include "matcher.h"
#include "configyacclex.h"
#include "config.h"

enum { DEBUG_CONFIG = false };

extern int infd; // extern from lex.yy.c

typedef struct Config
{
  int *input;
  Matcher *matcher;
  char *absolutepath;
  Array *stack;
} Config;

static Config configInstance;

Config *config_instance(void)
{
  return &configInstance;
}

static void config_set_absolutepath(Config *self, char *path)
{
  String *absolute;
  assert_valid(self);
  assert_valid(path);

  free(self->absolutepath);
  absolute = s_copy(path);
  filepath_make_absolute(&absolute);
  self->absolutepath = string_convert_escaped(estrdup_fs(s_to_c(absolute)));
  s_free(absolute);
}

void config_set_currentpath(char *path)
{
  assert_valid(path);
  config_set_absolutepath(config_instance(), path);
}


typedef Rule *(*rule_parse)(char *rule, char *setting, char *path);

static rule_parse ruleParserRegistry[] =
{
  extensionrule_parse,
  fileregexrule_parse,
  dirregexrule_parse,
  regexrule_parse,
  moderule_parse,
  allrule_parse
};

static Rule *config_parse_rule(Config *self, char *rule, char *setting)
{
  int i;
  int registrysize = static_array_length(ruleParserRegistry);
  Rule *result = nil;
  char *converted;
  assert_valid(self);

  converted = string_convert_single_escaped(estrdup_fs(setting), '>', '>');

  NOISE(DEBUG_CONFIG, 
    "rule name: %s setting: %s converted: %s path: %s", 
    rule, setting, converted, self->absolutepath);

  for(i = 0; i < registrysize && result == nil; ++i)
  {
    result = ruleParserRegistry[i](rule, converted, self->absolutepath);
  }

  free(converted);
  return result;
}

static void config_push_and_rule(Config *self)
{
  Rule *first;
  Rule *second;
  assert_valid(self);
  
  NOISE(DEBUG_CONFIG, "config_push_and_rule with stack size: %d",
      array_size(self->stack));

  second = (Rule *)array_pop(self->stack);
  first = (Rule *)array_pop(self->stack);
  array_push(self->stack, andrule_new(first, second, self->absolutepath));
}

static void config_push_or_rule(Config *self)
{
  Rule *first;
  Rule *second;
  assert_valid(self);
  
  NOISE(DEBUG_CONFIG, "config_push_or_rule with stack size: %d",
      array_size(self->stack));
  second = (Rule *)array_pop(self->stack);
  first = (Rule *)array_pop(self->stack);
  array_push(self->stack, orrule_new(first, second, self->absolutepath));
}

void config_and_setting(void)
{
  config_push_and_rule(config_instance());
}

void config_or_setting(void)
{
  config_push_or_rule(config_instance());
}

static void config_push_rule(Config *self, Rule *rule)
{
  assert_valid(self);
  assert_valid(rule);

  array_push(self->stack, rule);
}

bool config_push_setting(char *rulename, char *setting)
{
  Rule *rule;
  assert_valid(rulename);
  assert_valid(setting);

  rule = config_parse_rule(config_instance(), rulename, setting);
  if(rule == nil)
  {
    return false;
  }

  config_push_rule(config_instance(), rule);
  return true;
}

static void config_add_rule(Config *self)
{
  assert_valid(self);

  NOISE(DEBUG_CONFIG, "entering config_add_rule with stack size: %d",
      array_size(self->stack));

  matcher_add(self->matcher, array_pop(self->stack));
  assert(array_isempty(self->stack));
}

void config_rule_end(void)
{
  NOISE(DEBUG_CONFIG, "config_rule_end done with rule");
  config_add_rule(config_instance());
}


static bool config_init(Config *self, Matcher *matcher, char *file)
{
  assert_valid(self);
  assert_valid(matcher);
  assert_valid(file);

  self->input = &infd;
  *(self->input) = file_open(file, OREAD);
  if(!fd_isopen(*(self->input)))
  {
    ERROR(DEBUG_CONFIG, "config_init failed to open file: %s", file);
    return false;
  }

  self->matcher = matcher;
  self->absolutepath = nil;
  self->stack = array_new();
  return true;
}

static void config_destroy(Config *self)
{
  if(self == nil)
  {
    return;
  }
  
  array_free_with(self->stack, (functionunary)rule_free);
  self->stack = nil;
  free(self->absolutepath);
  self->absolutepath = nil;
  self->matcher = nil;
  file_close(*(self->input));
  *(self->input) = INVALID_FD;
}

static bool config_yyparse(void)
{
  NOISE(DEBUG_CONFIG, "config_yyparse about to call yyparse");
  return yyparse() == CONFIG_YACC_SUCCESS;
}

bool config_parse(Matcher *matcher, char *file)
{
  bool result;
  assert_valid(matcher);
  assert_valid(file);

  if(!config_init(config_instance(), matcher, file))
  {
    return false;
  }

  result = config_yyparse();
  NOISE(DEBUG_CONFIG, "config_parse done parsing with result: %d", result);
  
  config_destroy(config_instance());
  return result;
}



Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.