Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

909 lines
17 KiB

  1. /*
  2. process.c - Process the log files.
  3. Copyright (c) 1989, Microsoft. All Rights Reserved.
  4. 10-07-89 Matt Saettler
  5. 10-10-89 Update for log,aBlock,EXTFile,files structures
  6. */
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <malloc.h>
  10. #include <string.h>
  11. #include <assert.h>
  12. #include <search.h>
  13. #include "types.h"
  14. #include "docfmt.h"
  15. #include "ventura.h"
  16. #include "rtf.h"
  17. #include "process.h"
  18. #include "misc.h"
  19. #include "errstr.h"
  20. void dumptable(int numfiles, files * ptable);
  21. /*
  22. * @doc INTERNAL
  23. *
  24. * @func void | processLog | This function processes all the Log files.
  25. *
  26. * @xref readLog, initLogs, processLogs, doneLogs
  27. */
  28. void
  29. processLog(void)
  30. {
  31. logentry *cur_log;
  32. FILE *fpout;
  33. if(!head_log)
  34. return;
  35. cur_log=head_log;
  36. while(cur_log)
  37. {
  38. readLog(cur_log);
  39. cur_log=cur_log->next;
  40. }
  41. fpout=fopen(outputFile,"w");
  42. if(!fpout)
  43. return;
  44. cur_log=head_log;
  45. initLogs(fpout, &head_log);
  46. while(cur_log)
  47. {
  48. if(verbose>1) fprintf(errfp," Processing Log file: %s\n",cur_log->pchlogname);
  49. processLogs(fpout, cur_log);
  50. cur_log=cur_log->next;
  51. }
  52. doneLogs(fpout, head_log);
  53. fclose(fpout);
  54. if(verbose) fprintf(errfp,"%s is complete.\n",outputFile);
  55. }
  56. /*
  57. *
  58. * @doc INTERNAL
  59. *
  60. * @func void | processLogs | This functions processes all the files within
  61. * the specified log file structure.
  62. *
  63. * @parm FILE * | fpout | This is the output file to process the files
  64. * to.
  65. *
  66. * @parm logentry * | cur_log | This is the current log file to process.
  67. *
  68. * @xref initFiles, processFiles, doneFiles
  69. */
  70. void
  71. processLogs(FILE *fpout, logentry * cur_log)
  72. {
  73. initFiles(fpout, cur_log);
  74. if(cur_log->outheadMFile)
  75. processFiles(fpout, cur_log->outheadMFile);
  76. processFiles(fpout, cur_log->outheadFile);
  77. if(cur_log->outheadSUFile)
  78. processFiles(fpout, cur_log->outheadSUFile);
  79. doneFiles(fpout, cur_log->outheadFile);
  80. }
  81. /*
  82. * @doc INTERNAL
  83. *
  84. * @func void | cleanLogs | This function removes the log files structure
  85. * from memory and removes any files if the fCleanFiles flag is TRUE.
  86. *
  87. * @parm logentry * | cur_log | This specifies the log file structure to remove.
  88. *
  89. * @xref cleanFile, cleanLogs
  90. */
  91. void
  92. cleanLogs(logentry *cur_log)
  93. {
  94. if(!cur_log)
  95. return;
  96. cleanFile(cur_log->outheadFile);
  97. cleanFile(cur_log->outheadMFile);
  98. cleanFile(cur_log->outheadSUFile);
  99. // structs go here...
  100. cleanLogs(cur_log->next); /* recursive !! */
  101. if(fCleanFiles)
  102. unlink(cur_log->pchlogname);
  103. my_free(cur_log->pchlogname);
  104. my_free(cur_log);
  105. return;
  106. }
  107. /*
  108. * @doc INTERNAL PROCESS
  109. *
  110. * @func void | readLog | This function reads the logfile and creates
  111. * the logfile structure.
  112. *
  113. * @parm logentry * | cur_log | This specifies the logfile structure to
  114. * fill. The filename has been filled in.
  115. *
  116. * @xref parseFile
  117. */
  118. void
  119. readLog(logentry *cur_log)
  120. {
  121. FILE * tFile;
  122. files curFile;
  123. files curMFile;
  124. files curSUFile;
  125. files curTFile;
  126. tFile = fopen(cur_log->pchlogname, "r");
  127. if(tFile == NULL)
  128. {
  129. error(ERROR9, "xxx", cur_log->pchlogname );
  130. Usage();
  131. return;
  132. }
  133. cur_log->outheadFile=NULL;
  134. cur_log->outheadMFile=NULL;
  135. cur_log->outheadSUFile=NULL;
  136. fscanf(tFile, "%d\n",&cur_log->outputType);
  137. curTFile=(files)clear_alloc(sizeof (struct strfile) );
  138. curMFile=NULL;
  139. curSUFile=NULL;
  140. curFile=NULL;
  141. curFile=cur_log->outheadFile;
  142. while(parseFile(tFile, curTFile))
  143. {
  144. if(curTFile->blockType==MESSAGE && fSortMessage)
  145. {
  146. if(curMFile==NULL)
  147. {
  148. cur_log->outheadMFile=curTFile;
  149. }
  150. else
  151. {
  152. curMFile->next=curTFile;
  153. }
  154. curMFile=curTFile;
  155. }
  156. else if( (curTFile->blockType==STRUCTBLOCK) ||
  157. (curTFile->blockType==STRUCTBLOCK))
  158. {
  159. if(curSUFile==NULL)
  160. {
  161. cur_log->outheadSUFile=curTFile;
  162. }
  163. else
  164. {
  165. curSUFile->next=curTFile;
  166. }
  167. curSUFile=curTFile;
  168. }
  169. else
  170. {
  171. if(curFile==NULL)
  172. {
  173. cur_log->outheadFile=curTFile;
  174. }
  175. else
  176. {
  177. curFile->next=curTFile;
  178. }
  179. curFile=curTFile;
  180. }
  181. curTFile=(files)clear_alloc(sizeof (struct strfile) );
  182. }
  183. my_free(curTFile);
  184. curFile->next=NULL;
  185. #ifdef MMWIN // This causes GP fault
  186. curMFile->next=NULL; // just to be sure.
  187. curSUFile->next=NULL; // just to be sure.
  188. #endif
  189. fclose( tFile );
  190. }
  191. /*
  192. * @doc INTERNAL PROCESS
  193. *
  194. * @func int | initLogs | This function is called at the beginning of
  195. * processing the list of logs.
  196. *
  197. * @parm FILE * | phoutfile | This functions specifies the output file handle.
  198. *
  199. * @parm logentry **| phead_log | This specifies the pointer to the list of
  200. * log files to be processed. The head value may be modified due to sorting,
  201. * etc., by the output LogInit routine <f VenLogInit> or <f RTFLogInit>.
  202. *
  203. * @rdesc The return value is TRUE if the operation succeds.
  204. *
  205. * @xref VenLogInit, RTFLogInit
  206. *
  207. */
  208. int
  209. initLogs(FILE *phoutfile, logentry **phead_log)
  210. {
  211. switch(head_log->outputType)
  212. {
  213. case VENTURA:
  214. VenLogInit(phoutfile, phead_log);
  215. break;
  216. case RTFDOC:
  217. case RTFHELP:
  218. RTFLogInit(phoutfile, phead_log);
  219. break;
  220. default:
  221. fprintf(stderr, "Unknown Output Type");
  222. break;
  223. }
  224. return(TRUE);
  225. }
  226. /*
  227. * @doc INTERNAL PROCESS
  228. *
  229. * @func int |initFiles| This function is called before processing each
  230. * log file.
  231. *
  232. * @parm FILE *|phoutfile| This parmameter specifies the output file.
  233. *
  234. * @parm logentry * | curlog | This is the log file containing the files
  235. * to be processed.
  236. *
  237. * @rdesc The return value is TRUE if the initialization was successful.
  238. *
  239. * @comm The files are sorted by function name
  240. *
  241. * @xref VenFileInit, RTFFileInit
  242. *
  243. */
  244. int
  245. initFiles(FILE *phoutfile, logentry *curlog)
  246. {
  247. files curFile;
  248. int i;
  249. files *ptable;
  250. int numFiles;
  251. numFiles=0;
  252. curFile=curlog->outheadFile;
  253. if(!curFile)
  254. goto nofiles;
  255. while(curFile)
  256. {
  257. numFiles++;
  258. curFile=curFile->next;
  259. }
  260. /* sort the list */
  261. ptable=(files *)clear_alloc( sizeof (struct s_log) * (numFiles + 1) );
  262. curFile=curlog->outheadFile;
  263. for(i=0;i<numFiles; i++)
  264. {
  265. ptable[i]=curFile;
  266. curFile=curFile->next;
  267. }
  268. /* dumptable(numFiles, ptable); */
  269. qsort( ptable, numFiles, sizeof (files *), filecmp);
  270. /* dumptable(numFiles, ptable); */
  271. curlog->outheadFile=ptable[0];
  272. curFile=curlog->outheadFile;
  273. for(i=0;i<numFiles; i++)
  274. {
  275. curFile->next=ptable[i];
  276. curFile=curFile->next;
  277. }
  278. curFile->next=NULL;
  279. my_free(ptable);
  280. nofiles:
  281. ////////////////////////////////////////////////////////////////
  282. // sort messages
  283. numFiles=0;
  284. curFile=curlog->outheadMFile;
  285. if(!curFile)
  286. goto nomessages;
  287. while(curFile)
  288. {
  289. numFiles++;
  290. curFile=curFile->next;
  291. }
  292. /* sort the list */
  293. ptable=(files *)clear_alloc( sizeof (struct s_log) * (numFiles + 1) );
  294. curFile=curlog->outheadMFile;
  295. for(i=0;i<numFiles; i++)
  296. {
  297. ptable[i]=curFile;
  298. curFile=curFile->next;
  299. }
  300. /* dumptable(numFiles, ptable); */
  301. qsort( ptable, numFiles, sizeof (files *), filecmp);
  302. /* dumptable(numFiles, ptable); */
  303. curlog->outheadMFile=ptable[0];
  304. curFile=curlog->outheadMFile;
  305. for(i=0;i<numFiles; i++)
  306. {
  307. curFile->next=ptable[i];
  308. curFile=curFile->next;
  309. }
  310. curFile->next=NULL;
  311. my_free(ptable);
  312. nomessages:
  313. ////////////////////////////////////////////////////////////////
  314. // sort structs/unions
  315. numFiles=0;
  316. curFile=curlog->outheadSUFile;
  317. if(!curFile)
  318. goto nosu;
  319. while(curFile)
  320. {
  321. numFiles++;
  322. curFile=curFile->next;
  323. }
  324. /* sort the list */
  325. ptable=(files *)clear_alloc( sizeof (struct s_log) * (numFiles + 1) );
  326. curFile=curlog->outheadSUFile;
  327. for(i=0;i<numFiles; i++)
  328. {
  329. ptable[i]=curFile;
  330. curFile=curFile->next;
  331. }
  332. /* dumptable(numFiles, ptable); */
  333. qsort( ptable, numFiles, sizeof (files *), filecmp);
  334. /* dumptable(numFiles, ptable); */
  335. curlog->outheadSUFile=ptable[0];
  336. curFile=curlog->outheadSUFile;
  337. for(i=0;i<numFiles; i++)
  338. {
  339. curFile->next=ptable[i];
  340. curFile=curFile->next;
  341. }
  342. curFile->next=NULL;
  343. my_free(ptable);
  344. nosu:
  345. //////////////////////////////////////////////////////////////
  346. // Init file/section output
  347. // this is a little out of design because we now have multiple
  348. // files (text and messages and soon structs...
  349. switch(outputType)
  350. {
  351. case VENTURA:
  352. VenFileInit(phoutfile, curlog);
  353. break;
  354. case RTFDOC:
  355. case RTFHELP:
  356. RTFFileInit(phoutfile, curlog);
  357. break;
  358. default:
  359. fprintf(stderr, "Unknown Output Type");
  360. break;
  361. }
  362. return(TRUE);
  363. }
  364. /*
  365. * @doc INTERNAL PROCESS
  366. *
  367. * @func void|dumptable| This is a debug function to dump the list of
  368. * files.
  369. *
  370. * @parm int| numfiles | Specifies the nmber of entries in the table.
  371. *
  372. * @parm files * | ptable | Specifies the table to dump.
  373. *
  374. * @xref initFiles
  375. *
  376. */
  377. void
  378. dumptable(int numfiles, files * ptable)
  379. {
  380. int i;
  381. for(i=0;i<numfiles;i++)
  382. fprintf(stderr, "%s\t\t%s\n",ptable[i]->name,ptable[i]->filename);
  383. }
  384. /*
  385. * @doc INTERNAL PROCESS
  386. *
  387. * @func int | filecmp | This routine is used in the qsort. It does a
  388. * case insensitive compare of the names.
  389. *
  390. * @parm files * | f1 | This is the first file to compare.
  391. *
  392. * @parm files * | f2 | This is the second file to compare.
  393. *
  394. * @rdesc The return is the same as <f strcmp>. See <f qsort>.
  395. *
  396. * @xref qsort, strcmp, initFiles
  397. */
  398. int
  399. filecmp(files * f1, files * f2)
  400. {
  401. int order;
  402. order=stricmp((*f1)->name,(*f2)->name);
  403. return(order);
  404. }
  405. /*
  406. * @doc INTERNAL PROCESS
  407. *
  408. * @func int | processFiles | This routine processes all the files in
  409. * a log file structure by calling the appropriate file output routine.
  410. *
  411. * @parm FILE * | phoutfile | This is the output file handle.
  412. *
  413. * @parm files |headFile| This is the head of the list of files to process.
  414. *
  415. * @xref VenFileProcess, RTFFileProcess
  416. */
  417. int
  418. processFiles(FILE * phoutfile, files headFile)
  419. {
  420. files curFile;
  421. curFile=headFile;
  422. while(curFile && curFile->name)
  423. {
  424. if(verbose>1) fprintf(errfp," Copying Block %s\n",curFile->name);
  425. switch(outputType)
  426. {
  427. case VENTURA:
  428. VenFileProcess(phoutfile, curFile);
  429. break;
  430. case RTFDOC:
  431. case RTFHELP:
  432. RTFFileProcess(phoutfile, curFile);
  433. break;
  434. default:
  435. fprintf(stderr, "Unknown Output Type");
  436. break;
  437. }
  438. curFile=curFile->next;
  439. }
  440. return TRUE;
  441. }
  442. /*
  443. * @doc INTERNAL PROCESS
  444. *
  445. * @func int | parseFile | This routine parses a file structure from a log file.
  446. *
  447. * @parm FILE * | pfh | The input file handle of the log file.
  448. *
  449. * @parm files | curFile| The file structure to place the data from the file.
  450. *
  451. */
  452. int
  453. parseFile(FILE * pfh, files curFile)
  454. {
  455. char achbuf[80];
  456. if(fscanf(pfh,"%d ",&(curFile->blockType)) == EOF)
  457. return(FALSE);
  458. if(fscanf(pfh, "%s",achbuf) == EOF)
  459. return(FALSE);
  460. curFile->name=cp_alloc(achbuf);
  461. if(fscanf(pfh, " %s\n",achbuf) == EOF)
  462. return(FALSE);
  463. curFile->filename=cp_alloc(achbuf);
  464. return(TRUE);
  465. }
  466. /*
  467. * @doc INTERNAL PROCESS
  468. *
  469. * @func void | doneLogs | This function is called after all the logs
  470. * in the list have been processed.
  471. *
  472. * @parm FILE *|phoutfile| Specifies the output file.
  473. *
  474. * @parm logentry * | headLog | Specifies the head of the list of log structure.
  475. *
  476. * @xref VenLogDone, RTFLogDone, cleanLogs
  477. *
  478. * @comm If the fCleanFiles flag is set, then the log files are cleaned.
  479. *
  480. */
  481. void
  482. doneLogs(FILE *phoutfile, logentry *headLog)
  483. {
  484. switch(outputType)
  485. {
  486. case VENTURA:
  487. VenLogDone(phoutfile, headLog);
  488. break;
  489. case RTFDOC:
  490. case RTFHELP:
  491. RTFLogDone(phoutfile, headLog);
  492. break;
  493. default:
  494. fprintf(stderr, "Unknown Output Type");
  495. break;
  496. }
  497. if(fCleanFiles)
  498. cleanLogs(headLog);
  499. return;
  500. }
  501. /*
  502. * @doc INTERNAL PROCESS
  503. *
  504. * @func void | doneFiles | This function is called when all the files
  505. * in the current log have been processed.
  506. *
  507. * @parm FILE *|phoutfile| Specifies the output file.
  508. *
  509. * @parm files | headFile| Specifies the list of files that have been processed.
  510. *
  511. * @xref VenFileDone, RTFFileDone
  512. */
  513. void
  514. doneFiles(FILE *phoutfile, files headFile)
  515. {
  516. switch(outputType)
  517. {
  518. case VENTURA:
  519. VenFileDone(phoutfile, headFile);
  520. break;
  521. case RTFDOC:
  522. case RTFHELP:
  523. RTFFileDone(phoutfile, headFile);
  524. break;
  525. default:
  526. fprintf(stderr, "Unknown Output Type");
  527. break;
  528. }
  529. return;
  530. }
  531. /*
  532. * @doc INTERNAL PROCESS
  533. *
  534. * @func int | cleanFile | This function removes all the memory and
  535. * DOS files associated with the files data structure.
  536. *
  537. * @parm files | headFile| Specifies the list of files to be cleaned.
  538. *
  539. */
  540. int
  541. cleanFile(files headFile)
  542. {
  543. files curFile;
  544. files tcurFile;
  545. curFile=headFile;
  546. while(curFile && curFile->name)
  547. {
  548. unlink(curFile->filename);
  549. my_free(curFile->filename);
  550. my_free(curFile->name);
  551. tcurFile=curFile->next;
  552. my_free(curFile);
  553. curFile=tcurFile;
  554. }
  555. return TRUE;
  556. }
  557. /*
  558. * @doc INTERNAL PROCESS
  559. *
  560. * @func void | copyfile | This function appends the specified file name
  561. * to the specified output file.
  562. *
  563. * @parm FILE *|phoutfile| Specifies the output file.
  564. *
  565. * @parm char *| pchfilename| Specifies the input file.
  566. *
  567. */
  568. void
  569. copyfile(FILE *phoutfile, char *pchfilename)
  570. {
  571. FILE *fpin;
  572. int i;
  573. char *pch;
  574. pch=findfile(pchfilename);
  575. if(!pch)
  576. return;
  577. fpin=fopen(pch,"r");
  578. if(!fpin)
  579. return;
  580. while((i=fgetc(fpin))!=EOF)
  581. fputc(i,phoutfile);
  582. fclose(fpin);
  583. return;
  584. }
  585. /*
  586. * @doc INTERNAL PROCESS
  587. *
  588. * @func char * | findfile | This function tries to find the specified
  589. * file. It searches directories in this order: current, PATH, INIT
  590. * and finally INCLUDE.
  591. *
  592. * @parm char * |pch| Specifies the filename to find.
  593. *
  594. * @rdesc This function returns a pointer to the complete file/path
  595. * of the specified file. Just the file name is returned if it is
  596. * found in the current directory. NULL is returned if the file cannot
  597. * be found.
  598. *
  599. */
  600. char *
  601. findfile(char * pch)
  602. {
  603. FILE *fp;
  604. static char ach[128];
  605. static char *pchmode="r";
  606. strcpy(ach,pch);
  607. fp=fopen(ach, pchmode);
  608. if(fp)
  609. {
  610. fclose(fp);
  611. return(ach);
  612. }
  613. _searchenv(pch,"PATH",ach);
  614. fp=fopen(ach, pchmode);
  615. if(fp)
  616. {
  617. fclose(fp);
  618. return(ach);
  619. }
  620. _searchenv(pch,"INIT",ach);
  621. fp=fopen(ach, pchmode);
  622. if(fp)
  623. {
  624. fclose(fp);
  625. return(ach);
  626. }
  627. _searchenv(pch,"INCLUDE",ach);
  628. fp=fopen(ach, pchmode);
  629. if(fp)
  630. {
  631. fclose(fp);
  632. return(ach);
  633. }
  634. return(NULL);
  635. }
  636. /*
  637. * @doc INTERNAL PROCESS
  638. *
  639. * @func logentry * | add_logtoprocess | This function adds the specified
  640. * log file name to the list of logs to be processed.
  641. *
  642. * @parm char * | pch| Specifies log file name to bo added.
  643. *
  644. * @rdesc The return value specifies the logentry that was created
  645. * for the specified log file.
  646. *
  647. * @xref newlog
  648. */
  649. logentry *
  650. add_logtoprocess(char *pch)
  651. {
  652. logentry *cur_log;
  653. cur_log=newlog(&head_log);
  654. cur_log->pchlogname=cp_alloc(pch);
  655. return(cur_log);
  656. }
  657. /*
  658. * @doc INTERNAL PROCESS
  659. *
  660. * @func logentry * | newlog | This function creates a new log entry
  661. * in the specified list of logs.
  662. *
  663. * @parm logentry ** | start_log| Specifies the head of head of the list
  664. * of logs.
  665. *
  666. * @rdesc The return value specifies the logentry that was added.
  667. *
  668. * @comm The new log structure is added at the head of the list.
  669. *
  670. */
  671. logentry *
  672. newlog(logentry **start_log)
  673. {
  674. logentry * cur_log;
  675. logentry * tmp_log;
  676. cur_log=(logentry *)clear_alloc(sizeof(struct s_log));
  677. if(!*start_log)
  678. {
  679. *start_log=cur_log;
  680. }
  681. else
  682. {
  683. tmp_log=*start_log;
  684. while(tmp_log->next)
  685. tmp_log=tmp_log->next;
  686. tmp_log->next=cur_log;
  687. }
  688. return(cur_log);
  689. }
  690. /*
  691. * @doc INTERNAL PROCESS
  692. *
  693. * @func fileentry * | add_filetoprocess | This function adds an input
  694. * file to process to a log structure.
  695. *
  696. * @parm char * |pch| Specifies the filename to be added.
  697. *
  698. * @parm logentry *|curlog| Specifies the log structure.
  699. *
  700. * @rdesc The return value is the new file structure that is created
  701. * to hold the file entry in the log structure.
  702. *
  703. * @xref newfile
  704. */
  705. fileentry *
  706. add_filetoprocess(char *pch, logentry *curlog)
  707. {
  708. fileentry *cur_file;
  709. cur_file=newfile(&(curlog->inheadFile));
  710. cur_file->filename=cp_alloc(pch);
  711. cur_file->logfile=curlog;
  712. return(cur_file);
  713. }
  714. /*
  715. * @doc INTERNAL PROCESS
  716. *
  717. * @func fileentry * | newfile | This function creates a new file entry
  718. * in a list of files. It is similar to <f newlog>.
  719. *
  720. * @parm fileentry **|start_file| Specifies the head of the list of files.
  721. *
  722. * @rdesc The return value specifies the new file structure that was created
  723. * to hold the new file entry.
  724. *
  725. * @comm This routine inserts at the head of the list.
  726. *
  727. */
  728. fileentry *
  729. newfile(fileentry **start_file)
  730. {
  731. fileentry * cur_file;
  732. fileentry * tmp_file;
  733. cur_file=(fileentry *)clear_alloc(sizeof(struct strfile));
  734. if(!*start_file)
  735. {
  736. *start_file=cur_file;
  737. }
  738. else
  739. {
  740. tmp_file=*start_file;
  741. while(tmp_file->next)
  742. tmp_file=tmp_file->next;
  743. tmp_file->next=cur_file;
  744. }
  745. return(cur_file);
  746. }