home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / reviewed / volume02 / cextract / part04 < prev    next >
Encoding:
Internet Message Format  |  1992-11-02  |  56.6 KB

  1. From: Adam Bryant <adb@cs.bu.edu>
  2. Subject: v02i042: cextract - (Ver. 1.7) C prototyper/header file generator, Part04/05
  3. Newsgroups: comp.sources.reviewed
  4. Approved: csr@calvin.dgbt.doc.ca
  5.  
  6. Submitted-by: Adam Bryant <adb@cs.bu.edu>
  7. Posting-number: Volume 2, Issue 42
  8. Archive-name: cextract/part04
  9. Supersedes: cextract: Volume 1, Issue 4-8
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 4 (of 5)."
  18. # Contents:  io.c
  19. # Wrapped by adb@csa on Fri Oct 30 16:20:37 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'io.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'io.c'\"
  23. else
  24. echo shar: Extracting \"'io.c'\" \(54108 characters\)
  25. sed "s/^X//" >'io.c' <<'END_OF_FILE'
  26. X/*
  27. X *
  28. X * cextract input/output routines.
  29. X *
  30. X * Copyright (c) 1992 by Adam Bryant
  31. X *
  32. X * See the Copyright notice in the file parse.c or in the manual page.
  33. X *
  34. X */
  35. X#include "xtract.h"
  36. X#ifndef VAXC
  37. X#include <pwd.h>
  38. X#ifdef cyber
  39. Xextern struct passwd *getpwuid();
  40. X#endif /* cyber */
  41. X#ifdef CLIX
  42. Xextern struct passwd *getpwuid();
  43. X#endif /* CLIX */
  44. X#endif /* VAXC */
  45. X
  46. X/* declarations */
  47. Xchar cur_cfg_file[FNAME_SIZE], header_string[MID_SIZE];
  48. Xint out_filenum = 0;
  49. X
  50. X/* storage for the temporary buffers */
  51. XP_BUFDATA tempbuf[2] = { NULL, NULL };
  52. X#ifdef SETBUFFER
  53. Xchar outbuffer[BUFFER_SIZE], inbuffer[BUFFER_SIZE];
  54. X#endif /* SETBUFFER */
  55. X
  56. X/* output file */
  57. XFILE *fpout;
  58. Xchar output_file[2][MID_SIZE];
  59. X
  60. X/* preprocessor */
  61. Xchar cpp_prog[MID_SIZE];
  62. X
  63. X#ifdef NO_STRSTR
  64. X/*
  65. X * This function was written to handle Xenix sites without strstr().
  66. X * [It is a straightforward function, which I cannot take credit for,
  67. X * which was given by an anonymous c.s.r reviewer.]
  68. X */
  69. Xchar *
  70. Xstrstr(hoststr, search)
  71. X  char *hoststr;
  72. X  char *search;
  73. X{
  74. X  int len1 = 0, len2 = 0, index = 0;
  75. X  char *ptr1, *ptr2, *loc_ptr;
  76. X
  77. X  len1 = strlen(hoststr);
  78. X  len2 = strlen(search);
  79. X  while ( len1 >= len2 ) {
  80. X    index = len2;
  81. X    loc_ptr = hoststr;
  82. X    ptr1 = hoststr;
  83. X    ptr2 = search;
  84. X    while ( (index > 0) && (loc_ptr != NULL) ) {
  85. X      if ( (*ptr1) == (*ptr2) ) {
  86. X    ++ptr1;
  87. X    ++ptr2;
  88. X    --index;
  89. X      } else {
  90. X    loc_ptr = NULL;
  91. X      }
  92. X    }
  93. X    if ( loc_ptr != NULL ) {
  94. X      return( loc_ptr );
  95. X    } else {
  96. X      ++hoststr;
  97. X      --len1;
  98. X    }
  99. X  }
  100. X  return( NULL );
  101. X}
  102. X#endif /* NO_STRSTR */
  103. X
  104. X/* indicate if on or off */
  105. Xstatic void
  106. Xquick_rc (str, mode, fp)
  107. X  char *str;
  108. X  int mode;
  109. X  FILE *fp;
  110. X{
  111. X  sprintf(tmp_str, "%s%s\n", mode ? "":"!", str);
  112. X  fput_string(tmp_str, fp);
  113. X}
  114. X
  115. X/* check for divergent options */
  116. Xstatic void
  117. Xopt_quickrc (which, str, fp)
  118. X  Optype which;
  119. X  char *str;
  120. X  FILE *fp;
  121. X{
  122. X#ifdef CHECK_INPUTS
  123. X  if ((which < 0) ||
  124. X      (which >= OPT_NUMBER)) {
  125. X    fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
  126. X        which);
  127. X    exit(1);
  128. X  }
  129. X#endif /* CHECK_INPUTS */
  130. X  if (global_opts[0][which] != global_opts[1][which]) {
  131. X    fput_string("extract-only ", fp);
  132. X    quick_rc(str, global_opts[0][which], fp);
  133. X    fput_string("doc-only ", fp);
  134. X  }
  135. X  quick_rc(str, global_opts[1][which], fp);
  136. X}
  137. X
  138. X/* check for divergent numeric options */
  139. Xstatic void
  140. Xopt_numericrc (which, str, fp)
  141. X  Optype which;
  142. X  char *str;
  143. X  FILE *fp;
  144. X{
  145. X#ifdef CHECK_INPUTS
  146. X  if ((which < 0) ||
  147. X      (which >= OPT_NUMBER)) {
  148. X    fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
  149. X        which);
  150. X    exit(1);
  151. X  }
  152. X#endif /* CHECK_INPUTS */
  153. X  if (global_opts[0][which] != global_opts[1][which]) {
  154. X    fput_string("extract-only ", fp);
  155. X    sprintf(tmp_str, "%s: %d\n", str, global_opts[0][which]);
  156. X    fput_string(tmp_str, fp);
  157. X    fput_string("doc-only ", fp);
  158. X  }
  159. X  sprintf(tmp_str, "%s: %d\n", str, global_opts[1][which]);
  160. X  fput_string(tmp_str, fp);
  161. X}
  162. X
  163. X/* choose between three modes of the given option */
  164. Xstatic void
  165. Xopt_triplerc (which, str0, str1, str2, fp)
  166. X  Optype which;
  167. X  char *str0, *str1, *str2;
  168. X  FILE *fp;
  169. X{
  170. X#ifdef CHECK_INPUTS
  171. X  if ((which < 0) ||
  172. X      (which >= OPT_NUMBER)) {
  173. X    fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
  174. X        which);
  175. X    exit(1);
  176. X  }
  177. X#endif /* CHECK_INPUTS */
  178. X  if (global_opts[0][which] != global_opts[1][which]) {
  179. X
  180. X    /* first on */
  181. X    fput_string("extract-only ", fp);
  182. X    switch (global_opts[0][which]) {
  183. X    case 1:
  184. X      fput_string(str1, fp);
  185. X      break;
  186. X    case 2:
  187. X      fput_string(str2, fp);
  188. X      break;
  189. X    default:
  190. X      fput_string(str0, fp);
  191. X      break;
  192. X    }
  193. X    fput_string("\ndoc-only ", fp);
  194. X
  195. X  }
  196. X
  197. X  /* second on */
  198. X  switch (global_opts[1][which]) {
  199. X  case 1:
  200. X    fput_string(str1, fp);
  201. X    break;
  202. X  case 2:
  203. X    fput_string(str2, fp);
  204. X    break;
  205. X  default:
  206. X    fput_string(str0, fp);
  207. X    break;
  208. X  }
  209. X  fput_string("\n", fp);
  210. X}
  211. X
  212. X/* display string appropriately */
  213. Xstatic void
  214. Xopt_stringrc (ind, str, fp)
  215. X  int ind;
  216. X  char *str;
  217. X  FILE *fp;
  218. X{
  219. X  if (ind != 2) {
  220. X    if (ind == 1) {
  221. X      fput_string("doc-only ", fp);
  222. X    } else {
  223. X      fput_string("extract-only ", fp);
  224. X    }
  225. X  }
  226. X  fput_string(str, fp);
  227. X}
  228. X
  229. X/* attempt build of system config file */
  230. Xstatic void
  231. Xbuild_rc (fname)
  232. X  char *fname;
  233. X{
  234. X  int undlen = strlen(UNDEF_LEADER);
  235. X  int deflen = strlen(DEF_LEADER);
  236. X  int inclen = strlen(INC_LEADER);
  237. X  P_MACRO macro_temp;
  238. X  P_SUBST sub_tmp;
  239. X  FILE *rc_fp;
  240. X  int len;
  241. X
  242. X  /* open and write to config file */
  243. X  if ((rc_fp = fopen(fname, "w")) == NULL) {
  244. X    err_msg("unable to open system configuration file for writing");
  245. X    exit(1);
  246. X  }
  247. X
  248. X  /* provide header */
  249. X  sprintf(tmp_str, "#\n# File: %s\n#\n", fname);
  250. X  fput_string(tmp_str, rc_fp);
  251. X  fput_string("#   This config file was generated by ", rc_fp);
  252. X  sprintf(tmp_str, "version %d.%d of %s.\n",
  253. X      VERSION, PATCHLEVEL, prog_name);
  254. X  fput_string(tmp_str, rc_fp);
  255. X  fput_string("#   Edit carefully.\n", rc_fp);
  256. X  fput_string("#\n#   Created: ", rc_fp);
  257. X  strcpy(tmp_str, mach_time());
  258. X  len = strlen(tmp_str);
  259. X  if ((len > 0) && (tmp_str[len - 1] == '\n')) {
  260. X    tmp_str[len - 1] = '\0';
  261. X  }
  262. X  fput_string(tmp_str, rc_fp);
  263. X  fput_string("\n#\n", rc_fp);
  264. X
  265. X  /* first varargs */
  266. X  if (vargs_find()) {
  267. X    fprintf(stderr,
  268. X        "The generation of the varargs and FILE replacements might have\n");
  269. X    fprintf(stderr,
  270. X        "failed.  You may want to manually enter the necessary \"replace\"\n");
  271. X    fprintf(stderr,
  272. X        "commands into the system configuration file.\n");
  273. X  }
  274. X
  275. X  /* begin with the CPP */
  276. X  if (cpp_prog[0] != '\0') {
  277. X    sprintf(tmp_str, "cpp-program: %s\n", cpp_prog);
  278. X    fput_string(tmp_str, rc_fp);
  279. X  }
  280. X
  281. X  /* handle output file */
  282. X  if (strcmp(output_file[0], output_file[1]) != 0) {
  283. X    if (output_file[0][0] != '\0') {
  284. X      fput_string("extract-only ", rc_fp);
  285. X      sprintf(tmp_str, "output-file: %s\n", output_file[0]);
  286. X      fput_string(tmp_str, rc_fp);
  287. X    }
  288. X    if (output_file[1][0] != '\0') {
  289. X      fput_string("doc-only ", rc_fp);
  290. X    }
  291. X  }
  292. X  if (output_file[1][0] != '\0') {
  293. X    sprintf(tmp_str, "output-file: %s\n", output_file[1]);
  294. X    fput_string(tmp_str, rc_fp);
  295. X  }
  296. X
  297. X  /* differentiate modes */
  298. X#ifdef NOT_DONE
  299. X  switch (doc_extract) {
  300. X  case DOC_NONE:
  301. X    fput_string("extract-mode\n", rc_fp);
  302. X    break;
  303. X  case DOC_NORMAL:
  304. X    fput_string("doc-mode\n", rc_fp);
  305. X    break;
  306. X  case DOC_ROFF:
  307. X    fput_string("troff-mode\n", rc_fp);
  308. X    break;
  309. X  default:
  310. X    fprintf(stderr, "\tError, unknown mode.\n\n");
  311. X    exit(1);
  312. X    break;
  313. X  }
  314. X#else
  315. X  if (doc_extract == DOC_ROFF) {
  316. X    fput_string("doc-only troff-mode\n", rc_fp);
  317. X  }
  318. X#endif /* NOT_DONE */
  319. X
  320. X  /* output all options */
  321. X  if (header_string[0] != '\0') {
  322. X    sprintf(tmp_str, "header-string: %s\n", header_string);
  323. X    fput_string(tmp_str, rc_fp);
  324. X  }
  325. X  opt_quickrc(OPT_COMPACT, "merge-output", rc_fp);
  326. X  opt_quickrc(OPT_BOTHUSE, "dual-output", rc_fp);
  327. X  opt_quickrc(OPT_STDCUSE, "ansi-code", rc_fp);
  328. X  opt_quickrc(OPT_SHOWANYWAY, "show-anyway", rc_fp);
  329. X  opt_triplerc(OPT_SORTMODE, "!sort", "sort-by-files", "sort-all", rc_fp);
  330. X  opt_numericrc(OPT_WRAPPOINT, "wrap-parameters", rc_fp);
  331. X  opt_numericrc(OPT_TABWIDTH, "tab-width", rc_fp);
  332. X  opt_quickrc(OPT_TYPEWRAP, "break-after-types", rc_fp);
  333. X  opt_quickrc(OPT_FIRSTCOMMENT, "first-comments", rc_fp);
  334. X  opt_quickrc(OPT_PREPEND, "prepend-filename", rc_fp);
  335. X  opt_quickrc(OPT_COMMENTS, "yank-comments", rc_fp);
  336. X  opt_triplerc(OPT_STATICMODE, "statics: none", "statics: only",
  337. X           "statics: any", rc_fp);
  338. X  opt_quickrc(OPT_EXTERNS, "externs", rc_fp);
  339. X  opt_quickrc(OPT_SINGLECOMMENTS, "single-comments", rc_fp);
  340. X
  341. X  /* show all macros */
  342. X  if (macro_list != NULL) {
  343. X
  344. X    for (macro_temp = macro_list;
  345. X     macro_temp != NULL;
  346. X     macro_temp = macro_temp->next) {
  347. X      if (strncmp(DEF_LEADER, macro_temp->m_str, deflen) == 0) {
  348. X    sprintf(tmp_str, "define: %s\n",
  349. X        macro_temp->m_str + deflen);
  350. X      } else if (strncmp(INC_LEADER, macro_temp->m_str, inclen) == 0) {
  351. X    sprintf(tmp_str, "include: %s\n",
  352. X        macro_temp->m_str + inclen);
  353. X      } else if (strncmp(UNDEF_LEADER, macro_temp->m_str, undlen) == 0) {
  354. X    sprintf(tmp_str, "undefine: %s\n",
  355. X        macro_temp->m_str + deflen);
  356. X      } else {
  357. X    fprintf(stderr, "unknown macro encountered: %s\n",
  358. X        macro_temp->m_str);
  359. X    continue;
  360. X      }
  361. X      opt_stringrc(macro_temp->usewhen, tmp_str, rc_fp);
  362. X    
  363. X    }
  364. X  }
  365. X
  366. X  /* check substitutions */
  367. X  if (subst_list != NULL) {
  368. X
  369. X    for (sub_tmp = subst_list;
  370. X     sub_tmp != NULL;
  371. X     sub_tmp = sub_tmp->next) {
  372. X
  373. X      /* check it */
  374. X      switch (sub_tmp->submode) {
  375. X      case SUBST_FULL:
  376. X    /* the full string needs replacing? */
  377. X    sprintf(tmp_str, "replace all \"%s\" with \"%s\"\n",
  378. X        sub_tmp->from_str, sub_tmp->to_str);
  379. X    break;
  380. X      case SUBST_TYPE:
  381. X    /* the type only needs replacing? */
  382. X    sprintf(tmp_str, "replace type \"%s\" with \"%s\"\n",
  383. X        sub_tmp->from_str, sub_tmp->to_str);
  384. X    break;
  385. X      case SUBST_NAME:
  386. X    /* the variable only needs replacing? WHY!? */
  387. X    sprintf(tmp_str, "replace name \"%s\" with \"%s\"\n",
  388. X        sub_tmp->from_str, sub_tmp->to_str);
  389. X    break;
  390. X      }
  391. X      opt_stringrc(sub_tmp->usewhen, tmp_str, rc_fp);
  392. X
  393. X    }
  394. X  }
  395. X
  396. X  /* done */
  397. X  fput_string("#\n", rc_fp);
  398. X  fclose(rc_fp);
  399. X}
  400. X
  401. X/* close up properly; sending out final output */
  402. Xvoid
  403. Xcxt_close()
  404. X{
  405. X  P_BUFDATA holdbuf;
  406. X  int len;
  407. X
  408. X  /* close up buffers and open file */
  409. X  out_char(-1, '\0');
  410. X  if (output_file[doc_extract != DOC_NONE][0] != '\0') {
  411. X    if ((fpout = fopen(output_file[doc_extract != DOC_NONE], "w")) == NULL) {
  412. X      sprintf(tmp_str, "unable to open output file <%s>",
  413. X          output_file[doc_extract != DOC_NONE]);
  414. X      err_msg(tmp_str);
  415. X      exit(1);
  416. X    }
  417. X  }
  418. X
  419. X#ifdef SETBUFFER
  420. X  /* now set the buffer */
  421. X  setbuffer(fpout, outbuffer, BUFFER_SIZE);
  422. X#endif /* SETBUFFER */
  423. X
  424. X  /* send everything straight out in doc modes */
  425. X  if (doc_extract != DOC_NONE) {
  426. X
  427. X    /* do all */
  428. X    for (; tempbuf[1] != NULL; tempbuf[1] = holdbuf) {
  429. X      /* output and free */
  430. X      holdbuf = tempbuf[1]->next;
  431. X      fput_string(tempbuf[1]->data, fpout);
  432. X      free(tempbuf[1]);
  433. X    }
  434. X
  435. X    /* close up */
  436. X    if (fpout != stdout) {
  437. X      if (fclose(fpout) == EOF) {
  438. X    err_msg("Error in closing output file");
  439. X    exit(1);
  440. X      }
  441. X    }
  442. X    return;
  443. X  }
  444. X
  445. X  /* start header */
  446. X  fput_string("/*\n *   This file was automatically generated by ", fpout);
  447. X  sprintf(tmp_str, "version %d.%d of %s.\n",
  448. X      VERSION, PATCHLEVEL, prog_name);
  449. X  fput_string(tmp_str, fpout);
  450. X  fput_string(" *   Manual editing not recommended.\n", fpout);
  451. X  fput_string(" *\n *   Created: ", fpout);
  452. X  strcpy(tmp_str, mach_time());
  453. X  len = strlen(tmp_str);
  454. X  if ((len > 0) && (tmp_str[len - 1] == '\n')) {
  455. X    tmp_str[len - 1] = '\0';
  456. X  }
  457. X  fput_string(tmp_str, fpout);
  458. X  fput_string("\n */\n", fpout);
  459. X
  460. X  /* enclosing directives */
  461. X  if (header_string[0] != '\0') {
  462. X    sprintf(tmp_str, "#ifndef %s\n", header_string);
  463. X    fput_string(tmp_str, fpout);
  464. X  } else {
  465. X    fput_string("#ifndef __CEXTRACT__\n", fpout);
  466. X  }
  467. X  if (header_string[0] != '\0') {
  468. X    sprintf(tmp_str, "#define %s\n", header_string);
  469. X    fput_string(tmp_str, fpout);
  470. X  }
  471. X  if (get_option(OPT_COMPACT)) {
  472. X    fput_string("#if __STDC__\n", fpout);
  473. X    fput_string("#define PL_(x) x\n", fpout);
  474. X    fput_string("#else\n", fpout);
  475. X    fput_string("#define PL_(x) ( )\n", fpout);
  476. X    fput_string("#endif /* __STDC__ */\n", fpout);
  477. X  } else if (get_option(OPT_BOTHUSE) ||
  478. X         get_option(OPT_STDCUSE)) {
  479. X    fput_string("#if __STDC__\n", fpout);
  480. X  }
  481. X
  482. X  /* first region */
  483. X  for (; tempbuf[0] != NULL; tempbuf[0] = holdbuf) {
  484. X    /* output and free */
  485. X    holdbuf = tempbuf[0]->next;
  486. X    fput_string(tempbuf[0]->data, fpout);
  487. X    free(tempbuf[0]);
  488. X  }
  489. X
  490. X  /* more? */
  491. X  if (!get_option(OPT_COMPACT) &&
  492. X      get_option(OPT_BOTHUSE)) {
  493. X
  494. X    /* separator */
  495. X    fput_string("\n#else /* __STDC__ */\n", fpout);
  496. X
  497. X    /* send second portion */
  498. X    for (; tempbuf[1] != NULL; tempbuf[1] = holdbuf) {
  499. X      /* output and free */
  500. X      holdbuf = tempbuf[1]->next;
  501. X      fput_string(tempbuf[1]->data, fpout);
  502. X      free(tempbuf[1]);
  503. X    }
  504. X
  505. X  }
  506. X
  507. X  /* finish header */
  508. X  putc('\n', fpout);
  509. X  if (get_option(OPT_COMPACT)) {
  510. X    fput_string("#undef PL_\n", fpout);
  511. X  } else if (get_option(OPT_BOTHUSE) ||
  512. X         get_option(OPT_STDCUSE)) {
  513. X    fput_string("#endif /* __STDC__ */\n", fpout);
  514. X  }
  515. X  if (header_string[0] != '\0') {
  516. X    sprintf(tmp_str, "#endif /* %s */\n", header_string);
  517. X    fput_string(tmp_str, fpout);
  518. X  } else {
  519. X    fput_string("#endif /* __CEXTRACT__ */\n", fpout);
  520. X  }
  521. X
  522. X  /* close up */
  523. X  if (fpout != stdout) {
  524. X    if (fclose(fpout) == EOF) {
  525. X      err_msg("Error in closing output file");
  526. X      exit(1);
  527. X    }
  528. X  }
  529. X}
  530. X
  531. X/* output results of entire file search */
  532. Xvoid
  533. Xsend_file()
  534. X{
  535. X  /* sort? */
  536. X  if (get_option(OPT_SORTMODE) != SORT_NONE) {
  537. X    sort_proto();
  538. X  }
  539. X
  540. X  /* output everything */
  541. X  while (proto_list != NULL) {
  542. X
  543. X    /* determine type */
  544. X    if (doc_extract == DOC_NONE) {
  545. X
  546. X      /* ANSI? */
  547. X      if (get_option(OPT_COMPACT)) {
  548. X    out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
  549. X      } else if (get_option(OPT_BOTHUSE)) {
  550. X    out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
  551. X    out_proto(1, proto_list, MODE_OLDC - get_option(OPT_SHOWANYWAY),
  552. X          get_option(OPT_SHOWANYWAY) *
  553. X          get_option(OPT_COMMENTS));
  554. X      } else {
  555. X    if (get_option(OPT_STDCUSE)) {
  556. X      out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
  557. X    } else {
  558. X      out_proto(0, proto_list, MODE_OLDC - get_option(OPT_SHOWANYWAY),
  559. X            get_option(OPT_COMMENTS));
  560. X    }
  561. X      }
  562. X
  563. X    } else {
  564. X
  565. X      /* ANSI in docs */
  566. X      out_proto(1, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
  567. X
  568. X    }
  569. X    total_out++;
  570. X    pop_proto();
  571. X
  572. X  }
  573. X}
  574. X
  575. X/* does the string match a minimum number of characters */
  576. Xint
  577. Xminmatch_str(str_in, str_base, num)
  578. X  char *str_in, *str_base;
  579. X  int num;
  580. X{
  581. X  int i;
  582. X
  583. X  for (i = 0; (str_base[i] != '\0') && (str_in[i] != '\0') &&
  584. X       (str_in[i] != ':') && (str_in[i] != '='); i++) {
  585. X    if (str_base[i] != str_in[i]) return(0);
  586. X  }
  587. X  if (i >= num) {
  588. X    return(i);
  589. X  }
  590. X  return(0);
  591. X}
  592. X
  593. X/* send an error message about a config command */
  594. Xstatic void
  595. Xcfg_err(str, cmd_line)
  596. X  char *str;
  597. X  int cmd_line;
  598. X{
  599. X  fprintf(stderr, "%s", str);
  600. X  if (cmd_line) {
  601. X    fprintf(stderr, " on the command line\n");
  602. X  } else if (cur_cfg_file[0] == '\0') {
  603. X    fprintf(stderr, " in a configuration file\n");
  604. X  } else {
  605. X    fprintf(stderr, " in %s\n", cur_cfg_file);
  606. X  }
  607. X}
  608. X
  609. X/* mode selector */
  610. Xstatic int setmode_value;
  611. X
  612. X#ifndef VMS
  613. X/* parse string for single char commands */
  614. Xstatic void
  615. Xsinglechar_cmds(cmd_str, set_val)
  616. X  char *cmd_str;
  617. X  int set_val;
  618. X{
  619. X  int count, len = strlen(cmd_str);
  620. X
  621. X  for (count = 0; count < len; count++) {
  622. X
  623. X    switch (cmd_str[count]) {
  624. X    case 'A':
  625. X      if (files_parsed == 0) {
  626. X    if (set_val) {
  627. X      set_option(OPT_SORTMODE, setmode_value, SORT_ALL);
  628. X    } else {
  629. X      set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
  630. X    }
  631. X      } else {
  632. X    fprintf(stderr, "The '-A' flag must precede any file arguments\n");
  633. X    show_usage();
  634. X      }
  635. X      break;
  636. X    case 'a':
  637. X      if (get_option(OPT_SORTMODE) != SORT_ALL) {
  638. X    if (set_val) {
  639. X      set_option(OPT_SORTMODE, setmode_value, SORT_FILE);
  640. X    } else {
  641. X      set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
  642. X    }
  643. X      }
  644. X      break;
  645. X    case 'b':
  646. X      build_rc(CONFIG_FILE);
  647. X      exit(0);
  648. X      break;
  649. X    case 'B':
  650. X      build_rc(SYS_CONFIG);
  651. X      exit(0);
  652. X    case 'C':
  653. X      set_option(OPT_FIRSTCOMMENT, setmode_value, set_val);
  654. X      break;
  655. X    case 'c':
  656. X      set_option(OPT_COMMENTS, setmode_value, set_val);
  657. X      break;
  658. X    case 'D':
  659. X    case 'd':
  660. X      /* add to macro list */
  661. X      if (count != 0) {
  662. X    fprintf(stderr, "The -D flag must be a separate argument\n");
  663. X    show_usage();
  664. X      }
  665. X      sprintf(tmp_str, "%s%s", DEF_LEADER, cmd_str + 1);
  666. X      add_macro(setmode_value, tmp_str);
  667. X      return;
  668. X    case 'E':
  669. X      set_option(OPT_EXTERNS, setmode_value, set_val);
  670. X      break;
  671. X    case 'F':
  672. X      set_option(OPT_PREPEND, setmode_value, set_val);
  673. X      break;
  674. X    case 'f':
  675. X      /* set font */
  676. X      if (count != 0) {
  677. X    fprintf(stderr, "The -f flag must be a separate argument\n");
  678. X    show_usage();
  679. X      } else if (files_parsed > 0) {
  680. X    fprintf(stderr, "The -f flag must precede any file arguments\n");
  681. X    show_usage();
  682. X      }
  683. X
  684. X      /* check format */
  685. X      if ((strlen(cmd_str + 1) < 2) ||
  686. X      (strlen(cmd_str + 1) > 3)) {
  687. X    fprintf(stderr, "A proper troff font must be specified\n");
  688. X    show_usage();
  689. X      }
  690. X
  691. X      /* check font */
  692. X      switch (cmd_str[1]) {
  693. X      case '1':
  694. X      case 't':
  695. X      case 'T':
  696. X    /* title */
  697. X    strncpy(ft_title, &(cmd_str[2]), 2);
  698. X    ft_title[2] = '\0';
  699. X    break;
  700. X      case '2':
  701. X      case 'c':
  702. X      case 'C':
  703. X    /* comment */
  704. X    strncpy(ft_comment, &(cmd_str[2]), 2);
  705. X    ft_comment[2] = '\0';
  706. X    break;
  707. X      case '3':
  708. X      case 'n':
  709. X      case 'N':
  710. X    /* function name */
  711. X    strncpy(ft_name, &(cmd_str[2]), 2);
  712. X    ft_name[2] = '\0';
  713. X    break;
  714. X      case '4':
  715. X      case 'p':
  716. X      case 'P':
  717. X    /* prototype list */
  718. X    strncpy(ft_plist, &(cmd_str[2]), 2);
  719. X    ft_plist[2] = '\0';
  720. X    break;
  721. X      default:
  722. X    /* huh? */
  723. X    fprintf(stderr, "unknown font selector '%c' in %s\n",
  724. X        cmd_str[1], cmd_str);
  725. X    show_usage();
  726. X      }
  727. X      return;
  728. X    case 'H':
  729. X      /* header string */
  730. X      if (files_parsed == 0) {
  731. X    if (count != 0) {
  732. X      fprintf(stderr, "The -H flag must be a separate argument\n");
  733. X      show_usage();
  734. X    }
  735. X    if (cmd_str[2] != '\0') {
  736. X      strcpy(header_string, cmd_str + 1);
  737. X    } else {
  738. X      fprintf(stderr,
  739. X          "A string must be specified following the -H flag\n");
  740. X      show_usage();
  741. X    }
  742. X      } else {
  743. X    fprintf(stderr, "The -H flag must precede any file arguments\n");
  744. X    show_usage();
  745. X      }
  746. X      return;
  747. X    case 'I':
  748. X    case 'i':
  749. X      /* include file */
  750. X      if (count != 0) {
  751. X    fprintf(stderr, "The -I flag must be a separate argument\n");
  752. X    show_usage();
  753. X      }
  754. X      sprintf(tmp_str, "%s%s", INC_LEADER, cmd_str + 1);
  755. X      add_macro(setmode_value, tmp_str);
  756. X      return;
  757. X    case 'm':
  758. X      set_option(OPT_SINGLECOMMENTS, setmode_value, (TRUE ^ set_val));
  759. X      break;
  760. X    case 'N':
  761. X      /* roff mode */
  762. X      if (files_parsed > 0) {
  763. X    fprintf(stderr, "The -N flag must precede any file arguments\n");
  764. X    show_usage();
  765. X      }
  766. X      doc_extract = DOC_ROFF;
  767. X      break;
  768. X    case 'n':
  769. X      /* docs mode */
  770. X      if (files_parsed > 0) {
  771. X    fprintf(stderr, "The -n flag must precede any file arguments\n");
  772. X    show_usage();
  773. X      }
  774. X      doc_extract = DOC_NORMAL;
  775. X      break;
  776. X    case 'o':
  777. X      if (out_filenum < 3) {
  778. X    out_filenum = 1;
  779. X      } else {
  780. X    fprintf(stderr, "The -o flag must precede any file arguments\n");
  781. X    show_usage();
  782. X      }
  783. X      break;
  784. X    case 'p':
  785. X      /* ANSI C prototypes */
  786. X      if (files_parsed == 0) {
  787. X    set_option(OPT_STDCUSE, setmode_value, set_val);
  788. X      } else {
  789. X    fprintf(stderr, "The -p flag must precede any file arguments\n");
  790. X    show_usage();
  791. X      }
  792. X      break;
  793. X    case 'P':
  794. X      /* both ANSI and K&R */
  795. X      if (files_parsed == 0) {
  796. X    set_option(OPT_BOTHUSE, setmode_value, set_val);
  797. X      } else {
  798. X    fprintf(stderr, "The -P flag must precede any file arguments\n");
  799. X    show_usage();
  800. X      }
  801. X      break;
  802. X    case 'Q':
  803. X      /* not here */
  804. X      fprintf(stderr, "The -Q flag must be the very first argument\n");
  805. X      show_usage();
  806. X    case 'q':
  807. X      /* input config file */
  808. X      if (count != 0) {
  809. X    fprintf(stderr, "The -q flag must be a separate argument\n");
  810. X    show_usage();
  811. X      }
  812. X      if (cmd_str[1] != '\0') {
  813. X    parse_config(cmd_str + 1);
  814. X      } else {
  815. X    fprintf(stderr, "No file was specified for the -q argument\n");
  816. X    show_usage();
  817. X      }
  818. X      return;
  819. X    case 'r':
  820. X      /* remove variable names */
  821. X      set_option(OPT_NONAMES, setmode_value, set_val);
  822. X      break;
  823. X    case 'S':
  824. X      /* full info for non-ANSI */
  825. X      set_option(OPT_SHOWANYWAY, setmode_value, set_val);
  826. X      break;
  827. X    case 's':
  828. X      /* static functions */
  829. X      if ((cmd_str[count + 1] == ':') ||
  830. X      (cmd_str[count + 1] == '=')) {
  831. X    count += 2;
  832. X    switch(cmd_str[count]) {
  833. X    case 'a':
  834. X      /* all */
  835. X      set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
  836. X      if ((strncmp(cmd_str + count, "all", 3) == 0) ||
  837. X          (strncmp(cmd_str + count, "any", 3) == 0)) {
  838. X        count += 3;
  839. X      } else {
  840. X        count++;
  841. X      }
  842. X      break;
  843. X    case 'o':
  844. X      /* only statics */
  845. X      set_option(OPT_STATICMODE, setmode_value, ONLY_STATICS);
  846. X      if (strncmp(cmd_str + count, "only", 4) == 0) {
  847. X        count += 4;
  848. X      } else {
  849. X        count++;
  850. X      }
  851. X      break;
  852. X    case 'n':
  853. X      /* no statics */
  854. X      set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
  855. X      if (strncmp(cmd_str + count, "none", 4) == 0) {
  856. X        count += 4;
  857. X      } else if (strncmp(cmd_str + count, "no", 2) == 0) {
  858. X        count += 2;
  859. X      } else {
  860. X        count++;
  861. X      }
  862. X      break;
  863. X    default:
  864. X      /* huh? */
  865. X      count--;
  866. X      break;
  867. X    }
  868. X      } else {
  869. X    if (set_val) {
  870. X      set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
  871. X    } else {
  872. X      set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
  873. X    }
  874. X      }
  875. X      break;
  876. X    case 'T':
  877. X      /* tab width */
  878. X      if (count != 0) {
  879. X    fprintf(stderr, "The -T flag must be a separate argument\n");
  880. X    show_usage();
  881. X      }
  882. X      if (len == 2) {
  883. X    set_option(OPT_TABWIDTH, setmode_value, 8);
  884. X      } else {
  885. X    int tab_width = 0;
  886. X    for (count++; count < len; count++) {
  887. X      if (!isdigit(cmd_str[count])) {
  888. X        fprintf(stderr, "Unknown tab width in argument %s\n",
  889. X            cmd_str);
  890. X        show_usage();
  891. X      } else {
  892. X        tab_width *= 10;
  893. X        tab_width += cmd_str[count] - '0';
  894. X      }
  895. X    }
  896. X    set_option(OPT_TABWIDTH, setmode_value, tab_width);
  897. X      }
  898. X      return;
  899. X    case 'U':
  900. X    case 'u':
  901. X      /* undefine */
  902. X      if (count != 0) {
  903. X    fprintf(stderr, "The -U flag must be a separate argument\n");
  904. X    show_usage();
  905. X      }
  906. X      if (removed_macro(setmode_value, cmd_str + 1) != TRUE) {
  907. X    sprintf(tmp_str, "%s%s", UNDEF_LEADER, cmd_str + 1);
  908. X    add_macro(setmode_value, tmp_str);
  909. X      }
  910. X      return;
  911. X    case 'V':
  912. X      show_settings();
  913. X    case 'v':
  914. X      show_version();
  915. X      exit(0);
  916. X    case 'W':
  917. X      /* wrapping */
  918. X      set_option(OPT_TYPEWRAP, setmode_value, set_val);
  919. X      break;
  920. X    case 'w':
  921. X      /* more wrapping */
  922. X      if (isdigit(cmd_str[count + 1])) {
  923. X
  924. X    /* use given wrap locale */
  925. X    int wrap_point = 0;
  926. X    for (count++; isdigit(cmd_str[count]); count++) {
  927. X      wrap_point *= 10;
  928. X      wrap_point += (cmd_str[count] - '0');
  929. X    }
  930. X    count--;
  931. X    set_option(OPT_WRAPPOINT, setmode_value, wrap_point);    
  932. X
  933. X      } else {
  934. X
  935. X    if (set_val) {
  936. X      /* default */
  937. X      set_option(OPT_WRAPPOINT, setmode_value, 72);
  938. X    } else {
  939. X      /* off */
  940. X      set_option(OPT_WRAPPOINT, setmode_value, 0);
  941. X    }
  942. X
  943. X      }
  944. X      break;
  945. X    case 'x':
  946. X      /* extraction mode */
  947. X      if (files_parsed > 0) {
  948. X    fprintf(stderr, "The -x flag must precede any file arguments\n");
  949. X    show_usage();
  950. X      }
  951. X      doc_extract = DOC_NONE;
  952. X      break;
  953. X    case 'Y':
  954. X      /* C preprocessor */
  955. X      if (files_parsed == 0) {
  956. X    if (count != 0) {
  957. X      fprintf(stderr, "The -Y flag must be a separate argument\n");
  958. X      show_usage();
  959. X    }
  960. X    if (cmd_str[2] != '\0') {
  961. X      strcpy(cpp_prog, cmd_str + 1);
  962. X    } else {
  963. X      fprintf(stderr,
  964. X          "A string must be specified following the -Y flag\n");
  965. X      show_usage();
  966. X    }
  967. X      } else {
  968. X    fprintf(stderr, "The -Y flag must precede any file arguments\n");
  969. X    show_usage();
  970. X      }
  971. X      break;
  972. X    case 'Z':
  973. X      /* merge output */
  974. X      if (files_parsed == 0) {
  975. X    set_option(OPT_COMPACT, setmode_value, set_val);
  976. X      } else {
  977. X    fprintf(stderr, "The -Z flag must precede any file arguments\n");
  978. X    show_usage();
  979. X      }
  980. X      break;
  981. X    default:
  982. X      /* huh? */
  983. X      fprintf(stderr, "Unknown option '%c' in <%s>\n", cmd_str[count],
  984. X          cmd_str);
  985. X      show_usage();
  986. X    }
  987. X  }
  988. X}
  989. X#endif /* VMS */
  990. X
  991. X/* determine the configuration command, exit if invalid */
  992. Xvoid
  993. Xparse_cmd (cmd_str, set_val, cmd_line)
  994. X  char *cmd_str;
  995. X  int set_val, cmd_line;
  996. X{
  997. X  int len, count, did_cmd_parse = FALSE, had_start = FALSE;
  998. X  char t2_str[MID_SIZE];
  999. X
  1000. X  /* clean ends of spaces */
  1001. X  trim_str(cmd_str);
  1002. X
  1003. X  /* by default, set for both */
  1004. X  setmode_value = 2;
  1005. X
  1006. X  /* non-command line */
  1007. X  if (cmd_line == FALSE) {
  1008. X
  1009. X    /* selection? */
  1010. X    if (strncmp("extract-only ", cmd_str, 13) == 0) {
  1011. X      setmode_value = 0;
  1012. X      for (count = 0; count < 13; count++)
  1013. X    cmd_str[count] = ' ';
  1014. X      trim_str(cmd_str);
  1015. X    } else if (strncmp("doc-only ", cmd_str, 9) == 0) {
  1016. X      setmode_value = 1;
  1017. X      for (count = 0; count < 9; count++)
  1018. X    cmd_str[count] = ' ';
  1019. X      trim_str(cmd_str);
  1020. X    }
  1021. X
  1022. X  }
  1023. X
  1024. X  /* off? */
  1025. X  if (cmd_str[0] == '!') {
  1026. X    cmd_str[0] = ' ';
  1027. X    trim_str(cmd_str);
  1028. X    set_val ^= TRUE;
  1029. X    had_start = TRUE;
  1030. X  } else {
  1031. X    if (strncmp("no-", cmd_str, 3) == 0) {
  1032. X      for (count = 0; count < 3; count++)
  1033. X    cmd_str[count] = ' ';
  1034. X      trim_str(cmd_str);
  1035. X      set_val ^= TRUE;
  1036. X      had_start = TRUE;
  1037. X    } else if (strncmp("no", cmd_str, 2) == 0) {
  1038. X      for (count = 0; count < 2; count++)
  1039. X    cmd_str[count] = ' ';
  1040. X      trim_str(cmd_str);
  1041. X      set_val ^= TRUE;
  1042. X      had_start = TRUE;
  1043. X    }
  1044. X  }
  1045. X  len = strlen(cmd_str);
  1046. X
  1047. X  /* parse actual command */
  1048. X  switch (cmd_str[0]) {
  1049. X  case '\0':
  1050. X  case '#':
  1051. X    /* comment */
  1052. X    did_cmd_parse = TRUE;
  1053. X    break;
  1054. X  case 'a':
  1055. X    /* ansi C code */
  1056. X    if (minmatch_str(cmd_str, "ansi-code", 4)) {
  1057. X      did_cmd_parse = TRUE;
  1058. X      if (files_parsed > 0) {
  1059. X    if (cmd_line) {
  1060. X      fprintf(stderr, "Error, ansi-code flag found after file argument\n");
  1061. X      exit(1);
  1062. X    }
  1063. X      } else {
  1064. X    set_option(OPT_STDCUSE, setmode_value, set_val);
  1065. X      }
  1066. X    }
  1067. X    break;
  1068. X  case 'b':
  1069. X    if (minmatch_str(cmd_str, "build-config", 5)) {
  1070. X      did_cmd_parse = TRUE;
  1071. X      if (cmd_line) {
  1072. X    build_rc(CONFIG_FILE);
  1073. X    exit(0);
  1074. X      } else {
  1075. X    cfg_err("warning, the build-config command is unsupported", cmd_line);
  1076. X      }
  1077. X    } else if (minmatch_str(cmd_str, "break-types", 5) ||
  1078. X           minmatch_str(cmd_str, "break-after-types", 5)) {
  1079. X      set_option(OPT_TYPEWRAP, setmode_value, set_val);
  1080. X      did_cmd_parse = TRUE;
  1081. X    }
  1082. X    break;
  1083. X  case 'c':
  1084. X    /* get comments */
  1085. X    if (minmatch_str(cmd_str, "comments", 4)) {
  1086. X      set_option(OPT_COMMENTS, setmode_value, set_val);
  1087. X      did_cmd_parse = TRUE;
  1088. X    } else if (count = minmatch_str(cmd_str, "cpp-program", 3)) {
  1089. X      did_cmd_parse = TRUE;
  1090. X      if (files_parsed > 0) {
  1091. X    if (cmd_line) {
  1092. X      fprintf(stderr,
  1093. X          "Error: cpp-program flag found after file arguments\n");
  1094. X      exit(1);
  1095. X    }
  1096. X      } else {
  1097. X    for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1098. X      if ((cmd_str[count] == ':') ||
  1099. X          (cmd_str[count] == '=')) {
  1100. X        count++;
  1101. X        break;
  1102. X      }
  1103. X    }
  1104. X    strcpy(tmp_str, cmd_str + count);
  1105. X    trim_str(tmp_str);
  1106. X    if (strlen(tmp_str) > 0) {
  1107. X      strcpy(cpp_prog, tmp_str);
  1108. X    } else {
  1109. X      cfg_err("warning, blank cpp-program name", cmd_line);
  1110. X    }
  1111. X      }
  1112. X    } else if (count = minmatch_str(cmd_str, "config-file", 4)) {
  1113. X      did_cmd_parse = TRUE;
  1114. X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1115. X    if ((cmd_str[count] == ':') ||
  1116. X        (cmd_str[count] == '=')) {
  1117. X      count++;
  1118. X      break;
  1119. X    }
  1120. X      }
  1121. X      strcpy(tmp_str, cmd_str + count);
  1122. X      trim_str(tmp_str);
  1123. X      if (strlen(tmp_str) > 0) {
  1124. X    parse_config(tmp_str);
  1125. X      } else {
  1126. X    cfg_err("warning, blank config file name", cmd_line);
  1127. X      }
  1128. X    }
  1129. X    break;
  1130. X  case 'd':
  1131. X    if (minmatch_str(cmd_str, "dual-output", 4)) {
  1132. X      did_cmd_parse = TRUE;
  1133. X      if (files_parsed > 0) {
  1134. X    if (cmd_line) {
  1135. X      fprintf(stderr,
  1136. X          "Error, dual-output flag found after file argument\n");
  1137. X      exit(1);
  1138. X    }
  1139. X      } else {
  1140. X    set_option(OPT_BOTHUSE, setmode_value, set_val);
  1141. X      }
  1142. X    } else if (minmatch_str(cmd_str, "discard-names", 4)) {
  1143. X      set_option(OPT_NONAMES, setmode_value, set_val);
  1144. X      did_cmd_parse = TRUE;
  1145. X    } else if (minmatch_str(cmd_str, "doc-mode", 3)) {
  1146. X      did_cmd_parse = TRUE;
  1147. X      if (files_parsed > 0) {
  1148. X    if (cmd_line) {
  1149. X      fprintf(stderr, "Error, doc-mode flag found after file argument\n");
  1150. X      exit(1);
  1151. X    }
  1152. X      } else {
  1153. X    doc_extract = DOC_NORMAL;
  1154. X      }
  1155. X    } else if (count = minmatch_str(cmd_str, "define", 3)) {
  1156. X      did_cmd_parse = TRUE;
  1157. X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1158. X    if ((cmd_str[count] == ':') ||
  1159. X        (cmd_str[count] == '=')) {
  1160. X      count++;
  1161. X      break;
  1162. X    }
  1163. X      }
  1164. X      strcpy(tmp_str, cmd_str + count);
  1165. X      trim_str(tmp_str);
  1166. X      if (strlen(tmp_str) > 0) {
  1167. X    sprintf(cmd_str, "%s%s", DEF_LEADER, tmp_str);
  1168. X    add_macro(setmode_value, cmd_str);
  1169. X      } else {
  1170. X    cfg_err("warning, blank define command", cmd_line);
  1171. X      }
  1172. X    }
  1173. X    break;
  1174. X  case 'e':
  1175. X    if (minmatch_str(cmd_str, "externs", 4)) {
  1176. X      /* extern prepending */
  1177. X      did_cmd_parse = TRUE;
  1178. X      set_option(OPT_EXTERNS, setmode_value, set_val);
  1179. X    } else if (minmatch_str(cmd_str, "extract-mode", 3)) {
  1180. X      /* extract mode */
  1181. X      did_cmd_parse = TRUE;
  1182. X      if (files_parsed > 0) {
  1183. X    if (cmd_line) {
  1184. X      fprintf(stderr, "Error, extract-mode found after file argument\n");
  1185. X      exit(1);
  1186. X    }
  1187. X      } else {
  1188. X    doc_extract = DOC_NONE;
  1189. X      }
  1190. X    }
  1191. X    break;
  1192. X  case 'f':
  1193. X    if (minmatch_str(cmd_str, "first-comments", 4)) {
  1194. X      /* grabs first comments */
  1195. X      did_cmd_parse = TRUE;
  1196. X      set_option(OPT_FIRSTCOMMENT, setmode_value, set_val);
  1197. X    } else if (minmatch_str(cmd_str, "filename", 4)) {
  1198. X      /* prepend file name */
  1199. X      did_cmd_parse = TRUE;
  1200. X      set_option(OPT_PREPEND, setmode_value, set_val);
  1201. X    } else if (strncmp("font", cmd_str, 4) == 0) {
  1202. X      /* fonts */
  1203. X      did_cmd_parse = TRUE;
  1204. X      if (files_parsed > 0) {
  1205. X    if (cmd_line) {
  1206. X      fprintf(stderr, "Error, -font flag found after file argument\n");
  1207. X      exit(1);
  1208. X    }
  1209. X      } else {
  1210. X    switch (cmd_str[5]) {
  1211. X    case '1':
  1212. X    case 't':
  1213. X    case 'T':
  1214. X      /* title */
  1215. X      if ((cmd_str[6] != '\0') &&
  1216. X          (isalnum(cmd_str[7]) &&
  1217. X           (isalnum(cmd_str[8]) ||
  1218. X        (cmd_str[8] == '\0')))) {
  1219. X        ft_title[0] = cmd_str[7];
  1220. X        ft_title[1] = cmd_str[8];
  1221. X        ft_title[2] = '\0';
  1222. X      } else {
  1223. X        fprintf(stderr, "warning: improper font type in:\n");
  1224. X        fprintf(stderr, "   ==> %s\n", cmd_str);
  1225. X        goto prop_font;
  1226. X      }
  1227. X      break;
  1228. X    case '2':
  1229. X    case 'c':
  1230. X    case 'C':
  1231. X      /* comment */
  1232. X      if ((cmd_str[6] != '\0') &&
  1233. X          (isalnum(cmd_str[7]) &&
  1234. X           (isalnum(cmd_str[8]) ||
  1235. X        (cmd_str[8] == '\0')))) {
  1236. X        ft_comment[0] = cmd_str[7];
  1237. X        ft_comment[1] = cmd_str[8];
  1238. X        ft_comment[2] = '\0';
  1239. X      } else {
  1240. X        fprintf(stderr, "warning: improper font type in:\n");
  1241. X        fprintf(stderr, "   ==> %s\n", cmd_str);
  1242. X        goto prop_font;
  1243. X      }
  1244. X      break;
  1245. X    case '3':
  1246. X    case 'n':
  1247. X    case 'N':
  1248. X      /* function name */
  1249. X      if ((cmd_str[6] != '\0') &&
  1250. X          (isalnum(cmd_str[7]) &&
  1251. X           (isalnum(cmd_str[8]) ||
  1252. X        (cmd_str[8] == '\0')))) {
  1253. X        ft_name[0] = cmd_str[7];
  1254. X        ft_name[1] = cmd_str[8];
  1255. X        ft_name[2] = '\0';
  1256. X      } else {
  1257. X        fprintf(stderr, "warning: improper font type in:\n");
  1258. X        fprintf(stderr, "   ==> %s\n", cmd_str);
  1259. X        goto prop_font;
  1260. X      }
  1261. X      break;
  1262. X    case '4':
  1263. X    case 'p':
  1264. X    case 'P':
  1265. X      /* parameter font */
  1266. X      if ((cmd_str[6] != '\0') &&
  1267. X          (isalnum(cmd_str[7]) &&
  1268. X           (isalnum(cmd_str[8]) ||
  1269. X        (cmd_str[8] == '\0')))) {
  1270. X        ft_plist[0] = cmd_str[7];
  1271. X        ft_plist[1] = cmd_str[8];
  1272. X        ft_plist[2] = '\0';
  1273. X      } else {
  1274. X        fprintf(stderr, "warning: improper font type in:\n");
  1275. X        fprintf(stderr, "   ==> %s\n", cmd_str);
  1276. X        goto prop_font;
  1277. X      }
  1278. X      break;
  1279. X    default:
  1280. X      /* oops */
  1281. X      fprintf(stderr, "warning: font format invalid\n");
  1282. X    prop_font:
  1283. X      if (cmd_line) {
  1284. X        fprintf(stderr, "Proper format:  -font-%%-##\n");
  1285. X      } else {
  1286. X        fprintf(stderr, "Proper format:  font %% ##\n");
  1287. X      }
  1288. X      fprintf(stderr, "Where %% = one of:\n");
  1289. X      fprintf(stderr, "     '1' or 't'  - font for titles\n");
  1290. X      fprintf(stderr, "     '2' or 'c'  - comment font\n");
  1291. X      fprintf(stderr, "     '3' or 'n'  - function name font\n");
  1292. X      fprintf(stderr, "     '4' or 'p'  - parameter list font\n");
  1293. X      fprintf(stderr, "and ## is the one or two character roff font.\n");
  1294. X      break;
  1295. X    }
  1296. X      }
  1297. X    }
  1298. X    break;
  1299. X  case 'h':
  1300. X    /* header string */
  1301. X    if (count = minmatch_str(cmd_str, "header-string", 4)) {
  1302. X      did_cmd_parse = TRUE;
  1303. X      /* can only replace on the command line */
  1304. X      if ((header_string[0] != '\0') && !cmd_line) break;
  1305. X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1306. X    if ((cmd_str[count] == ':') ||
  1307. X        (cmd_str[count] == '=')) {
  1308. X      count++;
  1309. X      break;
  1310. X    }
  1311. X      }
  1312. X      strcpy(tmp_str, cmd_str + count);
  1313. X      trim_str(tmp_str);
  1314. X      if (strlen(tmp_str) > 0) {
  1315. X    strcpy(header_string, tmp_str);
  1316. X      } else {
  1317. X    cfg_err("warning: blank header-string command", cmd_line);
  1318. X      }
  1319. X    }
  1320. X    break;
  1321. X  case 'i':
  1322. X    /* include file */
  1323. X    if (count = minmatch_str(cmd_str, "include", 3)) {
  1324. X      did_cmd_parse = TRUE;
  1325. X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1326. X    if ((cmd_str[count] == ':') ||
  1327. X        (cmd_str[count] == '=')) {
  1328. X      count++;
  1329. X      break;
  1330. X    }
  1331. X      }
  1332. X      strcpy(tmp_str, cmd_str + count);
  1333. X      trim_str(tmp_str);
  1334. X      if (strlen(tmp_str) > 0) {
  1335. X    sprintf(cmd_str, "%s%s", INC_LEADER, tmp_str);
  1336. X    add_macro(setmode_value, cmd_str);
  1337. X      } else {
  1338. X    cfg_err("warning: blank include command", cmd_line);
  1339. X      }
  1340. X    }
  1341. X    break;
  1342. X  case 'm':
  1343. X    /* multiple comments */
  1344. X    if (minmatch_str(cmd_str, "multi-comments", 4) ||
  1345. X    minmatch_str(cmd_str, "multiple-comments", 4)) {
  1346. X      did_cmd_parse = TRUE;
  1347. X      set_option(OPT_SINGLECOMMENTS, setmode_value, (TRUE ^ set_val));
  1348. X    } else if (minmatch_str(cmd_str, "merge-output", 5)) {
  1349. X      did_cmd_parse = TRUE;
  1350. X      if (files_parsed > 0) {
  1351. X    if (cmd_line) {
  1352. X      fprintf(stderr,
  1353. X          "Error: merge-output flag found after file argument\n");
  1354. X      exit(1);
  1355. X    }
  1356. X      } else {
  1357. X    set_option(OPT_COMPACT, setmode_value, set_val);
  1358. X      }
  1359. X    }
  1360. X    break;
  1361. X  case 'o':
  1362. X    /* output file */
  1363. X    if (count = minmatch_str(cmd_str, "output-file", 3)) {
  1364. X      did_cmd_parse = TRUE;
  1365. X      if (files_parsed > 0) {
  1366. X    if (cmd_line) {
  1367. X      fprintf(stderr,
  1368. X          "Error: output-file flag found after file arguments\n");
  1369. X      exit(1);
  1370. X    }
  1371. X      } else {
  1372. X    for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1373. X      if ((cmd_str[count] == ':') ||
  1374. X          (cmd_str[count] == '=')) {
  1375. X        count++;
  1376. X        break;
  1377. X      }
  1378. X    }
  1379. X    strcpy(tmp_str, cmd_str + count);
  1380. X    trim_str(tmp_str);
  1381. X    if (strlen(tmp_str) > 0) {
  1382. X      if ((setmode_value % 2) == 0) {
  1383. X        strcpy(output_file[0], tmp_str);
  1384. X      }
  1385. X      if (setmode_value != 0) {
  1386. X        strcpy(output_file[1], tmp_str);
  1387. X      }
  1388. X      out_filenum = 2;
  1389. X    } else if (!cmd_line) {
  1390. X      cfg_err("warning, blank output-file specifier", cmd_line);
  1391. X    } else {
  1392. X      out_filenum = 1;
  1393. X    }
  1394. X      }
  1395. X    }
  1396. X    break;
  1397. X  case 'p':
  1398. X    /* prepend the file name to the output */
  1399. X    if (minmatch_str(cmd_str, "prepend-filename", 4)) {
  1400. X      did_cmd_parse = TRUE;
  1401. X      set_option(OPT_PREPEND, setmode_value, set_val);
  1402. X    }
  1403. X    break;
  1404. X  case 'r':
  1405. X    if (strncmp(cmd_str, "replace", 7) == 0) {
  1406. X
  1407. X      if (cmd_line) {
  1408. X    fprintf(stderr,
  1409. X        "Error, -replace is not a valid command line option\n");
  1410. X    exit(1);
  1411. X      }
  1412. X
  1413. X      /* check type */
  1414. X      if (strncmp("all ", cmd_str + 8, 4) == 0) {
  1415. X    len = 12;
  1416. X    count = SUBST_FULL; 
  1417. X      } else if (strncmp("type ", cmd_str + 8, 5) == 0) {
  1418. X    len = 13;
  1419. X    count = SUBST_TYPE;
  1420. X      } else if (strncmp("name ", cmd_str + 8, 5) == 0) {
  1421. X    len = 13;
  1422. X    count = SUBST_NAME;
  1423. X      } else if (strncmp("variable ", cmd_str + 8, 9) == 0) {
  1424. X    len = 17;
  1425. X    count = SUBST_NAME;
  1426. X      } else {
  1427. X    cfg_err("warning, bad replace format", cmd_line);
  1428. X    fprintf(stderr, "   ==> %s\n", cmd_str);
  1429. X    count = len = 0;
  1430. X    did_cmd_parse = TRUE;
  1431. X      }
  1432. X
  1433. X      /* do it */
  1434. X      if (did_cmd_parse == FALSE) {
  1435. X
  1436. X    did_cmd_parse = TRUE;
  1437. X    if ((set_val = copy_str(tmp_str, cmd_str + len)) == -1) {
  1438. X      cfg_err("warning, bad replace format", cmd_line);
  1439. X      fprintf(stderr, "   ==> %s\n", cmd_str);
  1440. X      break;
  1441. X    }
  1442. X    len += set_val;
  1443. X    if ((set_val = copy_str(t2_str, cmd_str + len)) == -1) {
  1444. X      cfg_err("warning, bad replace format", cmd_line);
  1445. X      fprintf(stderr, "   ==> %s\n", cmd_str);
  1446. X      break;
  1447. X    }
  1448. X
  1449. X    /* add substitution macro */
  1450. X    add_subst(count, setmode_value, tmp_str, t2_str);
  1451. X
  1452. X      }
  1453. X
  1454. X    } else if (minmatch_str(cmd_str, "read-config", 4)) {
  1455. X      if (cmd_line) {
  1456. X    fprintf(stderr, "The -read-config flag must be the first argument\n");
  1457. X    show_usage();
  1458. X      } else {
  1459. X    cfg_err("The -read-config command is not supported", cmd_line);
  1460. X    exit(1);
  1461. X      }
  1462. X    } else if (minmatch_str(cmd_str, "remove-names", 3)) {
  1463. X      /* remove variables? */
  1464. X      set_option(OPT_NONAMES, setmode_value, set_val);
  1465. X      did_cmd_parse = TRUE;
  1466. X    } else if (minmatch_str(cmd_str, "roff-mode", 4)) {
  1467. X
  1468. X      did_cmd_parse = TRUE;
  1469. X      if (files_parsed > 0) {
  1470. X    if (cmd_line) {
  1471. X      fprintf(stderr, "Error: -roff-mode found after file argument\n");
  1472. X      exit(1);
  1473. X    }
  1474. X      } else {
  1475. X    doc_extract = DOC_ROFF;
  1476. X      }
  1477. X
  1478. X    }
  1479. X    break;
  1480. X  case 's':
  1481. X    if ((count = minmatch_str(cmd_str, "statics", 4))) {
  1482. X
  1483. X      /* statics? */
  1484. X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1485. X    if ((cmd_str[count] == ':') ||
  1486. X        (cmd_str[count] == '=')) {
  1487. X      count++;
  1488. X      break;
  1489. X    }
  1490. X      }
  1491. X      strcpy(tmp_str, cmd_str + count);
  1492. X      trim_str(tmp_str);
  1493. X      if (strlen(tmp_str) > 0) {
  1494. X
  1495. X    /* which? */
  1496. X    switch(tmp_str[0]) {
  1497. X    case 'a':
  1498. X      /* all statics are allowed */
  1499. X      set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
  1500. X      did_cmd_parse = TRUE;
  1501. X      break;
  1502. X    case 'o':
  1503. X      /* only statics are allowed */
  1504. X      set_option(OPT_STATICMODE, setmode_value, ONLY_STATICS);
  1505. X      did_cmd_parse = TRUE;
  1506. X      break;
  1507. X    case 'n':
  1508. X      /* no statics are allowed */
  1509. X      set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
  1510. X      did_cmd_parse = TRUE;
  1511. X      break;
  1512. X    default:
  1513. X      /* not one that I know of */
  1514. X      break;
  1515. X    }
  1516. X
  1517. X      } else {
  1518. X
  1519. X    /* defaults */
  1520. X    if (set_val) {
  1521. X      set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
  1522. X    } else {
  1523. X      set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
  1524. X    }
  1525. X    did_cmd_parse = TRUE;
  1526. X
  1527. X      }
  1528. X
  1529. X    } else if (minmatch_str(cmd_str, "sort-all", 4)) {
  1530. X      /* sort? */
  1531. X      did_cmd_parse = TRUE;
  1532. X      if (set_val) {
  1533. X    set_option(OPT_SORTMODE, setmode_value, SORT_ALL);
  1534. X      } else {
  1535. X    set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
  1536. X      }
  1537. X    } else if (minmatch_str(cmd_str, "show-all", 4) ||
  1538. X           minmatch_str(cmd_str, "show-anyway", 4)) {
  1539. X      /* ANSI? */
  1540. X      set_option(OPT_SHOWANYWAY, setmode_value, set_val);
  1541. X      did_cmd_parse = TRUE;
  1542. X    } else if (minmatch_str(cmd_str, "settings", 3)) {
  1543. X      did_cmd_parse = TRUE;
  1544. X      if (cmd_line) {
  1545. X    show_settings();
  1546. X      } else {
  1547. X    cfg_err("warning, the -settings command is unsupported", cmd_line);
  1548. X      }
  1549. X    } else if (minmatch_str(cmd_str, "system-build", 6)) {
  1550. X      did_cmd_parse = TRUE;
  1551. X      if (cmd_line) {
  1552. X    build_rc(SYS_CONFIG);
  1553. X    exit(0);
  1554. X      } else {
  1555. X    cfg_err("warning, the -system-build command is unsupported", cmd_line);
  1556. X      }
  1557. X    } else if (minmatch_str(cmd_str, "sort-by-files", 6)) {
  1558. X      /* file sort? */
  1559. X      did_cmd_parse = TRUE;
  1560. X      if (global_opts[setmode_value == 1][OPT_SORTMODE] != SORT_ALL) {
  1561. X    if (set_val) {
  1562. X      set_option(OPT_SORTMODE, setmode_value, SORT_FILE);
  1563. X    } else {
  1564. X      set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
  1565. X    }
  1566. X      }
  1567. X    } else if (minmatch_str(cmd_str, "single-comments", 3)) {
  1568. X      /* !multiple comments? */
  1569. X      did_cmd_parse = TRUE;
  1570. X      set_option(OPT_SINGLECOMMENTS, setmode_value, set_val);
  1571. X    }
  1572. X    break;
  1573. X  case 't':
  1574. X    if (count = minmatch_str(cmd_str, "tab-width", 3)) {
  1575. X      int tab_width;
  1576. X      did_cmd_parse = TRUE;
  1577. X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1578. X    if ((cmd_str[count] == ':') ||
  1579. X        (cmd_str[count] == '=')) {
  1580. X      count++;
  1581. X      break;
  1582. X    }
  1583. X      }
  1584. X      strcpy(tmp_str, cmd_str + count);
  1585. X      trim_str(tmp_str);
  1586. X      if (sscanf(tmp_str, "%d", &tab_width) != 1) {
  1587. X    tab_width = 0;
  1588. X      }
  1589. X      set_option(OPT_TABWIDTH, setmode_value, tab_width);
  1590. X    } else if (minmatch_str(cmd_str, "troff-mode", 4)) {
  1591. X      did_cmd_parse = TRUE;
  1592. X      if (files_parsed > 0) {
  1593. X    if (cmd_line) {
  1594. X      fprintf(stderr, "Error: -troff-mode found after file argument\n");
  1595. X      exit(1);
  1596. X    }
  1597. X      } else {
  1598. X    doc_extract = DOC_ROFF;
  1599. X      }
  1600. X    }
  1601. X    break;
  1602. X  case 'u':
  1603. X    /* undefine macro */
  1604. X    if (count = minmatch_str(cmd_str, "undefine", 3)) {
  1605. X      did_cmd_parse = TRUE;
  1606. X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1607. X    if ((cmd_str[count] == ':') ||
  1608. X        (cmd_str[count] == '=')) {
  1609. X      count++;
  1610. X      break;
  1611. X    }
  1612. X      }
  1613. X      strcpy(tmp_str, cmd_str + count);
  1614. X      trim_str(tmp_str);
  1615. X      if (strlen(tmp_str) > 0) {
  1616. X    if (removed_macro(setmode_value, tmp_str) != TRUE) {
  1617. X      sprintf(cmd_str, "%s%s", UNDEF_LEADER, tmp_str);
  1618. X      add_macro(setmode_value, cmd_str);
  1619. X    }
  1620. X      } else {
  1621. X    cfg_err("warning: blank undefine", cmd_line);
  1622. X      }
  1623. X    }
  1624. X    break;
  1625. X  case 'v':
  1626. X    if (minmatch_str(cmd_str, "version-info", 3)) {
  1627. X      did_cmd_parse = TRUE;
  1628. X      if (cmd_line) {
  1629. X    show_version();
  1630. X    exit(0);
  1631. X      } else {
  1632. X    cfg_err("warning, the -version-info command is unsupported", cmd_line);
  1633. X      }
  1634. X    }
  1635. X    break;
  1636. X  case 'w':
  1637. X    /* wrapping */
  1638. X    if (count = minmatch_str(cmd_str, "wrap-parameters", 4)) {
  1639. X      did_cmd_parse = TRUE;
  1640. X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1641. X    if ((cmd_str[count] == ':') ||
  1642. X        (cmd_str[count] == '=')) {
  1643. X      count++;
  1644. X      break;
  1645. X    }
  1646. X      }
  1647. X      strcpy(tmp_str, cmd_str + count);
  1648. X      trim_str(tmp_str);
  1649. X      count = 0;
  1650. X      if (isdigit(tmp_str[count])) {
  1651. X    /* use given */
  1652. X    int wrap_point = 0;
  1653. X    for (; isdigit(tmp_str[count]); count++) {
  1654. X      wrap_point *= 10;
  1655. X      wrap_point += (tmp_str[count] - '0');
  1656. X    }
  1657. X    count--;
  1658. X    set_option(OPT_WRAPPOINT, setmode_value, wrap_point);
  1659. X      } else if (set_val) {
  1660. X    /* default */
  1661. X    set_option(OPT_WRAPPOINT, setmode_value, 72);
  1662. X      } else {
  1663. X    /* off */
  1664. X    set_option(OPT_WRAPPOINT, setmode_value, 0);
  1665. X      }
  1666. X    }
  1667. X    break;
  1668. X  case 'y':
  1669. X    /* get comments */
  1670. X    if (minmatch_str(cmd_str, "yank-comments", 4)) {
  1671. X      did_cmd_parse = TRUE;
  1672. X      set_option(OPT_COMMENTS, setmode_value, set_val);
  1673. X    }
  1674. X    break;
  1675. X  default:
  1676. X    /* huh? */
  1677. X    break;
  1678. X  }
  1679. X
  1680. X  /* find it? */
  1681. X  if (did_cmd_parse == FALSE) {
  1682. X#ifndef VMS
  1683. X    if (!cmd_line || (had_start == TRUE)) {
  1684. X#endif /* VMS */
  1685. X      cfg_err("unknown option encountered", cmd_line);
  1686. X      fprintf(stderr, "   ==> %s\n", cmd_str);
  1687. X      exit(1);
  1688. X#ifndef VMS
  1689. X    } else {
  1690. X      singlechar_cmds(cmd_str, set_val);
  1691. X    }
  1692. X#endif /* VMS */
  1693. X  }
  1694. X}
  1695. X
  1696. X/* function to parse the configuration file */
  1697. Xvoid
  1698. Xparse_config (conf_fname)
  1699. X  char *conf_fname;
  1700. X{
  1701. X  char conf_data[MID_SIZE], tmp_fname[FNAME_SIZE];
  1702. X  FILE *conf_fp;
  1703. X
  1704. X  /* check input */
  1705. X  if ((conf_fp = fopen(conf_fname, "r")) == NULL) return;
  1706. X  strcpy(tmp_fname, cur_cfg_file);
  1707. X  strcpy(cur_cfg_file, conf_fname);
  1708. X
  1709. X  /* read it all */
  1710. X  while (!feof(conf_fp)) {
  1711. X
  1712. X    /* get a line */
  1713. X    conf_data[0] = '\0';
  1714. X    if (fgets(conf_data, MID_SIZE, conf_fp) != NULL) {
  1715. X      /* parse it */
  1716. X      parse_cmd(conf_data, TRUE, FALSE);
  1717. X    }
  1718. X
  1719. X  }
  1720. X
  1721. X  /* done */
  1722. X  fclose(conf_fp);
  1723. X  strcpy(cur_cfg_file, tmp_fname);
  1724. X}
  1725. X
  1726. X/* send a system error message */
  1727. Xvoid
  1728. Xerr_msg(estr)
  1729. X  char *estr;
  1730. X{
  1731. X#ifdef NO_PERROR
  1732. X  fprintf(stderr, "%s: %s\n", prog_name, estr);
  1733. X#else
  1734. X  fprintf(stderr, "%s\n", estr);
  1735. X  perror(prog_name);
  1736. X#endif /* NO_PERROR */
  1737. X}
  1738. X
  1739. X/* send a message that their was a syntax error */
  1740. Xvoid
  1741. Xsyntax_err(estr)
  1742. X  char *estr;
  1743. X{
  1744. X  /* use messages similar to gcc error messages */
  1745. X  fprintf(stderr, "%s:%d: %s\n", errout_filename, line_count, estr);
  1746. X}
  1747. X
  1748. X/* routine to check return value of fputs */
  1749. Xvoid
  1750. Xfput_string (outstr, filep)
  1751. X  char *outstr;
  1752. X  FILE *filep;
  1753. X{
  1754. X  /* check the output of fputs */
  1755. X  if (fputs(outstr, filep) == EOF) {
  1756. X    err_msg("unable to write to file");
  1757. X    exit(1);
  1758. X  }
  1759. X}
  1760. X
  1761. X/* quickie function to distinquish proper switches */
  1762. Xint
  1763. Xis_switch (ch)
  1764. X  int ch;
  1765. X{
  1766. X  if (ch == '-') return(TRUE);
  1767. X  if (ch == '+') return(TRUE);
  1768. X#ifdef VMS
  1769. X  if (ch == '/') return(TRUE);
  1770. X#endif /* VMS */
  1771. X  return(FALSE);
  1772. X}
  1773. X
  1774. X/* call the external routine out_char() and send out all characters */
  1775. Xvoid
  1776. Xout_str(omode, str)
  1777. X  int omode;
  1778. X  char *str;
  1779. X{
  1780. X  /* simple function */
  1781. X  if (str != NULL) {
  1782. X    while (*str != '\0') {
  1783. X      out_char(omode, *str);
  1784. X      str++;
  1785. X    }
  1786. X  }
  1787. X}
  1788. X
  1789. X/* output given function prototype */
  1790. Xvoid
  1791. Xout_proto(omode, f_ptr, mode, do_comments)
  1792. X  int omode;
  1793. X  P_PROTO f_ptr;
  1794. X  int mode, do_comments;
  1795. X{
  1796. X  char *ch_out, tempstr[MID_SIZE];
  1797. X  int did_leader = FALSE;
  1798. X  int outch_cnt = 0, leader_cnt;
  1799. X  int wrap_point = get_option(OPT_WRAPPOINT);
  1800. X
  1801. X  /* stupidity? */
  1802. X  if (f_ptr == NULL) return;
  1803. X
  1804. X  /* initial comment output */
  1805. X  if (get_option(OPT_FIRSTCOMMENT) &&
  1806. X      (start_comment[0] != '\0')) {
  1807. X
  1808. X    /* first comment? */
  1809. X    strcpy(tempstr, "/*");
  1810. X    if (get_option(OPT_PREPEND)) {
  1811. X      strcat(tempstr, " ");
  1812. X      strcat(tempstr, file_name);
  1813. X      strcat(tempstr, ":");
  1814. X    }
  1815. X    send_first_comment(tempstr);
  1816. X    did_leader = TRUE;
  1817. X    start_comment[0] = '\0';
  1818. X  }
  1819. X
  1820. X  /* preamble? */
  1821. X  if (doc_extract != DOC_NONE) {
  1822. X    if (dont_space == FALSE) {
  1823. X      if (doc_extract != DOC_ROFF) {
  1824. X    out_char(omode, '\n');
  1825. X    out_char(omode, '\n');
  1826. X      } else {
  1827. X    out_str(omode, ".sp 2\n");
  1828. X      }
  1829. X    } else if (doc_extract == DOC_ROFF) {
  1830. X      init_roff(omode);
  1831. X    }
  1832. X    dont_space = FALSE;
  1833. X    if (doc_extract != DOC_ROFF) {
  1834. X      out_str(omode, "Function: ");
  1835. X      out_str(omode, f_ptr->name);
  1836. X      out_str(omode, "\nFile:     ");
  1837. X    } else {
  1838. X      if (start_block == FALSE) {
  1839. X    out_str(omode, ".KS\n");
  1840. X      } else {
  1841. X    start_block = FALSE;
  1842. X      }
  1843. X      out_str(omode, ".nf\n");
  1844. X      out_str(omode, "\\f1Function: \\f3");
  1845. X      out_str(omode, f_ptr->name);
  1846. X      out_str(omode, "\n\\f1File:     \\f3");
  1847. X    }
  1848. X    out_str(omode, f_ptr->fname);
  1849. X    out_char(omode, '\n');
  1850. X  }
  1851. X
  1852. X  /* preceeding comment? */
  1853. X  if (do_comments) {
  1854. X    if (doc_extract != DOC_ROFF) {
  1855. X      out_char(omode, '\n');
  1856. X      if (f_ptr->comment != NULL) {
  1857. X    out_str(omode, f_ptr->comment);
  1858. X    out_char(omode, '\n');
  1859. X      }
  1860. X    } else {
  1861. X      out_str(omode, ".sp\n\\f2");
  1862. X      out_str(omode, f_ptr->comment);
  1863. X      out_char(omode, '\n');
  1864. X    }
  1865. X  } else if ((doc_extract != DOC_NONE) ||
  1866. X         (total_out == 0) ||
  1867. X         did_leader) {
  1868. X    if (doc_extract != DOC_ROFF) {
  1869. X      out_char(omode, '\n');
  1870. X    } else {
  1871. X      out_str(omode, ".sp\n");
  1872. X    }
  1873. X  }
  1874. X
  1875. X  /* fill mode for troff? */
  1876. X  if (doc_extract == DOC_ROFF) {
  1877. X    out_str(omode, ".fi\n");
  1878. X    out_str(omode, ".in +0.5i\n");
  1879. X    out_str(omode, ".ti -0.5i\n");
  1880. X  }
  1881. X
  1882. X  /* show the full function name and type */
  1883. X  if (doc_extract == DOC_ROFF) {
  1884. X    out_str(omode, "\\f3");
  1885. X    out_str(omode, f_ptr->ftype);
  1886. X    out_str(omode, " ( \\c\n\\f4");
  1887. X  } else {
  1888. X    if (get_option(OPT_TYPEWRAP)) {
  1889. X      char *second_half;
  1890. X
  1891. X      /* split at function name */
  1892. X      if (second_half = strstr(f_ptr->ftype, f_ptr->name)) {
  1893. X    outch_cnt = strlen(second_half);
  1894. X    for (ch_out = f_ptr->ftype;
  1895. X         (ch_out != second_half) &&
  1896. X         ((*ch_out != ' ') ||
  1897. X          (ch_out != second_half - 1));
  1898. X         ch_out++) {
  1899. X      out_char(omode, *ch_out);
  1900. X    }
  1901. X    out_char(omode, '\n');
  1902. X    out_str(omode, second_half);
  1903. X      } else {
  1904. X    /* normal output */
  1905. X    outch_cnt = strlen(f_ptr->ftype);
  1906. X    out_str(omode, f_ptr->ftype);
  1907. X      }
  1908. X    } else {
  1909. X      /* normal output */
  1910. X      outch_cnt = strlen(f_ptr->ftype);
  1911. X      out_str(omode, f_ptr->ftype);
  1912. X    }
  1913. X    if (get_option(OPT_COMPACT)) {
  1914. X      out_str(omode, " PL_((");
  1915. X      outch_cnt += 6;
  1916. X    } else {
  1917. X      out_str(omode, " (");
  1918. X      outch_cnt += 2;
  1919. X    }
  1920. X  }
  1921. X  leader_cnt = outch_cnt + 1;
  1922. X  
  1923. X  if (mode != MODE_OLDC) {
  1924. X
  1925. X    /* begin comment? */
  1926. X    if (mode == MODE_COMMENT) {
  1927. X      out_str(omode, "/*");
  1928. X      outch_cnt += 2;
  1929. X    }
  1930. X
  1931. X    /* prototype list */
  1932. X    if (doc_extract == DOC_ROFF) {
  1933. X
  1934. X      /* break at each variable */
  1935. X      for (ch_out = f_ptr->plist;
  1936. X       *ch_out != '\0';
  1937. X       ch_out++) {
  1938. X
  1939. X    /* send out list; breaking for ','s */
  1940. X    out_char(omode, *ch_out);
  1941. X    if (*ch_out == ',') {
  1942. X      out_str(omode, "\\c\n");
  1943. X    }
  1944. X      }
  1945. X
  1946. X    } else if ((wrap_point > 0) &&
  1947. X           (f_ptr->plist != NULL) &&
  1948. X           (f_ptr->plist[0] != '\0') &&
  1949. X           (strlen(f_ptr->plist) + outch_cnt > wrap_point - 1)) {
  1950. X      char *next_space;
  1951. X
  1952. X      /* break at appropriate positions */
  1953. X      ch_out = f_ptr->plist;
  1954. X      next_space = index(f_ptr->plist, ' ');
  1955. X      do {
  1956. X
  1957. X    /* check for break point */
  1958. X    if (next_space == NULL) {
  1959. X
  1960. X      /* wrap point within reach? */
  1961. X      if (strlen(ch_out) + outch_cnt > wrap_point) {
  1962. X        out_char(omode, '\n');
  1963. X        for (outch_cnt = 0;
  1964. X         outch_cnt < leader_cnt - 1;
  1965. X         outch_cnt++) {
  1966. X          out_char(omode, ' ');
  1967. X        }
  1968. X      }
  1969. X      out_char(omode, ' ');
  1970. X      out_str(omode, ch_out);
  1971. X      ch_out = NULL;
  1972. X
  1973. X    } else {
  1974. X
  1975. X      /* wrap point within reach? */
  1976. X      if (next_space - ch_out + outch_cnt > wrap_point) {
  1977. X        out_char(omode, '\n');
  1978. X        for (outch_cnt = 0;
  1979. X         outch_cnt < leader_cnt;
  1980. X         outch_cnt++) {
  1981. X          out_char(omode, ' ');
  1982. X        }
  1983. X      } else {
  1984. X        out_char(omode, ' ');
  1985. X        outch_cnt++;
  1986. X      }
  1987. X      for (; ch_out < next_space; ch_out++) {
  1988. X        out_char(omode, *ch_out);
  1989. X        outch_cnt++;
  1990. X      }
  1991. X      ch_out = next_space + 1;
  1992. X
  1993. X      /* determine the next space location */
  1994. X      next_space = index(next_space + 1, ' ');
  1995. X
  1996. X    }
  1997. X
  1998. X      } while (ch_out != NULL);
  1999. X      out_char(omode, ' ');
  2000. X
  2001. X    } else {
  2002. X
  2003. X      /* send out parameter list */
  2004. X      out_char(omode, ' ');
  2005. X      out_str(omode, f_ptr->plist);
  2006. X      if ((f_ptr->plist) &&
  2007. X      (f_ptr->plist[0] != '\0')) {
  2008. X    out_char(omode, ' ');
  2009. X      }
  2010. X
  2011. X    }
  2012. X
  2013. X    /* end comments? */
  2014. X    if (mode == MODE_COMMENT) {
  2015. X      out_str(omode, "*/");
  2016. X    }
  2017. X
  2018. X  }
  2019. X
  2020. X  /* close up */
  2021. X  if (doc_extract == DOC_ROFF) {
  2022. X    out_str(omode, "\\f3 );\n");
  2023. X  } else {
  2024. X    if (get_option(OPT_COMPACT)) {
  2025. X      out_char(omode, ')');
  2026. X    }
  2027. X    out_str(omode, ");\n");
  2028. X  }
  2029. X
  2030. X  /* turn off fill for troff */
  2031. X  if (doc_extract == DOC_ROFF) {
  2032. X    out_str(omode, ".nf\n");
  2033. X    out_str(omode, ".in -0.5i\n");
  2034. X    out_str(omode, ".KE\n");
  2035. X  }
  2036. X}
  2037. X
  2038. X/* set home config file path indicating success */
  2039. Xstatic int
  2040. Xset_home_config()
  2041. X{
  2042. X#ifndef VAXC
  2043. X  struct passwd *pwtemp = NULL;
  2044. X#endif /* VAXC */
  2045. X  char home_file[MID_SIZE];
  2046. X
  2047. X  if (getenv("HOME") != NULL) {
  2048. X    strcpy(home_file, (char *)getenv("HOME"));
  2049. X#ifndef VAXC
  2050. X  } else if ((pwtemp = getpwuid(getuid())) != NULL) {
  2051. X    strcpy(home_file, pwtemp->pw_dir);
  2052. X#endif /* VAXC */
  2053. X  } else {
  2054. X#ifdef VMS
  2055. X    strcpy(home_file, "sys$login:");
  2056. X#else
  2057. X    /* oops */
  2058. X    return(FALSE);
  2059. X#endif /* VMS */
  2060. X  }
  2061. X
  2062. X  /* build the file */
  2063. X  strcat(home_file, DIR_SEPARATOR);
  2064. X  strcat(home_file, CONFIG_FILE);
  2065. X
  2066. X  /* record it */
  2067. X  strcpy(tmp_str, home_file);
  2068. X  return(TRUE);
  2069. X}
  2070. X
  2071. X/* Create test file for varargs and FILE test */
  2072. Xstatic int
  2073. Xbld_testfile(fname)
  2074. X  char *fname;
  2075. X{
  2076. X  FILE *fp;
  2077. X
  2078. X  if ((fp = fopen(fname, "w")) == NULL) {
  2079. X    sprintf(tmp_str, "Error opening varargs test file <%s>", fname);
  2080. X    err_msg(tmp_str);
  2081. X    return(TRUE);
  2082. X  }
  2083. X  fput_string("#include <stdio.h>\n", fp);
  2084. X  fput_string("#include <varargs.h>\n", fp);
  2085. X  fput_string("int function1(va_alist)\nva_dcl\n", fp);
  2086. X  fput_string("{ /* empty function */ }\n", fp);
  2087. X  fput_string("int function2(fstrct)\nFILE fstrct;\n", fp);
  2088. X  fput_string("{ /* empty function */ }\n", fp);
  2089. X  if (fclose(fp) == EOF) {
  2090. X    sprintf(tmp_str, "Error closing varargs test file <%s>", fname);
  2091. X    err_msg(tmp_str);
  2092. X    return(TRUE);
  2093. X  }
  2094. X  return(FALSE);
  2095. X}
  2096. X
  2097. X/* search for expanded value of the varargs setup */
  2098. Xint
  2099. Xvargs_find ()
  2100. X{
  2101. X  char sys_cmd[MID_SIZE], tmpfname[MID_SIZE];
  2102. X  char t_instr[MID_SIZE], t_outstr[MID_SIZE];
  2103. X  int hold = FALSE, type_select = 0;
  2104. X  extern int dont_stop;
  2105. X
  2106. X  /* build temp file name */
  2107. X  sprintf(tmpfname, TMPFILE_FMT, getpid());
  2108. X
  2109. X  /* generate it */
  2110. X  if (bld_testfile(tmpfname)) {
  2111. X    return(TRUE);
  2112. X  }
  2113. X
  2114. X  /* launch a CPP process */
  2115. X  sprintf(sys_cmd, "%s %s", cpp_prog, tmpfname);
  2116. X  if ((fpin = open_input(sys_cmd, "r")) == NULL) {
  2117. X    sprintf(tmp_str, "unable to open CPP \"pipe\" to file <%s>",
  2118. X       tmpfname);
  2119. X    err_msg(tmp_str);
  2120. X    return(TRUE);
  2121. X  }
  2122. X
  2123. X  /* now parse it */
  2124. X  dont_stop = TRUE;
  2125. X  parse_file();
  2126. X  dont_stop = FALSE;
  2127. X  close_input(fpin);
  2128. X  unlink(tmpfname);
  2129. X  fpin = NULL;
  2130. X
  2131. X  /* retrieve the info */
  2132. X  while (proto_list != NULL) {
  2133. X
  2134. X    /* get proper function */
  2135. X    if (strcmp(proto_list->name, "function1") == 0) {
  2136. X      /* varargs */
  2137. X      if (strcmp(proto_list->plist, "...") == 0) goto skip_it;
  2138. X      strcpy(t_instr, proto_list->plist);
  2139. X      strcpy(t_outstr, "...");
  2140. X      type_select = SUBST_FULL;
  2141. X    } else if (strcmp(proto_list->name, "function2") == 0) {
  2142. X      /* FILE structure */
  2143. X      for (type_select = strlen(proto_list->plist) - 1;
  2144. X       type_select > 0;
  2145. X       type_select--) {
  2146. X    if (proto_list->plist[type_select] == ' ') {
  2147. X      proto_list->plist[type_select] = '\0';
  2148. X      break;
  2149. X    }
  2150. X      }
  2151. X      if (strcmp(proto_list->plist, "FILE") == 0) goto skip_it;
  2152. X      strcpy(t_instr, proto_list->plist);
  2153. X      strcpy(t_outstr, "FILE");
  2154. X      type_select = SUBST_TYPE;
  2155. X    } else {
  2156. X      /* huh? */
  2157. X      fprintf(stderr,
  2158. X          "Warning: unable to locate the FILE and varargs replacements\n");
  2159. X      hold = TRUE;
  2160. X      goto skip_it;
  2161. X    }
  2162. X
  2163. X    /* copy the information */
  2164. X    add_subst(type_select, 2, t_instr, t_outstr);
  2165. X
  2166. X  skip_it:
  2167. X    /* clean up */
  2168. X    pop_proto();
  2169. X  }
  2170. X
  2171. X  /* get out */
  2172. X  return(hold);
  2173. X}
  2174. X
  2175. X/* read in all configuration files */
  2176. Xvoid
  2177. Xdo_config ()
  2178. X{
  2179. X  /* system configuration file */
  2180. X  if (cfg_switch & 1) {
  2181. X    parse_config(SYS_CONFIG);
  2182. X  }
  2183. X
  2184. X  /* personal configuration file */
  2185. X  if (cfg_switch & 2) {
  2186. X    if (set_home_config()) {
  2187. X      parse_config(tmp_str);
  2188. X    }
  2189. X  }
  2190. X
  2191. X  /* current directory */
  2192. X  if (cfg_switch & 4) {
  2193. X    parse_config(CONFIG_FILE);
  2194. X  }
  2195. X
  2196. X  /* random config file */
  2197. X  if (cfg_file[0] != '\0') {
  2198. X    parse_config(cfg_file);
  2199. X  }
  2200. X}
  2201. X
  2202. X/* return pointer to string containing the date */
  2203. Xchar *
  2204. Xmach_time ()
  2205. X{
  2206. X  long timeval;
  2207. X
  2208. X  timeval = time(0);
  2209. X  return(ctime(&timeval));
  2210. X}
  2211. X
  2212. X#ifdef NO_POPEN
  2213. X/* strings for faking a popen call */
  2214. Xchar newcommand[FNAME_SIZE];
  2215. Xchar pipetmpfile[FNAME_SIZE];
  2216. X#endif /* NO_POPEN */
  2217. X
  2218. X/* function to open a "pipe" to the input */
  2219. XFILE *
  2220. Xopen_input (pname, modestr)
  2221. X  char *pname, *modestr;
  2222. X{
  2223. X#ifdef NO_POPEN
  2224. X  static int tmpnameset = FALSE;
  2225. X
  2226. X  /* build file name */
  2227. X  if (tmpnameset == FALSE) {
  2228. X    sprintf(pipetmpfile, PIPETMP_FMT, getpid());
  2229. X    tmpnameset = TRUE;
  2230. X  }
  2231. X
  2232. X  /* this "popen()" hack is only useful for reading from the "pipe" */
  2233. X  sprintf(newcommand, PIPEOUT_FMT, pname, pipetmpfile);
  2234. X  if (system(newcommand) == SYSCMD_FAILED) {
  2235. X    return((FILE *) NULL);
  2236. X  }
  2237. X  return(fopen(pipetmpfile, modestr));
  2238. X#else
  2239. X  return(popen(pname, modestr));
  2240. X#endif /* NO_POPEN */
  2241. X}
  2242. X
  2243. X/* close up the "pipe" */
  2244. Xint
  2245. Xclose_input (stream)
  2246. X  FILE *stream;
  2247. X{
  2248. X#ifdef NO_POPEN
  2249. X  if (fclose(stream) == EOF) return(-1);
  2250. X  return(unlink(pipetmpfile));
  2251. X#else
  2252. X  return(pclose(stream));
  2253. X#endif /* NO_POPEN */
  2254. X}
  2255. END_OF_FILE
  2256. if test 54108 -ne `wc -c <'io.c'`; then
  2257.     echo shar: \"'io.c'\" unpacked with wrong size!
  2258. fi
  2259. # end of 'io.c'
  2260. fi
  2261. echo shar: End of archive 4 \(of 5\).
  2262. cp /dev/null ark4isdone
  2263. MISSING=""
  2264. for I in 1 2 3 4 5 ; do
  2265.     if test ! -f ark${I}isdone ; then
  2266.     MISSING="${MISSING} ${I}"
  2267.     fi
  2268. done
  2269. if test "${MISSING}" = "" ; then
  2270.     echo You have unpacked all 5 archives.
  2271.     rm -f ark[1-9]isdone
  2272. else
  2273.     echo You still need to unpack the following archives:
  2274.     echo "        " ${MISSING}
  2275. fi
  2276. ##  End of shell archive.
  2277. exit 0
  2278.  
  2279. exit 0 # Just in case...
  2280.