chm2dcf.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. CHM2DCF - converter for HHC and HHK files used by the Microsoft CHM compiler
  3. to a QT Assistant DCF file
  4. Copyright (C) 2003-2004 Kevin Kofler
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software Foundation,
  15. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  16. */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #define fatal(s) ({fprintf(stderr,"Error: %s\n",s);exit(1);})
  21. int main(void)
  22. {
  23. FILE *hhc,*hhk,*dcf;
  24. char buffer[32768];
  25. char **handledrefs=0;
  26. int handledrefc=0;
  27. int i;
  28. const char *close="";
  29. hhc=fopen("Contents.hhc","rt");
  30. if (!hhc) fatal("Failed to open Contents.hhc.");
  31. hhk=fopen("Index.hhk","rt");
  32. if (!hhk) {fclose(hhc);fatal("Failed to open Index.hhk.");}
  33. dcf=fopen("qt-assistant.dcf","wt");
  34. if (!dcf) {fclose(hhc);fclose(hhk);fatal("Failed to open qt-assistant.dcf.");}
  35. fputs("<!DOCTYPE DCF>\n<DCF ref=\"index.html\" category=\"development\" "
  36. "title=\"TIGCC Documentation\">\n",dcf);
  37. for (i=0;i<12;i++) fgets(buffer,32768,hhc); // skip 11 junk lines, read 12th
  38. // line
  39. while (buffer[strlen(buffer)-1]=='\r'||buffer[strlen(buffer)-1]=='\n')
  40. buffer[strlen(buffer)-1]=0; // drop line ending characters
  41. while (strcmp(buffer,"</BODY>")) {
  42. if (!strcmp(buffer,"<LI> <OBJECT TYPE=\"TEXT/SITEMAP\">")) {
  43. char title[32768],ref[32768];
  44. fgets(buffer,32768,hhc); // get title
  45. while (buffer[strlen(buffer)-1]=='\r'||buffer[strlen(buffer)-1]=='\n')
  46. buffer[strlen(buffer)-1]=0; // drop line ending characters
  47. if (strncmp(buffer,"<PARAM NAME=\"Name\" VALUE=\"",26)) goto junk;
  48. strcpy(title,buffer+26);
  49. if (strlen(title)<2||title[strlen(title)-1]!='>'
  50. ||title[strlen(title)-2]!='\"') {
  51. printf("Invalid title: %s\n",title);
  52. goto junk;
  53. }
  54. title[strlen(title)-2]=0;
  55. fgets(buffer,32768,hhc); // get ref
  56. while (buffer[strlen(buffer)-1]=='\r'||buffer[strlen(buffer)-1]=='\n')
  57. buffer[strlen(buffer)-1]=0; // drop line ending characters
  58. if (!strcmp(buffer,"</OBJECT>")) {
  59. fprintf(dcf,"%s<section ref=\"index.html\" title=\"%s\"",close,title);
  60. close="/>\n";
  61. } else {
  62. char keywordref[32768];
  63. int lineno;
  64. if (strncmp(buffer,"<PARAM NAME=\"Local\" VALUE=\"",27)) goto junk;
  65. strcpy(ref,buffer+27);
  66. if (strlen(ref)<2||ref[strlen(ref)-1]!='>'
  67. ||ref[strlen(ref)-2]!='\"') {
  68. printf("Invalid ref: %s\n",ref);
  69. goto junk;
  70. }
  71. ref[strlen(ref)-2]=0;
  72. fgets(buffer,32768,hhc); // drop junk line
  73. fprintf(dcf,"%s<section ref=\"%s\" title=\"%s\"",close,ref,title);
  74. close="/>\n";
  75. // skip keyword handling if we already had this URL
  76. for (i=0;i<handledrefc;i++)
  77. if (!strcmp(ref,handledrefs[i])) goto skipkwd;
  78. // record this URL
  79. handledrefs=realloc(handledrefs,(++handledrefc)*sizeof(char *));
  80. handledrefs[handledrefc-1]=strdup(ref);
  81. sprintf(keywordref,"<PARAM NAME=\"Local\" VALUE=\"%s",ref);
  82. lineno=0;
  83. fseek(hhk,0,SEEK_SET);
  84. do {
  85. char kwdref[32768],kwd[32768],fullkwd[32768];
  86. int ullevel=0;
  87. while(1) { // search for any keywords for this section
  88. int tempullevel;
  89. lineno++;
  90. fgets(buffer,32768,hhk);
  91. if (feof(hhk)) {lineno=0;break;}
  92. if (!strncmp(buffer,"<UL>",4)) {ullevel++;continue;}
  93. if (!strncmp(buffer,"</UL>",5)) {ullevel--;continue;}
  94. while (buffer[strlen(buffer)-1]=='\r'||buffer[strlen(buffer)-1]=='\n')
  95. buffer[strlen(buffer)-1]=0; // drop line ending characters
  96. if (!strncmp(buffer,keywordref,strlen(keywordref))) { // keyword found
  97. int goback=0;
  98. strcpy(kwdref,buffer+27);
  99. if (strlen(kwdref)<2||kwdref[strlen(kwdref)-1]!='>'
  100. ||kwdref[strlen(kwdref)-2]!='\"') {
  101. printf("Invalid keyword ref: %s\n",kwdref);
  102. kwdjunk:
  103. fclose(hhc);
  104. fclose(hhk);
  105. fclose(dcf);
  106. printf("Invalid line: %s\n",buffer);
  107. fatal("Junk line in Index.hhk.");
  108. }
  109. kwdref[strlen(kwdref)-2]=0;
  110. *fullkwd=0;
  111. tempullevel=ullevel;
  112. up2lines:
  113. fseek(hhk,0,SEEK_SET); // search 2 lines higher for the title
  114. goback+=2;
  115. for (i=0;i<lineno-goback;i++) fgets(buffer,32768,hhk);
  116. while (buffer[strlen(buffer)-1]=='\r'||buffer[strlen(buffer)-1]=='\n')
  117. buffer[strlen(buffer)-1]=0; // drop line ending characters
  118. if (!strncmp(buffer,"<PARAM NAME=\"Local\" VALUE=\"",27)) goto up2lines;
  119. if (strncmp(buffer,"<PARAM NAME=\"Name\" VALUE=\"",26)) goto kwdjunk;
  120. strcpy(kwd,buffer+26);
  121. if (strlen(kwd)<2||kwd[strlen(kwd)-1]!='>'
  122. ||kwd[strlen(kwd)-2]!='\"') {
  123. printf("Invalid keyword: %s\n",kwd);
  124. goto kwdjunk;
  125. }
  126. kwd[strlen(kwd)-2]=0;
  127. if (*fullkwd) {
  128. memmove(fullkwd+strlen(kwd)+2,fullkwd,strlen(fullkwd)+1);
  129. strncpy(fullkwd,kwd,strlen(kwd));
  130. fullkwd[strlen(kwd)]=',';fullkwd[strlen(kwd)+1]=' ';
  131. } else strcpy(fullkwd,kwd);
  132. if (tempullevel>=2) {
  133. // This is actually just a disambiguator, so we need to go up for the actual
  134. // keyword.
  135. fseek(hhk,0,SEEK_SET); // search 2 lines higher for <UL>
  136. goback+=2;
  137. for (i=0;i<lineno-goback;i++) fgets(buffer,32768,hhk);
  138. if (!strncmp(buffer,"<UL>",4)) {goback+=2; tempullevel--; goto up2lines;}
  139. while (1) { // We know there is an <UL> somewhere, so keep looking.
  140. fseek(hhk,0,SEEK_SET); // search 5 lines higher for <UL>
  141. goback+=5;
  142. for (i=0;i<lineno-goback;i++) fgets(buffer,32768,hhk);
  143. if (!strncmp(buffer,"<UL>",4)) {goback+=2; tempullevel--; goto up2lines;}
  144. }
  145. }
  146. if (!strcmp(close,"/>\n")) fputs(">\n",dcf);
  147. fprintf(dcf,"<keyword ref=\"%s\">%s</keyword>\n",kwdref,fullkwd);
  148. close="</section>\n";
  149. for (i=0;i<goback;i++) fgets(buffer,32768,hhk); // go back to the original line
  150. }
  151. }
  152. } while (lineno);
  153. skipkwd:;
  154. }
  155. } else if (!strcmp(buffer,"<UL>")) {
  156. if (!strcmp(close,"</section>\n")) close=""; else close=">\n";
  157. } else if (!strcmp(buffer,"</UL>")) {
  158. fprintf(dcf,"%s",close);
  159. close="</section>\n";
  160. } else {
  161. junk:
  162. fclose(hhc);
  163. fclose(hhk);
  164. fclose(dcf);
  165. printf("Invalid line: %s\n",buffer);
  166. fatal("Junk line in Contents.hhc.");
  167. }
  168. fgets(buffer,32768,hhc); // read next line
  169. while (buffer[strlen(buffer)-1]=='\r'||buffer[strlen(buffer)-1]=='\n')
  170. buffer[strlen(buffer)-1]=0; // drop line ending characters
  171. }
  172. fputs("</DCF>\n",dcf);
  173. fclose(hhc);
  174. fclose(hhk);
  175. fclose(dcf);
  176. return 0;
  177. }