Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlog2lines.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS log2lines 00003 * Written by Jan Roeloffzen 00004 * 00005 * - Initialization, translation and main loop 00006 */ 00007 00008 #include <errno.h> 00009 #include <stdio.h> 00010 #include <string.h> 00011 #include <stdlib.h> 00012 00013 #include "util.h" 00014 #include "version.h" 00015 #include "compat.h" 00016 #include "options.h" 00017 #include "image.h" 00018 #include "cache.h" 00019 #include "log2lines.h" 00020 #include "help.h" 00021 #include "cmd.h" 00022 #include "match.h" 00023 00024 00025 static FILE *dbgIn = NULL; 00026 static FILE *dbgOut = NULL; 00027 static FILE *conIn = NULL; 00028 static FILE *conOut = NULL; 00029 static const char *kdbg_prompt = KDBG_PROMPT; 00030 static const char *kdbg_cont = KDBG_CONT; 00031 00032 LIST sources; 00033 LINEINFO lastLine; 00034 FILE *logFile = NULL; 00035 LIST cache; 00036 SUMM summ; 00037 REVINFO revinfo; 00038 00039 00040 static void 00041 clearLastLine(void) 00042 { 00043 memset(&lastLine, 0, sizeof(LINEINFO)); 00044 } 00045 00046 static void 00047 log_file(FILE *outFile, char *fileName, int line) 00048 { 00049 int i = 0, min = 0, max = 0; 00050 char s[LINESIZE]; 00051 FILE *src; 00052 00053 strcpy(s, opt_SourcesPath); 00054 strcat(s, fileName); 00055 00056 max = line + opt_SrcPlus; 00057 if ((src = fopen(s, "r"))) 00058 { 00059 min = line - opt_Source; 00060 min = (min < 0) ? 0 : min; 00061 while (i < max && fgets(s, LINESIZE, src)) 00062 { 00063 if (i >= min) 00064 { 00065 if (i == line) 00066 log(outFile, "| ----\n"); 00067 log(outFile, "| %4.4d %s", i + 1, s); 00068 } 00069 i++; 00070 } 00071 fclose(src); 00072 if ( i < min ) 00073 log(outFile, "| S--- source has only %d lines! (check source/revision)\n", i); 00074 } 00075 else 00076 l2l_dbg(1, "Can't open: %s (check " SOURCES_ENV ")\n", s); 00077 } 00078 00079 static void 00080 logSource(FILE *outFile) 00081 { 00082 log_file(outFile, lastLine.file1, lastLine.nr1); 00083 if (lastLine.nr2) 00084 { 00085 log(outFile, "| ---- [%u] ----\n", lastLine.nr2); 00086 log_file(outFile, lastLine.file2, lastLine.nr2); 00087 } 00088 } 00089 00090 static void 00091 reportSource(FILE *outFile) 00092 { 00093 if (!opt_Source) 00094 return; 00095 if (lastLine.valid) 00096 logSource(outFile); 00097 } 00098 00099 static void 00100 report(FILE *outFile) 00101 { 00102 reportRevision(outFile); 00103 reportSource(outFile); 00104 clearLastLine(); 00105 } 00106 00107 00108 static int 00109 print_offset(void *data, size_t offset, char *toString) 00110 { 00111 PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data; 00112 PROSSYM_ENTRY e = NULL; 00113 PROSSYM_ENTRY e2 = NULL; 00114 int bFileOffsetChanged = 0; 00115 char fmt[LINESIZE]; 00116 char *Strings = (char *)data + RosSymHeader->StringsOffset; 00117 00118 fmt[0] = '\0'; 00119 e = find_offset(data, offset); 00120 if (opt_twice) 00121 { 00122 e2 = find_offset(data, offset - 1); 00123 00124 if (e == e2) 00125 e2 = NULL; 00126 else 00127 summ.diff++; 00128 00129 if (opt_Twice && e2) 00130 { 00131 e = e2; 00132 e2 = NULL; 00133 /* replaced (transparantly), but updated stats */ 00134 } 00135 } 00136 if (e || e2) 00137 { 00138 strcpy(lastLine.file1, &Strings[e->FileOffset]); 00139 strcpy(lastLine.func1, &Strings[e->FunctionOffset]); 00140 lastLine.nr1 = e->SourceLine; 00141 sources_entry_create(&sources, lastLine.file1, SVN_PREFIX); 00142 lastLine.valid = 1; 00143 if (e2) 00144 { 00145 strcpy(lastLine.file2, &Strings[e2->FileOffset]); 00146 strcpy(lastLine.func2, &Strings[e2->FunctionOffset]); 00147 lastLine.nr2 = e2->SourceLine; 00148 sources_entry_create(&sources, lastLine.file2, SVN_PREFIX); 00149 bFileOffsetChanged = e->FileOffset != e2->FileOffset; 00150 if (e->FileOffset != e2->FileOffset || e->FunctionOffset != e2->FunctionOffset) 00151 summ.majordiff++; 00152 00153 /* 00154 * - "%.0s" displays nothing, but processes argument 00155 * - bFileOffsetChanged implies always display 2nd SourceLine even if the same 00156 * - also for FunctionOffset 00157 */ 00158 strcat(fmt, "%s"); 00159 if (bFileOffsetChanged) 00160 strcat(fmt, "[%s]"); 00161 else 00162 strcat(fmt, "%.0s"); 00163 00164 strcat(fmt, ":%u"); 00165 if (e->SourceLine != e2->SourceLine || bFileOffsetChanged) 00166 strcat(fmt, "[%u]"); 00167 else 00168 strcat(fmt, "%.0u"); 00169 00170 strcat(fmt, " (%s"); 00171 if (e->FunctionOffset != e2->FunctionOffset || bFileOffsetChanged) 00172 strcat(fmt, "[%s])"); 00173 else 00174 strcat(fmt, "%.0s)"); 00175 00176 if (toString) 00177 { // put in toString if provided 00178 snprintf(toString, LINESIZE, fmt, 00179 &Strings[e->FileOffset], 00180 &Strings[e2->FileOffset], 00181 (unsigned int)e->SourceLine, 00182 (unsigned int)e2->SourceLine, 00183 &Strings[e->FunctionOffset], 00184 &Strings[e2->FunctionOffset]); 00185 } 00186 else 00187 { 00188 strcat(fmt, "\n"); 00189 printf(fmt, 00190 &Strings[e->FileOffset], 00191 &Strings[e2->FileOffset], 00192 (unsigned int)e->SourceLine, 00193 (unsigned int)e2->SourceLine, 00194 &Strings[e->FunctionOffset], 00195 &Strings[e2->FunctionOffset]); 00196 } 00197 } 00198 else 00199 { 00200 if (toString) 00201 { // put in toString if provided 00202 snprintf(toString, LINESIZE, "%s:%u (%s)", 00203 &Strings[e->FileOffset], 00204 (unsigned int)e->SourceLine, 00205 &Strings[e->FunctionOffset]); 00206 } 00207 else 00208 { 00209 printf("%s:%u (%s)\n", 00210 &Strings[e->FileOffset], 00211 (unsigned int)e->SourceLine, 00212 &Strings[e->FunctionOffset]); 00213 } 00214 } 00215 return 0; 00216 } 00217 return 1; 00218 } 00219 00220 static int 00221 process_data(const void *FileData, size_t offset, char *toString) 00222 { 00223 int res; 00224 00225 PIMAGE_SECTION_HEADER PERosSymSectionHeader = get_sectionheader((char *)FileData); 00226 if (!PERosSymSectionHeader) 00227 return 2; 00228 00229 res = print_offset((char *)FileData + PERosSymSectionHeader->PointerToRawData, offset, toString); 00230 if (res) 00231 { 00232 if (toString) 00233 sprintf(toString, "??:0"); 00234 else 00235 printf("??:0"); 00236 l2l_dbg(1, "Offset not found: %x\n", (unsigned int)offset); 00237 summ.offset_errors++; 00238 } 00239 00240 return res; 00241 } 00242 00243 static int 00244 process_file(const char *file_name, size_t offset, char *toString) 00245 { 00246 void *FileData; 00247 size_t FileSize; 00248 int res = 1; 00249 00250 FileData = load_file(file_name, &FileSize); 00251 if (!FileData) 00252 { 00253 l2l_dbg(0, "An error occured loading '%s'\n", file_name); 00254 } 00255 else 00256 { 00257 res = process_data(FileData, offset, toString); 00258 free(FileData); 00259 } 00260 return res; 00261 } 00262 00263 static int 00264 translate_file(const char *cpath, size_t offset, char *toString) 00265 { 00266 size_t base = 0; 00267 LIST_MEMBER *pentry = NULL; 00268 int res = 0; 00269 char *path, *dpath; 00270 00271 dpath = path = convert_path(cpath); 00272 if (!path) 00273 return 1; 00274 00275 // The path could be absolute: 00276 if (get_ImageBase(path, &base)) 00277 { 00278 pentry = entry_lookup(&cache, path); 00279 if (pentry) 00280 { 00281 path = pentry->path; 00282 base = pentry->ImageBase; 00283 if (base == INVALID_BASE) 00284 { 00285 l2l_dbg(1, "No, or invalid base address: %s\n", path); 00286 res = 2; 00287 } 00288 } 00289 else 00290 { 00291 l2l_dbg(1, "Not found in cache: %s\n", path); 00292 res = 3; 00293 } 00294 } 00295 00296 if (!res) 00297 { 00298 res = process_file(path, offset, toString); 00299 } 00300 00301 free(dpath); 00302 return res; 00303 } 00304 00305 static void 00306 translate_char(int c, FILE *outFile) 00307 { 00308 fputc(c, outFile); 00309 if (logFile) 00310 fputc(c, logFile); 00311 } 00312 00313 static char * 00314 remove_mark(char *Line) 00315 { 00316 if (Line[1] == ' ' && Line[2] == '<') 00317 if (Line[0] == '*' || Line[0] == '?') 00318 return Line + 2; 00319 return Line; 00320 } 00321 00322 static void 00323 translate_line(FILE *outFile, char *Line, char *path, char *LineOut) 00324 { 00325 size_t offset; 00326 int cnt, res; 00327 char *sep, *tail, *mark, *s; 00328 unsigned char ch; 00329 00330 if (!*Line) 00331 return; 00332 00333 res = 1; 00334 mark = ""; 00335 s = remove_mark(Line); 00336 if (opt_undo) 00337 { 00338 /* Strip all lines added by this tool: */ 00339 char buf[NAMESIZE]; 00340 if (sscanf(s, "| %s", buf) == 1) 00341 if (buf[0] == '0' || strcmp(buf, "----") == 0 || strcmp(buf, "L2L-") == 0 || strcmp(buf, "S---") == 0 || strcmp(buf, "R---") == 0 || atoi(buf)) 00342 res = 0; 00343 } 00344 00345 sep = strchr(s, ':'); 00346 if (sep) 00347 { 00348 *sep = ' '; 00349 cnt = sscanf(s, "<%s %x%c", path, (unsigned int *)(&offset), &ch); 00350 if (opt_undo) 00351 { 00352 if (cnt == 3 && ch == ' ') 00353 { 00354 tail = strchr(s, '>'); 00355 tail = tail ? tail - 1 : tail; 00356 if (tail && tail[0] == ')' && tail[1] == '>') 00357 { 00358 res = 0; 00359 tail += 2; 00360 mark = opt_mark ? "* " : ""; 00361 if (opt_redo && !(res = translate_file(path, offset, LineOut))) 00362 { 00363 log(outFile, "%s<%s:%x (%s)>%s", mark, path, (unsigned int)offset, LineOut, tail); 00364 summ.redo++; 00365 } 00366 else 00367 { 00368 log(outFile, "%s<%s:%x>%s", mark, path, (unsigned int)offset, tail); 00369 summ.undo++; 00370 } 00371 } 00372 else 00373 { 00374 mark = opt_Mark ? "? " : ""; 00375 summ.skipped++; 00376 } 00377 summ.total++; 00378 } 00379 } 00380 00381 if (!opt_undo || opt_redo) 00382 { 00383 if (cnt == 3 && ch == '>') 00384 { 00385 tail = strchr(s, '>') + 1; 00386 if (!(res = translate_file(path, offset, LineOut))) 00387 { 00388 mark = opt_mark ? "* " : ""; 00389 log(outFile, "%s<%s:%x (%s)>%s", mark, path, (unsigned int)offset, LineOut, tail); 00390 summ.translated++; 00391 } 00392 else 00393 { 00394 mark = opt_Mark ? "? " : ""; 00395 summ.skipped++; 00396 } 00397 summ.total++; 00398 } 00399 } 00400 } 00401 if (res) 00402 { 00403 if (sep) 00404 *sep = ':'; // restore because not translated 00405 log(outFile, "%s%s", mark, s); 00406 } 00407 memset(Line, '\0', LINESIZE); // flushed 00408 } 00409 00410 static int 00411 translate_files(FILE *inFile, FILE *outFile) 00412 { 00413 char *Line = malloc(LINESIZE + 1); 00414 char *path = malloc(LINESIZE + 1); 00415 char *LineOut = malloc(LINESIZE + 1); 00416 int c; 00417 unsigned char ch; 00418 int i = 0; 00419 const char *pc = kdbg_cont; 00420 const char *p = kdbg_prompt; 00421 const char *p_eos = p + sizeof(KDBG_PROMPT) - 1; //end of string pos 00422 00423 if (Line && path && LineOut) 00424 { 00425 memset(Line, '\0', LINESIZE + 1); 00426 if (opt_console) 00427 { 00428 while ((c = fgetc(inFile)) != EOF) 00429 { 00430 if (opt_quit)break; 00431 00432 ch = (unsigned char)c; 00433 if (!opt_raw) 00434 { 00435 switch (ch) 00436 { 00437 case '\n': 00438 if ( strncmp(Line, KDBG_DISCARD, sizeof(KDBG_DISCARD)-1) == 0 ) 00439 { 00440 memset(Line, '\0', LINESIZE); // flushed 00441 } 00442 else 00443 { 00444 Line[1] = handle_escape_cmd(outFile, Line, path, LineOut); 00445 if (Line[1] != KDBG_ESC_CHAR) 00446 { 00447 if (p == p_eos) 00448 { 00449 // kdbg prompt, so already echoed char by char 00450 memset(Line, '\0', LINESIZE); 00451 translate_char(c, outFile); 00452 } 00453 else 00454 { 00455 if (match_line(outFile, Line)) 00456 { 00457 translate_line(outFile, Line, path, LineOut); 00458 translate_char(c, outFile); 00459 report(outFile); 00460 } 00461 } 00462 } 00463 } 00464 i = 0; 00465 p = kdbg_prompt; 00466 pc = kdbg_cont; 00467 break; 00468 case '<': 00469 i = 0; 00470 Line[i++] = ch; 00471 break; 00472 case '>': 00473 if (ch == *p) 00474 { 00475 p = p_eos; 00476 translate_line(outFile, Line, path, LineOut); 00477 } 00478 00479 if (p != p_eos) 00480 { 00481 if (i < LINESIZE) 00482 { 00483 Line[i++] = ch; 00484 translate_line(outFile, Line, path, LineOut); 00485 } 00486 else 00487 { 00488 translate_line(outFile, Line, path, LineOut); 00489 translate_char(c, outFile); 00490 } 00491 } 00492 else 00493 translate_char(c, outFile); 00494 i = 0; 00495 break; 00496 default: 00497 if (ch == *p)p++; 00498 if (ch == *pc)pc++; 00499 if (i < LINESIZE) 00500 { 00501 Line[i++] = ch; 00502 if (p == p_eos) 00503 { 00504 translate_char(c, outFile); 00505 } 00506 else if (!*pc) 00507 { 00508 translate_line(outFile, Line, path, LineOut); 00509 i = 0; 00510 } 00511 } 00512 else 00513 { 00514 translate_line(outFile, Line, path, LineOut); 00515 translate_char(c, outFile); 00516 i = 0; 00517 } 00518 } 00519 } 00520 else 00521 translate_char(c, outFile); 00522 } 00523 } 00524 else 00525 { // Line by line, slightly faster but less interactive 00526 while (fgets(Line, LINESIZE, inFile) != NULL) 00527 { 00528 if (opt_quit)break; 00529 00530 if (!opt_raw) 00531 { 00532 translate_line(outFile, Line, path, LineOut); 00533 report(outFile); 00534 } 00535 else 00536 log(outFile, "%s", Line); 00537 } 00538 } 00539 } 00540 00541 if (opt_Revision && (strstr(opt_Revision, "regscan") == opt_Revision)) 00542 { 00543 char *s = strchr(opt_Revision, ','); 00544 if (s) 00545 { 00546 *s++ = '\0'; 00547 revinfo.range = atoi(s); 00548 } 00549 regscan(outFile); 00550 } 00551 00552 if (opt_stats) 00553 { 00554 stat_print(outFile, &summ); 00555 if (logFile) 00556 stat_print(logFile, &summ); 00557 } 00558 free(LineOut); 00559 free(Line); 00560 free(path); 00561 return 0; 00562 } 00563 00564 00565 int 00566 main(int argc, const char **argv) 00567 { 00568 int res = 0; 00569 int optCount = 0; 00570 00571 dbgIn = stdin; 00572 conOut = stdout; 00573 (void)conIn; 00574 (void)dbgOut; 00575 00576 memset(&cache, 0, sizeof(LIST)); 00577 memset(&sources, 0, sizeof(LIST)); 00578 stat_clear(&summ); 00579 memset(&revinfo, 0, sizeof(REVINFO)); 00580 clearLastLine(); 00581 00582 optionInit(argc, argv); 00583 optCount = optionParse(argc, argv); 00584 if (optCount < 0) 00585 { 00586 return optCount; 00587 } 00588 00589 argc -= optCount; 00590 00591 if (opt_Revision && (strcmp(opt_Revision, "update") == 0)) 00592 { 00593 res = updateSvnlog(); 00594 return res; 00595 } 00596 00597 if (check_directory(opt_force)) 00598 return 3; 00599 00600 create_cache(opt_force, 0); 00601 if (opt_exit) 00602 return 0; 00603 00604 read_cache(); 00605 l2l_dbg(4, "Cache read complete\n"); 00606 00607 if (set_LogFile(&logFile)) 00608 return 2; 00609 l2l_dbg(4, "opt_logFile processed\n"); 00610 00611 if (opt_Pipe) 00612 { 00613 l2l_dbg(3, "Command line: \"%s\"\n",opt_Pipe); 00614 00615 if (!(dbgIn = POPEN(opt_Pipe, "r"))) 00616 { 00617 dbgIn = stdin; //restore 00618 l2l_dbg(0, "Could not popen '%s' (%s)\n", opt_Pipe, strerror(errno)); 00619 free(opt_Pipe); opt_Pipe = NULL; 00620 } 00621 } 00622 l2l_dbg(4, "opt_Pipe processed\n"); 00623 00624 if (argc > 1) 00625 { // translate {<exefile> <offset>} 00626 int i = 1; 00627 const char *exefile = NULL; 00628 const char *offset = NULL; 00629 char Line[LINESIZE + 1]; 00630 00631 while (i < argc) 00632 { 00633 Line[0] = '\0'; 00634 offset = argv[optCount + i++]; 00635 if (isOffset(offset)) 00636 { 00637 if (exefile) 00638 { 00639 l2l_dbg(2, "translating %s %s\n", exefile, offset); 00640 translate_file(exefile, my_atoi(offset), Line); 00641 printf("%s\n", Line); 00642 report(conOut); 00643 } 00644 else 00645 { 00646 l2l_dbg(0, "<exefile> expected\n"); 00647 res = 3; 00648 break; 00649 } 00650 } 00651 else 00652 { 00653 // Not an offset so must be an exefile: 00654 exefile = offset; 00655 } 00656 } 00657 } 00658 else 00659 { // translate logging from stdin 00660 translate_files(dbgIn, conOut); 00661 } 00662 00663 if (logFile) 00664 fclose(logFile); 00665 00666 if (opt_Pipe) 00667 PCLOSE(dbgIn); 00668 00669 return res; 00670 } 00671 00672 /* EOF */ Generated on Thu May 24 2012 04:38:05 for ReactOS by
1.7.6.1
|