Changeset 4ba05fcbd5ad0573c31ed6af7ac50f72f3d4b3e9
- Timestamp:
- 04/22/08 14:31:48 (9 months ago)
- Parents:
- c929863ac8839608b81f31d8c7877cb11792961e
- Children:
- aeada46012e3db439288c894f0ca0dad1638cb57, f84102bad115887754ae1fafed8c072360deee9b
- git-committer:
- dave <dave@06fd6eb0-0002-0410-a719-e5602cce40bc> / 2008-04-22T04:31:48Z+0000
- Location:
- c
- Files:
-
- 4 modified
-
include/internal.h (modified) (1 diff)
-
include/search.h (modified) (2 diffs)
-
src/q_parser.c (modified) (24 diffs)
-
src/q_parser.y (modified) (44 diffs)
Legend:
- Unmodified
- Added
- Removed
-
c/include/internal.h
rc92986 r4ba05f 270 270 #define QParser FrtQParser 271 271 #define Query FrtQuery 272 #define QueryParser FrtQueryParser 272 273 #define QueryType FrtQueryType 273 274 #define RAMFile FrtRAMFile -
c/include/search.h
rc92986 r4ba05f 899 899 } FrtFieldStack; 900 900 901 typedef struct FrtQ Parser901 typedef struct FrtQueryParser 902 902 { 903 903 frt_mutex_t mutex; … … 929 929 bool use_keywords : 1; 930 930 bool use_typed_range_query : 1; 931 } FrtQParser; 931 } FrtQueryParser; 932 typedef FrtQueryParser FrtQParser; /* QParser is an alias for QueryParser */ 932 933 933 934 extern FrtQParser *frt_qp_new(FrtHashSet *all_fields, FrtHashSet *def_fields, -
c/src/q_parser.c
rc92986 r4ba05f 99 99 100 100 /* Copy the first part of user declarations. */ 101 #line 55"src/q_parser.y"101 #line 84 "src/q_parser.y" 102 102 103 103 #include <string.h> … … 150 150 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 151 151 typedef union YYSTYPE 152 #line 84"src/q_parser.y"152 #line 113 "src/q_parser.y" 153 153 { 154 154 Query *query; … … 170 170 171 171 /* Copy the second part of user declarations. */ 172 #line 92"src/q_parser.y"172 #line 121 "src/q_parser.y" 173 173 174 174 static int yylex(YYSTYPE *lvalp, QParser *qp); … … 551 551 552 552 /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ 553 static const yytype_uint 8yyrline[] =554 { 555 0, 189, 189, 190, 192, 193, 194, 195, 197, 198,556 199, 201, 202, 204, 205, 206, 207, 208, 209, 210,557 2 12, 213, 214, 216, 218, 218, 220, 220, 220, 223,558 2 24, 226, 227, 228, 229, 231, 232, 233, 234, 235,559 2 37, 238, 239, 240, 241, 242, 243, 244, 245, 246,560 2 47, 248553 static const yytype_uint16 yyrline[] = 554 { 555 0, 218, 218, 219, 221, 222, 223, 224, 226, 227, 556 228, 230, 231, 233, 234, 235, 236, 237, 238, 239, 557 241, 242, 243, 245, 247, 247, 249, 249, 249, 252, 558 253, 255, 256, 257, 258, 260, 261, 262, 263, 264, 559 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 560 276, 277 561 561 }; 562 562 #endif … … 1217 1217 { 1218 1218 case 27: /* "bool_q" */ 1219 #line 184"src/q_parser.y"1219 #line 213 "src/q_parser.y" 1220 1220 { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); }; 1221 1221 #line 1222 "src/q_parser.c" 1222 1222 break; 1223 1223 case 28: /* "bool_clss" */ 1224 #line 186"src/q_parser.y"1224 #line 215 "src/q_parser.y" 1225 1225 { if ((yyvaluep->bclss) && qp->destruct) bca_destroy((yyvaluep->bclss)); }; 1226 1226 #line 1227 "src/q_parser.c" 1227 1227 break; 1228 1228 case 29: /* "bool_cls" */ 1229 #line 185"src/q_parser.y"1229 #line 214 "src/q_parser.y" 1230 1230 { if ((yyvaluep->bcls) && qp->destruct) bc_deref((yyvaluep->bcls)); }; 1231 1231 #line 1232 "src/q_parser.c" 1232 1232 break; 1233 1233 case 30: /* "boosted_q" */ 1234 #line 184"src/q_parser.y"1234 #line 213 "src/q_parser.y" 1235 1235 { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); }; 1236 1236 #line 1237 "src/q_parser.c" 1237 1237 break; 1238 1238 case 31: /* "q" */ 1239 #line 184"src/q_parser.y"1239 #line 213 "src/q_parser.y" 1240 1240 { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); }; 1241 1241 #line 1242 "src/q_parser.c" 1242 1242 break; 1243 1243 case 32: /* "term_q" */ 1244 #line 184"src/q_parser.y"1244 #line 213 "src/q_parser.y" 1245 1245 { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); }; 1246 1246 #line 1247 "src/q_parser.c" 1247 1247 break; 1248 1248 case 33: /* "wild_q" */ 1249 #line 184"src/q_parser.y"1249 #line 213 "src/q_parser.y" 1250 1250 { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); }; 1251 1251 #line 1252 "src/q_parser.c" 1252 1252 break; 1253 1253 case 34: /* "field_q" */ 1254 #line 184"src/q_parser.y"1254 #line 213 "src/q_parser.y" 1255 1255 { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); }; 1256 1256 #line 1257 "src/q_parser.c" 1257 1257 break; 1258 1258 case 39: /* "phrase_q" */ 1259 #line 184"src/q_parser.y"1259 #line 213 "src/q_parser.y" 1260 1260 { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); }; 1261 1261 #line 1262 "src/q_parser.c" 1262 1262 break; 1263 1263 case 40: /* "ph_words" */ 1264 #line 187"src/q_parser.y"1264 #line 216 "src/q_parser.y" 1265 1265 { if ((yyvaluep->phrase) && qp->destruct) ph_destroy((yyvaluep->phrase)); }; 1266 1266 #line 1267 "src/q_parser.c" 1267 1267 break; 1268 1268 case 41: /* "range_q" */ 1269 #line 184"src/q_parser.y"1269 #line 213 "src/q_parser.y" 1270 1270 { if ((yyvaluep->query) && qp->destruct) q_deref((yyvaluep->query)); }; 1271 1271 #line 1272 "src/q_parser.c" … … 1578 1578 { 1579 1579 case 2: 1580 #line 189"src/q_parser.y"1580 #line 218 "src/q_parser.y" 1581 1581 { qp->result = (yyval.query) = NULL; } 1582 1582 break; 1583 1583 1584 1584 case 3: 1585 #line 190"src/q_parser.y"1585 #line 219 "src/q_parser.y" 1586 1586 { T qp->result = (yyval.query) = get_bool_q((yyvsp[(1) - (1)].bclss)); E } 1587 1587 break; 1588 1588 1589 1589 case 4: 1590 #line 192"src/q_parser.y"1590 #line 221 "src/q_parser.y" 1591 1591 { T (yyval.bclss) = first_cls((yyvsp[(1) - (1)].bcls)); E } 1592 1592 break; 1593 1593 1594 1594 case 5: 1595 #line 193"src/q_parser.y"1595 #line 222 "src/q_parser.y" 1596 1596 { T (yyval.bclss) = add_and_cls((yyvsp[(1) - (3)].bclss), (yyvsp[(3) - (3)].bcls)); E } 1597 1597 break; 1598 1598 1599 1599 case 6: 1600 #line 194"src/q_parser.y"1600 #line 223 "src/q_parser.y" 1601 1601 { T (yyval.bclss) = add_or_cls((yyvsp[(1) - (3)].bclss), (yyvsp[(3) - (3)].bcls)); E } 1602 1602 break; 1603 1603 1604 1604 case 7: 1605 #line 195"src/q_parser.y"1605 #line 224 "src/q_parser.y" 1606 1606 { T (yyval.bclss) = add_default_cls(qp, (yyvsp[(1) - (2)].bclss), (yyvsp[(2) - (2)].bcls)); E } 1607 1607 break; 1608 1608 1609 1609 case 8: 1610 #line 197"src/q_parser.y"1610 #line 226 "src/q_parser.y" 1611 1611 { T (yyval.bcls) = get_bool_cls((yyvsp[(2) - (2)].query), BC_MUST); E } 1612 1612 break; 1613 1613 1614 1614 case 9: 1615 #line 198"src/q_parser.y"1615 #line 227 "src/q_parser.y" 1616 1616 { T (yyval.bcls) = get_bool_cls((yyvsp[(2) - (2)].query), BC_MUST_NOT); E } 1617 1617 break; 1618 1618 1619 1619 case 10: 1620 #line 199"src/q_parser.y"1620 #line 228 "src/q_parser.y" 1621 1621 { T (yyval.bcls) = get_bool_cls((yyvsp[(1) - (1)].query), BC_SHOULD); E } 1622 1622 break; 1623 1623 1624 1624 case 12: 1625 #line 2 02"src/q_parser.y"1625 #line 231 "src/q_parser.y" 1626 1626 { T if ((yyvsp[(1) - (3)].query)) sscanf((yyvsp[(3) - (3)].str),"%f",&((yyvsp[(1) - (3)].query)->boost)); (yyval.query)=(yyvsp[(1) - (3)].query); E } 1627 1627 break; 1628 1628 1629 1629 case 14: 1630 #line 2 05"src/q_parser.y"1630 #line 234 "src/q_parser.y" 1631 1631 { T (yyval.query) = bq_new_max(true, qp->max_clauses); E } 1632 1632 break; 1633 1633 1634 1634 case 15: 1635 #line 2 06"src/q_parser.y"1635 #line 235 "src/q_parser.y" 1636 1636 { T (yyval.query) = get_bool_q((yyvsp[(2) - (3)].bclss)); E } 1637 1637 break; 1638 1638 1639 1639 case 20: 1640 #line 2 12"src/q_parser.y"1640 #line 241 "src/q_parser.y" 1641 1641 { FLDS((yyval.query), get_term_q(qp, field, (yyvsp[(1) - (1)].str))); Y} 1642 1642 break; 1643 1643 1644 1644 case 21: 1645 #line 2 13"src/q_parser.y"1645 #line 242 "src/q_parser.y" 1646 1646 { FLDS((yyval.query), get_fuzzy_q(qp, field, (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str))); Y} 1647 1647 break; 1648 1648 1649 1649 case 22: 1650 #line 2 14"src/q_parser.y"1650 #line 243 "src/q_parser.y" 1651 1651 { FLDS((yyval.query), get_fuzzy_q(qp, field, (yyvsp[(1) - (2)].str), NULL)); Y} 1652 1652 break; 1653 1653 1654 1654 case 23: 1655 #line 2 16"src/q_parser.y"1655 #line 245 "src/q_parser.y" 1656 1656 { FLDS((yyval.query), get_wild_q(qp, field, (yyvsp[(1) - (1)].str))); Y} 1657 1657 break; 1658 1658 1659 1659 case 24: 1660 #line 2 18"src/q_parser.y"1660 #line 247 "src/q_parser.y" 1661 1661 { qp_pop_fields(qp); } 1662 1662 break; 1663 1663 1664 1664 case 25: 1665 #line 2 19"src/q_parser.y"1665 #line 248 "src/q_parser.y" 1666 1666 { (yyval.query) = (yyvsp[(3) - (4)].query); } 1667 1667 break; 1668 1668 1669 1669 case 26: 1670 #line 2 20"src/q_parser.y"1670 #line 249 "src/q_parser.y" 1671 1671 { qp_push_fields(qp, qp->all_fields, false); } 1672 1672 break; 1673 1673 1674 1674 case 27: 1675 #line 2 20"src/q_parser.y"1675 #line 249 "src/q_parser.y" 1676 1676 { qp_pop_fields(qp); } 1677 1677 break; 1678 1678 1679 1679 case 28: 1680 #line 2 21"src/q_parser.y"1680 #line 250 "src/q_parser.y" 1681 1681 { (yyval.query) = (yyvsp[(4) - (5)].query); } 1682 1682 break; 1683 1683 1684 1684 case 29: 1685 #line 2 23"src/q_parser.y"1685 #line 252 "src/q_parser.y" 1686 1686 { (yyval.hashset) = first_field(qp, (yyvsp[(1) - (1)].str)); } 1687 1687 break; 1688 1688 1689 1689 case 30: 1690 #line 2 24"src/q_parser.y"1690 #line 253 "src/q_parser.y" 1691 1691 { (yyval.hashset) = add_field(qp, (yyvsp[(3) - (3)].str));} 1692 1692 break; 1693 1693 1694 1694 case 31: 1695 #line 2 26"src/q_parser.y"1695 #line 255 "src/q_parser.y" 1696 1696 { (yyval.query) = get_phrase_q(qp, (yyvsp[(2) - (3)].phrase), NULL); } 1697 1697 break; 1698 1698 1699 1699 case 32: 1700 #line 2 27"src/q_parser.y"1700 #line 256 "src/q_parser.y" 1701 1701 { (yyval.query) = get_phrase_q(qp, (yyvsp[(2) - (5)].phrase), (yyvsp[(5) - (5)].str)); } 1702 1702 break; 1703 1703 1704 1704 case 33: 1705 #line 2 28"src/q_parser.y"1705 #line 257 "src/q_parser.y" 1706 1706 { (yyval.query) = NULL; } 1707 1707 break; 1708 1708 1709 1709 case 34: 1710 #line 2 29"src/q_parser.y"1710 #line 258 "src/q_parser.y" 1711 1711 { (yyval.query) = NULL; (void)(yyvsp[(4) - (4)].str);} 1712 1712 break; 1713 1713 1714 1714 case 35: 1715 #line 2 31"src/q_parser.y"1715 #line 260 "src/q_parser.y" 1716 1716 { (yyval.phrase) = ph_first_word((yyvsp[(1) - (1)].str)); } 1717 1717 break; 1718 1718 1719 1719 case 36: 1720 #line 2 32"src/q_parser.y"1720 #line 261 "src/q_parser.y" 1721 1721 { (yyval.phrase) = ph_first_word(NULL); } 1722 1722 break; 1723 1723 1724 1724 case 37: 1725 #line 2 33"src/q_parser.y"1725 #line 262 "src/q_parser.y" 1726 1726 { (yyval.phrase) = ph_add_word((yyvsp[(1) - (2)].phrase), (yyvsp[(2) - (2)].str)); } 1727 1727 break; 1728 1728 1729 1729 case 38: 1730 #line 2 34"src/q_parser.y"1730 #line 263 "src/q_parser.y" 1731 1731 { (yyval.phrase) = ph_add_word((yyvsp[(1) - (3)].phrase), NULL); } 1732 1732 break; 1733 1733 1734 1734 case 39: 1735 #line 2 35"src/q_parser.y"1735 #line 264 "src/q_parser.y" 1736 1736 { (yyval.phrase) = ph_add_multi_word((yyvsp[(1) - (3)].phrase), (yyvsp[(3) - (3)].str)); } 1737 1737 break; 1738 1738 1739 1739 case 40: 1740 #line 2 37"src/q_parser.y"1740 #line 266 "src/q_parser.y" 1741 1741 { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), true, true)); Y} 1742 1742 break; 1743 1743 1744 1744 case 41: 1745 #line 2 38"src/q_parser.y"1745 #line 267 "src/q_parser.y" 1746 1746 { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), true, false)); Y} 1747 1747 break; 1748 1748 1749 1749 case 42: 1750 #line 2 39"src/q_parser.y"1750 #line 268 "src/q_parser.y" 1751 1751 { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), false, true)); Y} 1752 1752 break; 1753 1753 1754 1754 case 43: 1755 #line 2 40"src/q_parser.y"1755 #line 269 "src/q_parser.y" 1756 1756 { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), false, false)); Y} 1757 1757 break; 1758 1758 1759 1759 case 44: 1760 #line 2 41"src/q_parser.y"1760 #line 270 "src/q_parser.y" 1761 1761 { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[(2) - (3)].str), false, false)); Y} 1762 1762 break; 1763 1763 1764 1764 case 45: 1765 #line 2 42"src/q_parser.y"1765 #line 271 "src/q_parser.y" 1766 1766 { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[(2) - (3)].str), false, true)); Y} 1767 1767 break; 1768 1768 1769 1769 case 46: 1770 #line 2 43"src/q_parser.y"1770 #line 272 "src/q_parser.y" 1771 1771 { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (3)].str), NULL,true, false)); Y} 1772 1772 break; 1773 1773 1774 1774 case 47: 1775 #line 2 44"src/q_parser.y"1775 #line 273 "src/q_parser.y" 1776 1776 { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (3)].str), NULL,false, false)); Y} 1777 1777 break; 1778 1778 1779 1779 case 48: 1780 #line 2 45"src/q_parser.y"1780 #line 274 "src/q_parser.y" 1781 1781 { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[(2) - (2)].str), false, false)); Y} 1782 1782 break; 1783 1783 1784 1784 case 49: 1785 #line 2 46"src/q_parser.y"1785 #line 275 "src/q_parser.y" 1786 1786 { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[(3) - (3)].str), false, true)); Y} 1787 1787 break; 1788 1788 1789 1789 case 50: 1790 #line 2 47"src/q_parser.y"1790 #line 276 "src/q_parser.y" 1791 1791 { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(3) - (3)].str), NULL,true, false)); Y} 1792 1792 break; 1793 1793 1794 1794 case 51: 1795 #line 2 48"src/q_parser.y"1795 #line 277 "src/q_parser.y" 1796 1796 { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[(2) - (2)].str), NULL,false, false)); Y} 1797 1797 break; … … 2013 2013 2014 2014 2015 #line 2 50"src/q_parser.y"2015 #line 279 "src/q_parser.y" 2016 2016 2017 2017 … … 2482 2482 } 2483 2483 2484 /** 2485 * Build a phrase query for a single field. It might seem like a better idea 2486 * to build the PhraseQuery once and duplicate it for each field but this 2487 * would be buggy in the case of PerFieldAnalyzers in which case a different 2488 * tokenizer could be used for each field. 2489 * 2490 * Note that the query object returned by this method is not always a 2491 * PhraseQuery. If there is only one term in the query then the query is 2492 * simplified to a TermQuery. If there are multiple terms but only a single 2493 * position, then a MultiTermQuery is retured. 2494 * 2495 * Note that each word in the query gets tokenized. Unlike get_term_q, if the 2496 * word gets tokenized into more than one token, the rest of the tokens are 2497 * ignored. 2498 */ 2484 2499 static Query *get_phrase_query(QParser *qp, char *field, 2485 2500 Phrase *phrase, char *slop_str) … … 2502 2517 for (i = 0; i < word_count; i++) { 2503 2518 token = ts_next(get_cached_ts(qp, field, words[i])); 2504 free(words[i]);2505 2519 if (token) { 2520 free(words[i]); 2506 2521 last_word = words[i] = estrdup(token->text); 2507 2522 ++term_cnt; 2508 2523 } 2509 2524 else { 2510 words[i] = estrdup(""); 2525 /* empty words will later be ignored */ 2526 words[i][0] = '\0'; 2511 2527 } 2512 2528 } … … 2522 2538 q = multi_tq_new_conf(field, term_cnt, 0.0); 2523 2539 for (i = 0; i < word_count; i++) { 2540 /* ignore empty words */ 2524 2541 if (words[i][0]) { 2525 2542 multi_tq_add_term(q, words[i]); … … 2587 2604 } 2588 2605 2606 /** 2607 * Get a phrase query from the Phrase object. The Phrase object is built up by 2608 * the query parser as the all PhraseQuery didn't work well for this. Once the 2609 * PhraseQuery has been built the Phrase object needs to be destroyed. 2610 */ 2589 2611 static Query *get_phrase_q(QParser *qp, Phrase *phrase, char *slop_str) 2590 2612 { … … 2595 2617 } 2596 2618 2619 /** 2620 * Gets a RangeQuery object. 2621 * 2622 * Just like with WildCardQuery, RangeQuery needs to downcase its terms if the 2623 * tokenizer also downcased its terms. 2624 */ 2597 2625 static Query *get_r_q(QParser *qp, char *field, char *from, char *to, 2598 2626 bool inc_lower, bool inc_upper) 2599 2627 { 2600 2628 Query *rq; 2601 if (qp->wild_lower) { 2629 if (qp->wild_lower 2630 && (!qp->tokenized_fields || hs_exists(qp->tokenized_fields, field))) { 2602 2631 if (from) { 2603 2632 lower_str(from); … … 2608 2637 } 2609 2638 /* 2639 * terms don't get tokenized as it doesn't really make sense to do so for 2640 * range queries. 2641 2610 2642 if (from) { 2611 2643 TokenStream *stream = get_cached_ts(qp, field, from); … … 2626 2658 } 2627 2659 2660 /** 2661 * Every time the query parser sees a new field modifier ("field1|field2:") 2662 * it pushes a new FieldStack object onto the stack and sets its fields to the 2663 * fields specified in the fields modifier. If the field modifier is '*', 2664 * fs->fields is set to all_fields. fs->fields is set to +qp->def_field+ at 2665 * the bottom of the stack (ie the very first set of fields pushed onto the 2666 * stack). 2667 */ 2628 2668 static void qp_push_fields(QParser *self, HashSet *fields, bool destroy) 2629 2669 { … … 2638 2678 } 2639 2679 2680 /** 2681 * Pops the top of the fields stack and frees any memory used by it. This will 2682 * get called when query modified by a field modifier ("field1|field2:") has 2683 * been fully parsed and the field specifier no longer applies. 2684 */ 2640 2685 static void qp_pop_fields(QParser *self) 2641 2686 { … … 2652 2697 } 2653 2698 2699 /** 2700 * Free all memory allocated by the QueryParser. 2701 */ 2654 2702 void qp_destroy(QParser *self) 2655 2703 { … … 2674 2722 } 2675 2723 2724 /** 2725 * Creates a new QueryParser setting all boolean parameters to their defaults. 2726 * If +def_fields+ is NULL then +all_fields+ is used in place of +def_fields+. 2727 * Not also that this method ensures that all fields that exist in 2728 * +def_fields+ must also exist in +all_fields+. This should make sense. 2729 */ 2676 2730 QParser *qp_new(HashSet *all_fields, HashSet *def_fields, 2677 2731 HashSet *tokenized_fields, Analyzer *analyzer) … … 2708 2762 self->ts_cache = h_new_str(NULL, (free_ft)&ts_deref); 2709 2763 self->buf_index = 0; 2710 self->dynbuf = 0;2764 self->dynbuf = NULL; 2711 2765 self->non_tokenizer = non_tokenizer_new(); 2712 2766 mutex_init(&self->mutex, NULL); … … 2717 2771 static const char *PHRASE_CHARS = "<>|\""; 2718 2772 2719 static void str_insert(char *str, int len, char chr) 2773 /** 2774 * +str_insert_char+ inserts a character at the beginning of a string by 2775 * shifting the rest of the string right. 2776 */ 2777 static void str_insert_char(char *str, int len, char chr) 2720 2778 { 2721 2779 memmove(str+1, str, len*sizeof(char)); … … 2723 2781 } 2724 2782 2725 /***************************************************************************** 2726 * qp_clean_str method which basically scans the query string and ensures that 2727 * all open and close parentheses '()' and quotes '"' are balanced. It does 2728 * this be inserting or appending extra parentheses or quotes which is not 2729 * necessarily going to be exactly what the user wanted but it will help 2730 * prevent the parser from failing so it's the best we can do at this stage. 2731 * It also checks 2732 *****************************************************************************/ 2783 /** 2784 * +qp_clean_str+ basically scans the query string and ensures that all open 2785 * and close parentheses '()' and quotes '"' are balanced. It does this by 2786 * inserting or appending extra parentheses or quotes to the string. This 2787 * obviously won't necessarily be exactly what the user wanted but we are 2788 * never going to know that anyway. The main job of this method is to help the 2789 * query at least parse correctly. 2790 * 2791 * It also checks that all special characters within phrases (ie between 2792 * quotes) are escaped correctly unless they have meaning within a phrase 2793 * ( <>,|," ). Note that '<' and '>' will also be escaped unless the appear 2794 * together like so; '<>'. 2795 */ 2733 2796 char *qp_clean_str(char *str) 2734 2797 { … … 2749 2812 } 2750 2813 *nsp++ = b; 2751 /* \ \ has escaped itself so has no power. Assign pb random char :*/2752 pb = ((b == '\\') ? ' :' : b);2814 /* \ has escaped itself so has no power. Assign pb random char 'r' */ 2815 pb = ((b == '\\') ? 'r' : b); 2753 2816 continue; 2754 2817 } … … 2775 2838 if (!quote_open) { 2776 2839 if (br_cnt == 0) { 2777 str_insert (new_str, (int)(nsp - new_str), '(');2840 str_insert_char(new_str, (int)(nsp - new_str), '('); 2778 2841 nsp++; 2779 2842 } … … 2820 2883 } 2821 2884 2885 /** 2886 * Takes a string and finds whatever tokens it can using the QueryParser's 2887 * analyzer. It then turns these tokens (if any) into a boolean query. If it 2888 * fails to find any tokens, this method will return NULL. 2889 */ 2822 2890 static Query *qp_get_bad_query(QParser *qp, char *str) 2823 2891 { … … 2828 2896 } 2829 2897 2898 /** 2899 * +qp_parse+ takes a string and turns it into a Query object using Ferret's 2900 * query language. It must either raise an error or return a query object. It 2901 * must not return NULL. If the yacc parser fails it will use a very basic 2902 * boolean query parser which takes whatever tokens it can find in the query 2903 * and terns them into a boolean query on the default fields. 2904 */ 2830 2905 Query *qp_parse(QParser *self, char *qstr) 2831 2906 { 2832 2907 Query *result = NULL; 2833 2908 mutex_lock(&self->mutex); 2909 /* if qp->fields_top->next is not NULL we have a left over field-stack 2910 * object that was not popped during the last query parse */ 2911 assert(NULL == self->fields_top->next);
