txt2hlp.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 1996 Greg Janson
  5. * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. //Custom fgetc function to dump \r's and replace \xFF's and /x1's.
  26. int fgetc2(FILE *fp) {
  27. int t1=fgetc(fp);
  28. if(t1=='\r') return fgetc2(fp);
  29. if(t1==255) return 32;
  30. if(t1==1) return 2;
  31. return t1;
  32. }
  33. #define fgetc(f) fgetc2(f)
  34. void main(int argc,char *argv[]) {
  35. int t1,t2,t3;
  36. char tstr[81]="";
  37. long tlong;
  38. printf("\n\n");
  39. if(argc<3) {
  40. printf("Usage: TXT2HLP source.txt output.fil\n\n\a");
  41. return;
  42. }
  43. FILE *source;
  44. FILE *dest;
  45. source=fopen(argv[1],"rb");
  46. if(source==NULL) {
  47. printf("Error opening %s for input.\n\n\a",argv[1]);
  48. return;
  49. }
  50. dest=fopen(argv[2],"wb");
  51. if(dest==NULL) {
  52. fclose(source);
  53. printf("Error opening %s for output.\n\n\a",argv[2]);
  54. return;
  55. }
  56. //Source/dest files open. Now scan source for number of filenames.
  57. //A new file is designated by a # as the first character of a line.
  58. int numfiles=1;
  59. //Count context sensitive links too. A link is designated by a : as
  60. //the first character of a line, followed by three numerals, followed
  61. //by the end of the line. (a \n)
  62. int numlinks=0;
  63. do {
  64. t1=fgetc(source);
  65. if(t1=='#') numfiles++;
  66. if(t1==':') {
  67. //Check next chars
  68. t2=0;
  69. t1=fgetc(source);
  70. if(isdigit(t1)) {
  71. t2+=100*(t1-'0');
  72. t1=fgetc(source);
  73. if(isdigit(t1)) {
  74. t2+=10*(t1-'0');
  75. t1=fgetc(source);
  76. if(isdigit(t1)) {
  77. t2+=t1-'0';
  78. t1=fgetc(source);
  79. if(((t1=='\n')||(t1==':'))&&(t2>=numlinks)) numlinks=t2+1;
  80. }
  81. }
  82. }
  83. }
  84. if(t1=='\n') continue;
  85. while(fgetc(source)!='\n') if(feof(source)) break;
  86. } while(!feof(source));
  87. printf("Files: %d Links: %d\n",numfiles,numlinks);
  88. //Number of files obtained. Write header, with room, to dest. This
  89. //includes number of links and blank spaces to add in filenames and
  90. //link info.
  91. fwrite(&numfiles,1,2,dest);
  92. for(t1=0;t1<numfiles;t1++)
  93. fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",21,1,dest);
  94. fwrite(&numlinks,1,2,dest);
  95. if(numlinks>0)
  96. for(t1=0;t1<numlinks;t1++)
  97. fwrite("\0\0\0\0\0\0\0\0\0\0\0\0",12,1,dest);
  98. //Now we start our actual file chain. Current file info-
  99. char curr_file[13]="MAIN.HLP";
  100. char max_file[13]="(none)";
  101. long file_offs=ftell(dest);
  102. long file_len=1;//For first byte
  103. long curr_file_storage=2;//Location to store current file's info
  104. int curr_lnum=1;//For error/warning info
  105. //Links info-
  106. char curr_link_ref=0;//Ref- not actual link number
  107. int link_numbers[1000];//Actual numbers of the links
  108. long link_offsets[1000];//Offsets within current file
  109. //Current line info-
  110. int line_len=0;//Used for warnings
  111. //Global info-
  112. long biggest_file=0;//For help allocation
  113. //Reset position on source...
  114. fseek(source,0,SEEK_SET);
  115. //...and begin our parse! New files start with a 1.
  116. fputc(1,dest);
  117. printf("Processing file %s...\n",curr_file);
  118. do {
  119. //Our loop. Read first char of current line
  120. line_len=0;
  121. t1=fgetc(source);
  122. switch(t1) {
  123. case '$'://Centered line- write prefix...
  124. fputc(255,dest); fputc('$',dest); file_len+=2;
  125. //...and read first character...
  126. case '.'://Normal line- read first character
  127. mesg://Jump point to copy until and through an \n
  128. t1=fgetc(source);
  129. default://Normal line (first char in t1)
  130. //Copy until a \n
  131. if(t1=='\n') goto blanko;
  132. while(!feof(source)) {
  133. fputc(t1,dest); file_len++;
  134. line_len++;
  135. t1=fgetc(source);
  136. if(t1=='\n') break;
  137. }
  138. //Now put an \n
  139. blanko:
  140. fputc('\n',dest); file_len++;
  141. break;
  142. case '>'://Choice of some type
  143. fputc(255,dest); file_len++;
  144. //See if dest is normal or file
  145. t1=fgetc(source);
  146. if(t1=='#') {
  147. //File.
  148. fputc('<',dest); file_len++;
  149. //Grab name.
  150. t2=t3=0;//t2 counts str size, t3 counts colons passed
  151. do {
  152. t1=fgetc(source);
  153. if((t1==':')&&t3) break;
  154. if(t1=='\n') break;
  155. if(t1==':') t3++;
  156. tstr[t2++]=t1;
  157. } while(!feof(source));
  158. tstr[t2]=0;
  159. if(t2==10) //10 len not allowed
  160. printf("Error- Label length of 10 on line %d, file %s.\n",
  161. curr_lnum,curr_file);
  162. fputc(t2,dest); file_len++;
  163. fwrite(tstr,++t2,1,dest); file_len+=t2;
  164. //Now do actual message after the label/file.
  165. goto mesg;
  166. }
  167. //Non-file.
  168. fputc('>',dest); file_len++;
  169. //Grab name.
  170. t2=0;//t2 counts str size
  171. do {
  172. if((t1==':')||(t1=='\n')) break;
  173. tstr[t2++]=t1;
  174. t1=fgetc(source);
  175. } while(!feof(source));
  176. tstr[t2]=0;
  177. if(t2==1) //1 len not allowed
  178. printf("Error- Label length of 1 on line %d, file %s.\n",
  179. curr_lnum,curr_file);
  180. if(t2==10) //10 len not allowed
  181. printf("Error- Label length of 10 on line %d, file %s.\n",
  182. curr_lnum,curr_file);
  183. fputc(t2,dest); file_len++;
  184. fwrite(tstr,++t2,1,dest); file_len+=t2;
  185. //Now do actual message after the label.
  186. goto mesg;
  187. case ':'://Label, possibly with a message attached
  188. fputc(255,dest); fputc(':',dest); file_len+=2;
  189. //Grab name.
  190. t2=0;//Counts str length
  191. do {
  192. t1=fgetc(source);
  193. if((t1==':')||(t1=='\n')) break;
  194. tstr[t2++]=t1;
  195. } while(!feof(source));
  196. tstr[t2]=0;
  197. if(t2==1) //1 len not allowed
  198. printf("Error- Label length of 1 on line %d, file %s.\n",
  199. curr_lnum,curr_file);
  200. if(t2==10) //10 len not allowed
  201. printf("Error- Label length of 10 on line %d, file %s.\n",
  202. curr_lnum,curr_file);
  203. fputc(t2,dest); file_len++;
  204. fwrite(tstr,++t2,1,dest); file_len+=t2;
  205. //Is this a context-link?
  206. if((t2==4)&&(isdigit(tstr[0]))&&
  207. (isdigit(tstr[1]))&&(isdigit(tstr[2]))) {
  208. //Yep.
  209. t3=atoi(tstr);
  210. link_numbers[curr_link_ref]=t3;
  211. link_offsets[curr_link_ref++]=file_len-7;
  212. }
  213. //Is there a message next?
  214. if(t1==':') goto mesg;//Yep.
  215. //Nope- Just output an EOL.
  216. fputc('\n',dest); file_len++;
  217. break;
  218. case '#'://New file
  219. //First, end current
  220. fputc(0,dest); file_len++;
  221. if(file_len>biggest_file) {
  222. biggest_file=file_len;
  223. strcpy(max_file,curr_file);
  224. }
  225. //Put it's info at the start
  226. tlong=ftell(dest);
  227. fseek(dest,curr_file_storage,SEEK_SET);
  228. fwrite(curr_file,1,13,dest);
  229. fwrite(&file_offs,1,4,dest);
  230. fwrite(&file_len,1,4,dest);
  231. if(file_len>65535U) printf("Warning- File %s over 64k bytes in length.\n",curr_file);
  232. //Write in links info
  233. for(t1=0;t1<curr_link_ref;t1++) {
  234. fseek(dest,4+numfiles*21+link_numbers[t1]*12,SEEK_SET);
  235. fwrite(&file_offs,1,4,dest);
  236. fwrite(&file_len,1,4,dest);
  237. fwrite(&link_offsets[t1],1,4,dest);
  238. }
  239. //Start next file
  240. fseek(dest,tlong,SEEK_SET);
  241. file_offs=tlong;
  242. file_len=curr_lnum=1;
  243. curr_file_storage+=21;
  244. curr_link_ref=0;
  245. fputc(1,dest);
  246. //Get new filename
  247. t2=0;//Counts str length
  248. do {
  249. t1=fgetc(source);
  250. if(t1=='\n') break;
  251. tstr[t2++]=t1;
  252. } while(!feof(source));
  253. tstr[t2]=0;
  254. if(t2>12) tstr[12]=0;
  255. //Copy over new filename
  256. strcpy(curr_file,tstr);
  257. //Next file ready to roar!
  258. printf("Processing file %s...\n",curr_file);
  259. break;
  260. case '@'://End of help.doc file
  261. goto alldone;
  262. }
  263. if(line_len>64)
  264. printf("Warning: Line %d over 64 chars in file %s.\n",curr_lnum,curr_file);
  265. curr_lnum++;
  266. //Done with this line.
  267. } while(!feof(source));
  268. alldone:
  269. //End last file
  270. fputc(0,dest); file_len++;
  271. if(file_len>biggest_file) {
  272. biggest_file=file_len;
  273. strcpy(max_file,curr_file);
  274. }
  275. //Put it's info at the start
  276. fseek(dest,curr_file_storage,SEEK_SET);
  277. fwrite(curr_file,1,13,dest);
  278. fwrite(&file_offs,1,4,dest);
  279. fwrite(&file_len,1,4,dest);
  280. if(file_len>65535U) printf("Warning- File %s over 64k bytes in length.\n",curr_file);
  281. //Write in links info
  282. for(t1=0;t1<curr_link_ref;t1++) {
  283. fseek(dest,4+numfiles*21+link_numbers[t1]*12,SEEK_SET);
  284. fwrite(&file_offs,1,4,dest);
  285. fwrite(&file_len,1,4,dest);
  286. fwrite(&link_offsets[t1],1,4,dest);
  287. }
  288. //All done! Close files.
  289. fclose(dest);
  290. fclose(source);
  291. printf("Done! Biggest file- %ld bytes. (%s)\n\n",biggest_file,max_file);
  292. }