@@ -72,6 +72,7 @@ typedef const unsigned char *chartables; /* Type of chartable sets */
7272
7373/* Contents of callout data */
7474struct cod {
75+ long subj_start ; /* Start of subject string */
7576 value * v_substrings_p ; /* Pointer to substrings matched so far */
7677 value * v_cof_p ; /* Pointer to callout function */
7778 value v_exn ; /* Possible exception raised by callout function */
@@ -124,13 +125,21 @@ struct pcre_ocaml_tables {
124125 and OCaml chooses the larger possibility for representing integers when
125126 available (also in arrays) - not so the PCRE!
126127*/
127- static inline void copy_ovector (const int * ovec_src , caml_int_ptr ovec_dst ,
128- int subgroups2 ) {
129- while (subgroups2 -- ) {
130- * ovec_dst = Val_int (* ovec_src );
131- -- ovec_src ;
132- -- ovec_dst ;
133- }
128+ static inline void copy_ovector (long subj_start , const int * ovec_src ,
129+ caml_int_ptr ovec_dst , int subgroups2 ) {
130+ if (subj_start == 0 )
131+ while (subgroups2 -- ) {
132+ * ovec_dst = Val_int (* ovec_src );
133+ -- ovec_src ;
134+ -- ovec_dst ;
135+ }
136+ else
137+ while (subgroups2 -- ) {
138+ * ovec_dst =
139+ (* ovec_src == -1 ) ? Val_int (-1 ) : Val_long (* ovec_src + subj_start );
140+ -- ovec_src ;
141+ -- ovec_dst ;
142+ }
134143}
135144
136145/* Callout handler */
@@ -153,13 +162,14 @@ static int pcre_callout_handler(pcre_callout_block *cb) {
153162 const int * ovec_src = cb -> offset_vector + subgroups2_1 ;
154163 caml_int_ptr ovec_dst =
155164 (long * )& Field (Field (v_substrings , 1 ), 0 ) + subgroups2_1 ;
165+ long subj_start = cod -> subj_start ;
156166
157- copy_ovector (ovec_src , ovec_dst , subgroups2 );
167+ copy_ovector (subj_start , ovec_src , ovec_dst , subgroups2 );
158168
159169 Field (v_callout_data , 0 ) = Val_int (cb -> callout_number );
160170 Field (v_callout_data , 1 ) = v_substrings ;
161- Field (v_callout_data , 2 ) = Val_int (cb -> start_match );
162- Field (v_callout_data , 3 ) = Val_int (cb -> current_position );
171+ Field (v_callout_data , 2 ) = Val_int (cb -> start_match + subj_start );
172+ Field (v_callout_data , 3 ) = Val_int (cb -> current_position + subj_start );
163173 Field (v_callout_data , 4 ) = Val_int (capture_top );
164174 Field (v_callout_data , 5 ) = Val_int (cb -> capture_last );
165175 Field (v_callout_data , 6 ) = Val_int (cb -> pattern_position );
@@ -538,14 +548,15 @@ static inline void handle_exec_error(char *loc, const int ret) {
538548}
539549
540550static inline void handle_pcre_exec_result (int * ovec , value v_ovec ,
541- long ovec_len , int ret ) {
551+ long ovec_len , long subj_start ,
552+ int ret ) {
542553 caml_int_ptr ocaml_ovec = (caml_int_ptr )& Field (v_ovec , 0 );
543554 const int subgroups2 = ret * 2 ;
544555 const int subgroups2_1 = subgroups2 - 1 ;
545556 const int * ovec_src = ovec + subgroups2_1 ;
546557 caml_int_ptr ovec_clear_stop = ocaml_ovec + (ovec_len * 2 ) / 3 ;
547558 caml_int_ptr ovec_dst = ocaml_ovec + subgroups2_1 ;
548- copy_ovector (ovec_src , ovec_dst , subgroups2 );
559+ copy_ovector (subj_start , ovec_src , ovec_dst , subgroups2 );
549560 while (++ ovec_dst < ovec_clear_stop )
550561 * ovec_dst = -1 ;
551562}
@@ -556,21 +567,28 @@ static inline void handle_pcre_exec_result(int *ovec, value v_ovec,
556567 function */
557568
558569CAMLprim value pcre_exec_stub0 (intnat v_opt , value v_rex , intnat v_pos ,
559- value v_subj , value v_ovec , value v_maybe_cof ,
560- value v_workspace ) {
570+ intnat v_subj_start , value v_subj , value v_ovec ,
571+ value v_maybe_cof , value v_workspace ) {
561572 int ret ;
562573 int is_dfa = v_workspace != (value )NULL ;
563- long pos = v_pos , len = caml_string_length (v_subj );
574+ long pos = v_pos , len = caml_string_length (v_subj ), subj_start = v_subj_start ;
564575 long ovec_len = Wosize_val (v_ovec );
565576
566- if (pos > len || pos < 0 )
577+ if (pos > len || pos < subj_start )
567578 caml_invalid_argument ("Pcre.pcre_exec_stub: illegal position" );
568579
580+ if (subj_start > len || subj_start < 0 )
581+ caml_invalid_argument ("Pcre.pcre_exec_stub: illegal subject start" );
582+
583+ pos -= subj_start ;
584+ len -= subj_start ;
585+
569586 {
570- const pcre * code = get_rex (v_rex ); /* Compiled pattern */
571- const pcre_extra * extra = get_extra (v_rex ); /* Extra info */
572- const char * ocaml_subj = String_val (v_subj ); /* Subject string */
573- const int opt = v_opt ; /* Runtime options */
587+ const pcre * code = get_rex (v_rex ); /* Compiled pattern */
588+ const pcre_extra * extra = get_extra (v_rex ); /* Extra info */
589+ const char * ocaml_subj =
590+ String_val (v_subj ) + subj_start ; /* Subject string */
591+ const int opt = v_opt ; /* Runtime options */
574592
575593 /* Special case when no callout functions specified */
576594 if (Is_none (v_maybe_cof )) {
@@ -587,7 +605,7 @@ CAMLprim value pcre_exec_stub0(intnat v_opt, value v_rex, intnat v_pos,
587605 if (ret < 0 )
588606 handle_exec_error ("pcre_exec_stub" , ret );
589607 else
590- handle_pcre_exec_result (ovec , v_ovec , ovec_len , ret );
608+ handle_pcre_exec_result (ovec , v_ovec , ovec_len , subj_start , ret );
591609 }
592610
593611 /* There are callout functions */
@@ -598,7 +616,7 @@ CAMLprim value pcre_exec_stub0(intnat v_opt, value v_rex, intnat v_pos,
598616 int * ovec = caml_stat_alloc (sizeof (int ) * ovec_len );
599617 int workspace_len ;
600618 int * workspace ;
601- struct cod cod = {(value * )NULL , (value * )NULL , (value )NULL };
619+ struct cod cod = {0 , (value * )NULL , (value * )NULL , (value )NULL };
602620 struct pcre_extra new_extra =
603621#ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
604622#ifdef PCRE_EXTRA_MARK
@@ -614,6 +632,7 @@ CAMLprim value pcre_exec_stub0(intnat v_opt, value v_rex, intnat v_pos,
614632 {PCRE_EXTRA_CALLOUT_DATA , NULL , 0 , NULL , NULL };
615633#endif
616634
635+ cod .subj_start = subj_start ;
617636 memcpy (subj , ocaml_subj , len );
618637
619638 Begin_roots4 (v_rex , v_cof , v_substrings , v_ovec );
@@ -658,7 +677,7 @@ CAMLprim value pcre_exec_stub0(intnat v_opt, value v_rex, intnat v_pos,
658677 else
659678 handle_exec_error ("pcre_exec_stub(callout)" , ret );
660679 } else {
661- handle_pcre_exec_result (ovec , v_ovec , ovec_len , ret );
680+ handle_pcre_exec_result (ovec , v_ovec , ovec_len , subj_start , ret );
662681 if (is_dfa ) {
663682 caml_int_ptr ocaml_workspace_dst =
664683 (caml_int_ptr )& Field (v_workspace , 0 );
@@ -680,23 +699,25 @@ CAMLprim value pcre_exec_stub0(intnat v_opt, value v_rex, intnat v_pos,
680699}
681700
682701CAMLprim value pcre_exec_stub (intnat v_opt , value v_rex , intnat v_pos ,
683- value v_subj , value v_ovec , value v_maybe_cof ) {
684- return pcre_exec_stub0 (v_opt , v_rex , v_pos , v_subj , v_ovec , v_maybe_cof ,
685- (value )NULL );
702+ intnat v_subj_start , value v_subj , value v_ovec ,
703+ value v_maybe_cof ) {
704+ return pcre_exec_stub0 (v_opt , v_rex , v_pos , v_subj_start , v_subj , v_ovec ,
705+ v_maybe_cof , (value )NULL );
686706}
687707
688708/* Byte-code hook for pcre_exec_stub
689709 Needed, because there are more than 5 arguments */
690710CAMLprim value pcre_exec_stub_bc (value * argv , int __unused argn ) {
691- return pcre_exec_stub0 (Int_val (argv [0 ]), argv [1 ], Int_val (argv [2 ]), argv [3 ],
692- argv [4 ], argv [5 ], (value )NULL );
711+ return pcre_exec_stub0 (Int_val (argv [0 ]), argv [1 ], Int_val (argv [2 ]),
712+ Int_val (argv [3 ]), argv [4 ], argv [5 ], argv [6 ],
713+ (value )NULL );
693714}
694715
695716/* Byte-code hook for pcre_dfa_exec_stub
696717 Needed, because there are more than 5 arguments */
697718CAMLprim value pcre_dfa_exec_stub_bc (value * argv , int __unused argn ) {
698- return pcre_exec_stub0 (Int_val (argv [0 ]), argv [1 ], Int_val (argv [2 ]), argv [ 3 ],
699- argv [4 ], argv [5 ], argv [6 ]);
719+ return pcre_exec_stub0 (Int_val (argv [0 ]), argv [1 ], Int_val (argv [2 ]),
720+ Int_val ( argv [3 ]), argv [ 4 ], argv [5 ], argv [6 ], argv [ 7 ]);
700721}
701722
702723static struct custom_operations tables_ops = {
0 commit comments