Removed the revision number.
[selector.git] / selector.c
index e9807c9..5c9d85f 100644 (file)
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 #include <ncurses.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
@@ -42,7 +43,7 @@
 #include <regex.h>
 #include <locale.h>
 
-#define VERSION "1.0"
+#define VERSION "1.0.1"
 
 #define BUFFER_SIZE 4096
 
@@ -65,6 +66,19 @@ int error_flash = 0;
 
 int attr_modeline, attr_focus_line, attr_error;
 
+/********************************************************************/
+
+/* malloc with error checking.  */
+
+void *safe_malloc(size_t n) {
+  void *p = malloc(n);
+  if (!p && n != 0) {
+    printf("Can not allocate memory: %s\n", strerror(errno));
+    exit(EXIT_FAILURE);
+  }
+  return p;
+}
+
 /*********************************************************************/
 
 void inject_into_tty_buffer(char *string, int add_control_qs) {
@@ -93,7 +107,7 @@ void check_opt(int argc, char **argv, int n_opt, int n, const char *help) {
   if(n_opt + n >= argc) {
     fprintf(stderr, "Selector: Missing argument for %s, expecting %s.\n",
             argv[n_opt], help);
-    exit(1);
+    exit(EXIT_FAILURE);
   }
 }
 
@@ -114,7 +128,7 @@ int string_to_positive_integer(char *string) {
     fprintf(stderr,
             "Selector: Value `%s' is not a positive integer.\n",
             string);
-    exit(1);
+    exit(EXIT_FAILURE);
   }
 
   return result;
@@ -128,6 +142,40 @@ void error_feedback() {
   }
 }
 
+void print_help(FILE *out) {
+
+  fprintf(out, "Selector version %s (%s)\n", VERSION, UNAME);
+  fprintf(out, "Written by Francois Fleuret <francois@fleuret.org>.\n");
+  fprintf(out, "\n");
+  fprintf(out, "Usage: selector [options] [<filename1> [<filename2> ...]]\n");
+  fprintf(out, "\n");
+  fprintf(out, " -h      show this help\n");
+  fprintf(out, " -v      inject the selected line in the tty\n");
+  fprintf(out, " -w      quote control characters with ^Qs when using -v\n");
+  fprintf(out, " -d      remove duplicated lines\n");
+  fprintf(out, " -b      remove the bash history line prefix\n");
+  fprintf(out, " -z      remove the zsh history line prefix\n");
+  fprintf(out, " -i      invert the order of lines\n");
+  fprintf(out, " -e      start in regexp mode\n");
+  fprintf(out, " -a      start in case sensitive mode\n");
+  fprintf(out, " -m      monochrome mode\n");
+  fprintf(out, " -q      make a flash instead of a beep on an edition error\n");
+  fprintf(out, " --      all following arguments are filenames\n");
+  fprintf(out, " -t <title>\n");
+  fprintf(out, "         add a title in the modeline\n");
+  fprintf(out, " -c <fg modeline> <bg modeline> <fg highlight> <bg highlight>\n");
+  fprintf(out, "         set the display colors\n");
+  fprintf(out, " -o <output filename>\n");
+  fprintf(out, "         set a file to write the selected line to\n");
+  fprintf(out, " -s <pattern separator>\n");
+  fprintf(out, "         set the symbol to separate substrings in the pattern\n");
+  fprintf(out, " -x <label separator>\n");
+  fprintf(out, "         set the symbol to terminate the label\n");
+  fprintf(out, " -l <max number of lines>\n");
+  fprintf(out, "         set the maximum number of lines to take into account\n");
+  fprintf(out, "\n");
+}
+
 /*********************************************************************/
 
 /* A quick and dirty hash table */
@@ -145,10 +193,10 @@ struct hash_table_t *new_hash_table(int size) {
   int k;
   struct hash_table_t *hash_table;
 
-  hash_table = (struct hash_table_t *) malloc(sizeof(struct hash_table_t));
+  hash_table = safe_malloc(sizeof(struct hash_table_t));
 
   hash_table->size = size;
-  hash_table->entries = (int *) malloc(hash_table->size * sizeof(int));
+  hash_table->entries = safe_malloc(hash_table->size * sizeof(int));
 
   for(k = 0; k < hash_table->size; k++) {
     hash_table->entries[k] = -1;
@@ -266,10 +314,10 @@ void initialize_matcher(int use_regexp, int case_sensitive,
     }
 
     matcher->splitted_patterns =
-      (char *) malloc((strlen(pattern) + 1) * sizeof(char));
+      safe_malloc((strlen(pattern) + 1) * sizeof(char));
 
     matcher->patterns =
-      (char **) malloc(matcher->nb_patterns * sizeof(char *));
+      safe_malloc(matcher->nb_patterns * sizeof(char *));
 
     strcpy(matcher->splitted_patterns, pattern);
 
@@ -648,7 +696,7 @@ void store_line(struct hash_table_t *hash_table,
   }
 
   if(dup < 0) {
-    lines[*nb_lines] = (char *) malloc((strlen(new_line) + 1) * sizeof(char));
+    lines[*nb_lines] = safe_malloc((strlen(new_line) + 1) * sizeof(char));
     strcpy(lines[*nb_lines], new_line);
   } else {
     /* The string was already in there, so we do not allocate a new
@@ -672,7 +720,7 @@ void read_file(struct hash_table_t *hash_table,
 
   if(!file) {
     fprintf(stderr, "Selector: Can not open `%s'.\n", input_filename);
-    exit(1);
+    exit(EXIT_FAILURE);
   }
 
   start = 0;
@@ -708,7 +756,7 @@ void read_file(struct hash_table_t *hash_table,
               BUFFER_SIZE);
       fprintf(stderr, raw_line);
       fprintf(stderr, "\n");
-      exit(1);
+      exit(EXIT_FAILURE);
     }
 
     /* If we got a line, we replace the carriage return by a \0 to
@@ -747,7 +795,7 @@ int main(int argc, char **argv) {
 
   if(!isatty(STDIN_FILENO)) {
     fprintf(stderr, "Selector: The standard input is not a tty.\n");
-    exit(1);
+    exit(EXIT_FAILURE);
   }
 
   color_fg_modeline  = COLOR_WHITE;
@@ -843,7 +891,7 @@ int main(int argc, char **argv) {
     else if(strcmp(argv[i], "-t") == 0) {
       check_opt(argc, argv, i, 1, "<title>");
       free(title);
-      title = (char *) malloc((strlen(argv[i+1]) + 1) * sizeof(char));
+      title = safe_malloc((strlen(argv[i+1]) + 1) * sizeof(char));
       strcpy(title, argv[i+1]);
       i += 2;
     }
@@ -881,48 +929,16 @@ int main(int argc, char **argv) {
   }
 
   if(show_help || error) {
-    FILE *out;
-    if(show_help) {
-      out = stdout;
+    if(error) {
+      print_help(stderr);
+      exit(EXIT_FAILURE);
     } else {
-      out = stderr;
-    }
-
-    fprintf(out, "Selector version %s-R%s\n", VERSION, REVISION_NUMBER);
-    fprintf(out, "Written by Francois Fleuret <francois@fleuret.org>.\n");
-    fprintf(out, "\n");
-    fprintf(out, "Usage: %s [options] [<filename1> [<filename2> ...]]\n",
-            argv[0]);
-    fprintf(out, "\n");
-    fprintf(out, " -h      show this help\n");
-    fprintf(out, " -v      inject the selected line in the tty\n");
-    fprintf(out, " -w      quote control characters with ^Qs when using -v\n");
-    fprintf(out, " -d      remove duplicated lines\n");
-    fprintf(out, " -b      remove the bash history line prefix\n");
-    fprintf(out, " -z      remove the zsh history line prefix\n");
-    fprintf(out, " -i      invert the order of lines\n");
-    fprintf(out, " -e      start in regexp mode\n");
-    fprintf(out, " -a      start in case sensitive mode\n");
-    fprintf(out, " -m      monochrome mode\n");
-    fprintf(out, " -q      make a flash instead of a beep on an edition error\n");
-    fprintf(out, " --      all following arguments are filenames\n");
-    fprintf(out, " -t <title>\n");
-    fprintf(out, "         add a title in the modeline\n");
-    fprintf(out, " -c <fg modeline> <bg modeline> <fg highlight> <bg highlight>\n");
-    fprintf(out, "         set the display colors\n");
-    fprintf(out, " -o <output filename>\n");
-    fprintf(out, "         set a file to write the selected line to\n");
-    fprintf(out, " -s <pattern separator>\n");
-    fprintf(out, "         set the symbol to separate substrings in the pattern\n");
-    fprintf(out, " -x <label separator>\n");
-    fprintf(out, "         set the symbol to terminate the label\n");
-    fprintf(out, " -l <max number of lines>\n");
-    fprintf(out, "         set the maximum number of lines to take into account\n");
-    fprintf(out, "\n");
-    exit(error);
+      print_help(stdout);
+      exit(EXIT_SUCCESS);
+    }
   }
 
-  lines = (char **) malloc(nb_lines_max * sizeof(char *));
+  lines = safe_malloc(nb_lines_max * sizeof(char *));
 
   nb_lines = 0;
 
@@ -972,7 +988,7 @@ int main(int argc, char **argv) {
      label_separator and transform control characters to printable
      ones */
 
-  labels = (char **) malloc(nb_lines * sizeof(char *));
+  labels = safe_malloc(nb_lines * sizeof(char *));
 
   for(l = 0; l < nb_lines; l++) {
     char *s, *t;
@@ -985,7 +1001,7 @@ int main(int argc, char **argv) {
       e += strlen(u);
     }
 
-    labels[l] = (char *) malloc((e + 1) * sizeof(char));
+    labels[l] = safe_malloc((e + 1) * sizeof(char));
     t = lines[l];
     s = labels[l];
     while(*t && *t != label_separator) {
@@ -1025,7 +1041,7 @@ int main(int argc, char **argv) {
       endwin();
       fprintf(stderr, "Selector: Color numbers have to be between 0 and %d.\n",
               COLORS - 1);
-      exit(1);
+      exit(EXIT_FAILURE);
     }
 
     init_pair(1, color_fg_modeline, color_bg_modeline);
@@ -1177,7 +1193,7 @@ int main(int argc, char **argv) {
         fprintf(stderr,
                 "Selector: Can not open %s for writing.\n",
                 output_filename);
-        exit(1);
+        exit(EXIT_FAILURE);
       }
       fclose(out);
     }
@@ -1195,5 +1211,5 @@ int main(int argc, char **argv) {
   free(lines);
   free(title);
 
-  exit(0);
+  exit(EXIT_SUCCESS);
 }