Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * regular expression module
  3.  *
  4.  * Important Note: do not support group name index
  5.  *
  6.  * $Id$
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <assert.h>
  11. #include "regexpr.c"
  12.  
  13. /* tinypy API to be use in this unit */
  14. extern tp_obj tp_data(TP,int magic,void *v);
  15. extern tp_obj tp_object_new(TP);
  16. extern tp_obj tp_object(TP);
  17. extern tp_obj tp_method(TP,tp_obj self,tp_obj v(TP));
  18. extern tp_obj tp_string_copy(TP, const char *s, int n);
  19. extern tp_obj tp_list(TP);
  20. extern tp_obj tp_copy(TP);
  21.  
  22. /* last error message */
  23. static const char * LastError = NULL;
  24.  
  25. /* lower level regex object */
  26. typedef struct {
  27.         struct re_pattern_buffer re_patbuf;     /* The compiled expression */
  28.         struct re_registers re_regs;            /* The registers from the last match */
  29.         char re_fastmap[256];                           /* Storage for fastmap */
  30.         unsigned char *re_translate;            /* String object for translate table */
  31.         unsigned char *re_lastok;                       /* String object last matched/searched */
  32.  
  33.         /* supplementary */
  34.         int re_errno;                                           /* error num */
  35.         int re_syntax;                                          /* syntax */
  36. } regexobject;
  37.  
  38. /* local declarations */
  39. static regexobject* getre(TP, tp_obj rmobj);
  40. static tp_obj match_obj_group(TP);
  41. static tp_obj match_obj_groups(TP);
  42. static tp_obj match_obj_start(TP);
  43. static tp_obj match_obj_end(TP);
  44. static tp_obj match_obj_span(TP);
  45.  
  46. /*
  47.  * helper function: return lower level regex object
  48.  * rmobj        - regex or match object
  49.  */
  50. static regexobject * getre(TP, tp_obj rmobj)
  51. {
  52.         tp_obj reobj_data = tp_get(tp, rmobj, tp_string("__data__"));
  53.         regexobject *re = NULL;
  54.  
  55.         /* validate magic */
  56.         if (reobj_data.data.magic != sizeof(regexobject)) {
  57.                 LastError = "broken regex object";
  58.                 return (NULL);
  59.         }
  60.         re = (regexobject*)reobj_data.data.val;
  61.         assert(re);
  62.  
  63.         return (re);
  64. }
  65.  
  66. /*
  67.  * derive match object from regex object
  68.  */
  69. static tp_obj match_object(TP, tp_obj reobj)
  70. {
  71.         tp_obj mo = tp_object(tp);      /* match object */
  72.         tp_obj redata;                          /* regex object data */
  73.         tp_obj madata;                          /* match object data */
  74.         regexobject *re = NULL;         /* lower level regex object */
  75.  
  76.         redata = tp_get(tp, reobj, tp_string("__data__"));
  77.         re = (regexobject *)redata.data.val;
  78.         assert(re);
  79.         madata = tp_data(tp, (int)sizeof(regexobject), re);
  80.  
  81.         tp_set(tp, mo, tp_string("group"),      tp_method(tp, mo, match_obj_group));
  82.         tp_set(tp, mo, tp_string("groups"),     tp_method(tp, mo, match_obj_groups));
  83.         tp_set(tp, mo, tp_string("start"),      tp_method(tp, mo, match_obj_start));
  84.         tp_set(tp, mo, tp_string("end"),        tp_method(tp, mo, match_obj_end));
  85.         tp_set(tp, mo, tp_string("span"),       tp_method(tp, mo, match_obj_span));
  86.         tp_set(tp, mo, tp_string("__data__"), madata);
  87.  
  88.         return (mo);
  89. }
  90.  
  91. /*
  92.  * FUNC: regexobj.search(str[,pos=0])
  93.  * self         - regex object
  94.  * str          - string to be searched
  95.  * pos          - optional starting offset
  96.  *
  97.  * RETURN:
  98.  * match object - when matched
  99.  * None                 - not matched
  100.  */
  101. static tp_obj regex_obj_search(TP)
  102. {
  103.         tp_obj self = TP_OBJ();         /* regex object */
  104.         tp_obj str = TP_STR();
  105.         tp_obj pos = TP_DEFAULT(tp_number(0));
  106.         tp_obj maobj;                           /* match object */
  107.         regexobject *re = NULL;
  108.         int r = -2;                                     /* -2 indicate exception */
  109.         int range;
  110.  
  111.         if (pos.number.val < 0 || pos.number.val > str.string.len) {
  112.                 LastError = "search offset out of range";
  113.                 goto exception;
  114.         }
  115.         range = str.string.len - pos.number.val;
  116.  
  117.         re = getre(tp, self);
  118.         re->re_lastok = NULL;
  119.         r = re_search(&re->re_patbuf, (unsigned char *)str.string.val,
  120.                         str.string.len, pos.number.val, range, &re->re_regs);
  121.  
  122.         /* cannot match pattern */
  123.         if (r == -1)
  124.                 goto notfind;
  125.  
  126.         /* error occurred */
  127.         if (r == -2)
  128.                 goto exception;
  129.  
  130.         /* matched */
  131.         re->re_lastok = (unsigned char *)str.string.val;
  132.  
  133.         /* match obj */
  134.         maobj = match_object(tp, self);
  135.  
  136.         return (maobj);
  137.  
  138. notfind:
  139.         re->re_lastok = NULL;
  140.         return (tp_None);
  141. exception:
  142.         re->re_lastok = NULL;
  143.         tp_raise(tp_None, tp_string("regex search error"));
  144. }
  145.  
  146. /*
  147.  * FUNC: regexobj.match(str[,pos=0])
  148.  * self         - regex object
  149.  * str          - string to be matched
  150.  * pos          - optional starting position
  151.  *
  152.  * RETURN:
  153.  * match object - when matched
  154.  * None                 - not matched
  155.  */
  156. static tp_obj regex_obj_match(TP)
  157. {
  158.         tp_obj self = TP_OBJ();         /* regex object */
  159.         tp_obj str = TP_STR();
  160.         tp_obj pos = TP_DEFAULT(tp_number(0));
  161.         tp_obj maobj;                           /* match object */
  162.         regexobject *re = NULL;
  163.         int r = -2;                                     /* -2 indicate exception */
  164.  
  165.         re = getre(tp, self);
  166.         re->re_lastok = NULL;
  167.         r = re_match(&re->re_patbuf, (unsigned char *)str.string.val,
  168.                         str.string.len, pos.number.val, &re->re_regs);
  169.  
  170.         /* cannot match pattern */
  171.         if (r == -1)
  172.                 goto nomatch;
  173.  
  174.         /* error occurred */
  175.         if (r == -2)
  176.                 goto exception;
  177.  
  178.         /* matched */
  179.         re->re_lastok = (unsigned char *)str.string.val;
  180.  
  181.         /* match obj */
  182.         maobj = match_object(tp, self);
  183.  
  184.         return (maobj);
  185.  
  186. nomatch:
  187.         re->re_lastok = NULL;
  188.         return (tp_None);
  189. exception:
  190.         re->re_lastok = NULL;
  191.         tp_raise(tp_None, tp_string("regex match error"));
  192. }
  193.  
  194. /*
  195.  * regex object split()
  196.  * self         - regex object
  197.  * restr        - regex string
  198.  * maxsplit     - max split field, default 0, mean no limit
  199.  */
  200. static tp_obj regex_obj_split(TP)
  201. {
  202.         tp_obj self             = TP_OBJ();     /* regex object */
  203.         tp_obj restr    = TP_OBJ();     /* string */
  204.         tp_obj maxsplit = TP_DEFAULT(tp_number(0));
  205.         tp_obj maobj;                           /* match object */
  206.         regexobject *re = NULL;         /* lower level regex object */
  207.         tp_obj result   = tp_list(tp);
  208.         tp_obj grpstr;                          /* group string */
  209.         int     slen;                                   /* string length */
  210.         int srchloc;                            /* search location */
  211.  
  212.         /* maxsplit == 0 means no limit */
  213.         if ((int)maxsplit.number.val == 0)
  214.                 maxsplit.number.val = RE_NREGS;
  215.         assert(maxsplit.number.val > 0);
  216.  
  217.         srchloc = 0;
  218.         slen = strlen((char *)restr.string.val);
  219.  
  220.         do {
  221.                 /* generate a temp match object */
  222.                 tp_params_v(tp, 3, self, restr, tp_number(srchloc));
  223.                 maobj = regex_obj_search(tp);
  224.                 if (!tp_bool(tp, maobj))
  225.                         break;
  226.  
  227.                 re = getre(tp, maobj);
  228.                 if (re->re_lastok == NULL) {
  229.                         tp_raise(tp_None, tp_string("no match for split()"));
  230.                 }
  231.  
  232.                 /* extract fields */
  233.                 if ((int)maxsplit.number.val > 0) {
  234.                         int start = re->re_regs.start[0];
  235.                         int end   = re->re_regs.end[0];
  236.                         /*printf("%s:start(%d),end(%d)\n", __func__, start, end);*/
  237.                         if (start < 0 || end < 0)
  238.                                 break;
  239.  
  240.                         grpstr = tp_string_copy(tp,
  241.                                         (const char *)re->re_lastok + srchloc, start - srchloc);
  242.  
  243.                         if (tp_bool(tp, grpstr)) {
  244.                                 tp_set(tp, result, tp_None, grpstr);
  245.                                 maxsplit.number.val--;
  246.                         }
  247.  
  248.                         srchloc = end;
  249.                 }
  250.         } while (srchloc < slen && (int)maxsplit.number.val > 0);
  251.  
  252.         /* collect remaining string, if necessary */
  253.         if (srchloc < slen) {
  254.                 grpstr = tp_string_copy(tp,
  255.                                 (const char *)restr.string.val + srchloc, slen - srchloc);
  256.                 if (tp_bool(tp, grpstr))
  257.                         tp_set(tp, result, tp_None, grpstr);
  258.         }
  259.  
  260.         return (result);
  261. }
  262.  
  263. /*
  264.  * regex object findall()
  265.  * self         - regex object
  266.  * restr        - regex string
  267.  * pos          - starting position, default 0
  268.  */
  269. static tp_obj regex_obj_findall(TP)
  270. {
  271.         tp_obj self             = TP_OBJ();     /* regex object */
  272.         tp_obj restr    = TP_OBJ();     /* string */
  273.         tp_obj pos              = TP_DEFAULT(tp_number(0));
  274.         tp_obj maobj;                           /* match object */
  275.         regexobject *re = NULL;         /* lower level regex object */
  276.         tp_obj result   = tp_list(tp);
  277.         tp_obj grpstr;                          /* group string */
  278.         int     slen;                                   /* string length */
  279.         int srchloc;                            /* search location */
  280.  
  281.         srchloc = (int)pos.number.val;
  282.         slen    = strlen((char *)restr.string.val);
  283.         if (srchloc < 0 || srchloc >= slen)
  284.                 tp_raise(tp_None, tp_string("starting position out of range"));
  285.  
  286.         do {
  287.                 /* generate a temp match object */
  288.                 tp_params_v(tp, 3, self, restr, tp_number(srchloc));
  289.                 maobj = regex_obj_search(tp);
  290.                 if (!tp_bool(tp, maobj))
  291.                         break;
  292.  
  293.                 re = getre(tp, maobj);
  294.                 if (re->re_lastok == NULL) {
  295.                         tp_raise(tp_None, tp_string("no match for findall()"));
  296.                 }
  297.  
  298.                 /* extract fields */
  299.                 if (srchloc < slen) {
  300.                         int start = re->re_regs.start[0];
  301.                         int end   = re->re_regs.end[0];
  302.                         /*printf("%s:start(%d),end(%d)\n", __func__, start, end);*/
  303.                         if (start < 0 || end < 0)
  304.                                 break;
  305.  
  306.                         grpstr = tp_string_copy(tp,
  307.                                         (const char *)re->re_lastok + start, end - start);
  308.  
  309.                         if (tp_bool(tp, grpstr)) {
  310.                                 tp_set(tp, result, tp_None, grpstr);
  311.                         }
  312.  
  313.                         srchloc = end;
  314.                 }
  315.         } while (srchloc < slen);
  316.  
  317.         return (result);
  318. }
  319.  
  320. /*
  321.  * FUNC: matchobj.group([group1, ...])
  322.  * self         - match object
  323.  * args         - optional group indices, default 0
  324.  *
  325.  * return specified group.
  326.  */
  327. static tp_obj match_obj_group(TP)
  328. {
  329.         tp_obj self = TP_OBJ();         /* match object */
  330.         tp_obj grpidx;                          /* a group index */
  331.         regexobject *re = NULL;
  332.         int indices[RE_NREGS];
  333.         int start;
  334.         int end;
  335.         int i;
  336.         int single = 0;                         /* single group index? */
  337.         tp_obj result;
  338.  
  339.         /* get lower level regex object representation */
  340.         re = getre(tp, self);
  341.         if (re->re_lastok == NULL)
  342.                 tp_raise(tp_None,
  343.                                 tp_string("group() only valid after successful match/search"));
  344.  
  345.         for (i = 0; i < RE_NREGS; i++)
  346.                 indices[i] = -1;
  347.  
  348.         /*
  349.          * if no group index provided, supply default group index 0; else
  350.          * fill in indices[] with provided group index list.
  351.          */
  352.         if (tp->params.list.val->len == 0) {
  353.                 indices[0] = 0;
  354.                 single = 1;
  355.         } else if (tp->params.list.val->len == 1) {
  356.                 indices[0] = (int)TP_NUM();
  357.                 single = 1;
  358.         } else {
  359.                 i = 0;
  360.                 TP_LOOP(grpidx)
  361.                 if (grpidx.number.val < 0 || grpidx.number.val > RE_NREGS)
  362.                         tp_raise(tp_None, tp_string("group() grpidx out of range"));
  363.                 indices[i++] = (int)grpidx.number.val;
  364.                 TP_END
  365.         }
  366.  
  367.         /* generate result string list */
  368.         result = tp_list(tp);
  369.         for (i = 0; i < RE_NREGS && indices[i] >= 0; i++) {
  370.                 tp_obj grpstr;
  371.                 start = re->re_regs.start[indices[i]];
  372.                 end   = re->re_regs.end[indices[i]];
  373.                 if (start < 0 || end < 0) {
  374.                         grpstr = tp_None;
  375.                 } else {
  376.                         grpstr = tp_string_copy(tp, (const char *)re->re_lastok + start,
  377.                                         end - start);
  378.                 }
  379.                 tp_set(tp, result, tp_None, grpstr);
  380.         }
  381.         return (single ? tp_get(tp, result, tp_number(0)) : result);
  382. }
  383.  
  384. /*
  385.  * FUNC: matchobj.groups()
  386.  * self - match object.
  387.  * return all groups.
  388.  * Note: CPython allow a 'default' argument, but we disallow it.
  389.  */
  390. static tp_obj match_obj_groups(TP)
  391. {
  392.         tp_obj self = TP_OBJ();         /* match object */
  393.         regexobject *re = NULL;
  394.         int start;
  395.         int end;
  396.         int i;
  397.         tp_obj result = tp_list(tp);
  398.  
  399.         re = getre(tp, self);
  400.         if (re->re_lastok == NULL) {
  401.                 tp_raise(tp_None,
  402.                                 tp_string("groups() only valid after successful match/search"));
  403.         }
  404.  
  405.         for (i = 1; i < RE_NREGS; i++) {
  406.                 start = re->re_regs.start[i];
  407.                 end   = re->re_regs.end[i];
  408.                 if (start < 0 || end < 0)
  409.                         break;
  410.  
  411.                 tp_obj grpstr = tp_string_copy(tp,
  412.                                 (const char *)re->re_lastok + start, end - start);
  413.  
  414.                 if (tp_bool(tp, grpstr))
  415.                         tp_set(tp, result, tp_None, grpstr);
  416.         }
  417.  
  418.         return (result);
  419. }
  420.  
  421. /*
  422.  * FUNC: matchobj.start([group])
  423.  * self         - match object
  424.  * group        - group index
  425.  * return starting position of matched 'group' substring.
  426.  */
  427. static tp_obj match_obj_start(TP)
  428. {
  429.         tp_obj self = TP_OBJ();                                         /* match object */
  430.         tp_obj group = TP_DEFAULT(tp_number(0));        /* group */
  431.         regexobject *re = NULL;
  432.         int start;
  433.  
  434.         re = getre(tp, self);
  435.         if (re->re_lastok == NULL) {
  436.                 tp_raise(tp_None,
  437.                                 tp_string("start() only valid after successful match/search"));
  438.         }
  439.  
  440.         if (group.number.val < 0 || group.number.val > RE_NREGS)
  441.                 tp_raise(tp_None, tp_string("IndexError: group index out of range"));
  442.  
  443.         start = re->re_regs.start[(int)group.number.val];
  444.  
  445.         return (tp_number(start));
  446. }
  447.  
  448. /*
  449.  * FUNC: matchobj.end([group])
  450.  * self         - match object
  451.  * group        - group index
  452.  * return ending position of matched 'group' substring.
  453.  */
  454. static tp_obj match_obj_end(TP)
  455. {
  456.         tp_obj self = TP_OBJ();                                         /* match object */
  457.         tp_obj group = TP_DEFAULT(tp_number(0));        /* group */
  458.         regexobject *re = NULL;
  459.         int end;
  460.  
  461.         re = getre(tp, self);
  462.         if (re->re_lastok == NULL) {
  463.                 tp_raise(tp_None,
  464.                                 tp_string("end() only valid after successful match/search"));
  465.         }
  466.  
  467.         if (group.number.val < 0 || group.number.val > RE_NREGS)
  468.                 tp_raise(tp_None, tp_string("IndexError: group index out of range"));
  469.  
  470.         end = re->re_regs.end[(int)group.number.val];
  471.  
  472.         return (tp_number(end));
  473. }
  474.  
  475. /*
  476.  * FUNC: matchobj.span([group])
  477.  * self         - match object
  478.  * group        - group index
  479.  * return [start,end] position pair of matched 'group' substring.
  480.  */
  481. static tp_obj match_obj_span(TP)
  482. {
  483.         tp_obj self = TP_OBJ();                                         /* match object */
  484.         tp_obj group = TP_DEFAULT(tp_number(0));        /* group */
  485.         regexobject *re = NULL;
  486.         int start;
  487.         int end;
  488.         tp_obj result;
  489.  
  490.         re = getre(tp, self);
  491.         if (re->re_lastok == NULL) {
  492.                 tp_raise(tp_None,
  493.                                 tp_string("span() only valid after successful match/search"));
  494.         }
  495.  
  496.         if (group.number.val < 0 || group.number.val > RE_NREGS)
  497.                 tp_raise(tp_None, tp_string("IndexError: group index out of range"));
  498.  
  499.         start = re->re_regs.start[(int)group.number.val];
  500.         end   = re->re_regs.end[(int)group.number.val];
  501.  
  502.         result = tp_list(tp);
  503.         tp_set(tp, result, tp_None, tp_number(start));
  504.         tp_set(tp, result, tp_None, tp_number(end));
  505.  
  506.         return (result);
  507. }
  508.  
  509. /*
  510.  * compile out a re object
  511.  * repat        - regex pattern
  512.  * resyn        - regex syntax
  513.  */
  514. static tp_obj regex_compile(TP)
  515. {
  516.         char *error = NULL;
  517.         char const *pat = NULL;
  518.         int size = 0;
  519.         tp_obj reobj_data;
  520.         tp_obj repat = TP_TYPE(TP_STRING);                                              /* pattern */
  521.         tp_obj resyn = TP_DEFAULT(tp_number(RE_SYNTAX_EMACS));  /* syntax */
  522.         tp_obj reobj;   /* regex object */
  523.         regexobject *re;
  524.  
  525.         /*
  526.          * create regex object, its parent is builtin 'object'
  527.          */
  528.         reobj = tp_object(tp);
  529.  
  530.         re = (regexobject *)malloc(sizeof(regexobject));
  531.         if (!re) {
  532.                 error = "malloc lower level regex object failed";
  533.                 goto finally;
  534.         }
  535.  
  536.         re->re_patbuf.buffer = NULL;
  537.         re->re_patbuf.allocated = 0;
  538.         re->re_patbuf.fastmap = (unsigned char *)re->re_fastmap;
  539.         re->re_patbuf.translate = NULL;
  540.         re->re_translate = NULL;
  541.         re->re_lastok = NULL;
  542.  
  543.         re->re_errno = 0;
  544.         re->re_syntax = (int)resyn.number.val;
  545.  
  546.         pat = repat.string.val;
  547.         size = repat.string.len;
  548.         error = re_compile_pattern((unsigned char *)pat, size, &re->re_patbuf);
  549.         if (error != NULL) {
  550.                 LastError = error;
  551.                 goto finally;
  552.         }
  553.  
  554.         /* regexobject's size as magic */
  555.         reobj_data = tp_data(tp, (int)sizeof(regexobject), re);
  556.  
  557.         /*
  558.          * bind to regex object
  559.          */
  560.         tp_set(tp, reobj, tp_string("search"),
  561.                         tp_method(tp, reobj, regex_obj_search));
  562.         tp_set(tp, reobj, tp_string("match"),
  563.                         tp_method(tp, reobj, regex_obj_match));
  564.         tp_set(tp, reobj, tp_string("split"),
  565.                         tp_method(tp, reobj, regex_obj_split));
  566.         tp_set(tp, reobj, tp_string("findall"),
  567.                         tp_method(tp, reobj, regex_obj_findall));
  568.         tp_set(tp, reobj, tp_string("__data__"), reobj_data);
  569.  
  570.         tp_set(tp, reobj, tp_string("__name__"),
  571.                         tp_string("regular expression object"));
  572.         tp_set(tp, reobj, tp_string("__doc__"), tp_string(
  573.                                 "regular expression object, support methods:\n"
  574.                                 "search(str[,pos=0])-search 'str' from 'pos'\n"
  575.                                 "match(str[,pos=0])     -match 'str' from 'pos'\n"
  576.                                 ));
  577.  
  578.         return (reobj);
  579.  
  580. finally:
  581.         tp_raise(tp_None, tp_string(error));
  582. }
  583.  
  584. /*
  585.  * module level search()
  586.  */
  587. static tp_obj regex_search(TP)
  588. {
  589.         tp_obj repat = TP_OBJ();        /* pattern */
  590.         tp_obj restr = TP_OBJ();        /* string */
  591.         tp_obj resyn = TP_DEFAULT(tp_number(RE_SYNTAX_EMACS));
  592.         tp_obj reobj;                           /* regex object */
  593.         tp_obj maobj;                           /* match object */
  594.  
  595.         /* compile out regex object */
  596.         tp_params_v(tp, 2, repat, resyn);
  597.         reobj = regex_compile(tp);
  598.        
  599.         /* call r.search() */
  600.         tp_params_v(tp, 3, reobj, restr, tp_number(0));
  601.         maobj = regex_obj_search(tp);
  602.  
  603.         return (maobj);
  604. }
  605.  
  606. /*
  607.  * module level match()
  608.  */
  609. static tp_obj regex_match(TP)
  610. {
  611.         tp_obj repat = TP_OBJ();        /* pattern */
  612.         tp_obj restr = TP_OBJ();        /* string */
  613.         tp_obj resyn = TP_DEFAULT(tp_number(RE_SYNTAX_EMACS));
  614.         tp_obj reobj;                           /* regex object */
  615.         tp_obj maobj;                           /* match object */
  616.  
  617.         /* compile out regex object */
  618.         tp_params_v(tp, 2, repat, resyn);
  619.         reobj = regex_compile(tp);
  620.        
  621.         /* call r.search() */
  622.         tp_params_v(tp, 3, reobj, restr, tp_number(0));
  623.         maobj = regex_obj_match(tp);
  624.  
  625.         return (maobj);
  626. }
  627.  
  628. /*
  629.  * module level split()
  630.  * repat        - regex pattern
  631.  * restr        - regex string
  632.  * maxsplit     - max split field, default 0, mean no limit
  633.  */
  634. static tp_obj regex_split(TP)
  635. {
  636.         tp_obj repat = TP_OBJ();        /* pattern */
  637.         tp_obj restr = TP_OBJ();        /* string */
  638.         tp_obj maxsplit = TP_DEFAULT(tp_number(0));
  639.         tp_obj reobj;                           /* regex object */
  640.  
  641.         /* generate a temp regex object */
  642.         tp_params_v(tp, 2, repat, tp_number(RE_SYNTAX_EMACS));
  643.         reobj = regex_compile(tp);
  644.        
  645.         tp_params_v(tp, 3, reobj, restr, maxsplit);
  646.         return regex_obj_split(tp);
  647. }
  648.  
  649. /*
  650.  * module level findall()
  651.  * repat        - regex pattern
  652.  * restr        - regex string
  653.  * resyn        - regex syntax, optional, default RE_SYNTAX_EMAC
  654.  */
  655. static tp_obj regex_findall(TP)
  656. {
  657.         tp_obj repat = TP_OBJ();        /* pattern */
  658.         tp_obj restr = TP_OBJ();        /* string */
  659.         tp_obj resyn = TP_DEFAULT(tp_number(RE_SYNTAX_EMACS));
  660.         tp_obj reobj;                           /* regex object */
  661.  
  662.         /* generate a temp regex object */
  663.         tp_params_v(tp, 2, repat, resyn);
  664.         reobj = regex_compile(tp);
  665.        
  666.         tp_params_v(tp, 2, reobj, restr);
  667.         return regex_obj_findall(tp);
  668. }
  669.  
  670.  
  671. /*
  672.  * re mod can only support 'set_syntax', 'get_syntax', and 'compile' functions,
  673.  * 'compile' function will return a 'reobj', and this 'reobj' will support
  674.  * methods 'search', 'match', 'group', 'groupall', el al.
  675.  */
  676. void re_init(TP)
  677. {
  678.         /*
  679.          * module dict for re
  680.          */
  681.         tp_obj re_mod = tp_dict(tp);
  682.  
  683.         /*
  684.          * bind to re module
  685.          */
  686.         tp_set(tp, re_mod, tp_string("compile"),          tp_fnc(tp, regex_compile));
  687.         tp_set(tp, re_mod, tp_string("search"),           tp_fnc(tp, regex_search));
  688.         tp_set(tp, re_mod, tp_string("match"),            tp_fnc(tp, regex_match));
  689.         tp_set(tp, re_mod, tp_string("split"),            tp_fnc(tp, regex_split));
  690.         tp_set(tp, re_mod, tp_string("findall"),          tp_fnc(tp, regex_findall));
  691.         tp_set(tp, re_mod, tp_string("AWK_SYNTAX"),   tp_number(RE_SYNTAX_AWK));
  692.         tp_set(tp, re_mod, tp_string("EGREP_SYNTAX"), tp_number(RE_SYNTAX_EGREP));
  693.         tp_set(tp, re_mod, tp_string("GREP_SYNTAX"),  tp_number(RE_SYNTAX_GREP));
  694.         tp_set(tp, re_mod, tp_string("EMACS_SYNTAX"), tp_number(RE_SYNTAX_EMACS));
  695.  
  696.         /*
  697.          * bind special attibutes to re module
  698.          */
  699.         tp_set(tp, re_mod, tp_string("__name__"),
  700.                         tp_string("regular expression module"));
  701.         tp_set(tp, re_mod, tp_string("__file__"), tp_string(__FILE__));
  702.         tp_set(tp, re_mod, tp_string("__doc__"),
  703.                         tp_string("simple regular express implementation"));
  704.  
  705.         /*
  706.          * bind regex module to tinypy modules[]
  707.          */
  708.         tp_set(tp, tp->modules, tp_string("re"), re_mod);
  709. }
  710.  
  711.