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.

1180 lines
24 KiB

  1. /*
  2. docfmt.c - Take the output from extract program and format it.
  3. Copyright (c) 1989, Microsoft. All Rights Reserved.
  4. ...
  5. 10-06-89 Matt Saettler
  6. ...
  7. 10-15-89 Matt Saettler - Autodoc'ed added functions
  8. 3-26-91 Ported for use with Win32 (NigelT)
  9. */
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <malloc.h>
  13. #include <string.h>
  14. #include <assert.h>
  15. #include <search.h>
  16. #include <io.h>
  17. #include <direct.h>
  18. #include <ctype.h>
  19. #ifdef MMWIN
  20. #include <mmsysver.h>
  21. #endif
  22. #include "version.h"
  23. #include "types.h"
  24. #include "text.h"
  25. #include "docfmt.h"
  26. #include "readext.h"
  27. #include "ventura.h"
  28. #include "process.h"
  29. #include "misc.h"
  30. #include "rtf.h"
  31. #include "errstr.h"
  32. void addexternal(char *pch);
  33. int levelOK(aBlock *pBlock);
  34. void parseargfile(char *filename);
  35. /* globals */
  36. char *progName = "docfmt"; // name of our program.
  37. char *dirPath = NULL; // path for creation of temporary files
  38. char *outputFile = NULL; // the final output file name
  39. int noOutput = OFF; // if ON then no output is generated.
  40. int outputType; // type of output to be generated
  41. int fprocessFiles; // flag: should files be processed?
  42. int fCleanFiles; // flag: should temporary files be cleaned up?
  43. int fMMUserEd=FALSE; // flag: generating for User Ed?
  44. logentry *head_log=NULL; // head of list of log files
  45. aLine *headExternal=NULL; // head of list of external names to process
  46. int fprocessOverride=FALSE; // has fprocessFiles been set by user?
  47. int fCleanOverride=FALSE; // has fCleanFiles been set by user?
  48. char achtmpbuf[128]; // a global temporary buffer
  49. int verbose=FALSE;
  50. // Definitions for Error Strings
  51. //
  52. int warninglevel=2; // warning level
  53. int prlineno=TRUE; // print line numbers
  54. int prinfo=TRUE; // print INFO messages ?
  55. long haderror=0; // count of number of errors
  56. int therewaserror=FALSE; // flag: TRUE if there was an error
  57. int dumplevels=FALSE; // flag: TRUE if want to dump doc levels
  58. int fSortMessage=TRUE; // flag: TRUE if want to sort messages
  59. // seperately from APIs
  60. /*
  61. * @doc INTERNAL
  62. *
  63. * @func int | docfmt | Formats the input from the given file and
  64. * prints it to 'stdout'. If the given filename is NULL, input is
  65. * taken from 'stdin'.
  66. *
  67. * @parm char * | fileName | Specifies the name of the
  68. * file to be processed.
  69. *
  70. * @rdesc A return value of zero indicates success; a non-zero return value
  71. * indicates an error.
  72. */
  73. int docfmt(fileName, pcur_log)
  74. char *fileName;
  75. logentry *pcur_log;
  76. {
  77. int nStatus;
  78. int wtag;
  79. aBlock *pcurBlock;
  80. EXTFile *pExt;
  81. char ach[120];
  82. pExt=(EXTFile *)clear_alloc(sizeof (struct _EXTFile));
  83. if(!pExt)
  84. {
  85. error(ERROR3);
  86. exit(7);
  87. }
  88. /* file from standard input? */
  89. if( fileName == NULL )
  90. {
  91. pExt->EXTFilename=cp_alloc("<stdin>");
  92. pExt->fp = stdin;
  93. }
  94. else
  95. {
  96. pExt->EXTFilename=cp_alloc(fileName);
  97. pExt->fp = fopen( pExt->EXTFilename, "r");
  98. if(pExt->fp == NULL )
  99. {
  100. /* or from user-supplied filename? */
  101. strcpy( achtmpbuf, dirPath );
  102. strcat( achtmpbuf, fileName );
  103. my_free(pExt->EXTFilename);
  104. pExt->EXTFilename=cp_alloc(achtmpbuf);
  105. pExt->fp = fopen( achtmpbuf, "r");
  106. /* can file be opened? */
  107. if(pExt->fp == NULL)
  108. {
  109. error( ERROR1, achtmpbuf);
  110. exit(1);
  111. }
  112. }
  113. }
  114. #if 0
  115. // get header information
  116. getLine(pExt);
  117. wtag=HIWORD(getTag(pExt));
  118. while(wtag == T2_HEADER)
  119. {
  120. wtag=(int)getTag(pExt);
  121. switch( wtag)
  122. {
  123. case TG_BEGINHEAD:
  124. getLine(pExt);
  125. break;
  126. case TG_EXTRACTID:
  127. nStatus = processText( pExt, &((pcur_log->pExt)->extractid) );
  128. if( nStatus)
  129. return( nStatus );
  130. getLine(pExt);
  131. break;
  132. case TG_EXTRACTVER:
  133. nStatus = processText( pExt, &((pcur_log->pExt)->extractver) );
  134. if( nStatus)
  135. return( nStatus );
  136. getLine(pExt);
  137. break;
  138. case TG_EXTRACTDATE:
  139. nStatus = processText( pExt, &((pcur_log->pExt)->extractdate) );
  140. if( nStatus)
  141. return( nStatus );
  142. getLine(pExt);
  143. break;
  144. case TG_ENDHEAD:
  145. break;
  146. }
  147. wtag=HIWORD(getTag(pExt));
  148. }
  149. #endif
  150. if( getLine(pExt) )
  151. {
  152. pcurBlock=(aBlock *)1; // a do.. while loop
  153. while( pcurBlock )
  154. {
  155. if(verbose>1)
  156. fprintf(errfp," Reading: ");
  157. pcurBlock = getBlock(pExt);
  158. if(pcurBlock && levelOK(pcurBlock) )
  159. {
  160. if(verbose>1)
  161. fprintf(errfp," Writing.\n");
  162. putblock(pcurBlock, pcur_log);
  163. }
  164. else if(verbose>1)
  165. if(pcurBlock)
  166. fprintf(errfp," Skipping\n");
  167. else
  168. fprintf(errfp," End of File.\n");
  169. if(pcurBlock)
  170. destroyblock(pcurBlock);
  171. }
  172. }
  173. else
  174. {
  175. nStatus = ST_EOF;
  176. }
  177. /* close the file */
  178. fclose(pExt->fp);
  179. pExt->fp=NULL;
  180. if( nStatus == ST_EOF )
  181. return( 0 );
  182. else
  183. return( nStatus );
  184. }
  185. /*
  186. * @doc INTERNAL
  187. *
  188. * @func int | levelOK | Returns TRUE if the specified Block is
  189. * OK to output.
  190. *
  191. * @parm aBlock * | pBlock | Specifies the Block to check.
  192. *
  193. * @rdesc A return value of TRUE indicates the specified Block is
  194. * valid to output. If not valid to print, the return value is FALSE.
  195. */
  196. int
  197. levelOK(aBlock *pBlock)
  198. {
  199. aLine *pextern;
  200. aLine *pLevel;
  201. pextern=headExternal;
  202. while(pextern)
  203. {
  204. if(!strcmp(pextern->text,"*")) // '*' means everything
  205. return TRUE;
  206. pLevel=pBlock->doclevel;
  207. while(pLevel)
  208. {
  209. if(!stricmp(pLevel->text,pextern->text))
  210. return(TRUE); /* we found a match */
  211. pLevel=pLevel->next;
  212. }
  213. pextern=pextern->next;
  214. }
  215. /* no matches. */
  216. return FALSE;
  217. }
  218. /*
  219. * @doc INTERNAL
  220. *
  221. * @func void | Usage | Prints usage information to 'stderr'.
  222. *
  223. * @comm This function does not exit.
  224. */
  225. void Usage()
  226. {
  227. fprintf(stdout, "usage: \n%s [-x[ ]name] [-r[dh]] [-c[01] [-p[01] \n", progName);
  228. fprintf(stdout, "\t[-o[ ]filename] [-d[ ]dirpath] [-l[ ]logfile] [-Zs] [-V[level]] [files]\n");
  229. fprintf(stdout, "\t[@argfile]\n\n");
  230. fprintf(stdout, "[-x[ ]name\tDefines <name> to be generated from the extracted file.\n");
  231. fprintf(stdout, "\t\t\t\t(Default is external.)\n");
  232. fprintf(stdout, "[-X\t\tProcesses all names from extract file.\n");
  233. fprintf(stdout, "[-Zs]\t\t\tNo output, error check only.\n");
  234. fprintf(stdout, "[-Ze]\t\t\tEnables extensions: dump doc level in API.\n");
  235. fprintf(stdout, "[-rd]\t\t\tGenerate RTF output for printing.\n");
  236. fprintf(stdout, "[-rh]\t\t\tGenerate RTF output for WinHelp.\n");
  237. fprintf(stdout, "\t\t\t\t(Default is generate for Ventura.)\n");
  238. fprintf(stdout, "\t\t\t\t(Default RTF is for printing.)\n");
  239. fprintf(stdout, "[-p[01]] \t\tProcess output files.\n");
  240. fprintf(stdout, "\t\t\t\t(0 means don't process)\n");
  241. fprintf(stdout, "[-c[01]] \t\tClean up intermediate files.\n");
  242. fprintf(stdout, "\t\t\t\t(0 means don't clean)\n");
  243. fprintf(stdout, "[-m[01]] \t\tSort Messages seperately from APIs.\n");
  244. fprintf(stdout, "\t\t\t\t(0 means don't sort seperate)\n");
  245. fprintf(stdout, "[-d dirpath] \t\tSpecify the directory for temporary files.\n");
  246. fprintf(stdout, "\t\t\t\t(only one tmp path should be specified)\n");
  247. fprintf(stdout, "[-l logfile] \t\tSpecify the logfile.\n");
  248. fprintf(stdout, "\t\t\t\t(many logfiles may be specified)\n");
  249. fprintf(stdout, "\t\t\t\t(the logfile maps functions to files)\n");
  250. fprintf(stdout, "[-o outputfile] \tSpecify the output file.\n");
  251. fprintf(stdout, "[-v[level]] \t\tSets the Verbosity level.\n");
  252. fprintf(stdout, "[-M]] \t\t\tSets processing for MM User Ed.\n");
  253. fprintf(stdout, "[files] \t\tList of files to be processed.\n");
  254. fprintf(stdout, "[@argfile]\t\tName of file to get list of arguments from.\n");
  255. fprintf(stdout, "\nOptions may be placed in any order.\n");
  256. fprintf(stdout, "example: %s /xinternal /rd dspmgr.ext\n",progName);
  257. fprintf(stdout, "example: %s dspmgr.ext\n",progName);
  258. fprintf(stdout, "example: %s /d \\tmp /rh dspmgr.ext\n",progName);
  259. fprintf(stdout, "example: %s -x internal -x dspmgr -d\\tmp /rh dspmgr.ext /c0 /p0\n",progName);
  260. fprintf(stdout, "example: %s /rd @args /c0\n",progName);
  261. }
  262. /*
  263. * @doc INTERNAL
  264. *
  265. * @func int | main | This function formats documentation information
  266. * from the given input file and sends it to the standard output.
  267. * Information is not sorted or formatted.
  268. *
  269. * @parm int | argc | Specified the number of arguments.
  270. *
  271. * @parm char * | argv[] | Specifies an arrayof points to the arguments.
  272. *
  273. * @rdesc The return value is zero if there are no errors, otherwise the
  274. * return value is a non-zero error code.
  275. */
  276. int main(argc, argv)
  277. int argc; /* Specifies the number of arguments. */
  278. char *argv[]; /* Specifies an array of pointers to the arguments */
  279. {
  280. int nFiles = 0; /* # of files processed */
  281. int nStatus;
  282. int done;
  283. int temp;
  284. if(initerror())
  285. {
  286. fprintf(stderr, "%s: Internal Error 01\n",progName);
  287. exit(765);
  288. }
  289. errfp=stderr; // set error logging file to stderr
  290. /* announce our existance */
  291. initreadext();
  292. noOutput = FALSE;
  293. done = FALSE;
  294. outputType=VENTURA;
  295. fprocessFiles=TRUE;
  296. parsearg(argc,argv, FALSE);
  297. #if MMWIN
  298. sprintf(achtmpbuf," Version %d.%02d.%02d %s %s - %s %s\n",
  299. rmj, rmm, rup, __DATE__, __TIME__, szVerUser, MMSYSVERSIONSTR);
  300. error(LOGON,achtmpbuf);
  301. #endif
  302. if(!head_log)
  303. {
  304. Usage();
  305. exit(1);
  306. }
  307. if(!outputFile)
  308. {
  309. if(fprocessFiles)
  310. {
  311. if(head_log->inheadFile)
  312. {
  313. temp=findlshortname(head_log->inheadFile->filename);
  314. strncpy(achtmpbuf,head_log->inheadFile->filename,temp);
  315. }
  316. else
  317. {
  318. temp=findlshortname(head_log->pchlogname);
  319. strncpy(achtmpbuf,head_log->pchlogname,temp);
  320. }
  321. achtmpbuf[temp]='\0';
  322. switch(outputType)
  323. {
  324. case VENTURA:
  325. strcat(achtmpbuf,".txt");
  326. break;
  327. case RTFDOC:
  328. case RTFHELP:
  329. strcat(achtmpbuf,".rtf");
  330. break;
  331. }
  332. outputFile=cp_alloc(achtmpbuf);
  333. error(INFO_OUTFILEDEFAULT, achtmpbuf);
  334. if(!fCleanOverride)
  335. fCleanFiles=TRUE;
  336. }
  337. }
  338. if(!dirPath)
  339. {
  340. getcwd(achtmpbuf,128);
  341. if (achtmpbuf[strlen(achtmpbuf) - 1] != '\\')
  342. strcat(achtmpbuf,"\\");
  343. dirPath=cp_alloc(achtmpbuf);
  344. }
  345. if(!headExternal)
  346. {
  347. if(verbose>1)
  348. fprintf(errfp,"Document Level list DEFAULTS to %s\n","external");
  349. addexternal("external");
  350. }
  351. if(verbose) fprintf(errfp,"Reading input files...\n");
  352. formatFiles();
  353. if(fprocessFiles)
  354. {
  355. if(verbose) fprintf(errfp,"Creating %s...\n",outputFile);
  356. processLog();
  357. }
  358. return(FALSE); /* we exit ok */
  359. }
  360. /*
  361. * @doc INTERNAL
  362. *
  363. * @func void | formatFiles | This function formats the entire list
  364. * files and sends them to the specified output type.
  365. *
  366. * @comm The log files are filled in on exit.
  367. */
  368. void
  369. formatFiles()
  370. {
  371. fileentry *cur_file;
  372. FILE * fp;
  373. logentry *cur_log=head_log;
  374. while(cur_log)
  375. {
  376. fp=fopen(cur_log->pchlogname,"w");
  377. if(!fp)
  378. {
  379. fprintf(errfp,"Can't open %s\n",cur_log->pchlogname);
  380. error(ERROR3);
  381. exit(1);
  382. }
  383. /* output per-log header data */
  384. cur_log->outputType=outputType;
  385. fprintf(fp,"%d\n",cur_log->outputType);
  386. /* close log header */
  387. fclose(fp);
  388. if(verbose>1) fprintf(errfp,"Processing log file %s\n",cur_log->pchlogname);
  389. cur_file=cur_log->inheadFile;
  390. while(cur_file)
  391. {
  392. cur_file->logfile=cur_log;
  393. if(verbose>1) fprintf(errfp," Reading file %s\n",cur_file->filename);
  394. docfmt(cur_file->filename, cur_log);
  395. cur_file=cur_file->next;
  396. }
  397. cur_log=cur_log->next;
  398. }
  399. }
  400. /*
  401. * @doc INTERNAL
  402. *
  403. * @func void | parsearg | This function parses and process the
  404. * arguments that it is passed.
  405. *
  406. * @parm int | argc | Specified the number of arguments.
  407. *
  408. * @parm char * | argv[] | Specifies an arrayof points to the arguments.
  409. *
  410. * @parm int | flag | Specifies where the arguments came from.
  411. *
  412. * @flag TRUE | Arguments came from a file.
  413. *
  414. * @flag FALSE | Arguments came from the command line.
  415. *
  416. * @rdesc The return value is zero if there are no errors, otherwise the
  417. * return value is a non-zero error code.
  418. */
  419. void
  420. parsearg(argc,argv, flag)
  421. unsigned argc;
  422. char **argv;
  423. int flag;
  424. {
  425. unsigned i,j;
  426. char copt;
  427. int fsamearg;
  428. i = 1;
  429. while( i < argc )
  430. {
  431. switch (*argv[i])
  432. {
  433. case '@':
  434. ++argv[i];
  435. if(*argv[i]==':')
  436. ++argv[i];
  437. if(strlen(argv[i])==0) /* we have @<space><file> */
  438. i++;
  439. if(*argv[i])
  440. parseargfile(argv[i]);
  441. else
  442. {
  443. error(ERR_FILE_OPTION, '@');
  444. Usage();
  445. exit(1);
  446. }
  447. break;
  448. #ifdef MSDOS
  449. case '/' :
  450. #endif
  451. case '-' :
  452. ++argv[i];
  453. fsamearg=TRUE;
  454. while(*argv[i] && fsamearg)
  455. {
  456. copt=*argv[i];
  457. switch( *argv[i] )
  458. {
  459. case 'V':
  460. case 'v':
  461. ++argv[i];
  462. fsamearg=FALSE;
  463. if(*argv[i])
  464. verbose=atoi( argv[i]);
  465. else
  466. verbose=1;
  467. if(verbose>0)
  468. prinfo=TRUE;
  469. else
  470. prinfo=FALSE;
  471. break;
  472. case 'o':
  473. case 'O':
  474. ++argv[i];
  475. fsamearg=FALSE;
  476. if(*argv[i]==':')
  477. ++argv[i];
  478. if(strlen(argv[i])==0) /* we have /o<space><file> */
  479. i++;
  480. if(*argv[i])
  481. setoutputfile(argv[i]);
  482. else
  483. {
  484. if(flag)
  485. {
  486. fprintf(errfp,"%s. Line %d\n",argv[0],i);
  487. }
  488. error(ERR_FILE_OPTION, copt);
  489. Usage();
  490. exit(1);
  491. }
  492. break;
  493. case 'd':
  494. case 'D':
  495. ++argv[i];
  496. fsamearg=FALSE;
  497. if(*argv[i]==':')
  498. ++argv[i];
  499. if(strlen(argv[i])==0) /* we have /d<space><file> */
  500. i++;
  501. if(*argv[i])
  502. settmppath(argv[i]);
  503. else
  504. {
  505. if(flag)
  506. {
  507. fprintf(errfp,"%s. Line %d\n",argv[0],i);
  508. }
  509. error(ERR_FILE_OPTION, copt);
  510. Usage();
  511. exit(1);
  512. }
  513. break;
  514. case 'X':
  515. ++argv[i];
  516. addexternal("*");
  517. break;
  518. case 'x':
  519. ++argv[i];
  520. fsamearg=FALSE;
  521. if(*argv[i]==':')
  522. ++argv[i];
  523. if(strlen(argv[i])==0) /* we have /l<space><name> */
  524. i++;
  525. if(*argv[i])
  526. addexternal(argv[i]);
  527. else
  528. {
  529. if(flag)
  530. {
  531. fprintf(errfp,"%s. Line %d\n",argv[0],i);
  532. }
  533. error(ERR_NAME_OPTION, copt);
  534. Usage();
  535. exit(1);
  536. }
  537. break;
  538. case 'l':
  539. case 'L':
  540. ++argv[i];
  541. fsamearg=FALSE;
  542. if(*argv[i]==':')
  543. ++argv[i];
  544. if(strlen(argv[i])==0) /* we have /l<space><file> */
  545. i++;
  546. fprocessFiles=TRUE;
  547. if(*argv[i])
  548. add_logtoprocess(argv[i]);
  549. else
  550. {
  551. if(flag)
  552. {
  553. fprintf(errfp,"%s. Line %d\n",argv[0],i);
  554. }
  555. error(ERR_FILE_OPTION, copt);
  556. Usage();
  557. exit(1);
  558. }
  559. break;
  560. case 'c':
  561. case 'C':
  562. ++argv[i];
  563. fsamearg=FALSE;
  564. if(*argv[i]==':')
  565. ++argv[i];
  566. fCleanFiles=atoi( argv[i]);
  567. fCleanOverride=TRUE;
  568. break;
  569. case 'm':
  570. ++argv[i];
  571. fsamearg=FALSE;
  572. if(*argv[i]==':')
  573. ++argv[i];
  574. fSortMessage=atoi( argv[i]);
  575. break;
  576. case 'p':
  577. case 'P':
  578. ++argv[i];
  579. fsamearg=FALSE;
  580. if(*argv[i]==':')
  581. ++argv[i];
  582. fprocessFiles=atoi( argv[i]);
  583. fprocessOverride=TRUE;
  584. break;
  585. case 'r':
  586. case 'R':
  587. ++argv[i];
  588. if(!argv[i][0]) /* if no parms, default to RTFDOC */
  589. {
  590. outputType=RTFDOC;
  591. break;
  592. }
  593. switch(argv[i][0])
  594. {
  595. case 'h':
  596. case 'H':
  597. outputType=RTFHELP;
  598. break;
  599. case 'd':
  600. case 'D':
  601. outputType=RTFDOC;
  602. break;
  603. default:
  604. if(flag)
  605. {
  606. fprintf(errfp,"%s. Line %d\n",argv[0],i);
  607. }
  608. error(ERR_XOPTION, copt, argv[i][0]);
  609. break;
  610. }
  611. ++argv[i];
  612. break;
  613. case 'M':
  614. ++argv[i];
  615. fsamearg=TRUE;
  616. fMMUserEd=1;
  617. break;
  618. case 'Z':
  619. ++argv[i];
  620. while(argv[i][0])
  621. {
  622. switch(argv[i][0])
  623. {
  624. case 'e': // enable extensions
  625. dumplevels= TRUE;
  626. break;
  627. case 's': // syntax check only
  628. noOutput = YES;
  629. break;
  630. default:
  631. if(flag)
  632. {
  633. fprintf(errfp,"%s. Line %d\n",argv[0],i);
  634. }
  635. error(ERR_XOPTION,copt, argv[i][0]);
  636. break;
  637. }
  638. ++argv[i];
  639. }
  640. break;
  641. default:
  642. error(ERR_OPTION, copt);
  643. Usage();
  644. exit(1);
  645. }
  646. }
  647. break;
  648. default:
  649. /* let's look to see what kind of file it is */
  650. j=findlshortname(argv[i]);
  651. if(j==strlen(argv[i]))
  652. {
  653. /* it has no extension */
  654. if(flag)
  655. {
  656. fprintf(errfp,"%s. Line %d\n",argv[0],i);
  657. }
  658. error(ERR_UNKNOWN_FILE, argv[i]);
  659. Usage();
  660. exit(1);
  661. }
  662. else
  663. {
  664. #if 0
  665. if(!stricmp(argv[i]+j,".sav"))
  666. {
  667. add_infile(argv[i]);
  668. }
  669. else if(!stricmp(argv[i]+j,".ind"))
  670. { /* it's an input file */
  671. add_infile(argv[i]);
  672. }
  673. else if(!stricmp(argv[i]+j,".db"))
  674. { /* it's an input file */
  675. add_infile(argv[i]);
  676. }
  677. else if(!stricmp(argv[i]+j,".xrf"))
  678. {
  679. add_xrffile(argv[i]);
  680. }
  681. else
  682. #endif
  683. {
  684. /* default file type */
  685. /* add it */
  686. if(!head_log)
  687. {
  688. j=findlshortname(argv[i]);
  689. strncpy(achtmpbuf,argv[i],j);
  690. achtmpbuf[j]='\0';
  691. strcat(achtmpbuf,".log");
  692. add_logtoprocess(achtmpbuf);
  693. error(INFO_LOGFILEDEFAULT, achtmpbuf);
  694. if(!fprocessOverride)
  695. fprocessFiles=TRUE;
  696. }
  697. add_filetoprocess(argv[i], head_log);
  698. #if 0
  699. if(!baseFile)
  700. {
  701. argv[i][j]='\0';
  702. while(j>=0 && (argv[i][j]!='\\' || argv[i][j]!='/') )
  703. j--;
  704. j++;
  705. baseFile=cp_alloc(argv[i]+j);
  706. }
  707. #endif
  708. }
  709. }
  710. break;
  711. } /* switch */
  712. i++;
  713. } /*while */
  714. }
  715. /*
  716. * @doc INTERNAL
  717. *
  718. * @func void | parseargfile | This function processes a file as arguments.
  719. *
  720. * @parm char * | filename | specifies the filename to process.
  721. *
  722. */
  723. void
  724. parseargfile(char *filename)
  725. {
  726. static reenter=0;
  727. FILE *fp;
  728. int lineno,i;
  729. char * * ppch;
  730. char *pch;
  731. aLine *pLine=NULL;
  732. aLine *pHLine=NULL;
  733. assert(!reenter);
  734. reenter++;
  735. fp=fopen(filename,"r");
  736. if(!fp)
  737. {
  738. fprintf(errfp,"Cannot open argument file %s\n",filename);
  739. exit(1);
  740. }
  741. lineno=0;
  742. while(fgets(achtmpbuf,128,fp))
  743. {
  744. // comment is # or ; on first significant character
  745. pch=achtmpbuf;
  746. while(*pch && isspace(*pch))
  747. pch++;
  748. if(*pch=='#' || *pch==';')
  749. continue;
  750. pLine=lineMake(pch);
  751. if(pHLine)
  752. pLine->next=pHLine;
  753. pHLine=pLine;
  754. lineno++;
  755. }
  756. fclose(fp);
  757. if(lineno>0 && pHLine )
  758. {
  759. lineno++; // leave room for arg 0
  760. ppch=(char * *)clear_alloc( (sizeof (char *)) * (lineno+1));
  761. assert(ppch);
  762. pLine=pHLine;
  763. sprintf(achtmpbuf,"Arg file: %s",filename);
  764. ppch[0]=cp_alloc(achtmpbuf);
  765. for(i=1;i<lineno;i++)
  766. {
  767. assert(pLine);
  768. ppch[i]=pLine->text;
  769. pLine=pLine->next;
  770. }
  771. parsearg(lineno,ppch, TRUE); /* do the dirty work */
  772. lineDestroy(pHLine);
  773. my_free(*ppch);
  774. my_free(ppch);
  775. }
  776. reenter--;
  777. }
  778. /*
  779. * @doc INTERNAL
  780. *
  781. * @func void | addexternal | This function adds the specified string
  782. * to the list of defined externals to extract.
  783. *
  784. * @parm char * | pch | Specifies the string to add.
  785. *
  786. */
  787. void
  788. addexternal(char *pch)
  789. {
  790. aLine *pLine;
  791. pLine=lineMake(pch);
  792. assert(pLine);
  793. assert(pch);
  794. if(headExternal) /* insert at head */
  795. pLine->next=headExternal;
  796. headExternal=pLine;
  797. }
  798. /*
  799. * @doc INTERNAL
  800. *
  801. * @func void | setoutputfile | This sets the output file name.
  802. *
  803. * @parm char * | pch | Specifies the filename.
  804. *
  805. */
  806. void
  807. setoutputfile(char * pch)
  808. {
  809. assert(pch);
  810. assert(!outputFile);
  811. outputFile=cp_alloc(pch);
  812. return;
  813. }
  814. /*
  815. * @doc INTERNAL
  816. *
  817. * @func void | settmppath | This sets the path for temporary files.
  818. *
  819. * @parm char * | pch | Specifies the path name.
  820. *
  821. */
  822. void
  823. settmppath(char *pch)
  824. {
  825. int temp;
  826. char ach[80];
  827. assert(pch);
  828. assert(!dirPath);
  829. strcpy( ach, pch );
  830. temp = strlen( ach );
  831. if( (temp != 0) && (ach[temp-1] != '\\') )
  832. {
  833. ach[temp++] = '\\';
  834. ach[temp] = '\0';
  835. }
  836. dirPath=cp_alloc(ach);
  837. return;
  838. }
  839. /*
  840. * @doc INTERNAL
  841. *
  842. * @func files | add_outfile | This function adds the specified file to
  843. * the list of output files for the specified log file.
  844. *
  845. * @parm char * | pchfile | Specifies the filename.
  846. *
  847. * @parm logentry * | pcur_log | Specifies the log file.
  848. *
  849. * @rdesc The return value is the outfile of the specified file.
  850. *
  851. */
  852. files
  853. add_outfile(char *pchfile, logentry *pcur_log)
  854. {
  855. files pfile;
  856. files pcurfile;
  857. assert(pcur_log);
  858. pfile=(files)clear_alloc(sizeof (struct strfile));
  859. if(!pfile)
  860. return(NULL);
  861. pfile->filename=cp_alloc(pchfile);
  862. pfile->logfile=pcur_log;
  863. if(pcur_log->outheadFile)
  864. {
  865. pcurfile=pcur_log->outheadFile;
  866. while(pcurfile->next)
  867. {
  868. pcurfile=pcurfile->next;
  869. }
  870. pcurfile->next=pfile;
  871. }
  872. else
  873. pcur_log->outheadFile=pfile;
  874. return(pfile);
  875. }
  876. /**********************************************************/
  877. /*
  878. * @doc INTERNAL
  879. *
  880. * @func int | putblock | This function outputs a specifed block.
  881. *
  882. * @parm aBlock * |pBlock | Specifies the block to output.
  883. *
  884. * @parm logentry * | pcur_log | Specifies the log to add the output file.
  885. *
  886. * @rdesc The return value is TRUE if no error has occured.
  887. *
  888. */
  889. int
  890. putblock( aBlock *pBlock, logentry *pcur_log)
  891. {
  892. char achFile[128];
  893. FILE *tFile;
  894. files pfile;
  895. assert(pBlock);
  896. assert(pcur_log);
  897. /* output function documentation */
  898. if( !noOutput )
  899. {
  900. mymktemp(dirPath,achFile);
  901. pfile=add_outfile(achFile, pcur_log);
  902. assert(pfile);
  903. /* open the file */
  904. tFile = fopen( pfile->filename, "w" );
  905. if( !tFile )
  906. {
  907. error(ERROR10, pfile->filename);
  908. return(FALSE);
  909. }
  910. /* output information */
  911. switch(outputType)
  912. {
  913. case VENTURA:
  914. VenturaBlockOut(pBlock, tFile);
  915. break;
  916. case RTFDOC:
  917. case RTFHELP:
  918. RTFBlockOut( pBlock, tFile );
  919. break;
  920. default:
  921. fprintf(errfp, "\nInternal Error: Unknown Output Type. Block name:%s\n",pBlock->name->text);
  922. break;
  923. }
  924. fclose(tFile);
  925. /* add to the logfile */
  926. tFile = fopen(pcur_log->pchlogname, "a");
  927. if( !tFile )
  928. {
  929. error(ERROR9, pcur_log->pchlogname );
  930. }
  931. else
  932. {
  933. fprintf(tFile, "%d ", pBlock->blockType); // output type
  934. VentextOut( tFile, pBlock->name, FALSE ); // block name
  935. fprintf( tFile, " \t%s\n", pfile->filename ); // filename
  936. fclose( tFile );
  937. }
  938. }
  939. return(TRUE);
  940. }
  941. /*
  942. * @doc INTERNAL
  943. *
  944. * @func void |destroyblock | This functions deletes all the data structures
  945. * associated withe a block.
  946. *
  947. * @parm aBlock *| pcurblock | Specifies the Block to be destroyed.
  948. *
  949. */
  950. void
  951. destroyblock(aBlock *pcurblock)
  952. {
  953. aBlock *pcbBlock;
  954. if(!pcurblock)
  955. return;
  956. destroyBlockchain(pcurblock->cb);
  957. pcurblock->cb=NULL;
  958. /* free all elements of the aBlock structure */
  959. my_free( pcurblock->srcfile );
  960. pcurblock->srcfile=NULL;
  961. lineDestroy( pcurblock->doclevel );
  962. pcurblock->doclevel=NULL;
  963. lineDestroy( pcurblock->name );
  964. pcurblock->name=NULL;
  965. lineDestroy( pcurblock->type );
  966. pcurblock->type=NULL;
  967. lineDestroy( pcurblock->desc );
  968. pcurblock->desc=NULL;
  969. parmDestroy( pcurblock->parm );
  970. pcurblock->parm=NULL;
  971. regDestroy( pcurblock->reg );
  972. pcurblock->reg=NULL;
  973. fieldDestroy( pcurblock->field);
  974. pcurblock->field=NULL;
  975. otherDestroy( pcurblock->other);
  976. pcurblock->other=NULL;
  977. lineDestroy( pcurblock->tagname);
  978. pcurblock->tagname=NULL;
  979. lineDestroy( pcurblock->rtndesc );
  980. pcurblock->rtndesc=NULL;
  981. flagDestroy( pcurblock->rtnflag );
  982. pcurblock->rtnflag=NULL;
  983. lineDestroy( pcurblock->comment );
  984. pcurblock->comment=NULL;
  985. lineDestroy( pcurblock->xref );
  986. pcurblock->xref=NULL;
  987. /* now, free the aBlock structure itself */
  988. my_free( pcurblock );
  989. }
  990. /*
  991. * @doc INTERNAL
  992. *
  993. * @func void |destroyBlockchain | This function deletes a list of Blocks.
  994. *
  995. * @parm aBlock * |pcurblock | Specifies the head of the list of Blocks.
  996. *
  997. * @comm This function is recursive.
  998. */
  999. void
  1000. destroyBlockchain(aBlock *pcurblock)
  1001. {
  1002. if(!pcurblock)
  1003. return;
  1004. if(pcurblock->next)
  1005. destroyBlockchain(pcurblock->next);
  1006. destroyblock(pcurblock);
  1007. }