* sed now supports addresses (numeric or regexp, with negation) and
authorErik Andersen <andersen@codepoet.org>
Wed, 29 Dec 1999 22:19:46 +0000 (22:19 -0000)
committerErik Andersen <andersen@codepoet.org>
Wed, 29 Dec 1999 22:19:46 +0000 (22:19 -0000)
    has an append command, thanks to Marco Pantaleoni <panta@prosa.it>
* Fixed dmesg.  It wasn't parsing its options (-n or -s) properly.
* Some cosmetic fixes to ls output formatting to make it behave more
    like GNU ls.
 -Erik

Changelog
coreutils/ls.c
dmesg.c
editors/sed.c
ls.c
sed.c
util-linux/dmesg.c

index 8ba73692d788cba2ddf3f2bd1b88c58b011a3683..37570d29206a265c3dfd20c0a0024583d79a409c 100644 (file)
--- a/Changelog
+++ b/Changelog
            them so they should now work as expected.  
        * New app: loadacm contributed by Peter Novodvorsky <petya@logic.ru>
            for loading application character maps for working with Unicode fonts.
+       * sed now supports addresses (numeric or regexp, with negation) and 
+           has an append command, thanks to Marco Pantaleoni <panta@prosa.it>
+       * Fixed dmesg.  It wasn't parsing its options (-n or -s) properly.  
+       * Some cosmetic fixes to ls output formatting to make it behave more
+           like GNU ls.
            
 
        -Erik Andersen
index 571c962c708e9e715b667570b31164a87ff0c931..862da436854de79f2222a60804fe3c25f2e62359 100644 (file)
@@ -193,11 +193,13 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
                fputs(" ", stdout);
 #ifdef BB_FEATURE_LS_USERNAME
                if (!(opts & DISP_NUMERIC)) {
-                       scratch[0]='\0';
+                       memset ( scratch, 0, sizeof (scratch));
                        my_getpwuid( scratch, info->st_uid);
-                       scratch[8]='\0';
-                       if (*scratch)
-                               wr(scratch,8);
+                       if (*scratch) {
+                           fputs(scratch, stdout);
+                           if ( strlen( scratch) <= 8 )
+                               wr("         ", 8-strlen( scratch));
+                       }
                        else {
                                writenum((long) info->st_uid,(short)8);
                                fputs(" ", stdout);
@@ -208,20 +210,21 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
                    writenum((long) info->st_uid,(short)8);
                    fputs(" ", stdout);
                }
-               tab(16);
 #ifdef BB_FEATURE_LS_USERNAME
                if (!(opts & DISP_NUMERIC)) {
-                       scratch[0]='\0';
+                       memset ( scratch, 0, sizeof (scratch));
                        my_getgrgid( scratch, info->st_gid);
-                       scratch[8]='\0';
-                       if (*scratch)
-                               wr(scratch,8);
+                       if (*scratch) {
+                           fputs(scratch, stdout);
+                           if ( strlen( scratch) <= 8 )
+                               wr("         ", 8-strlen( scratch));
+                       }
                        else 
-                               writenum((long) info->st_gid,(short)8);
+                           writenum((long) info->st_gid,(short)8);
                } else
 #endif
                writenum((long) info->st_gid,(short)8);
-               tab(17);
+               //tab(26);
                if (S_ISBLK(mode) || S_ISCHR(mode)) {
                        writenum((long)MAJOR(info->st_rdev),(short)3);
                        fputs(", ", stdout);
@@ -230,6 +233,7 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
                else
                        writenum((long)info->st_size,(short)8);
                fputs(" ", stdout);
+               //tab(32);
 #ifdef BB_FEATURE_LS_TIMESTAMPS
                {
                        time_t cal;
diff --git a/dmesg.c b/dmesg.c
index aa26f5836c7e9c6e6b319d875c84920a96d614dc..e38fd55551cebfb6a87c862b0f84d73dc5e914ba 100644 (file)
--- a/dmesg.c
+++ b/dmesg.c
@@ -44,10 +44,15 @@ int dmesg_main( int argc, char** argv )
    int  level = 0;
    int  lastc;
    int  cmd = 3;
+   int stopDoingThat;
+
+   argc--;
+   argv++;
 
     /* Parse any options */
     while (argc && **argv == '-') {
-       while (*++(*argv))
+       stopDoingThat = FALSE;
+       while (stopDoingThat == FALSE && *++(*argv)) {
            switch (**argv) {
            case 'c':
                cmd = 4;
@@ -57,19 +62,22 @@ int dmesg_main( int argc, char** argv )
                if (--argc == 0)
                    goto end;
                level = atoi (*(++argv));
-               --argc;
-               ++argv;
+               if (--argc > 0)
+                   ++argv;
+               stopDoingThat = TRUE;
                break;
            case 's':
                if (--argc == 0)
                    goto end;
                bufsize = atoi (*(++argv));
-               --argc;
-               ++argv;
+               if (--argc > 0)
+                   ++argv;
+               stopDoingThat = TRUE;
                break;
            default:
                goto end;
            }
+       }
     }
    
    if (argc > 1) {
index 4dfc0246c9e87a9b54033a587ad842dbb99ea8b9..8e5f695c4bd6a426d4e11a1d9edd01d7a583a095 100644 (file)
@@ -5,6 +5,11 @@
  * Copyright (C) 1999 by Lineo, inc.
  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
  *
+ * Modifications for addresses and append command have been
+ * written by Marco Pantaleoni <panta@prosa.it>, <panta@elasticworld.org>
+ * and are:
+ * Copyright (C) 1999 Marco Pantaleoni.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
 #include <time.h>
 #include <ctype.h>
 
-static const char sed_usage[] = 
-"sed [-n] [-e script] [file...]\n\n"
-"Allowed sed scripts come in the following form:\n"
-"\t's/regexp/replacement/[gp]'\n"
-"which attempt to match regexp against the pattern space\n"
-"and if successful replaces the matched portion with replacement.\n\n"
-"Options:\n"
-"-e\tadd the script to the commands to be executed\n"
-"-n\tsuppress automatic printing of pattern space\n\n"
+static const char sed_usage[] =
+    "sed [-n] -e script [file...]\n\n"
+    "Allowed sed scripts come in the following form:\n"
+    "\t'ADDR [!] COMMAND'\n\n"
+    "\twhere address ADDR can be:\n"
+    "\t  NUMBER    Match specified line number\n"
+    "\t  $         Match last line\n"
+    "\t  /REGEXP/  Match specified regexp\n"
+    "\t  (! inverts the meaning of the match)\n\n"
+    "\tand COMMAND can be:\n"
+    "\t  s/regexp/replacement/[gp]\n"
+    "\t     which attempt to match regexp against the pattern space\n"
+    "\t     and if successful replaces the matched portion with replacement.\n\n"
+    "\t  aTEXT\n"
+    "\t     which appends TEXT after the pattern space\n"
+    "Options:\n"
+    "-e\tadd the script to the commands to be executed\n"
+    "-n\tsuppress automatic printing of pattern space\n\n"
 #if defined BB_REGEXP
-"This version of sed matches full regular expresions.\n";
+    "This version of sed matches full regular expresions.\n";
 #else
-"This version of sed matches strings (not full regular expresions).\n";
+    "This version of sed matches strings (not full regular expresions).\n";
 #endif
-    
 
-static void do_sed(FILE *fp, char *needle, char *newNeedle, int ignoreCase, int printFlag, int quietFlag)
+/* Flags & variables */
+
+typedef enum { f_none, f_replace, f_append } sed_function;
+
+#define NO_LINE                -2
+#define LAST_LINE      -1
+static int addr_line = NO_LINE;
+static char *addr_pattern = NULL;
+static int negated = 0;
+
+#define SKIPSPACES(p)          do { while (isspace(*(p))) (p)++; } while (0)
+
+#define BUFSIZE                1024
+
+static inline int at_last(FILE * fp)
 {
-    int foundOne=FALSE;
-    char haystack[1024];
+    int res = 0;
 
-    while (fgets (haystack, 1023, fp)) {
-       foundOne = replace_match(haystack, needle, newNeedle, ignoreCase);
-       if (foundOne==TRUE && printFlag==TRUE) {
-           fprintf(stdout, haystack);
+    if (feof(fp))
+       return 1;
+    else {
+       char ch;
+       if ((ch = fgetc(fp)) == EOF)
+           res++;
+       ungetc(ch, fp);
+    }
+    return res;
+}
+
+static void do_sed_repl(FILE * fp, char *needle, char *newNeedle,
+                       int ignoreCase, int printFlag, int quietFlag)
+{
+    int foundOne = FALSE;
+    char haystack[BUFSIZE];
+    int line = 1, doit;
+
+    while (fgets(haystack, BUFSIZE - 1, fp)) {
+       doit = 0;
+       if (addr_pattern) {
+           doit = !find_match(haystack, addr_pattern, FALSE);
+       } else if (addr_line == NO_LINE)
+           doit = 1;
+       else if (addr_line == LAST_LINE) {
+           if (at_last(fp))
+               doit = 1;
+       } else {
+           if (line == addr_line)
+               doit = 1;
+       }
+       if (negated)
+           doit = 1 - doit;
+       if (doit) {
+           foundOne =
+               replace_match(haystack, needle, newNeedle, ignoreCase);
+
+           if (foundOne == TRUE && printFlag == TRUE) {
+               fprintf(stdout, haystack);
+           }
        }
-       if (quietFlag==FALSE) {
+
+       if (quietFlag == FALSE) {
            fprintf(stdout, haystack);
        }
+
+       line++;
+    }
+}
+
+static void do_sed_append(FILE * fp, char *appendline, int quietFlag)
+{
+    char buffer[BUFSIZE];
+    int line = 1, doit;
+
+    while (fgets(buffer, BUFSIZE - 1, fp)) {
+       doit = 0;
+       if (addr_pattern) {
+           doit = !find_match(buffer, addr_pattern, FALSE);
+       } else if (addr_line == NO_LINE)
+           doit = 1;
+       else if (addr_line == LAST_LINE) {
+           if (at_last(fp))
+               doit = 1;
+       } else {
+           if (line == addr_line)
+               doit = 1;
+       }
+       if (negated)
+           doit = 1 - doit;
+       if (quietFlag == FALSE) {
+           fprintf(stdout, buffer);
+       }
+       if (doit) {
+           fputs(appendline, stdout);
+           fputc('\n', stdout);
+       }
+
+       line++;
     }
 }
 
-extern int sed_main (int argc, char **argv)
+extern int sed_main(int argc, char **argv)
 {
     FILE *fp;
-    char *needle=NULL, *newNeedle=NULL;
+    char *needle = NULL, *newNeedle = NULL;
     char *name;
     char *cp;
-    int ignoreCase=FALSE;
-    int printFlag=FALSE;
-    int quietFlag=FALSE;
+    int ignoreCase = FALSE;
+    int printFlag = FALSE;
+    int quietFlag = FALSE;
     int stopNow;
+    char *line_s = NULL, saved;
+    char *appendline = NULL;
+    char *pos;
+    sed_function sed_f = f_none;
 
     argc--;
     argv++;
@@ -83,68 +184,119 @@ extern int sed_main (int argc, char **argv)
     if (**argv == '-') {
        argc--;
        cp = *argv++;
-       stopNow=FALSE;
+       stopNow = FALSE;
 
-       while (*++cp && stopNow==FALSE) {
+       while (*++cp && stopNow == FALSE) {
            switch (*cp) {
            case 'n':
                quietFlag = TRUE;
                break;
            case 'e':
-               if (*(cp+1)==0 && --argc < 0) {
-                   usage( sed_usage);
+               if (*(cp + 1) == 0 && --argc < 0) {
+                   usage(sed_usage);
                }
-               if ( *++cp != 's')
+               if (*++cp != 's')
                    cp = *argv++;
-               while( *cp ) {
-                   if (*cp == 's' && strlen(cp) > 3 && *(cp+1) == '/') {
-                       char* pos=needle=cp+2;
-                       for(;;) {
-                           pos = strchr(pos, '/');
-                           if (pos==NULL) {
-                               usage( sed_usage);
-                           }
-                           if (*(pos-1) == '\\') {
-                               pos++;
-                               continue;
-                           }
-                           break;
+
+               /* Read address if present */
+               SKIPSPACES(cp);
+               if (*cp == '$') {
+                   addr_line = LAST_LINE;
+                   cp++;
+               } else {
+                   if (isdigit(*cp)) { /* LINE ADDRESS   */
+                       line_s = cp;
+                       while (isdigit(*cp))
+                           cp++;
+                       if (cp > line_s) {
+                           /* numeric line */
+                           saved = *cp;
+                           *cp = '\0';
+                           addr_line = atoi(line_s);
+                           *cp = saved;
                        }
-                       *pos=0;
-                       newNeedle=++pos;
-                       for(;;) {
-                           pos = strchr(pos, '/');
-                           if (pos==NULL) {
-                               usage( sed_usage);
-                           }
-                           if (*(pos-1) == '\\') {
-                               pos++;
-                               continue;
-                           }
-                           break;
+                   } else if (*cp == '/') {    /* PATTERN ADDRESS */
+                       pos = addr_pattern = cp + 1;
+                       pos = strchr(pos, '/');
+                       if (!pos)
+                           usage(sed_usage);
+                       *pos = '\0';
+                       cp = pos + 1;
+                   }
+               }
+
+               SKIPSPACES(cp);
+               if (*cp == '!') {
+                   negated++;
+                   cp++;
+               }
+
+               /* Read command */
+
+               SKIPSPACES(cp);
+               switch (*cp) {
+               case 's':       /* REPLACE */
+                   if (strlen(cp) <= 3 || *(cp + 1) != '/')
+                       break;
+                   sed_f = f_replace;
+
+                   pos = needle = cp + 2;
+
+                   for (;;) {
+                       pos = strchr(pos, '/');
+                       if (pos == NULL) {
+                           usage(sed_usage);
+                       }
+                       if (*(pos - 1) == '\\') {
+                           pos++;
+                           continue;
                        }
-                       *pos=0;
-                       if (pos+2 != 0) {
-                           while (*++pos) {
-                               switch (*pos) {
-                                   case 'i':
-                                       ignoreCase=TRUE;
-                                       break;
-                                   case 'p':
-                                       printFlag=TRUE;
-                                       break;
-                                   case 'g':
-                                       break;
-                                   default:
-                                       usage( sed_usage);
-                               }
+                       break;
+                   }
+                   *pos = 0;
+                   newNeedle = ++pos;
+                   for (;;) {
+                       pos = strchr(pos, '/');
+                       if (pos == NULL) {
+                           usage(sed_usage);
+                       }
+                       if (*(pos - 1) == '\\') {
+                           pos++;
+                           continue;
+                       }
+                       break;
+                   }
+                   *pos = 0;
+                   if (pos + 2 != 0) {
+                       while (*++pos) {
+                           switch (*pos) {
+                           case 'i':
+                               ignoreCase = TRUE;
+                               break;
+                           case 'p':
+                               printFlag = TRUE;
+                               break;
+                           case 'g':
+                               break;
+                           default:
+                               usage(sed_usage);
                            }
                        }
                    }
-                   cp++;
+                   cp = pos;
+                   /* fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); */
+                   break;
+
+               case 'a':       /* APPEND */
+                   if (strlen(cp) < 2)
+                       break;
+                   sed_f = f_append;
+                   appendline = ++cp;
+                   /* fprintf(stderr, "append '%s'\n", appendline); */
+                   break;
                }
-               //fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle);
-               stopNow=TRUE;
+
+               stopNow = TRUE;
                break;
 
            default:
@@ -153,30 +305,48 @@ extern int sed_main (int argc, char **argv)
        }
     }
 
-    if (argc==0) {
-       do_sed( stdin, needle, newNeedle, ignoreCase, printFlag, quietFlag);
+    if (argc == 0) {
+       switch (sed_f) {
+       case f_none:
+           break;
+       case f_replace:
+           do_sed_repl(stdin, needle, newNeedle, ignoreCase, printFlag,
+                       quietFlag);
+           break;
+       case f_append:
+           do_sed_append(stdin, appendline, quietFlag);
+           break;
+       }
     } else {
        while (argc-- > 0) {
            name = *argv++;
 
-           fp = fopen (name, "r");
+           fp = fopen(name, "r");
            if (fp == NULL) {
-               perror (name);
+               perror(name);
                continue;
            }
 
-           do_sed( fp, needle, newNeedle, ignoreCase, printFlag, quietFlag);
+           switch (sed_f) {
+           case f_none:
+               break;
+           case f_replace:
+               do_sed_repl(fp, needle, newNeedle, ignoreCase, printFlag,
+                           quietFlag);
+               break;
+           case f_append:
+               do_sed_append(fp, appendline, quietFlag);
+               break;
+           }
 
-           if (ferror (fp))
-               perror (name);
+           if (ferror(fp))
+               perror(name);
 
-           fclose (fp);
+           fclose(fp);
        }
     }
-    exit( TRUE);
+    exit(TRUE);
 }
 
 
 /* END CODE */
-
-
diff --git a/ls.c b/ls.c
index 571c962c708e9e715b667570b31164a87ff0c931..862da436854de79f2222a60804fe3c25f2e62359 100644 (file)
--- a/ls.c
+++ b/ls.c
@@ -193,11 +193,13 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
                fputs(" ", stdout);
 #ifdef BB_FEATURE_LS_USERNAME
                if (!(opts & DISP_NUMERIC)) {
-                       scratch[0]='\0';
+                       memset ( scratch, 0, sizeof (scratch));
                        my_getpwuid( scratch, info->st_uid);
-                       scratch[8]='\0';
-                       if (*scratch)
-                               wr(scratch,8);
+                       if (*scratch) {
+                           fputs(scratch, stdout);
+                           if ( strlen( scratch) <= 8 )
+                               wr("         ", 8-strlen( scratch));
+                       }
                        else {
                                writenum((long) info->st_uid,(short)8);
                                fputs(" ", stdout);
@@ -208,20 +210,21 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
                    writenum((long) info->st_uid,(short)8);
                    fputs(" ", stdout);
                }
-               tab(16);
 #ifdef BB_FEATURE_LS_USERNAME
                if (!(opts & DISP_NUMERIC)) {
-                       scratch[0]='\0';
+                       memset ( scratch, 0, sizeof (scratch));
                        my_getgrgid( scratch, info->st_gid);
-                       scratch[8]='\0';
-                       if (*scratch)
-                               wr(scratch,8);
+                       if (*scratch) {
+                           fputs(scratch, stdout);
+                           if ( strlen( scratch) <= 8 )
+                               wr("         ", 8-strlen( scratch));
+                       }
                        else 
-                               writenum((long) info->st_gid,(short)8);
+                           writenum((long) info->st_gid,(short)8);
                } else
 #endif
                writenum((long) info->st_gid,(short)8);
-               tab(17);
+               //tab(26);
                if (S_ISBLK(mode) || S_ISCHR(mode)) {
                        writenum((long)MAJOR(info->st_rdev),(short)3);
                        fputs(", ", stdout);
@@ -230,6 +233,7 @@ static void list_single(const char *name, struct stat *info, const char *fullnam
                else
                        writenum((long)info->st_size,(short)8);
                fputs(" ", stdout);
+               //tab(32);
 #ifdef BB_FEATURE_LS_TIMESTAMPS
                {
                        time_t cal;
diff --git a/sed.c b/sed.c
index 4dfc0246c9e87a9b54033a587ad842dbb99ea8b9..8e5f695c4bd6a426d4e11a1d9edd01d7a583a095 100644 (file)
--- a/sed.c
+++ b/sed.c
@@ -5,6 +5,11 @@
  * Copyright (C) 1999 by Lineo, inc.
  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
  *
+ * Modifications for addresses and append command have been
+ * written by Marco Pantaleoni <panta@prosa.it>, <panta@elasticworld.org>
+ * and are:
+ * Copyright (C) 1999 Marco Pantaleoni.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
 #include <time.h>
 #include <ctype.h>
 
-static const char sed_usage[] = 
-"sed [-n] [-e script] [file...]\n\n"
-"Allowed sed scripts come in the following form:\n"
-"\t's/regexp/replacement/[gp]'\n"
-"which attempt to match regexp against the pattern space\n"
-"and if successful replaces the matched portion with replacement.\n\n"
-"Options:\n"
-"-e\tadd the script to the commands to be executed\n"
-"-n\tsuppress automatic printing of pattern space\n\n"
+static const char sed_usage[] =
+    "sed [-n] -e script [file...]\n\n"
+    "Allowed sed scripts come in the following form:\n"
+    "\t'ADDR [!] COMMAND'\n\n"
+    "\twhere address ADDR can be:\n"
+    "\t  NUMBER    Match specified line number\n"
+    "\t  $         Match last line\n"
+    "\t  /REGEXP/  Match specified regexp\n"
+    "\t  (! inverts the meaning of the match)\n\n"
+    "\tand COMMAND can be:\n"
+    "\t  s/regexp/replacement/[gp]\n"
+    "\t     which attempt to match regexp against the pattern space\n"
+    "\t     and if successful replaces the matched portion with replacement.\n\n"
+    "\t  aTEXT\n"
+    "\t     which appends TEXT after the pattern space\n"
+    "Options:\n"
+    "-e\tadd the script to the commands to be executed\n"
+    "-n\tsuppress automatic printing of pattern space\n\n"
 #if defined BB_REGEXP
-"This version of sed matches full regular expresions.\n";
+    "This version of sed matches full regular expresions.\n";
 #else
-"This version of sed matches strings (not full regular expresions).\n";
+    "This version of sed matches strings (not full regular expresions).\n";
 #endif
-    
 
-static void do_sed(FILE *fp, char *needle, char *newNeedle, int ignoreCase, int printFlag, int quietFlag)
+/* Flags & variables */
+
+typedef enum { f_none, f_replace, f_append } sed_function;
+
+#define NO_LINE                -2
+#define LAST_LINE      -1
+static int addr_line = NO_LINE;
+static char *addr_pattern = NULL;
+static int negated = 0;
+
+#define SKIPSPACES(p)          do { while (isspace(*(p))) (p)++; } while (0)
+
+#define BUFSIZE                1024
+
+static inline int at_last(FILE * fp)
 {
-    int foundOne=FALSE;
-    char haystack[1024];
+    int res = 0;
 
-    while (fgets (haystack, 1023, fp)) {
-       foundOne = replace_match(haystack, needle, newNeedle, ignoreCase);
-       if (foundOne==TRUE && printFlag==TRUE) {
-           fprintf(stdout, haystack);
+    if (feof(fp))
+       return 1;
+    else {
+       char ch;
+       if ((ch = fgetc(fp)) == EOF)
+           res++;
+       ungetc(ch, fp);
+    }
+    return res;
+}
+
+static void do_sed_repl(FILE * fp, char *needle, char *newNeedle,
+                       int ignoreCase, int printFlag, int quietFlag)
+{
+    int foundOne = FALSE;
+    char haystack[BUFSIZE];
+    int line = 1, doit;
+
+    while (fgets(haystack, BUFSIZE - 1, fp)) {
+       doit = 0;
+       if (addr_pattern) {
+           doit = !find_match(haystack, addr_pattern, FALSE);
+       } else if (addr_line == NO_LINE)
+           doit = 1;
+       else if (addr_line == LAST_LINE) {
+           if (at_last(fp))
+               doit = 1;
+       } else {
+           if (line == addr_line)
+               doit = 1;
+       }
+       if (negated)
+           doit = 1 - doit;
+       if (doit) {
+           foundOne =
+               replace_match(haystack, needle, newNeedle, ignoreCase);
+
+           if (foundOne == TRUE && printFlag == TRUE) {
+               fprintf(stdout, haystack);
+           }
        }
-       if (quietFlag==FALSE) {
+
+       if (quietFlag == FALSE) {
            fprintf(stdout, haystack);
        }
+
+       line++;
+    }
+}
+
+static void do_sed_append(FILE * fp, char *appendline, int quietFlag)
+{
+    char buffer[BUFSIZE];
+    int line = 1, doit;
+
+    while (fgets(buffer, BUFSIZE - 1, fp)) {
+       doit = 0;
+       if (addr_pattern) {
+           doit = !find_match(buffer, addr_pattern, FALSE);
+       } else if (addr_line == NO_LINE)
+           doit = 1;
+       else if (addr_line == LAST_LINE) {
+           if (at_last(fp))
+               doit = 1;
+       } else {
+           if (line == addr_line)
+               doit = 1;
+       }
+       if (negated)
+           doit = 1 - doit;
+       if (quietFlag == FALSE) {
+           fprintf(stdout, buffer);
+       }
+       if (doit) {
+           fputs(appendline, stdout);
+           fputc('\n', stdout);
+       }
+
+       line++;
     }
 }
 
-extern int sed_main (int argc, char **argv)
+extern int sed_main(int argc, char **argv)
 {
     FILE *fp;
-    char *needle=NULL, *newNeedle=NULL;
+    char *needle = NULL, *newNeedle = NULL;
     char *name;
     char *cp;
-    int ignoreCase=FALSE;
-    int printFlag=FALSE;
-    int quietFlag=FALSE;
+    int ignoreCase = FALSE;
+    int printFlag = FALSE;
+    int quietFlag = FALSE;
     int stopNow;
+    char *line_s = NULL, saved;
+    char *appendline = NULL;
+    char *pos;
+    sed_function sed_f = f_none;
 
     argc--;
     argv++;
@@ -83,68 +184,119 @@ extern int sed_main (int argc, char **argv)
     if (**argv == '-') {
        argc--;
        cp = *argv++;
-       stopNow=FALSE;
+       stopNow = FALSE;
 
-       while (*++cp && stopNow==FALSE) {
+       while (*++cp && stopNow == FALSE) {
            switch (*cp) {
            case 'n':
                quietFlag = TRUE;
                break;
            case 'e':
-               if (*(cp+1)==0 && --argc < 0) {
-                   usage( sed_usage);
+               if (*(cp + 1) == 0 && --argc < 0) {
+                   usage(sed_usage);
                }
-               if ( *++cp != 's')
+               if (*++cp != 's')
                    cp = *argv++;
-               while( *cp ) {
-                   if (*cp == 's' && strlen(cp) > 3 && *(cp+1) == '/') {
-                       char* pos=needle=cp+2;
-                       for(;;) {
-                           pos = strchr(pos, '/');
-                           if (pos==NULL) {
-                               usage( sed_usage);
-                           }
-                           if (*(pos-1) == '\\') {
-                               pos++;
-                               continue;
-                           }
-                           break;
+
+               /* Read address if present */
+               SKIPSPACES(cp);
+               if (*cp == '$') {
+                   addr_line = LAST_LINE;
+                   cp++;
+               } else {
+                   if (isdigit(*cp)) { /* LINE ADDRESS   */
+                       line_s = cp;
+                       while (isdigit(*cp))
+                           cp++;
+                       if (cp > line_s) {
+                           /* numeric line */
+                           saved = *cp;
+                           *cp = '\0';
+                           addr_line = atoi(line_s);
+                           *cp = saved;
                        }
-                       *pos=0;
-                       newNeedle=++pos;
-                       for(;;) {
-                           pos = strchr(pos, '/');
-                           if (pos==NULL) {
-                               usage( sed_usage);
-                           }
-                           if (*(pos-1) == '\\') {
-                               pos++;
-                               continue;
-                           }
-                           break;
+                   } else if (*cp == '/') {    /* PATTERN ADDRESS */
+                       pos = addr_pattern = cp + 1;
+                       pos = strchr(pos, '/');
+                       if (!pos)
+                           usage(sed_usage);
+                       *pos = '\0';
+                       cp = pos + 1;
+                   }
+               }
+
+               SKIPSPACES(cp);
+               if (*cp == '!') {
+                   negated++;
+                   cp++;
+               }
+
+               /* Read command */
+
+               SKIPSPACES(cp);
+               switch (*cp) {
+               case 's':       /* REPLACE */
+                   if (strlen(cp) <= 3 || *(cp + 1) != '/')
+                       break;
+                   sed_f = f_replace;
+
+                   pos = needle = cp + 2;
+
+                   for (;;) {
+                       pos = strchr(pos, '/');
+                       if (pos == NULL) {
+                           usage(sed_usage);
+                       }
+                       if (*(pos - 1) == '\\') {
+                           pos++;
+                           continue;
                        }
-                       *pos=0;
-                       if (pos+2 != 0) {
-                           while (*++pos) {
-                               switch (*pos) {
-                                   case 'i':
-                                       ignoreCase=TRUE;
-                                       break;
-                                   case 'p':
-                                       printFlag=TRUE;
-                                       break;
-                                   case 'g':
-                                       break;
-                                   default:
-                                       usage( sed_usage);
-                               }
+                       break;
+                   }
+                   *pos = 0;
+                   newNeedle = ++pos;
+                   for (;;) {
+                       pos = strchr(pos, '/');
+                       if (pos == NULL) {
+                           usage(sed_usage);
+                       }
+                       if (*(pos - 1) == '\\') {
+                           pos++;
+                           continue;
+                       }
+                       break;
+                   }
+                   *pos = 0;
+                   if (pos + 2 != 0) {
+                       while (*++pos) {
+                           switch (*pos) {
+                           case 'i':
+                               ignoreCase = TRUE;
+                               break;
+                           case 'p':
+                               printFlag = TRUE;
+                               break;
+                           case 'g':
+                               break;
+                           default:
+                               usage(sed_usage);
                            }
                        }
                    }
-                   cp++;
+                   cp = pos;
+                   /* fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); */
+                   break;
+
+               case 'a':       /* APPEND */
+                   if (strlen(cp) < 2)
+                       break;
+                   sed_f = f_append;
+                   appendline = ++cp;
+                   /* fprintf(stderr, "append '%s'\n", appendline); */
+                   break;
                }
-               //fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle);
-               stopNow=TRUE;
+
+               stopNow = TRUE;
                break;
 
            default:
@@ -153,30 +305,48 @@ extern int sed_main (int argc, char **argv)
        }
     }
 
-    if (argc==0) {
-       do_sed( stdin, needle, newNeedle, ignoreCase, printFlag, quietFlag);
+    if (argc == 0) {
+       switch (sed_f) {
+       case f_none:
+           break;
+       case f_replace:
+           do_sed_repl(stdin, needle, newNeedle, ignoreCase, printFlag,
+                       quietFlag);
+           break;
+       case f_append:
+           do_sed_append(stdin, appendline, quietFlag);
+           break;
+       }
     } else {
        while (argc-- > 0) {
            name = *argv++;
 
-           fp = fopen (name, "r");
+           fp = fopen(name, "r");
            if (fp == NULL) {
-               perror (name);
+               perror(name);
                continue;
            }
 
-           do_sed( fp, needle, newNeedle, ignoreCase, printFlag, quietFlag);
+           switch (sed_f) {
+           case f_none:
+               break;
+           case f_replace:
+               do_sed_repl(fp, needle, newNeedle, ignoreCase, printFlag,
+                           quietFlag);
+               break;
+           case f_append:
+               do_sed_append(fp, appendline, quietFlag);
+               break;
+           }
 
-           if (ferror (fp))
-               perror (name);
+           if (ferror(fp))
+               perror(name);
 
-           fclose (fp);
+           fclose(fp);
        }
     }
-    exit( TRUE);
+    exit(TRUE);
 }
 
 
 /* END CODE */
-
-
index aa26f5836c7e9c6e6b319d875c84920a96d614dc..e38fd55551cebfb6a87c862b0f84d73dc5e914ba 100644 (file)
@@ -44,10 +44,15 @@ int dmesg_main( int argc, char** argv )
    int  level = 0;
    int  lastc;
    int  cmd = 3;
+   int stopDoingThat;
+
+   argc--;
+   argv++;
 
     /* Parse any options */
     while (argc && **argv == '-') {
-       while (*++(*argv))
+       stopDoingThat = FALSE;
+       while (stopDoingThat == FALSE && *++(*argv)) {
            switch (**argv) {
            case 'c':
                cmd = 4;
@@ -57,19 +62,22 @@ int dmesg_main( int argc, char** argv )
                if (--argc == 0)
                    goto end;
                level = atoi (*(++argv));
-               --argc;
-               ++argv;
+               if (--argc > 0)
+                   ++argv;
+               stopDoingThat = TRUE;
                break;
            case 's':
                if (--argc == 0)
                    goto end;
                bufsize = atoi (*(++argv));
-               --argc;
-               ++argv;
+               if (--argc > 0)
+                   ++argv;
+               stopDoingThat = TRUE;
                break;
            default:
                goto end;
            }
+       }
     }
    
    if (argc > 1) {