manage space
[indent.git] / indent.c
index 2b8834583edf60f530378a8cd1a0a7a01b4a66c6..025aac814799a3b66180f10ab25206d2c16d51e7 100644 (file)
--- a/indent.c
+++ b/indent.c
 
 //#define BUFFERSIZE 4096
 #define BUFFERSIZE 256
+#define TABSIZE 2
+
+/* type definition */
+
+typedef enum {
+    e_unknown = 0,
+    e_ansi,
+    e_kr
+} cmode_t;
 
 /* gobal variables */
 
@@ -41,46 +50,145 @@ void usage (int ret)
 
 /* indent function */
 
-int indent (FILE *fin, FILE *fout) {
-    char buffer[BUFFERSIZE + 1] = {0};
+int indent (FILE *fin, FILE *fout, cmode_t cmode) {
+    char bufin[BUFFERSIZE + 1] = {0};
+    char bufout[BUFFERSIZE * TABSIZE + 1] = {0};
+    size_t i, nb;
+    size_t nbindent = 0;
+    int begin = 1;
+    int parent = 0;
+    int comment = 0;
+    int newline = 0;
+    int string = 0;
+    int character = 0;
+    int special = 0;
+    int space = 0;
 
-    char *pt = buffer;
     while (!feof (fin)) {
-        int nb = fread (pt, 1, BUFFERSIZE - (pt - buffer), fin);
-        VERBOSE (DEBUG, fprintf (stdout, "buffer: %d\n", nb));
-        pt = buffer;
-        int i = 0;
-        while (pt[i] != '\0') {
-            if (pt[i++] == '\n') {
-                pt[i - 1] = 0;
-
-                /* process line */
-                char *line = pt;
-                VERBOSE (DEBUG, fprintf (stdout, "line: %d\n", strlen (line)));
-                VERBOSE (DEBUG, fprintf (stdout, "out: %s\n", line));
-                int k = 0;
-                int begin = 0;
-                while (line[k] != '\0') {
-                    switch (line[k]) {
-                    case ' ':
-                    case '\t':
-                        if (begin) trailing++;
+        memset (bufin, 0, sizeof (bufin));
+        memset (bufout, 0, sizeof (bufout));
+
+        /* read file */
+        nb = fread (bufin, 1, BUFFERSIZE, fin);
+        VERBOSE (DEBUG, fprintf (stdout, "buffer in: %d\n", nb));
+        if (errno != 0) {
+            VERBOSE (ERROR, fprintf (stderr, "can't read file (%d)\n", errno));
+            exit (1);
+        }
+
+        /* process line */
+        char *ptin = bufin;
+        char *ptout = bufout;
+        while (*ptin != '\0') {
+            VERBOSE (DEBUG, fprintf (stdout, "caracter: %c\n", *ptin));
+
+            /* manage comment */
+            if (comment > 0) {
+                if (((comment == 1) && (*ptin == '\n')) ||
+                    ((comment == 2) && ((*ptin == '*') && (ptin[1] == '/')))) {
+                    comment = 0;
+                }
+                special = 0;
+                *ptout++ = *ptin++;
+                continue;
+            }
+
+            /* manage indent */
+            switch (*ptin) {
+                case '/':
+                    comment = (ptin[1] == '/') ? 1 : (ptin[1] == '*') ? 2 : 0;
+                    if (begin) {
+                        for (i = 0; i < nbindent * TABSIZE; i++) {
+                            *ptout++ = ' ';
+                        }
+                        begin = 0;
+                    }
+                    *ptout++ = *ptin;
+                    break;
+                case ' ':
+                case '\t':
+                    if (begin == 0) {
+                        if ((string) || (!space)) {
+                            *ptout++ = *ptin;
+                        }
+                    }
+                    break;
+                case '{':
+                    *ptout++ = '\n';
+                    for (i = 0; i < nbindent * TABSIZE; i++) {
+                        *ptout++ = ' ';
+                    }
+                    *ptout++ = *ptin;
+                    *ptout++ = '\n';
+                    nbindent++;
+                    newline = 1;
+                    begin = 1;
+                    break;
+                case '}':
+                    *ptout++ = '\n';
+                    nbindent--;
+                    for (i = 0; i < nbindent * TABSIZE; i++) {
+                        *ptout++ = ' ';
+                    }
+                    *ptout++ = *ptin;
+                    if (ptin[1] != ';') {
+                        *ptout++ = '\n';
+                    }
+                    newline = 1;
+                    begin = 1;
+                    break;
+                case ';':
+                    *ptout++ = *ptin;
+                    if (parent) {
                         break;
-                    default:
+                    }
+                    *ptout++ = '\n';
+                    newline = 1;
+                    begin = 1;
+                    break;
+                case '\n':
+                    if (newline == 1) {
+                        newline = 0;
+                    } else {
+                        *ptout++ = '\n';
+                    }
+                    begin = 1;
+                    break;
+                case '\r':
+                    break;
+                default:
+                    if ((*ptin == '"') && (!character) && (!special)) {
+                        string ^= 1;
+                    }
+                    if ((*ptin == '\'') && (!string) && (!special)) {
+                        character ^= 1;
+                    }
+                    if (begin) {
+                        for (i = 0; i < nbindent * TABSIZE; i++) {
+                            *ptout++ = ' ';
+                        }
                         begin = 0;
-
-                pt += i;
-                i = 0;
+                    }
+                    *ptout++ = *ptin;
             }
+            space = ((*ptin == ' ') || (*ptin == '\t'));
+            special = (*ptin == '\\');
+            parent += (*ptin == '(') ? +1 : (*ptin == ')') ? -1 : 0;
+            ptin++;
         }
-        /* copy end buffer */
-        int j = 0;
-        if (pt - buffer < BUFFERSIZE) {
-            for (i = pt - buffer; i < BUFFERSIZE; i++) {
-                buffer[j++] = *pt++;
+        ptout = '\0';
+
+        /* write file */
+        VERBOSE (DEBUG, fprintf (stdout, "buffer out: %d\n", strlen (bufout)));
+        ptout = bufout;
+        while ((nb = fwrite (ptout, 1, strlen (ptout), fout)) != strlen (ptout)) {
+            VERBOSE (DEBUG, fprintf (stdout, "buffer out: %d/%d\n", nb, strlen (ptout)));
+            if (errno != 0) {
+                VERBOSE (ERROR, fprintf (stderr, "can't write file (%d)\n", errno));
+                exit (1);
             }
-        } 
-        pt = buffer + j;
+            ptout += nb;
+        }
     }
 
     /* close all */
@@ -94,6 +202,7 @@ int indent (FILE *fin, FILE *fout) {
 
 int main (int argc, char *argv[]) 
 {
+    cmode_t cmode = e_unknown;
     char *input = NULL;
     char *mode = "ansi";
     char *output = NULL;
@@ -146,7 +255,7 @@ int main (int argc, char *argv[])
     /* check output */
     FILE *fout = NULL;
     if (output) {
-        fout = fopen (input, "wb");
+        fout = fopen (output, "wb");
         if (!fout) {
             VERBOSE (ERROR, fprintf (stderr, "error: can't open file '%s'\n", output));
             fclose (fin);
@@ -155,7 +264,16 @@ int main (int argc, char *argv[])
         fout = stdout;
     }
 
-    return indent (fin, fout);
+    /* check mode */
+    if (strcmp (mode, "ansi") == 0) {
+        cmode = e_ansi;
+    } else if (strcmp (mode, "k&r") == 0) {
+        cmode = e_kr;
+    } else {
+        VERBOSE (ERROR, fprintf (stderr, "error: mode '%s' unknown\n", mode));
+    }
+
+    return indent (fin, fout, cmode);
 }
 
 // test: indent.exe -h