@@ -375,7 +375,7 @@ static void just_read_file (FILE *);
375375
376376static language * get_language_from_langname (const char * );
377377static void readline (linebuffer * , FILE * );
378- static ptrdiff_t readline_internal (linebuffer * , FILE * , char const * );
378+ static ptrdiff_t readline_internal (linebuffer * , FILE * , char const * , const bool );
379379static bool nocase_tail (const char * );
380380static void get_tag (char * , char * * );
381381static void get_lispy_tag (char * );
@@ -399,7 +399,9 @@ static void free_fdesc (fdesc *);
399399static void pfnote (char * , bool , char * , ptrdiff_t , intmax_t , intmax_t );
400400static void invalidate_nodes (fdesc * , node * * );
401401static void put_entries (node * );
402+ static void clean_matched_file_tag (char const * const , char const * const );
402403
404+ static void do_move_file (const char * , const char * );
403405static char * concat (const char * , const char * , const char * );
404406static char * skip_spaces (char * );
405407static char * skip_non_spaces (char * );
@@ -1332,7 +1334,7 @@ main (int argc, char **argv)
13321334 if (parsing_stdin )
13331335 fatal ("cannot parse standard input "
13341336 "AND read file names from it" );
1335- while (readline_internal (& filename_lb , stdin , "-" ) > 0 )
1337+ while (readline_internal (& filename_lb , stdin , "-" , false ) > 0 )
13361338 process_file_name (filename_lb .buffer , lang );
13371339 }
13381340 else
@@ -1380,9 +1382,6 @@ main (int argc, char **argv)
13801382 /* From here on, we are in (CTAGS && !cxref_style) */
13811383 if (update )
13821384 {
1383- char * cmd =
1384- xmalloc (strlen (tagfile ) + whatlen_max +
1385- sizeof "mv..OTAGS;grep -Fv '\t\t' OTAGS >;rm OTAGS" );
13861385 for (i = 0 ; i < current_arg ; ++ i )
13871386 {
13881387 switch (argbuffer [i ].arg_type )
@@ -1393,17 +1392,8 @@ main (int argc, char **argv)
13931392 default :
13941393 continue ; /* the for loop */
13951394 }
1396- char * z = stpcpy (cmd , "mv " );
1397- z = stpcpy (z , tagfile );
1398- z = stpcpy (z , " OTAGS;grep -Fv '\t" );
1399- z = stpcpy (z , argbuffer [i ].what );
1400- z = stpcpy (z , "\t' OTAGS >" );
1401- z = stpcpy (z , tagfile );
1402- strcpy (z , ";rm OTAGS" );
1403- if (system (cmd ) != EXIT_SUCCESS )
1404- fatal ("failed to execute shell command" );
1395+ clean_matched_file_tag (tagfile , argbuffer [i ].what );
14051396 }
1406- free (cmd );
14071397 append_to_tagfile = true;
14081398 }
14091399
@@ -1448,6 +1438,51 @@ main (int argc, char **argv)
14481438 return EXIT_SUCCESS ;
14491439}
14501440
1441+ /*
1442+ * Equivalent to: mv tags OTAGS;grep -Fv ' filename ' OTAGS >tags;rm OTAGS
1443+ */
1444+ static void
1445+ clean_matched_file_tag (const char * tagfile , const char * match_file_name )
1446+ {
1447+ FILE * otags_f = fopen ("OTAGS" , "wb" );
1448+ FILE * tag_f = fopen (tagfile , "rb" );
1449+
1450+ if (otags_f == NULL )
1451+ pfatal ("OTAGS" );
1452+
1453+ if (tag_f == NULL )
1454+ pfatal (tagfile );
1455+
1456+ int buf_len = strlen (match_file_name ) + sizeof ("\t\t " ) + 1 ;
1457+ char * buf = xmalloc (buf_len );
1458+ snprintf (buf , buf_len , "\t%s\t" , match_file_name );
1459+
1460+ linebuffer line ;
1461+ linebuffer_init (& line );
1462+ while (readline_internal (& line , tag_f , tagfile , true) > 0 )
1463+ {
1464+ if (ferror (tag_f ))
1465+ pfatal (tagfile );
1466+
1467+ if (strstr (line .buffer , buf ) == NULL )
1468+ {
1469+ fprintf (otags_f , "%s\n" , line .buffer );
1470+ if (ferror (tag_f ))
1471+ pfatal (tagfile );
1472+ }
1473+ }
1474+ free (buf );
1475+ free (line .buffer );
1476+
1477+ if (fclose (otags_f ) == EOF )
1478+ pfatal ("OTAGS" );
1479+
1480+ if (fclose (tag_f ) == EOF )
1481+ pfatal (tagfile );
1482+
1483+ do_move_file ("OTAGS" , tagfile );
1484+ return ;
1485+ }
14511486
14521487/*
14531488 * Return a compressor given the file name. If EXTPTR is non-zero,
@@ -1831,7 +1866,7 @@ find_entries (FILE *inf)
18311866
18321867 /* Else look for sharp-bang as the first two characters. */
18331868 if (parser == NULL
1834- && readline_internal (& lb , inf , infilename ) > 0
1869+ && readline_internal (& lb , inf , infilename , false ) > 0
18351870 && lb .len >= 2
18361871 && lb .buffer [0 ] == '#'
18371872 && lb .buffer [1 ] == '!' )
@@ -6878,7 +6913,7 @@ analyze_regex (char *regex_arg)
68786913 if (regexfp == NULL )
68796914 pfatal (regexfile );
68806915 linebuffer_init (& regexbuf );
6881- while (readline_internal (& regexbuf , regexfp , regexfile ) > 0 )
6916+ while (readline_internal (& regexbuf , regexfp , regexfile , false ) > 0 )
68826917 analyze_regex (regexbuf .buffer );
68836918 free (regexbuf .buffer );
68846919 if (fclose (regexfp ) != 0 )
@@ -7226,19 +7261,21 @@ get_lispy_tag (register char *bp)
72267261
72277262/*
72287263 * Read a line of text from `stream' into `lbp', excluding the
7229- * newline or CR-NL, if any. Return the number of characters read from
7230- * `stream', which is the length of the line including the newline.
7264+ * newline or CR-NL (if `leave_cr` is false), if any. Return the
7265+ * number of characters read from `stream', which is the length
7266+ * of the line including the newline.
72317267 *
7232- * On DOS or Windows we do not count the CR character, if any before the
7233- * NL, in the returned length; this mirrors the behavior of Emacs on those
7268+ * On DOS or Windows, if `leave_cr` is false, we do not count the
7269+ * CR character, if any before the NL, in the returned length;
7270+ * this mirrors the behavior of Emacs on those
72347271 * platforms (for text files, it translates CR-NL to NL as it reads in the
72357272 * file).
72367273 *
72377274 * If multi-line regular expressions are requested, each line read is
72387275 * appended to `filebuf'.
72397276 */
72407277static ptrdiff_t
7241- readline_internal (linebuffer * lbp , FILE * stream , char const * filename )
7278+ readline_internal (linebuffer * lbp , FILE * stream , char const * filename , const bool leave_cr )
72427279{
72437280 char * buffer = lbp -> buffer ;
72447281 char * p = lbp -> buffer ;
@@ -7268,19 +7305,19 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
72687305 break ;
72697306 }
72707307 if (c == '\n' )
7271- {
7272- if (p > buffer && p [-1 ] == '\r' )
7273- {
7274- p -= 1 ;
7275- chars_deleted = 2 ;
7276- }
7277- else
7278- {
7279- chars_deleted = 1 ;
7280- }
7281- * p = '\0' ;
7282- break ;
7283- }
7308+ {
7309+ if (! leave_cr && p > buffer && p [-1 ] == '\r' )
7310+ {
7311+ p -= 1 ;
7312+ chars_deleted = 2 ;
7313+ }
7314+ else
7315+ {
7316+ chars_deleted = 1 ;
7317+ }
7318+ * p = '\0' ;
7319+ break ;
7320+ }
72847321 * p ++ = c ;
72857322 }
72867323 lbp -> len = p - buffer ;
@@ -7311,7 +7348,7 @@ static void
73117348readline (linebuffer * lbp , FILE * stream )
73127349{
73137350 linecharno = charno ; /* update global char number of line start */
7314- ptrdiff_t result = readline_internal (lbp , stream , infilename );
7351+ ptrdiff_t result = readline_internal (lbp , stream , infilename , false );
73157352 lineno += 1 ; /* increment global line number */
73167353 charno += result ; /* increment global char number */
73177354
@@ -7669,6 +7706,46 @@ etags_mktmp (void)
76697706 return templt ;
76707707}
76717708
7709+ static void
7710+ do_move_file (const char * src_file , const char * dst_file )
7711+ {
7712+ if (rename (src_file , dst_file ) == 0 )
7713+ return ;
7714+
7715+ FILE * src_f = fopen (src_file , "rb" );
7716+ FILE * dst_f = fopen (dst_file , "wb" );
7717+
7718+ if (src_f == NULL )
7719+ pfatal (src_file );
7720+
7721+ if (dst_f == NULL )
7722+ pfatal (dst_file );
7723+
7724+ int c ;
7725+ while ((c = fgetc (src_f )) != EOF )
7726+ {
7727+ if (ferror (src_f ))
7728+ pfatal (src_file );
7729+
7730+ if (ferror (dst_f ))
7731+ pfatal (dst_file );
7732+
7733+ if (fputc (c , dst_f ) == EOF )
7734+ pfatal ("cannot write" );
7735+ }
7736+
7737+ if (fclose (src_f ) == EOF )
7738+ pfatal (src_file );
7739+
7740+ if (fclose (dst_f ) == EOF )
7741+ pfatal (dst_file );
7742+
7743+ if (unlink (src_file ) == -1 )
7744+ pfatal ("unlink error" );
7745+
7746+ return ;
7747+ }
7748+
76727749/* Return a newly allocated string containing the file name of FILE
76737750 relative to the absolute directory DIR (which should end with a slash). */
76747751static char *
0 commit comments