1313 * Lesser General Public License for more details.
1414 *
1515 * You should have received a copy of the GNU Lesser General Public
16- * License along with this library; if not, write to the Free Software
17- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16+ * License along with this library; if not, see
17+ * <http://www.gnu.org/licenses/>.
1818 *
1919 * Davide Libenzi <davidel@xmailserver.org>
2020 *
2121 */
2222
2323#include "xinclude.h"
2424
25-
26-
27-
28- static long xdl_get_rec (xdfile_t * xdf , long ri , char const * * rec );
29- static int xdl_emit_record (xdfile_t * xdf , long ri , char const * pre , xdemitcb_t * ecb );
30-
31-
32-
33-
3425static long xdl_get_rec (xdfile_t * xdf , long ri , char const * * rec ) {
3526
3627 * rec = xdf -> recs [ri ]-> ptr ;
@@ -110,7 +101,7 @@ static long def_ff(const char *rec, long len, char *buf, long sz, void *priv)
110101
111102 if (len > 0 &&
112103 (isalpha ((unsigned char )* rec ) || /* identifier? */
113- * rec == '_' || /* also identifier? */
104+ * rec == '_' || /* also identifier? */
114105 * rec == '$' )) { /* identifiers from VMS and other esoterico */
115106 if (len > sz )
116107 len = sz ;
@@ -122,22 +113,20 @@ static long def_ff(const char *rec, long len, char *buf, long sz, void *priv)
122113 return -1 ;
123114}
124115
125- static int xdl_emit_common (xdfenv_t * xe , xdchange_t * xscr , xdemitcb_t * ecb ,
126- xdemitconf_t const * xecfg ) {
127- xdfile_t * xdf = & xe -> xdf2 ;
128- const char * rchg = xdf -> rchg ;
129- long ix ;
130-
131- (void )xscr ;
132- (void )xecfg ;
116+ static long match_func_rec (xdfile_t * xdf , xdemitconf_t const * xecfg , long ri ,
117+ char * buf , long sz )
118+ {
119+ const char * rec ;
120+ long len = xdl_get_rec (xdf , ri , & rec );
121+ if (!xecfg -> find_func )
122+ return def_ff (rec , len , buf , sz , xecfg -> find_func_priv );
123+ return xecfg -> find_func (rec , len , buf , sz , xecfg -> find_func_priv );
124+ }
133125
134- for (ix = 0 ; ix < xdf -> nrec ; ix ++ ) {
135- if (rchg [ix ])
136- continue ;
137- if (xdl_emit_record (xdf , ix , "" , ecb ))
138- return -1 ;
139- }
140- return 0 ;
126+ static int is_func_rec (xdfile_t * xdf , xdemitconf_t const * xecfg , long ri )
127+ {
128+ char dummy [1 ];
129+ return match_func_rec (xdf , xecfg , ri , dummy , sizeof (dummy )) >= 0 ;
141130}
142131
143132struct func_line {
@@ -148,17 +137,14 @@ struct func_line {
148137static long get_func_line (xdfenv_t * xe , xdemitconf_t const * xecfg ,
149138 struct func_line * func_line , long start , long limit )
150139{
151- find_func_t ff = xecfg -> find_func ? xecfg -> find_func : def_ff ;
152140 long l , size , step = (start > limit ) ? -1 : 1 ;
153141 char * buf , dummy [1 ];
154142
155143 buf = func_line ? func_line -> buf : dummy ;
156144 size = func_line ? sizeof (func_line -> buf ) : sizeof (dummy );
157145
158146 for (l = start ; l != limit && 0 <= l && l < xe -> xdf1 .nrec ; l += step ) {
159- const char * rec ;
160- long reclen = xdl_get_rec (& xe -> xdf1 , l , & rec );
161- long len = ff (rec , reclen , buf , size , xecfg -> find_func_priv );
147+ long len = match_func_rec (& xe -> xdf1 , xecfg , l , buf , size );
162148 if (len >= 0 ) {
163149 if (func_line )
164150 func_line -> len = len ;
@@ -168,16 +154,25 @@ static long get_func_line(xdfenv_t *xe, xdemitconf_t const *xecfg,
168154 return -1 ;
169155}
170156
157+ static int is_empty_rec (xdfile_t * xdf , long ri )
158+ {
159+ const char * rec ;
160+ long len = xdl_get_rec (xdf , ri , & rec );
161+
162+ while (len > 0 && XDL_ISSPACE (* rec )) {
163+ rec ++ ;
164+ len -- ;
165+ }
166+ return !len ;
167+ }
168+
171169int xdl_emit_diff (xdfenv_t * xe , xdchange_t * xscr , xdemitcb_t * ecb ,
172170 xdemitconf_t const * xecfg ) {
173171 long s1 , s2 , e1 , e2 , lctx ;
174172 xdchange_t * xch , * xche ;
175173 long funclineprev = -1 ;
176174 struct func_line func_line = { 0 };
177175
178- if (xecfg -> flags & XDL_EMIT_COMMON )
179- return xdl_emit_common (xe , xscr , ecb , xecfg );
180-
181176 for (xch = xscr ; xch ; xch = xche -> next ) {
182177 xche = xdl_get_hunk (& xch , xecfg );
183178 if (!xch )
@@ -187,7 +182,33 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
187182 s2 = XDL_MAX (xch -> i2 - xecfg -> ctxlen , 0 );
188183
189184 if (xecfg -> flags & XDL_EMIT_FUNCCONTEXT ) {
190- long fs1 = get_func_line (xe , xecfg , NULL , xch -> i1 , -1 );
185+ long fs1 , i1 = xch -> i1 ;
186+
187+ /* Appended chunk? */
188+ if (i1 >= xe -> xdf1 .nrec ) {
189+ long i2 = xch -> i2 ;
190+
191+ /*
192+ * We don't need additional context if
193+ * a whole function was added.
194+ */
195+ while (i2 < xe -> xdf2 .nrec ) {
196+ if (is_func_rec (& xe -> xdf2 , xecfg , i2 ))
197+ goto post_context_calculation ;
198+ i2 ++ ;
199+ }
200+
201+ /*
202+ * Otherwise get more context from the
203+ * pre-image.
204+ */
205+ i1 = xe -> xdf1 .nrec - 1 ;
206+ }
207+
208+ fs1 = get_func_line (xe , xecfg , NULL , i1 , -1 );
209+ while (fs1 > 0 && !is_empty_rec (& xe -> xdf1 , fs1 - 1 ) &&
210+ !is_func_rec (& xe -> xdf1 , xecfg , fs1 - 1 ))
211+ fs1 -- ;
191212 if (fs1 < 0 )
192213 fs1 = 0 ;
193214 if (fs1 < s1 ) {
@@ -196,7 +217,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
196217 }
197218 }
198219
199- again :
220+ post_context_calculation :
200221 lctx = xecfg -> ctxlen ;
201222 lctx = XDL_MIN (lctx , xe -> xdf1 .nrec - (xche -> i1 + xche -> chg1 ));
202223 lctx = XDL_MIN (lctx , xe -> xdf2 .nrec - (xche -> i2 + xche -> chg2 ));
@@ -208,6 +229,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
208229 long fe1 = get_func_line (xe , xecfg , NULL ,
209230 xche -> i1 + xche -> chg1 ,
210231 xe -> xdf1 .nrec );
232+ while (fe1 > 0 && is_empty_rec (& xe -> xdf1 , fe1 - 1 ))
233+ fe1 -- ;
211234 if (fe1 < 0 )
212235 fe1 = xe -> xdf1 .nrec ;
213236 if (fe1 > e1 ) {
@@ -221,11 +244,12 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
221244 * its new end.
222245 */
223246 if (xche -> next ) {
224- long l = xche -> next -> i1 ;
225- if (l <= e1 ||
247+ long l = XDL_MIN (xche -> next -> i1 ,
248+ xe -> xdf1 .nrec - 1 );
249+ if (l - xecfg -> ctxlen <= e1 ||
226250 get_func_line (xe , xecfg , NULL , l , e1 ) < 0 ) {
227251 xche = xche -> next ;
228- goto again ;
252+ goto post_context_calculation ;
229253 }
230254 }
231255 }
0 commit comments