1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <mruby.h>
5 #include <mruby/irep.h>
6 #include <mruby/dump.h>
7 
8 struct strip_args {
9   int argc_start;
10   int argc;
11   char **argv;
12   mrb_bool lvar;
13 };
14 
15 static void
print_usage(const char * f)16 print_usage(const char *f)
17 {
18   printf("Usage: %s [switches] irepfiles\n", f);
19   printf("switches:\n");
20   printf("  -l, --lvar   remove LVAR section too.\n");
21 }
22 
23 static int
parse_args(int argc,char ** argv,struct strip_args * args)24 parse_args(int argc, char **argv, struct strip_args *args)
25 {
26   int i;
27 
28   args->argc_start = 0;
29   args->argc = argc;
30   args->argv = argv;
31   args->lvar = FALSE;
32 
33   for (i = 1; i < argc; ++i) {
34     const size_t len = strlen(argv[i]);
35     if (len >= 2 && argv[i][0] == '-') {
36       switch (argv[i][1]) {
37       case 'l':
38         args->lvar = TRUE;
39         break;
40       case '-':
41         if (strncmp((*argv) + 2, "lvar", len) == 0) {
42           args->lvar = TRUE;
43           break;
44         }
45       default:
46         return -1;
47       }
48     }
49     else {
50       break;
51     }
52   }
53 
54   args->argc_start = i;
55   return i;
56 }
57 
58 static int
strip(mrb_state * mrb,struct strip_args * args)59 strip(mrb_state *mrb, struct strip_args *args)
60 {
61   int i;
62 
63   for (i = args->argc_start; i < args->argc; ++i) {
64     char *filename;
65     FILE *rfile;
66     mrb_irep *irep;
67     FILE *wfile;
68     int dump_result;
69 
70     filename = args->argv[i];
71     rfile = fopen(filename, "rb");
72     if (rfile == NULL) {
73       fprintf(stderr, "can't open file for reading %s\n", filename);
74       return EXIT_FAILURE;
75     }
76 
77     irep = mrb_read_irep_file(mrb, rfile);
78     fclose(rfile);
79     if (irep == NULL) {
80       fprintf(stderr, "can't read irep file %s\n", filename);
81       return EXIT_FAILURE;
82     }
83 
84     /* clear lv if --lvar is enabled */
85     if (args->lvar) {
86       mrb_irep_remove_lv(mrb, irep);
87     }
88 
89     wfile = fopen(filename, "wb");
90     if (wfile == NULL) {
91       fprintf(stderr, "can't open file for writing %s\n", filename);
92       mrb_irep_decref(mrb, irep);
93       return EXIT_FAILURE;
94     }
95 
96     /* debug flag must always be false */
97     dump_result = mrb_dump_irep_binary(mrb, irep, FALSE, wfile);
98 
99     fclose(wfile);
100     mrb_irep_decref(mrb, irep);
101 
102     if (dump_result != MRB_DUMP_OK) {
103       fprintf(stderr, "error occurred during dumping %s\n", filename);
104       return EXIT_FAILURE;
105     }
106   }
107   return EXIT_SUCCESS;
108 }
109 
110 int
main(int argc,char ** argv)111 main(int argc, char **argv)
112 {
113   struct strip_args args;
114   int args_result;
115   mrb_state *mrb;
116   int ret;
117 
118   if (argc <= 1) {
119     printf("no files to strip\n");
120     print_usage(argv[0]);
121     return EXIT_FAILURE;
122   }
123 
124   args_result = parse_args(argc, argv, &args);
125   if (args_result < 0) {
126     print_usage(argv[0]);
127     return EXIT_FAILURE;
128   }
129   mrb = mrb_open_core(mrb_default_allocf, NULL);
130   if (mrb == NULL) {
131     fputs("Invalid mrb_state, exiting mruby-strip\n", stderr);
132     return EXIT_FAILURE;
133   }
134 
135   ret = strip(mrb, &args);
136 
137   mrb_close(mrb);
138   return ret;
139 }
140