ttsplit.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /******************************************************************************
  2. *
  3. * project name: TI-68k Developer Utilities
  4. * file name: ttsplit.c
  5. * initial date: 23/08/2000
  6. * authors: thomas.nussbaumer@gmx.net
  7. * description: splits a file into two or more files
  8. *
  9. ******************************************************************************/
  10. /*
  11. This file is part of TI-68k Developer Utilities.
  12. This file is free software; you can redistribute it and/or
  13. modify it under the terms of the GNU Lesser General Public
  14. License as published by the Free Software Foundation; either
  15. version 2.1 of the License, or (at your option) any later version.
  16. As a special exception, UNMODIFIED copies of ttsplit may also be
  17. redistributed or sold without source code, for any purpose. (The Lesser
  18. General Public License restrictions do apply in other respects; for example,
  19. they cover modification of the program.) This exception notice must be
  20. removed on modified copies of this file.
  21. This program is distributed in the hope that it will be useful,
  22. but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  24. Lesser General Public License for more details.
  25. You should have received a copy of the GNU Lesser General Public
  26. License along with this library; if not, write to the Free Software
  27. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  28. */
  29. // if EMBEDDED_USE is defined, than we use this sourcefile from within another
  30. // sourcefile
  31. #ifndef EMBEDDED_USE
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <ctype.h>
  36. #include "tt.h" // generic defines
  37. #include "ttversion.h" // TI-68k Developer Utilities version info
  38. #include "revtools.h"
  39. #ifdef FILE_REVISION
  40. #undef FILE_REVISION
  41. #endif
  42. #define FILE_REVISION "1.7"
  43. //=============================================================================
  44. // outputs usage information of this tool
  45. //=============================================================================
  46. void PrintUsage() {
  47. fprintf(USAGE_OUT, "Usage: ttsplit [flags] <-t | -b> <offsetfile> <infile>\n"\
  48. " -t ... treat offsets as linenumbers (starting at 1)\n"\
  49. " -b ... treat offsets as byteoffsets (starting at 0)\n"\
  50. " -s <string> ... use inline split tag instead of offset file\n"\
  51. " -v ... output additionally messages\n\n"\
  52. "offsets are read from file offsetfile, which must contain offsets only\n"\
  53. "in ascending numbers (maximum: 999 offsets). each offset is treated as\n"\
  54. "the start of a new file. the first offset is the start of the second (!!!)\n"\
  55. "file and so on.\n"\
  56. "The outputfile names are generated from the inputfilename using\n"\
  57. "the following pattern:\n"\
  58. "<inputname>p<nr>.<inputextension>\n"\
  59. "nr ranges from 000 to 999\n\n");
  60. }
  61. #endif
  62. //=============================================================================
  63. // split text input file using a inline tag on a single line
  64. //=============================================================================
  65. unsigned int SplitWithTag(char* inputname,char* splittag,int verbose) {
  66. char* dot_position = strchr(inputname,'.');
  67. char extension[300];
  68. char prefix[300];
  69. unsigned long dpl;
  70. size_t len;
  71. FILE* fp;
  72. FILE* ofp = 0;
  73. unsigned int i;
  74. unsigned int generated_files = 0;
  75. long pos = 0;
  76. char ofname[1000];
  77. char buffer[10000];
  78. buffer[9999] = 0;
  79. if (!(fp = fopen(inputname,"r"))) {
  80. fprintf(stderr,"ERROR: cannot open inputfile %s\n",inputname);
  81. return 0;
  82. }
  83. if (!dot_position) {
  84. extension[0] = 0;
  85. strcpy(prefix,inputname);
  86. }
  87. else {
  88. dpl = dot_position - inputname;
  89. if (!dpl) prefix[0] = 0;
  90. else {
  91. strncpy(prefix,inputname,dpl);
  92. prefix[dpl] = 0;
  93. }
  94. len = strlen(inputname);
  95. if (len - dpl == 0) {
  96. extension[0] = 0;
  97. }
  98. else {
  99. strncpy(extension,&inputname[dpl],len - dpl);
  100. extension[len - dpl] = 0;
  101. }
  102. }
  103. if (verbose) {
  104. fprintf(stderr,"using prefix = [%s]\n",prefix);
  105. fprintf(stderr,"using extension = [%s]\n",extension);
  106. }
  107. pos = 1;
  108. i = 0;
  109. sprintf(ofname,"%sp%03d%s",prefix,i,extension);
  110. if (!(ofp = fopen(ofname,"w"))) {
  111. fprintf(stderr,"ERROR: cannot open outputfile %s\n",ofname);
  112. return generated_files;
  113. }
  114. do {
  115. if (fgets(buffer,9999,fp) == 0) {
  116. fclose(fp);
  117. fclose(ofp);
  118. return ++generated_files;
  119. }
  120. // check if line contains splittag
  121. if (strstr(buffer,splittag)) {
  122. fclose(ofp);
  123. generated_files++;
  124. sprintf(ofname,"%sp%03d%s",prefix,i+1,extension);
  125. if (!(ofp = fopen(ofname,"w"))) {
  126. fprintf(stderr,"ERROR: cannot open outputfile %s\n",ofname);
  127. return generated_files;
  128. }
  129. i++;
  130. continue;
  131. }
  132. if (fputs(buffer,ofp) == EOF) {
  133. fprintf(stderr,"ERROR: cannot write more lines to file %s\n",ofname);
  134. fclose(fp);
  135. fclose(ofp);
  136. return generated_files;
  137. }
  138. }
  139. while(1);
  140. return 0;
  141. }
  142. //=============================================================================
  143. // extract a part in binary mode
  144. //=============================================================================
  145. int ExtractBinary(FILE* ifp,char* outname,unsigned long start,unsigned long length)
  146. {
  147. FILE* ofp;
  148. int input;
  149. fprintf(stderr,"extracting to %s from start=%lu (length=%lu)\n",outname,start,length);
  150. if (!(ofp = fopen(outname,"wb"))) {
  151. fprintf(stderr,"ERROR: cannot open output filename %s\n",outname);
  152. return 0;
  153. }
  154. if (fseek(ifp,start,SEEK_SET)) {
  155. fprintf(stderr,"ERROR: cannot seek to binary offset %lu\n",start);
  156. fclose(ofp);
  157. return 0;
  158. }
  159. while (length--) {
  160. input = fgetc(ifp);
  161. if (input == EOF) {
  162. fprintf(stderr,"ERROR: cannot read more data from inputfile\n");
  163. fclose(ofp);
  164. return 0;
  165. }
  166. if (fputc(input,ofp) == EOF) {
  167. fprintf(stderr,"ERROR: cannot read write data to outputfile\n");
  168. fclose(ofp);
  169. return 0;
  170. }
  171. }
  172. fclose(ofp);
  173. return 1;
  174. }
  175. //=============================================================================
  176. // split the input file
  177. //=============================================================================
  178. unsigned int Split2Parts(char* inputname,int use_textmode,
  179. long* offsets, unsigned int offset_count)
  180. {
  181. char* dot_position = strchr(inputname,'.');
  182. char extension[300];
  183. char prefix[300];
  184. unsigned long dpl;
  185. size_t len;
  186. FILE* fp;
  187. FILE* ofp = 0;
  188. unsigned int i;
  189. unsigned int generated_files = 0;
  190. long pos = 0;
  191. char ofname[1000];
  192. char buffer[10000];
  193. buffer[9999] = 0;
  194. if (use_textmode) {
  195. fp = fopen(inputname,"r");
  196. }
  197. else {
  198. fp = fopen(inputname,"rb");
  199. }
  200. if (!fp) {
  201. fprintf(stderr,"ERROR: cannot open inputfile %s\n",inputname);
  202. return 0;
  203. }
  204. if (!dot_position) {
  205. extension[0] = 0;
  206. strcpy(prefix,inputname);
  207. }
  208. else {
  209. dpl = dot_position - inputname;
  210. if (!dpl) prefix[0] = 0;
  211. else {
  212. strncpy(prefix,inputname,dpl);
  213. prefix[dpl] = 0;
  214. }
  215. len = strlen(inputname);
  216. if (len - dpl == 0) {
  217. extension[0] = 0;
  218. }
  219. else {
  220. strncpy(extension,&inputname[dpl],len - dpl);
  221. extension[len - dpl] = 0;
  222. }
  223. }
  224. fprintf(stderr,"using prefix = [%s]\n",prefix);
  225. fprintf(stderr,"using extension = [%s]\n",extension);
  226. if (!use_textmode) {
  227. sprintf(ofname,"%sp000%s",prefix,extension);
  228. if (!ExtractBinary(fp,ofname,0,offsets[0])) {
  229. return generated_files;
  230. }
  231. generated_files++;
  232. for (i=0;i<offset_count-1;i++) {
  233. sprintf(ofname,"%sp%03d%s",prefix,i+1,extension);
  234. if (!ExtractBinary(fp,ofname,offsets[i],offsets[i+1]-offsets[i])) {
  235. return generated_files;
  236. }
  237. generated_files++;
  238. }
  239. fseek(fp,0,SEEK_END);
  240. pos = ftell(fp);
  241. sprintf(ofname,"%sp%03d%s",prefix,i+1,extension);
  242. if (!ExtractBinary(fp,ofname,offsets[offset_count-1],pos - offsets[offset_count-1])) {
  243. return generated_files;
  244. }
  245. generated_files++;
  246. return generated_files;
  247. }
  248. // here comes the textmode extraction ...
  249. pos = 1;
  250. i = 0;
  251. sprintf(ofname,"%sp%03d%s",prefix,i,extension);
  252. if (!(ofp = fopen(ofname,"w"))) {
  253. fprintf(stderr,"ERROR: cannot open outputfile %s\n",ofname);
  254. return generated_files;
  255. }
  256. do {
  257. if ( pos > 1
  258. && i < offset_count
  259. && pos == offsets[i]
  260. ) {
  261. fclose(ofp);
  262. generated_files++;
  263. sprintf(ofname,"%sp%03d%s",prefix,i+1,extension);
  264. if (!(ofp = fopen(ofname,"w"))) {
  265. fprintf(stderr,"ERROR: cannot open outputfile %s\n",ofname);
  266. return generated_files;
  267. }
  268. i++;
  269. }
  270. if (fgets(buffer,9999,fp) == 0) {
  271. fclose(fp);
  272. fclose(ofp);
  273. return ++generated_files;
  274. }
  275. pos++;
  276. if (fputs(buffer,ofp) == EOF) {
  277. fprintf(stderr,"ERROR: cannot write more lines to file %s\n",ofname);
  278. fclose(fp);
  279. fclose(ofp);
  280. return generated_files;
  281. }
  282. }
  283. while(1);
  284. return 0;
  285. }
  286. //=============================================================================
  287. // parse offsets from file
  288. //=============================================================================
  289. unsigned int ReadOffsets(char* filename,long* offsets) {
  290. FILE* fp = fopen(filename,"r");
  291. unsigned int count = 0;
  292. int read;
  293. if (!fp) {
  294. fprintf(stderr,"ERROR: cannot open offsetfile %s\n",filename);
  295. return 0;
  296. }
  297. do {
  298. read = fscanf(fp,"%ld",&offsets[count]);
  299. if (!read) {
  300. fclose(fp);
  301. fprintf(stderr,"ERROR: parsing offset[%u] from %s failed\n",count,filename);
  302. return 0;
  303. }
  304. if (read == EOF) {
  305. fclose(fp);
  306. return count;
  307. }
  308. // From 1.30-: offsets[count] < offsets[count] (???)
  309. if (count > 0 && offsets[count] < offsets[count - 1]) {
  310. fprintf(stderr,"ERROR: offsets are not ascending\n");
  311. fclose(fp);
  312. return 0;
  313. }
  314. if (offsets[count] == 0) {
  315. fprintf(stderr,"ERROR: offset 0 is invalid\n");
  316. fclose(fp);
  317. return 0;
  318. }
  319. count++;
  320. if (count==999) {
  321. fclose(fp);
  322. fprintf(stderr,"WARNING: read 1000 offsets. Dropping the rest.\n");
  323. return count;
  324. }
  325. }
  326. while (1);
  327. return 0;
  328. }
  329. //=============================================================================
  330. // nomen omen est
  331. //=============================================================================
  332. #ifndef EMBEDDED_USE
  333. int main(int argc, char* argv[]) {
  334. #else
  335. int TTSplit(int argc, char* argv[]) {
  336. #endif
  337. long offsets[1000]; // 1.40: from unsigned long.
  338. unsigned int offset_count;
  339. int i;
  340. unsigned int retval;
  341. int textmode = -1;
  342. int verbose = 0;
  343. char* splittag = 0;
  344. char* offsetname = 0;
  345. char* infilename = 0;
  346. #ifndef EMBEDDED_USE
  347. PRINT_ID("TTSplit");
  348. #endif
  349. for (i=1; i<argc; i++) {
  350. if (!strcmp(argv[i], "-b")) textmode = 0;
  351. else if (!strcmp(argv[i], "-t")) textmode = 1;
  352. else if (!strcmp(argv[i], "-v")) verbose = 1;
  353. else if (!strcmp(argv[i], "-s")) {
  354. if (i == argc - 1) {
  355. #ifndef EMBEDDED_USE
  356. PrintUsage();
  357. #endif
  358. return 1;
  359. }
  360. i++;
  361. splittag = argv[i];
  362. }
  363. else {
  364. if (!splittag && !offsetname) offsetname = argv[i];
  365. else if (!infilename) infilename = argv[i];
  366. }
  367. }
  368. if (!infilename || (!splittag && !offsetname) || textmode == -1) {
  369. #ifndef EMBEDDED_USE
  370. PrintUsage();
  371. #endif
  372. return 1;
  373. }
  374. if (!splittag) {
  375. if (!(offset_count = ReadOffsets(offsetname,offsets))) return 1;
  376. if (textmode && offsets[0] <= 1) {
  377. fprintf(stderr,"ERROR: offset with value 0 or 1 is not allowed for textmode\n");
  378. return 1;
  379. }
  380. retval = Split2Parts(infilename,textmode,offsets,offset_count);
  381. }
  382. else {
  383. retval = SplitWithTag(infilename,splittag,verbose);
  384. if (!retval) {
  385. fprintf(stderr,"ERROR: splitting inputfile %s failed\n",infilename);
  386. return 1;
  387. }
  388. if (verbose) fprintf(stderr,"successfully generated %u files\n",retval);
  389. return 0;
  390. }
  391. if (retval == offset_count+1) {
  392. fprintf(stderr,"generated ONLY %u out of %u files\n",retval,offset_count+1);
  393. }
  394. else {
  395. if (verbose) fprintf(stderr,"successfully generated %u out of %u files\n",retval,retval);
  396. }
  397. return (retval == offset_count+1) ? 0 : 1;
  398. }
  399. //#############################################################################
  400. //###################### NO MORE FAKES BEYOND THIS LINE #######################
  401. //#############################################################################
  402. //
  403. //=============================================================================
  404. // Revision History
  405. //=============================================================================
  406. //
  407. // Revision 1.7 2009/01/25 Lionel Debroux
  408. // Changes by Romain Liévin and/or me for 64-bit compatibility.
  409. // Adapt to new version display (revtools.h).
  410. //
  411. // Revision 1.6 2002/03/04 14:32:42 tnussb
  412. // now tool can be used as embedded version from within other tools
  413. // by defining EMBEDDED_VERSION before including the sourcefile
  414. //
  415. // Revision 1.5 2002/02/07 09:49:38 tnussb
  416. // all local includes changed, because header files are now located in pctools folder
  417. //
  418. // Revision 1.4 2000/11/28 00:07:32 Thomas Nussbaumer
  419. // using now USAGE_OUT stream for usage info
  420. //
  421. // Revision 1.3 2000/08/28 18:10:18 Thomas Nussbaumer
  422. // nasty bug (uninitialized variable) fixed which causes program to return
  423. // != 0 in good cases, too
  424. //
  425. // Revision 1.2 2000/08/26 19:00:36 Thomas Nussbaumer
  426. // inline split tag mode added to make ebook generation easier
  427. //
  428. // Revision 1.1 2000/08/23 20:18:10 Thomas Nussbaumer
  429. // initial version (quite a hack)
  430. //
  431. //
  432. //