OSDN Git Service

Merge remote-tracking branch 'toybox/master' into HEAD am: b62e8ff3da am: 63a7993a8f
[android-x86/external-toybox.git] / scripts / mkflags.c
index 001007e..e0e833c 100644 (file)
@@ -6,10 +6,12 @@
 // This is intentionally crappy code because we control the inputs. It leaks
 // memory like a sieve and segfaults if malloc returns null, but does the job.
 
+#include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <ctype.h>
 
 struct flag {
   struct flag *next;
@@ -17,11 +19,67 @@ struct flag {
   struct flag *lopt;
 };
 
+int chrtype(char c)
+{
+  if (strchr("?&^-:#|@*; ", c)) return 1;
+  if (strchr("=<>", c)) return 2;
+
+  return 0;
+}
+
+// replace chopped out USE_BLAH() sections with low-ascii characters
+// showing how many flags got skipped
+
+char *mark_gaps(char *flags, char *all)
+{
+  char *n, *new, c;
+  int bare = 1;
+
+  // Shell feeds in " " for blank args, leading space not meaningful.
+  while (isspace(*flags)) flags++;
+  while (isspace(*all)) all++;
+
+  n = new = strdup(all);
+  while (*all) {
+    // --longopt parentheticals dealt with as a unit
+    if (*all == '(') {
+      int len = 0;
+
+      while (all[len++] != ')');
+      if (strncmp(flags, all, len)) {
+        // bare longopts need their own skip placeholders
+        if (bare) *(new++) = 1;
+      } else {
+        memcpy(new, all, len);
+        new += len;
+        flags += len;
+      }
+      all += len;
+      continue;
+    }
+    c = *(all++);
+    if (bare) bare = chrtype(c);
+    if (*flags == c) {
+      *(new++) = c;
+      *flags++;
+      continue;
+    }
+
+    c = chrtype(c);
+    if (!c) *(new++) = 1;
+    else if (c==2) while (isdigit(*all)) all++;
+  }
+  *new = 0;
+
+  return n;
+}
+
 // Break down a command string into struct flag list.
 
 struct flag *digest(char *string)
 {
   struct flag *list = NULL;
+  char *err = string;
 
   while (*string) {
     // Groups must be at end.
@@ -44,13 +102,18 @@ struct flag *digest(char *string)
         blank->lopt = new;
         list = blank;
       }
-      while (*++string != ')') if (*string == '-') *string = '_';  // An empty longopt () would break this.
+      // An empty longopt () would break this.
+      while (*++string != ')') if (*string == '-') *string = '_';
       *(string++) = 0;
       continue;
     }
 
     if (strchr("?&^-:#|@*; ", *string)) string++;
     else if (strchr("=<>", *string)) {
+      if (!isdigit(string[1])) {
+        fprintf(stderr, "%c without number in '%s'", *string, err);
+        exit(1);
+      }
       while (isdigit(*++string)) {
         if (!list) {
            string++;
@@ -78,14 +141,38 @@ int main(int argc, char *argv[])
   // See "intentionally crappy", above.
   if (!(out = outbuf)) return 1;
 
+  printf("#undef FORCED_FLAG\n#undef FORCED_FLAGLL\n"
+    "#ifdef FORCE_FLAGS\n#define FORCED_FLAG 1\n#define FORCED_FLAGLL 1LL\n"
+    "#else\n#define FORCED_FLAG 0\n#define FORCED_FLAGLL 0\n#endif\n\n");
+
   for (;;) {
     struct flag *flist, *aflist, *offlist;
-    unsigned bit = 0;
+    char *mgaps = 0;
+    unsigned bit;
+
+    *command = *flags = *allflags = 0;
+    bit = fscanf(stdin, "%255s \"%1023[^\"]\" \"%1023[^\"]\"\n",
+                    command, flags, allflags);
+
+    if (getenv("DEBUG"))
+      fprintf(stderr, "command=%s, flags=%s, allflags=%s\n",
+        command, flags, allflags);
 
-    if (3 != fscanf(stdin, "%255s \"%1023[^\"]\" \"%1023[^\"]\"\n",
-                    command, flags, allflags)) break;
+    if (!*command) break;
+    if (bit != 3) {
+      fprintf(stderr, "\nError in %s (see generated/flags.raw)\n", command);
+      exit(1);
+    }
 
+    bit = 0;
     printf("// %s %s %s\n", command, flags, allflags);
+    if (*flags != ' ') mgaps = mark_gaps(flags, allflags);
+    else if (*allflags != ' ') mgaps = allflags;
+    // If command disabled, use allflags for OLDTOY()
+    printf("#undef OPTSTR_%s\n#define OPTSTR_%s ", command, command);
+    if (mgaps) printf("\"%s\"\n", mgaps);
+    else printf("0\n");
+    if (mgaps != allflags) free(mgaps);
 
     flist = digest(flags);
     offlist = aflist = digest(allflags);
@@ -109,35 +196,39 @@ int main(int argc, char *argv[])
     out += strlen(out);
 
     while (aflist) {
+      char *llstr = bit>31 ? "LL" : "";
+
+      // Output flag macro for bare longopts
       if (aflist->lopt) {
         if (flist && flist->lopt &&
             !strcmp(flist->lopt->command, aflist->lopt->command))
         {
-          sprintf(out, "#define FLAG_%s (1<<%d)\n", flist->lopt->command, bit);
+          sprintf(out, "#define FLAG_%s (1%s<<%d)\n", flist->lopt->command,
+            llstr, bit);
           flist->lopt = flist->lopt->next;
-        } else sprintf(out, "#define FLAG_%s 0\n", aflist->lopt->command);
+        } else sprintf(out, "#define FLAG_%s (FORCED_FLAG%s<<%d)\n",
+                       aflist->lopt->command, llstr, bit);
         aflist->lopt = aflist->lopt->next;
         if (!aflist->command) {
           aflist = aflist->next;
-          if (flist) {
-            flist = flist->next;
-            bit++;
-          }
+          bit++;
+          if (flist) flist = flist->next;
         }
+      // Output normal flag macro
       } else if (aflist->command) {
-        if (flist && (!aflist->command || *aflist->command == *flist->command))
-        {
+        if (flist && flist->command && *aflist->command == *flist->command) {
           if (aflist->command)
-            sprintf(out, "#define FLAG_%c (1<<%d)\n", *aflist->command, bit);
-          bit++;
+            sprintf(out, "#define FLAG_%c (1%s<<%d)\n", *aflist->command,
+              llstr, bit);
           flist = flist->next;
-        } else sprintf(out, "#define FLAG_%c 0\n", *aflist->command);
+        } else sprintf(out, "#define FLAG_%c (FORCED_FLAG%s<<%d)\n",
+                       *aflist->command, llstr, bit);
+        bit++;
         aflist = aflist->next;
       }
       out += strlen(out);
     }
-    sprintf(out, "#endif\n\n");
-    out += strlen(out);
+    out = stpcpy(out, "#endif\n\n");
   }
 
   if (fflush(0) && ferror(stdout)) return 1;
@@ -149,4 +240,6 @@ int main(int argc, char *argv[])
     if (i<0) return 1;
     out += i;
   }
+
+  return 0;
 }