/*************************************************************************
 * Log file format reading code
 * Copyright (c) 1998-9    Andy Kempling (aurikan@hotmail.com),
 * Copyright (c) 1998-2001 Colin Phipps (cph@lxdoom.linuxgames.com)
 *
 *  This program 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *************************************************************************/

/* $Id: log_regexp.c,v 1.7 2001/07/21 10:18:18 cph Exp $ */

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <ctype.h>

#include "ircstats.h"

const char nick_exp[] = { "^ @<>!:*" };
const char uh_exp[]   = { "^ :!*" };
const char nick_sub[] = { "[:nick:]" };
const char uh_sub[]   = { "[:uh:]" };

static const char* make_regexp(const char* str)
{
  size_t l;
  /* FUDGE: roughly speaking, even in the worse case we aren't likely 
   * to expand by much more than a factor of 3 */
  char *p = calloc(l = 3*strlen(str), sizeof(char));
  char *q = p;

  while (*str) {
    if (!strncmp(str, nick_sub, sizeof(nick_sub)-1)) {
      str += sizeof(nick_sub)-1;
      strcat(p, nick_exp); q += sizeof(nick_exp)-1;
    } else if (!strncmp(str, uh_sub, sizeof(uh_sub)-1)) {
      str += sizeof(uh_sub)-1;
      strcat(p, uh_exp); q += sizeof(uh_exp)-1;
    } else *q++ = *str++;
  }
  return p;
}

/* One string for each LT_type */
const char* lt_strings[] = { "null","text","act","join","part","quit","kick","topic","nick","mode","date_stamp","channel"};
/* One string for each LP_thing */
const char* lp_strings[] = { "time","nick","othernick","string","date","channel"};

struct log_parse_s* ReadLogFormatSpec(FILE* infp, int verbose)
{
#define BUFLEN 2048
  struct log_parse_s* plp = calloc(sizeof(struct log_parse_s), LT_NUM);
  char buf[BUFLEN];
  char lt_done[LT_NUM];
  int i;

  memset(lt_done,0,sizeof(lt_done)); lt_done[0] = 1; /* We want everything but null */
  if (sizeof(lt_strings) / sizeof(lt_strings[0]) != LT_NUM) {
    fprintf(stderr, "ReadLogFormatSpec: Internal LT inconsistency\n");
    exit(-1);
  }
  if (sizeof(lp_strings) / sizeof(lp_strings[0]) != LP_NUM) {
    fprintf(stderr, "ReadLogFormatSpec: Internal LP inconsistency\n");
    exit(-1);
  }

  while (1) {
    char *p,*q;
    if (!fgets(buf, BUFLEN, infp)) {
      if (feof(infp)) {
        for (i=0; i<LT_NUM; i++)
          if (!lt_done[i]) {
            fprintf(stderr, "No definition of %s found in format spec\n", lt_strings[i]);
            exit(-1);
        }
        return plp;
      } else {
        perror("ReadLogFormatSpec");
        exit(-1);
      }
    }
    if ((p = strchr(buf,';'))) *p = 0;  /* Remove comments         */
    if ((p = strchr(buf,'\n'))) *p = 0; /* Remove trailing newline */
    if ((p = strchr(buf,'='))) {
      enum line_type_e lt;

      *p++ = 0;
      for (i=0; i<LT_NUM; i++)
        if (!strcasecmp(buf, lt_strings[i])) break;
      lt = i;
      if (i == LT_NUM) fprintf(stderr, "Unrecognised line type %s\n", buf);
      else if (!*p) fprintf(stderr, "Bad regexp for %s\n", lt_strings[lt]);
      else if (lt_done[lt]) fprintf(stderr, "Repeat definition ignored for %s\n", lt_strings[lt]);
      else {
        int rc;
        
        q = strchr(p,',');
        if (q) *q++ = 0;
        p = make_regexp(p);
        if (!(rc = regcomp(&plp[lt].compiled_regex, p, REG_EXTENDED))) {
          if (verbose>1) fprintf(stderr, "Compiled regexp \"%s\" for %s\n", p, lt_strings[lt]);
          free(p);
          lt_done[lt] = 1; i = 0;
          while ((p = q) && *q) {
            int j;
            i++;
            q = strchr(p, ',');
            if (q) *q++ = 0;
            for (j=0; j<LP_NUM; j++)
              if (!strcasecmp(p, lp_strings[j])) break;
            if (strcasecmp(p, "null")) {
              if (j == LP_NUM) fprintf(stderr, "Unknown line part %s\n", p);
              else plp[lt].returned_bit[j] = i;
            }
          }
        } else {
          char errbuf[BUFLEN];
          regerror(rc, &plp[lt].compiled_regex, errbuf, BUFLEN);
          fprintf(stderr, "Error in \"%s\" - %s\n", p, errbuf);
          free(p);
        }
      }
    }
  }
  return NULL; /* Unreached */
}


syntax highlighted by Code2HTML, v. 0.9.1