[BACK]Return to mansearch.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/mansearch.c between version 1.12 and 1.13

version 1.12, 2013/12/31 03:41:14 version 1.13, 2014/01/04 23:43:53
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 62  struct expr {
Line 62  struct expr {
         uint64_t         bits;    /* type-mask */          uint64_t         bits;    /* type-mask */
         const char      *substr;  /* to search for, if applicable */          const char      *substr;  /* to search for, if applicable */
         regex_t          regexp;  /* compiled regexp, if applicable */          regex_t          regexp;  /* compiled regexp, if applicable */
           int              open;    /* opening parentheses before */
           int              and;     /* logical AND before */
           int              close;   /* closing parentheses after */
         struct expr     *next;    /* next in sequence */          struct expr     *next;    /* next in sequence */
 };  };
   
Line 131  static struct expr *exprcomp(const struct mansearch *,
Line 134  static struct expr *exprcomp(const struct mansearch *,
                                 int, char *[]);                                  int, char *[]);
 static  void             exprfree(struct expr *);  static  void             exprfree(struct expr *);
 static  struct expr     *exprterm(const struct mansearch *, char *, int);  static  struct expr     *exprterm(const struct mansearch *, char *, int);
   static  void             sql_append(char **sql, size_t *sz,
                                   const char *newstr, int count);
 static  void             sql_match(sqlite3_context *context,  static  void             sql_match(sqlite3_context *context,
                                 int argc, sqlite3_value **argv);                                  int argc, sqlite3_value **argv);
 static  void             sql_regexp(sqlite3_context *context,  static  void             sql_regexp(sqlite3_context *context,
Line 276  mansearch(const struct mansearch *search,
Line 281  mansearch(const struct mansearch *search,
                  * distribution of buckets in the table.                   * distribution of buckets in the table.
                  */                   */
                 while (SQLITE_ROW == (c = sqlite3_step(s))) {                  while (SQLITE_ROW == (c = sqlite3_step(s))) {
                         id = sqlite3_column_int64(s, 0);                          id = sqlite3_column_int64(s, 5);
                         idx = ohash_lookup_memory                          idx = ohash_lookup_memory
                                 (&htab, (char *)&id,                                  (&htab, (char *)&id,
                                  sizeof(uint64_t), (uint32_t)id);                                   sizeof(uint64_t), (uint32_t)id);
Line 287  mansearch(const struct mansearch *search,
Line 292  mansearch(const struct mansearch *search,
                         mp = mandoc_calloc(1, sizeof(struct match));                          mp = mandoc_calloc(1, sizeof(struct match));
                         mp->id = id;                          mp->id = id;
                         mp->file = mandoc_strdup                          mp->file = mandoc_strdup
                                 ((char *)sqlite3_column_text(s, 3));                                  ((char *)sqlite3_column_text(s, 0));
                         mp->desc = mandoc_strdup                          mp->desc = mandoc_strdup
                                 ((char *)sqlite3_column_text(s, 4));                                  ((char *)sqlite3_column_text(s, 3));
                         mp->form = sqlite3_column_int(s, 5);                          mp->form = sqlite3_column_int(s, 4);
                         ohash_insert(&htab, idx, mp);                          ohash_insert(&htab, idx, mp);
                 }                  }
   
Line 454  sql_regexp(sqlite3_context *context, int argc, sqlite3
Line 459  sql_regexp(sqlite3_context *context, int argc, sqlite3
             0, NULL, 0));              0, NULL, 0));
 }  }
   
   static void
   sql_append(char **sql, size_t *sz, const char *newstr, int count)
   {
           size_t           newsz;
   
           newsz = 1 < count ? (size_t)count : strlen(newstr);
           *sql = mandoc_realloc(*sql, *sz + newsz + 1);
           if (1 < count)
                   memset(*sql + *sz, *newstr, (size_t)count);
           else
                   memcpy(*sql + *sz, newstr, newsz);
           *sz += newsz;
           (*sql)[*sz] = '\0';
   }
   
 /*  /*
  * Prepare the search SQL statement.   * Prepare the search SQL statement.
  * We search for any of the words specified in our match expression.  
  * We filter the per-doc AND expressions when collecting results.  
  */   */
 static char *  static char *
 sql_statement(const struct expr *e, const char *arch, const char *sec)  sql_statement(const struct expr *e, const char *arch, const char *sec)
 {  {
         char            *sql;          char            *sql;
         const char      *substr = "(key MATCH ? AND bits & ?)";  
         const char      *regexp = "(key REGEXP ? AND bits & ?)";  
         const char      *andarch = "arch = ? AND ";  
         const char      *andsec = "sec = ? AND ";  
         size_t           substrsz;  
         size_t           regexpsz;  
         size_t           sz;          size_t           sz;
           int              needop;
   
         sql = mandoc_strdup          sql = mandoc_strdup("SELECT * FROM mpages WHERE ");
                 ("SELECT pageid,bits,key,file,desc,form,sec,arch "  
                  "FROM keys "  
                  "INNER JOIN mpages ON mpages.id=keys.pageid "  
                  "WHERE ");  
         sz = strlen(sql);          sz = strlen(sql);
         substrsz = strlen(substr);  
         regexpsz = strlen(regexp);  
   
         if (NULL != arch) {          if (NULL != arch)
                 sz += strlen(andarch) + 1;                  sql_append(&sql, &sz, "arch = ? AND ", 1);
                 sql = mandoc_realloc(sql, sz);          if (NULL != sec)
                 strlcat(sql, andarch, sz);                  sql_append(&sql, &sz, "sec = ? AND ", 1);
         }          sql_append(&sql, &sz, "(", 1);
   
         if (NULL != sec) {          for (needop = 0; NULL != e; e = e->next) {
                 sz += strlen(andsec) + 1;                  if (e->and)
                 sql = mandoc_realloc(sql, sz);                          sql_append(&sql, &sz, " AND ", 1);
                 strlcat(sql, andsec, sz);                  else if (needop)
                           sql_append(&sql, &sz, " OR ", 1);
                   if (e->open)
                           sql_append(&sql, &sz, "(", e->open);
                   sql_append(&sql, &sz, NULL == e->substr ?
                       "id IN (SELECT pageid FROM keys "
                       "WHERE key REGEXP ? AND bits & ?)" :
                       "id IN (SELECT pageid FROM keys "
                       "WHERE key MATCH ? AND bits & ?)", 1);
                   if (e->close)
                           sql_append(&sql, &sz, ")", e->close);
                   needop = 1;
         }          }
           sql_append(&sql, &sz, ")", 1);
   
         sz += 2;  
         sql = mandoc_realloc(sql, sz);  
         strlcat(sql, "(", sz);  
   
         for ( ; NULL != e; e = e->next) {  
                 sz += (NULL == e->substr ? regexpsz : substrsz) +  
                         (NULL == e->next ? 3 : 5);  
                 sql = mandoc_realloc(sql, sz);  
                 strlcat(sql, NULL == e->substr ? regexp : substr, sz);  
                 strlcat(sql, NULL == e->next ? ");" : " OR ", sz);  
         }  
   
         return(sql);          return(sql);
 }  }
   
Line 515  sql_statement(const struct expr *e, const char *arch, 
Line 522  sql_statement(const struct expr *e, const char *arch, 
 static struct expr *  static struct expr *
 exprcomp(const struct mansearch *search, int argc, char *argv[])  exprcomp(const struct mansearch *search, int argc, char *argv[])
 {  {
         int              i, cs;          int              i, toopen, logic, igncase, toclose;
         struct expr     *first, *next, *cur;          struct expr     *first, *next, *cur;
   
         first = cur = NULL;          first = cur = NULL;
           toopen = logic = igncase = toclose = 0;
   
         for (i = 0; i < argc; i++) {          for (i = 0; i < argc; i++) {
                 if (0 == strcmp("-i", argv[i])) {                  if (0 == strcmp("(", argv[i])) {
                         if (++i >= argc)                          if (igncase)
                                 return(NULL);                                  goto fail;
                         cs = 0;                          toopen++;
                 } else                          toclose++;
                         cs = 1;                          continue;
                 next = exprterm(search, argv[i], cs);                  } else if (0 == strcmp(")", argv[i])) {
                 if (NULL == next) {                          if (toopen || logic || igncase || NULL == cur)
                         exprfree(first);                                  goto fail;
                         return(NULL);                          cur->close++;
                           if (0 > --toclose)
                                   goto fail;
                           continue;
                   } else if (0 == strcmp("-a", argv[i])) {
                           if (toopen || logic || igncase || NULL == cur)
                                   goto fail;
                           logic = 1;
                           continue;
                   } else if (0 == strcmp("-o", argv[i])) {
                           if (toopen || logic || igncase || NULL == cur)
                                   goto fail;
                           logic = 2;
                           continue;
                   } else if (0 == strcmp("-i", argv[i])) {
                           if (igncase)
                                   goto fail;
                           igncase = 1;
                           continue;
                 }                  }
                   next = exprterm(search, argv[i], !igncase);
                   if (NULL == next)
                           goto fail;
                   next->open = toopen;
                   next->and = (1 == logic);
                 if (NULL != first) {                  if (NULL != first) {
                         cur->next = next;                          cur->next = next;
                         cur = next;                          cur = next;
                 } else                  } else
                         cur = first = next;                          cur = first = next;
                   toopen = logic = igncase = 0;
         }          }
           if ( ! (toopen || logic || igncase || toclose))
         return(first);                  return(first);
   fail:
           if (NULL != first)
                   exprfree(first);
           return(NULL);
 }  }
   
 static struct expr *  static struct expr *

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13

CVSweb