Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/editors/sed.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 992 by niro, Sun May 30 11:43:19 2010 UTC revision 1126 by niro, Wed Aug 18 22:00:28 2010 UTC
# Line 61  Line 61 
61  #include "libbb.h"  #include "libbb.h"
62  #include "xregex.h"  #include "xregex.h"
63    
64    enum {
65     OPT_in_place = 1 << 0,
66    };
67    
68  /* Each sed command turns into one of these structures. */  /* Each sed command turns into one of these structures. */
69  typedef struct sed_cmd_s {  typedef struct sed_cmd_s {
70   /* Ordered by alignment requirements: currently 36 bytes on x86 */   /* Ordered by alignment requirements: currently 36 bytes on x86 */
# Line 117  struct globals { Line 121  struct globals {
121   int idx; /* Space used */   int idx; /* Space used */
122   int len; /* Space allocated */   int len; /* Space allocated */
123   } pipeline;   } pipeline;
124  };  } FIX_ALIASING;
125  #define G (*(struct globals*)&bb_common_bufsiz1)  #define G (*(struct globals*)&bb_common_bufsiz1)
126  void BUG_sed_globals_too_big(void);  struct BUG_G_too_big {
127            char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
128    };
129  #define INIT_G() do { \  #define INIT_G() do { \
  if (sizeof(struct globals) > COMMON_BUFSIZE) \  
  BUG_sed_globals_too_big(); \  
130   G.sed_cmd_tail = &G.sed_cmd_head; \   G.sed_cmd_tail = &G.sed_cmd_head; \
131  } while (0)  } while (0)
132    
# Line 385  static int parse_subst_cmd(sed_cmd_t *se Line 389  static int parse_subst_cmd(sed_cmd_t *se
389   break;   break;
390   /* Comment */   /* Comment */
391   case '#':   case '#':
392   while (substr[++idx]) /*skip all*/;   // while (substr[++idx]) continue;
393     idx += strlen(substr + idx); // same
394   /* Fall through */   /* Fall through */
395   /* End of command */   /* End of command */
396   case ';':   case ';':
# Line 395  static int parse_subst_cmd(sed_cmd_t *se Line 400  static int parse_subst_cmd(sed_cmd_t *se
400   bb_error_msg_and_die("bad option in substitution expression");   bb_error_msg_and_die("bad option in substitution expression");
401   }   }
402   }   }
403  out:   out:
404   /* compile the match string into a regex */   /* compile the match string into a regex */
405   if (*match != '\0') {   if (*match != '\0') {
406   /* If match is empty, we use last regex used at runtime */   /* If match is empty, we use last regex used at runtime */
# Line 562  static void add_cmd(const char *cmdstr) Line 567  static void add_cmd(const char *cmdstr)
567   /* last part (mandatory) will be a command */   /* last part (mandatory) will be a command */
568   if (!*cmdstr)   if (!*cmdstr)
569   bb_error_msg_and_die("missing command");   bb_error_msg_and_die("missing command");
570   sed_cmd->cmd = *(cmdstr++);   sed_cmd->cmd = *cmdstr++;
571   cmdstr = parse_cmd_args(sed_cmd, cmdstr);   cmdstr = parse_cmd_args(sed_cmd, cmdstr);
572    
573   /* Add the command to the command array */   /* Add the command to the command array */
# Line 896  static void process_files(void) Line 901  static void process_files(void)
901    
902   /* Determine if this command matches this line: */   /* Determine if this command matches this line: */
903    
904     //bb_error_msg("match1:%d", sed_cmd->in_match);
905     //bb_error_msg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line
906     // && !sed_cmd->beg_match && !sed_cmd->end_match));
907     //bb_error_msg("match3:%d", (sed_cmd->beg_line > 0
908     // && (sed_cmd->end_line || sed_cmd->end_match
909     //    ? (sed_cmd->beg_line <= linenum)
910     //    : (sed_cmd->beg_line == linenum)
911     //    )
912     // )
913     //bb_error_msg("match4:%d", (beg_match(sed_cmd, pattern_space)));
914     //bb_error_msg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL));
915    
916   /* Are we continuing a previous multi-line match? */   /* Are we continuing a previous multi-line match? */
917   sed_cmd->in_match = sed_cmd->in_match   sed_cmd->in_match = sed_cmd->in_match
918   /* Or is no range necessary? */   /* Or is no range necessary? */
919   || (!sed_cmd->beg_line && !sed_cmd->end_line   || (!sed_cmd->beg_line && !sed_cmd->end_line
920   && !sed_cmd->beg_match && !sed_cmd->end_match)   && !sed_cmd->beg_match && !sed_cmd->end_match)
921   /* Or did we match the start of a numerical range? */   /* Or did we match the start of a numerical range? */
922   || (sed_cmd->beg_line > 0 && (sed_cmd->beg_line <= linenum))   || (sed_cmd->beg_line > 0
923        && (sed_cmd->end_line || sed_cmd->end_match
924      /* note: even if end is numeric and is < linenum too,
925       * GNU sed matches! We match too */
926     ? (sed_cmd->beg_line <= linenum)    /* N,end */
927     : (sed_cmd->beg_line == linenum)    /* N */
928     )
929        )
930   /* Or does this line match our begin address regex? */   /* Or does this line match our begin address regex? */
931   || (beg_match(sed_cmd, pattern_space))   || (beg_match(sed_cmd, pattern_space))
932   /* Or did we match last line of input? */   /* Or did we match last line of input? */
# Line 918  static void process_files(void) Line 942  static void process_files(void)
942    
943   if (matched) {   if (matched) {
944   /* once matched, "n,xxx" range is dead, disabling it */   /* once matched, "n,xxx" range is dead, disabling it */
945   if (sed_cmd->beg_line > 0)   if (sed_cmd->beg_line > 0
946     && !(option_mask32 & OPT_in_place) /* but not for -i */
947     ) {
948   sed_cmd->beg_line = -2;   sed_cmd->beg_line = -2;
949     }
950   sed_cmd->in_match = !(   sed_cmd->in_match = !(
951   /* has the ending line come, or is this a single address command? */   /* has the ending line come, or is this a single address command? */
952   (sed_cmd->end_line ?   (sed_cmd->end_line ?
# Line 965  static void process_files(void) Line 992  static void process_files(void)
992   }   }
993    
994   /* actual sedding */   /* actual sedding */
995     //bb_error_msg("pattern_space:'%s' next_line:'%s' cmd:%c",
996     //pattern_space, next_line, sed_cmd->cmd);
997   switch (sed_cmd->cmd) {   switch (sed_cmd->cmd) {
998    
999   /* Print line number */   /* Print line number */
# Line 976  static void process_files(void) Line 1005  static void process_files(void)
1005   case 'P':   case 'P':
1006   {   {
1007   char *tmp = strchr(pattern_space, '\n');   char *tmp = strchr(pattern_space, '\n');
   
1008   if (tmp) {   if (tmp) {
1009   *tmp = '\0';   *tmp = '\0';
1010   /* TODO: explain why '\n' below */   /* TODO: explain why '\n' below */
# Line 999  static void process_files(void) Line 1027  static void process_files(void)
1027   case 'D':   case 'D':
1028   {   {
1029   char *tmp = strchr(pattern_space, '\n');   char *tmp = strchr(pattern_space, '\n');
   
1030   if (tmp) {   if (tmp) {
1031   tmp = xstrdup(tmp+1);   overlapping_strcpy(pattern_space, tmp + 1);
  free(pattern_space);  
  pattern_space = tmp;  
1032   goto restart;   goto restart;
1033   }   }
1034   }   }
# Line 1048  static void process_files(void) Line 1073  static void process_files(void)
1073   case 'r':   case 'r':
1074   {   {
1075   FILE *rfile;   FILE *rfile;
   
1076   rfile = fopen_for_read(sed_cmd->string);   rfile = fopen_for_read(sed_cmd->string);
1077   if (rfile) {   if (rfile) {
1078   char *line;   char *line;
# Line 1096  static void process_files(void) Line 1120  static void process_files(void)
1120   {   {
1121   int len;   int len;
1122   /* If no next line, jump to end of script and exit. */   /* If no next line, jump to end of script and exit. */
1123     /* http://www.gnu.org/software/sed/manual/sed.html:
1124     * "Most versions of sed exit without printing anything
1125     * when the N command is issued on the last line of
1126     * a file. GNU sed prints pattern space before exiting
1127     * unless of course the -n command switch has been
1128     * specified. This choice is by design."
1129     */
1130   if (next_line == NULL) {   if (next_line == NULL) {
1131   /* Jump to end of script and exit */   //goto discard_line;
1132   free(next_line);   goto discard_commands; /* GNU behavior */
  next_line = NULL;  
  goto discard_line;  
  /* append next_line, read new next_line. */  
1133   }   }
1134     /* Append next_line, read new next_line. */
1135   len = strlen(pattern_space);   len = strlen(pattern_space);
1136   pattern_space = xrealloc(pattern_space, len + strlen(next_line) + 2);   pattern_space = xrealloc(pattern_space, len + strlen(next_line) + 2);
1137   pattern_space[len] = '\n';   pattern_space[len] = '\n';
# Line 1131  static void process_files(void) Line 1160  static void process_files(void)
1160   case 'y':   case 'y':
1161   {   {
1162   int i, j;   int i, j;
   
1163   for (i = 0; pattern_space[i]; i++) {   for (i = 0; pattern_space[i]; i++) {
1164   for (j = 0; sed_cmd->string[j]; j += 2) {   for (j = 0; sed_cmd->string[j]; j += 2) {
1165   if (pattern_space[i] == sed_cmd->string[j]) {   if (pattern_space[i] == sed_cmd->string[j]) {
# Line 1257  static void add_cmd_block(char *cmdstr) Line 1285  static void add_cmd_block(char *cmdstr)
1285  int sed_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;  int sed_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1286  int sed_main(int argc UNUSED_PARAM, char **argv)  int sed_main(int argc UNUSED_PARAM, char **argv)
1287  {  {
  enum {  
  OPT_in_place = 1 << 0,  
  };  
1288   unsigned opt;   unsigned opt;
1289   llist_t *opt_e, *opt_f;   llist_t *opt_e, *opt_f;
1290   int status = EXIT_SUCCESS;   int status = EXIT_SUCCESS;
# Line 1279  int sed_main(int argc UNUSED_PARAM, char Line 1304  int sed_main(int argc UNUSED_PARAM, char
1304   opt_e = opt_f = NULL;   opt_e = opt_f = NULL;
1305   opt_complementary = "e::f::" /* can occur multiple times */   opt_complementary = "e::f::" /* can occur multiple times */
1306                      "nn"; /* count -n */                      "nn"; /* count -n */
1307     /* -i must be first, to match OPT_in_place definition */
1308   opt = getopt32(argv, "irne:f:", &opt_e, &opt_f,   opt = getopt32(argv, "irne:f:", &opt_e, &opt_f,
1309      &G.be_quiet); /* counter for -n */      &G.be_quiet); /* counter for -n */
1310   //argc -= optind;   //argc -= optind;
# Line 1320  int sed_main(int argc UNUSED_PARAM, char Line 1346  int sed_main(int argc UNUSED_PARAM, char
1346   if (opt & OPT_in_place)   if (opt & OPT_in_place)
1347   bb_error_msg_and_die(bb_msg_requires_arg, "-i");   bb_error_msg_and_die(bb_msg_requires_arg, "-i");
1348   add_input_file(stdin);   add_input_file(stdin);
  process_files();  
1349   } else {   } else {
1350   int i;   int i;
1351   FILE *file;   FILE *file;
# Line 1352  int sed_main(int argc UNUSED_PARAM, char Line 1377  int sed_main(int argc UNUSED_PARAM, char
1377    
1378   /* Set permissions/owner of output file */   /* Set permissions/owner of output file */
1379   fstat(fileno(file), &statbuf);   fstat(fileno(file), &statbuf);
1380     /* chmod'ing AFTER chown would preserve suid/sgid bits,
1381     * but GNU sed 4.2.1 does not preserve them either */
1382   fchmod(nonstdoutfd, statbuf.st_mode);   fchmod(nonstdoutfd, statbuf.st_mode);
1383   fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid);   fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid);
1384   add_input_file(file);   add_input_file(file);
# Line 1364  int sed_main(int argc UNUSED_PARAM, char Line 1391  int sed_main(int argc UNUSED_PARAM, char
1391   free(G.outname);   free(G.outname);
1392   G.outname = NULL;   G.outname = NULL;
1393   }   }
1394   if (G.input_file_count > G.current_input_file)   /* Here, to handle "sed 'cmds' nonexistent_file" case we did:
1395   process_files();   * if (G.current_input_file >= G.input_file_count)
1396     * return status;
1397     * but it's not needed since process_files() works correctly
1398     * in this case too. */
1399   }   }
1400     process_files();
1401    
1402   return status;   return status;
1403  }  }

Legend:
Removed from v.992  
changed lines
  Added in v.1126