xref: /reactos/sdk/tools/log2lines/cmd.c (revision c2c66aff)
1 /*
2  * ReactOS log2lines
3  * Written by Jan Roeloffzen
4  *
5  * - Cli for escape commands
6  */
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 
12 #include "util.h"
13 #include "cmd.h"
14 #include "options.h"
15 #include "log2lines.h"
16 #include "help.h"
17 
18 /* When you edit the cmd line and/or use the history instead of just typing,
19  * a bunch of editing BS and space characters
20  * is inserted, so the string looks right on the console but still
21  * contains the original string, plus other garbage:
22  */
23 static char
24 *backSpaceEdit(char *s)
25 {
26     char c;
27     char *edit = s;
28     char *text = s;
29 
30     while (( c = *edit++ ))
31     {
32         switch (c)
33         {
34         case KDBG_BS_CHAR:
35             if (text > s)
36                 text --;
37             break;
38         default:
39             *text++ = c;
40         }
41     }
42     *text = '\0';
43 
44     return s;
45 }
46 
47 static int
48 handle_switch(FILE *outFile, int *sw, char *arg, char *desc)
49 {
50     int changed =0;
51     int x = 0;
52 
53     if (arg && (strcmp(arg,"") != 0))
54     {
55         x = atoi(arg);
56         if (x != *sw)
57         {
58             *sw = x;
59             changed = 1;
60         }
61     }
62     if (desc)
63     {
64         esclog(outFile, "%s is %d (%s)\n", desc, *sw, changed ? "changed":"unchanged");
65         if (!arg)
66             esclog(outFile, "(readonly)\n");
67     }
68 
69     return changed;
70 }
71 
72 static int
73 handle_switch_str(FILE *outFile, char *sw, char *arg, char *desc)
74 {
75     int changed =0;
76 
77     if (arg)
78     {
79         if (strcmp(arg,"") != 0)
80         {
81             if (strcmp(arg,KDBG_ESC_OFF) == 0)
82             {
83                 if (*sw)
84                     changed = 1;
85                 *sw = '\0';
86             }
87             else if (strcmp(arg, sw) != 0)
88             {
89                 strcpy(sw, arg);
90                 changed = 1;
91             }
92         }
93     }
94     if (desc)
95     {
96         esclog(outFile, "%s is \"%s\" (%s)\n", desc, sw, changed ? "changed":"unchanged");
97         if (!arg)
98             esclog(outFile, "(readonly)\n");
99     }
100 
101     return changed;
102 }
103 
104 static int
105 handle_switch_pstr(FILE *outFile, char **psw, char *arg, char *desc)
106 {
107     int changed =0;
108 
109     if (arg)
110     {
111         if (strcmp(arg,"") != 0)
112         {
113             if (strcmp(arg,KDBG_ESC_OFF) == 0)
114             {
115                 if (*psw)
116                     changed = 1;
117                 free(*psw);
118                 *psw = NULL;
119             }
120             else
121             {
122                 if (!*psw)
123                 {
124                     *psw = malloc(LINESIZE);
125                     **psw = '\0';
126                 }
127 
128                 if (strcmp(arg, *psw) != 0)
129                 {
130                     strcpy(*psw, arg);
131                     changed = 1;
132                 }
133             }
134         }
135     }
136     if (desc)
137     {
138         esclog(outFile, "%s is \"%s\" (%s)\n", desc, *psw, changed ? "changed":"unchanged");
139         if (!arg)
140             esclog(outFile, "(readonly)\n");
141     }
142 
143     return changed;
144 }
145 
146 static int
147 handle_address_cmd(FILE *outFile, char *arg)
148 {
149     PLIST_MEMBER plm;
150     char Image[NAMESIZE];
151     DWORD Offset;
152     int cnt;
153     char *s;
154 
155     if(( s = strchr(arg, ':') ))
156     {
157         *s = ' ';
158         if ( (cnt = sscanf(arg,"%20s %x", Image, &Offset)) == 2)
159         {
160             if (( plm = entry_lookup(&cache, Image) ))
161             {
162                 if (plm->RelBase != INVALID_BASE)
163                     esclog(outFile, "Address: 0x%lx\n", plm->RelBase + Offset)
164                 else
165                     esclog(outFile, "Relocated base missing for '%s' ('mod' will update)\n", Image);
166             }
167             else
168                 esclog(outFile, "Image '%s' not found\n", Image);
169         }
170         else
171             esclog(outFile, "usage: `a <Image>:<offset>\n");
172     }
173     else
174         esclog(outFile, "':' expected\n");
175 
176     return 1;
177 }
178 
179 char
180 handle_escape_cmd(FILE *outFile, char *Line, char *path, char *LineOut)
181 {
182     char cmd;
183     char sep = '\n';
184     char *arg;
185     char *l = Line;
186     int res = 1;
187     int cnt = 0;
188     int changed = 0;
189 
190     l = backSpaceEdit(l);
191     if (l[1] != KDBG_ESC_CHAR)
192         return l[1]; //for reprocessing as not escaped
193 
194     log(outFile, "\n");
195 
196     l += 2; //skip space+escape character
197     if ( (cnt=sscanf(l,"%c%c",&cmd,&sep)) < 1)
198     {
199         esclog(outFile, "Command expected\n");
200         res = 0;
201     }
202 
203     if (res && cnt==2 && sep != ' ')
204     {
205         esclog(outFile, "' ' expected\n");
206         res = 0;
207     }
208     l++; //skip cmd
209     while ( *l == ' ')l++; //skip more spaces
210     arg = l;
211     opt_cli = 1;
212     switch (cmd)
213     {
214     case 'a':
215         handle_address_cmd(outFile, arg);
216         break;
217     case 'h':
218         usage(1);
219         break;
220     case 'b':
221         if (handle_switch(outFile, &opt_buffered, arg, "-b Logfile buffering"))
222             set_LogFile(&logFile); //re-open same logfile
223         break;
224     case 'c':
225         handle_switch(outFile, &opt_console, NULL, "-c Console option");
226         break;
227     case 'd':
228         handle_switch_str(outFile, opt_dir, NULL, "-d Directory option");
229         break;
230     case 'l':
231         if (handle_switch_str(outFile, opt_logFile, arg, "-l logfile") || (strcmp(opt_mod,"a")!=0))
232         {
233             opt_mod = "a";
234             set_LogFile(&logFile); //open new logfile
235         }
236         break;
237     case 'L':
238         if (handle_switch_str(outFile, opt_logFile, arg, "-L logfile") || (strcmp(opt_mod,"w")!=0))
239         {
240             opt_mod = "w";
241             set_LogFile(&logFile); //open new logfile
242         }
243         break;
244     case 'm':
245         handle_switch(outFile, &opt_Mark, arg, "-m mark (*)");
246         break;
247     case 'M':
248         handle_switch(outFile, &opt_Mark, arg, "-M Mark (?)");
249         break;
250     case 'P':
251         handle_switch_str(outFile, opt_Pipe, NULL, "-P Pipeline option");
252         break;
253     case 'q':
254         opt_quit = 1;
255         esclog(outFile, "Bye!\n");
256         break;
257     case 'r':
258         handle_switch(outFile, &opt_raw, arg, "-r Raw");
259         break;
260     case 'R':
261         changed = handle_switch_pstr(outFile, &opt_Revision, arg, NULL);
262         opt_Revision_check = 0;
263         if (opt_Revision)
264         {
265             opt_Revision_check = 1;
266             if (strstr(opt_Revision, "check") == opt_Revision)
267             {
268                 esclog(outFile, "-R is \"%s\" (%s)\n", opt_Revision, changed ? "changed":"unchanged");
269             }
270             else if (strstr(opt_Revision, "regscan") == opt_Revision)
271             {
272                 char *s = strchr(opt_Revision, ',');
273 
274                 revinfo.range = DEF_RANGE;
275                 if (s)
276                 {
277                     *s++ = '\0';
278                     revinfo.range = atoi(s);
279                 }
280                 regscan(outFile);
281             }
282             else if (strstr(opt_Revision, "regclear") == opt_Revision)
283             {
284                 list_clear(&sources);
285                 summ.regfound = 0;
286                 esclog(outFile, "cleared regression scan results\n");
287             }
288         }
289         break;
290     case 's':
291         if (strcmp(arg,"clear") == 0)
292         {
293             memset(&summ, 0, sizeof(SUMM));
294             esclog(outFile, "Statistics cleared\n");
295         }
296         else
297             stat_print(outFile, &summ);
298         break;
299     case 'S':
300         cnt = sscanf(arg, "%d+%d", &opt_Source, &opt_SrcPlus);
301         if (opt_Source)
302         {
303             handle_switch(outFile, &opt_undo, "1", "-u Undo");
304             handle_switch(outFile, &opt_redo, "1", "-U Undo and reprocess");
305             opt_Revision_check = 1;
306         }
307         esclog(outFile, "-S Sources option is %d+%d,\"%s\"\n", opt_Source, opt_SrcPlus, opt_SourcesPath);
308         esclog(outFile, "(Setting source tree not implemented)\n");
309         break;
310     case 't':
311         handle_switch(outFile, &opt_twice, arg, "-t Translate twice");
312         break;
313     case 'T':
314         handle_switch(outFile, &opt_twice, arg, NULL);
315         handle_switch(outFile, &opt_Twice, arg, "-T Translate for (address-1)");
316         break;
317     case 'u':
318         handle_switch(outFile, &opt_undo, arg, "-u undo");
319         break;
320     case 'U':
321         handle_switch(outFile, &opt_undo, arg, NULL);
322         handle_switch(outFile, &opt_redo, arg, "-U Undo and reprocess");
323         break;
324     case 'v':
325         handle_switch(outFile, &opt_verbose, arg, "-v Verbosity");
326         break;
327     case 'z':
328         handle_switch_str(outFile, opt_7z, NULL, "-z 7z path");
329         break;
330     default:
331         if (strchr(optchars, cmd))
332             esclog(outFile, "Command not implemented in cli: %c %s\n",cmd, arg)
333         else
334             esclog(outFile, "Unknown command: %c %s\n",cmd, arg);
335     }
336     opt_cli = 0;
337 
338     memset(Line, '\0', LINESIZE);  // flushed
339 
340     return KDBG_ESC_CHAR; //handled escaped command
341 }
342 
343 /* EOF */
344