Initial. Seems to work.
authorlbatlle@npdl268.bpo.hp.com
Fri, 18 May 2007 18:59:39 +0200
changeset 0 31bc1c76aa85
child 1 10de83d11bd7
child 3 edae5c16989e
Initial. Seems to work.
Makefile
sreplace.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Fri May 18 18:59:39 2007 +0200
@@ -0,0 +1,2 @@
+CFLAGS=-g -O0
+sreplace: sreplace.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sreplace.c	Fri May 18 18:59:39 2007 +0200
@@ -0,0 +1,300 @@
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+/* Kind of string parameters */
+static int hex_strings = 0;
+
+static FILE * input, * output;
+
+struct String
+{
+  char *ptr;
+  int length;
+};
+
+struct CmpState
+{
+  struct String *str;
+  int matched;
+};
+
+struct String old_str;
+struct String new_str;
+struct CmpState cmp_state;
+
+/* Buffer:
+   [F] - read
+   [F] - read_cmp
+   [F]
+   [F] - filled
+   [ ]
+   [ ]
+
+   In the circular sense:
+   read <= read_cmp < filled
+*/
+struct Buffer
+{
+  char *base;
+  int filled;
+  int read;
+  int read_cmp;
+  int size;
+};
+
+static int get_buffer_space(struct Buffer *b, int start, int end)
+{
+  int space;
+  space = end - start + b->size;
+  if (space > b->size)
+    space -= b->size;
+
+  return space;
+}
+
+static int min(int a, int b)
+{
+  if (a < b)
+    return a;
+  return b;
+}
+
+static int one_before(struct Buffer *b, int pos)
+{
+  if (pos == 0)
+    return b->size - 1;
+
+  return pos - 1;
+}
+
+/* This should be called without any exceeding size */
+static int file_to_buffer(struct Buffer *b, int size)
+{
+  int blocksize;
+  int res;
+
+  blocksize = min(b->size - b->filled, size);
+  if (blocksize > 0)
+  {
+    res = fread(b->base + b->filled, 1, blocksize, input);
+    /*fprintf(stderr, "fread1 %i bytes (should %i).\n", res, blocksize);*/
+    size -= res;
+    b->filled = (b->filled + res) % b->size;
+
+    /* Check EOF */
+    if (res == 0)
+      return 0;
+  }
+
+  if (size > 0 && res == blocksize)
+  {
+    blocksize = min(b->read - 1, size);
+    res = fread(b->base, 1, blocksize, input);
+    /*fprintf(stderr, "fread2 %i bytes.\n", res);*/
+    size -= res;
+    b->filled = (b->filled + res) % b->size;
+  }
+  return 1;
+}
+
+static int file_read_more(struct Buffer *b)
+{
+  int can_read;
+  int res;
+
+  can_read = get_buffer_space(b, b->filled, b->read - 1);
+
+  /*fprintf(stderr, "file_to_buffer %i\n", can_read);*/
+
+  return file_to_buffer(b, can_read);
+}
+
+/* pos will be read or read_cmp, depending on
+   what to read */
+static int can_read_from_buffer(struct Buffer *b, int pos)
+{
+  /*
+   In the circular sense:
+   read <= read_cmp < filled
+   */
+  if (pos != b->filled)
+    return 1;
+  else
+    return 0;
+}
+
+static int getc_real(struct Buffer *b)
+{
+  int a;
+
+  if (!can_read_from_buffer(b, b->read))
+    a = EOF;
+  else
+  {
+    a = *(b->base + b->read);
+    b->read += 1;
+    if (b->read == b->size)
+      b->read = 0;
+  }
+  /*fprintf(stderr, "getc_real %x\n", a);*/
+
+  return a;
+}
+
+static int getc_cmp(struct Buffer *b)
+{
+  int a;
+  if (!can_read_from_buffer(b, b->read_cmp))
+    a = EOF;
+  else
+  {
+    a = *(b->base + b->read_cmp);
+    b->read_cmp += 1;
+    if (b->read_cmp == b->size)
+      b->read_cmp = 0;
+  }
+  /*fprintf(stderr, "getc_cmp %x\n", a);*/
+
+  return a;
+}
+
+/* This will not be moved farer than read_cmp */
+static void read_advance(struct Buffer *b, int adv)
+{
+  int i;
+  for (i=0; i < adv; ++i)
+    getc_real(b);
+};
+
+static void process_buffer(struct Buffer *b)
+{
+  int c;
+
+  while (1)
+  {
+    c = getc_cmp(b);
+
+    if (c == EOF)
+      break;
+
+    if (cmp_state.str->ptr[cmp_state.matched] == (char) c)
+    {
+      cmp_state.matched++;
+      if (cmp_state.matched == cmp_state.str->length)
+      {
+        fwrite(new_str.ptr, 1, new_str.length, output);
+        read_advance(b, cmp_state.matched);
+        cmp_state.matched = 0;
+      }
+    } else
+    {
+      int c;
+      c = getc_real(b); /* Will not be EOF. read_cmp is forwarder. */
+      fputc(c, output);
+      cmp_state.matched = 0;
+      b->read_cmp = b->read;
+    }
+  }
+}
+
+static void end_buffer(struct Buffer *b)
+{
+  int c;
+  while((c = getc_real(b)) != EOF)
+      fputc(c, output);
+}
+
+static void loop()
+{
+  struct Buffer b;
+
+  b.base = (char *) malloc(2048);
+  b.read = 0;
+  b.read_cmp = 0;
+  b.filled = 0;
+  b.size = 2048;
+
+  while(file_read_more(&b) > 0)
+  {
+    int c;
+    process_buffer(&b);
+  }
+
+  end_buffer(&b);;
+}
+
+static void show_usage(const char *pname)
+{
+  printf("usage: %s OLD_STR NEW_STR\n", pname);
+}
+
+static void parse_backslashes(char *str)
+{
+  int was_backslash = 0;
+  char *write_str = str;
+
+  while (*str != 0)
+  {
+    if (*str == '\\')
+      was_backslash = 1;
+    else
+    {
+      if (was_backslash)
+      {
+        switch(*str)
+        {
+          case '\\':
+            *(write_str++) = '\\';
+            break;
+          case 'n':
+            *(write_str++) = '\n';
+            break;
+          case 't':
+            *(write_str++) = '\t';
+            break;
+          default:
+            *(write_str++) = *str;
+        }
+      }
+      else
+      {
+        *(write_str++) = *str;
+      }
+      was_backslash = 0;
+    }
+    ++str;
+  }
+  *(write_str++) = '\0';
+}
+
+static void process_parameters(int argc, char **argv)
+{
+  if (argc != 3)
+  {
+    show_usage(argv[0]);
+    exit(1);
+  }
+
+  old_str.ptr = argv[1];
+  new_str.ptr = argv[2];
+
+  parse_backslashes(old_str.ptr);
+  parse_backslashes(new_str.ptr);
+
+  old_str.length = strlen(old_str.ptr);
+  new_str.length = strlen(new_str.ptr);
+}
+
+int main(int argc, char ** argv)
+{
+  process_parameters(argc, argv);
+  
+  cmp_state.str = &old_str;
+  cmp_state.matched = 0;
+
+  input = stdin;
+  output = stdout;
+
+  loop();
+}