Whamcloud - gitweb
libsupport: add C string printing and parsing functions
authorTheodore Ts'o <tytso@mit.edu>
Sat, 28 Jan 2017 17:11:46 +0000 (12:11 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 28 Jan 2017 21:29:52 +0000 (16:29 -0500)
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/support/Makefile.in
lib/support/cstring.c [new file with mode: 0644]
lib/support/cstring.h [new file with mode: 0644]

index 112ba24..cede23e 100644 (file)
@@ -12,7 +12,8 @@ INSTALL = @INSTALL@
 
 all::
 
-OBJS=          mkquota.o \
+OBJS=          cstring.o \
+               mkquota.o \
                plausible.o \
                profile.o \
                parse_qtype.o \
@@ -24,6 +25,7 @@ OBJS=         mkquota.o \
                dict.o
 
 SRCS=          $(srcdir)/argv_parse.c \
+               $(srcdir)/cstring.c \
                $(srcdir)/mkquota.c \
                $(srcdir)/parse_qtype.c \
                $(srcdir)/plausible.c \
@@ -67,10 +69,15 @@ test_profile: $(srcdir)/profile.c profile_helpers.o argv_parse.o \
                profile_helpers.o argv_parse.o $(STATIC_LIBCOM_ERR) \
                $(ALL_CFLAGS)
 
+test_cstring: $(srcdir)/cstring.c
+       $(E) " CC $@"
+       $(Q) $(CC) -o test_cstring -DDEBUG_PROGRAM $(srcdir)/cstring.c \
+               $(ALL_CFLAGS)
+
 clean::
        $(RM) -f \#* *.s *.o *.a *~ *.bak core profiled/* \
                ../libsupport.a ../libsupport_p.a $(SMANPAGES) \
-               prof_err.c prof_err.h test_profile
+               prof_err.c prof_err.h test_profile test_cstring
 
 #check:: tst_uuid
 #      LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_uuid
@@ -96,6 +103,8 @@ $(OBJS):
 #
 argv_parse.o: $(srcdir)/argv_parse.c $(top_builddir)/lib/config.h \
  $(top_builddir)/lib/dirpaths.h $(srcdir)/argv_parse.h
+cstring.o: $(srcdir)/cstring.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h
 mkquota.o: $(srcdir)/mkquota.c $(top_builddir)/lib/config.h \
  $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
  $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
diff --git a/lib/support/cstring.c b/lib/support/cstring.c
new file mode 100644 (file)
index 0000000..3250477
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * cstring.c -- parse and print strings using the C escape sequences
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#include <string.h>
+
+#include "cstring.h"
+
+int parse_c_string(char *str)
+{
+       unsigned char *to, *from, ch;
+       int v;
+
+       to = from = str;
+
+       for (to = from = (unsigned char *) str;
+            *from && *from != '"'; to++, from++) {
+               if (*from == '\\') {
+                       ch = *(++from);
+                       switch (ch) {
+                       case 'a':
+                               *to = '\a';
+                               break;
+                       case 'b':
+                               *to = '\b';
+                               break;
+                       case 'f':
+                               *to = '\f';
+                               break;
+                       case 'n':
+                               *to = '\n';
+                               break;
+                       case 't':
+                               *to = '\t';
+                               break;
+                       case 'v':
+                               *to = '\v';
+                               break;
+                       case 'x':
+                               ch = *(from + 1);
+                               if (ch >= 'a' && ch <= 'f')
+                                       ch = ch - 'a' + 'A';
+                               if (ch >= '0' && ch <= '9')
+                                       v = ch - '0';
+                               else if (ch >= 'A' && ch <= 'F')
+                                       v = ch + 10 - 'A';
+                               else {
+                                       ch = *from;
+                                       break;
+                               }
+                               from++;
+                               ch = *(from + 1);
+                               if (ch >= 'a' && ch <= 'f')
+                                       ch = ch - 'a' + 'A';
+                               if (ch >= '0' && ch <= '9')
+                                       v = (v * 16) + (ch - '0');
+                               else if (ch >= 'A' && ch <= 'F')
+                                       v = (v * 16) + (ch + 10 - 'A');
+                               else {
+                                       ch = *from;
+                                       break;
+                               }
+                               from++;
+                               *to = v;
+                               break;
+                       default:
+                               if (ch >= '0' && ch <= '9') {
+                                       v = ch - '0';
+                                       ch = *(from + 1);
+                                       if (ch >= '0' && ch <= '9') {
+                                               from++;
+                                               v = (8 * v) + (ch - '0');
+                                               ch = *(from + 1);
+                                               if (ch >= '0' && ch <= '9') {
+                                                       from++;
+                                                       v = (8 * v) + (ch - '0');
+                                               }
+                                       }
+                                       ch = v;
+                               }
+                               *to = ch;
+                       }
+                       continue;
+               }
+               *to = *from;
+       }
+       *to = '\0';
+       return to - (unsigned char *) str;
+}
+
+void print_c_string(FILE *f, const char *cp, int len)
+{
+       unsigned char   ch;
+
+       if (len < 0)
+               len = strlen(cp);
+
+       while (len--) {
+               ch = *cp++;
+               if (ch == '\a')
+                       fputs("\\a", f);
+               else if (ch == '\b')
+                       fputs("\\b", f);
+               else if (ch == '\f')
+                       fputs("\\f", f);
+               else if (ch == '\n')
+                       fputs("\\n", f);
+               else if (ch == '\t')
+                       fputs("\\t", f);
+               else if (ch == '\v')
+                       fputs("\\v", f);
+               else if (ch == '\\')
+                       fputs("\\\\", f);
+               else if (ch == '\'')
+                       fputs("\\\'", f);
+               else if (ch == '\"')
+                       fputs("\\\"", f);
+               else if ((ch < 32) || (ch > 126))
+                       fprintf(f, "\\%03o", ch);
+               else
+                       fputc(ch, f);
+       }
+}
+
+#ifdef DEBUG_PROGRAM
+int main(int argc, char **argv)
+{
+       char buf[4096];
+       int c, raw = 0;
+
+       while ((c = getopt(argc, argv, "r")) != EOF) {
+               switch (c) {
+               case 'r':
+                       raw++;
+                       break;
+               default:
+                       fprintf(stderr, "Usage: %s [-r]\n", argv[0]);
+                       exit(1);
+               }
+       }
+
+       while (!feof(stdin)) {
+               if (fgets(buf, sizeof(buf), stdin) == NULL)
+                       break;
+               c = parse_c_string(buf);
+               if (raw)
+                       fputs(buf, stdout);
+               else {
+                       print_c_string(stdout, buf, c);
+                       printf(" <%d>\n", c);
+               }
+       }
+}      
+#endif
diff --git a/lib/support/cstring.h b/lib/support/cstring.h
new file mode 100644 (file)
index 0000000..7f80f41
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * cstring.h -- header file for C string parse/print utilities
+ */
+
+extern int parse_c_string(char *str);
+extern void print_c_string(FILE *f, const char *cp, int len);