tpr.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  1. /*
  2. ktigcc - TIGCC IDE for KDE
  3. tpr handling routines adapted from tprbuilder
  4. Copyright (C) 2002 Romain Liévin
  5. Copyright (C) 2002-2006 Kevin Kofler
  6. Copyright (C) 2006 Joey Adams
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software Foundation,
  17. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. */
  19. #include <cstdio>
  20. #include <cstdlib>
  21. #include <cerrno>
  22. #include <cstring>
  23. #include <unistd.h>
  24. #include <sys/stat.h>
  25. #include <sys/dir.h>
  26. #include <qapplication.h>
  27. #include <qeventloop.h>
  28. #include <kapplication.h>
  29. #include <kcmdlineargs.h>
  30. #include <kaboutdata.h>
  31. #include <qstring.h>
  32. #include <qstringlist.h>
  33. #include <qcstring.h>
  34. #include <qregexp.h>
  35. #include <qtextcodec.h>
  36. #include <qdir.h>
  37. #include <glib.h>
  38. #include <ticonv.h>
  39. #include "ktigcc.h"
  40. #include "tpr.h"
  41. #include "preferences.h"
  42. #define find_param(s_,t_) find_param_ex((s_),(t_),sizeof(t_)-1)
  43. static char *find_param_ex(char *s, const char *t, size_t l)
  44. {
  45. if (!strncmp(s,t,l))
  46. return s+l;
  47. else
  48. return NULL;
  49. }
  50. static char *find_numbered_param(char *s, const char*t, int *i)
  51. {
  52. char *p;
  53. int endpos = 0;
  54. int ret = 0;
  55. char arglist[256];
  56. strcpy(arglist, t);
  57. strcat(arglist, "%n");
  58. ret = sscanf(s, arglist, i, &endpos);
  59. if(ret < 1 || !endpos) return NULL;
  60. p = s + endpos;
  61. return p;
  62. }
  63. // converts Windows paths to Unix paths if necessary.
  64. static QString convert_path_separators(const char *file)
  65. {
  66. QString s=file;
  67. int o;
  68. #ifndef __WIN32__
  69. while ((o=s.find('\\',0,TRUE))>=0)
  70. s[o]='/';
  71. #endif
  72. return s;
  73. }
  74. static char* strip(char *str)
  75. {
  76. int len = strlen(str);
  77. if(len > 0)
  78. if( (str[len-1] == '\r') || (str[len-1] == '\n') )
  79. str[len-1] = '\0';
  80. if(len > 1)
  81. if( (str[len-2] == '\r') || (str[len-2] == '\n') )
  82. str[len-2] = '\0';
  83. return str;
  84. }
  85. /*
  86. Read a line from file and do a clean-up
  87. */
  88. static int read_line(FILE *f, char *buffer, int *l)
  89. {
  90. strcpy(buffer, "");
  91. if(feof(f)) return EOF;
  92. if (!fgets(buffer, 256, f)) return feof(f)?EOF:1;
  93. strip(buffer);
  94. (*l)++;
  95. while( (buffer[0] == '\r') || (buffer[0] == '\n') || (buffer[0] == '\0') )
  96. {
  97. if(feof(f)) return EOF;
  98. if (!fgets(buffer, 256, f)) return feof(f)?EOF:1;
  99. strip(buffer);
  100. (*l)++;
  101. }
  102. return 0;
  103. }
  104. //some items from the TSR might still be ignored or not shown here.
  105. //if you need one of them, add an entry to one of the
  106. //definition "tables".
  107. //If you add an entry here, don't forget to add something to
  108. // save_tpr!
  109. static int parse_file(FILE *f,TPRDataStruct *dest)
  110. {
  111. char buffer[256];
  112. int l = 0;
  113. SectionType stype = SECTION_NONE;
  114. // Some defaults are different when opening an existing project.
  115. dest->settings.cc_switches="";
  116. dest->settings.as_switches="";
  117. dest->settings.a68k_switches="";
  118. dest->libopts.use_ti89=0;
  119. dest->libopts.use_ti92p=0;
  120. dest->libopts.use_v200=0;
  121. dest->libopts.use_minams=0;
  122. dest->libopts.save_screen=0;
  123. while(!feof(f))
  124. {
  125. char *p;
  126. // Get a line from file
  127. int result=read_line(f, buffer, &l);
  128. if (result == 1) return -1; // error
  129. if (result == EOF) break;
  130. // Search for sections
  131. if( !strcmp(buffer, "[Settings]") )
  132. {
  133. stype = SECTION_SETTINGS;
  134. continue;
  135. }
  136. if( !strcmp(buffer, "[Library Options]") )
  137. {
  138. stype = SECTION_LIBOPTS;
  139. continue;
  140. }
  141. if( !strcmp(buffer, "[File Editing]") )
  142. {
  143. stype = SECTION_FILEEDIT;
  144. continue;
  145. }
  146. if( !strcmp(buffer, "[Included Files]") )
  147. {
  148. stype = SECTION_FILES;
  149. continue;
  150. }
  151. // Keywords in the [Settings] section
  152. if(stype == SECTION_SETTINGS) {
  153. #define boolean_param(token,setting) \
  154. if ( (p=find_param(buffer, token)) ) \
  155. { \
  156. if(!strcmp(p, "0")) dest->settings.setting = FALSE; \
  157. else if(!strcmp(p, "1")) dest->settings.setting = TRUE; \
  158. else return l; \
  159. continue; \
  160. } else
  161. #define tistring_vparam(token,var) \
  162. if ( (p=find_param(buffer, token)) ) \
  163. { \
  164. if (*p) { \
  165. unsigned short *utf16=ticonv_charset_ti_to_utf16(CALC_TI89,p); \
  166. dest->var = QString::fromUcs2(utf16); \
  167. g_free(utf16); \
  168. } \
  169. continue; \
  170. } else
  171. #define tistring_param(token,setting) tistring_vparam(token,settings.setting)
  172. #define string_param(token,setting) \
  173. if ( (p=find_param(buffer, token)) ) \
  174. { \
  175. if (*p) dest->settings.setting = p; \
  176. continue; \
  177. } else
  178. #define ignore_param(token) \
  179. if( (p=find_param(buffer, token)) ) \
  180. { \
  181. continue; \
  182. } else
  183. boolean_param("Archive=",archive)
  184. boolean_param("Pack=",pack)
  185. tistring_param("Packed Variable=",pack_name)
  186. tistring_vparam("Project Name=",prj_name)
  187. string_param("GCC Switches=",cc_switches)
  188. string_param("Assembler Switches=",a68k_switches)
  189. ignore_param("Linker Switches=") // Obsolete. Ignore.
  190. ignore_param("GNU Linker Switches=") // Obsolete. Ignore.
  191. string_param("GNU Assembler Switches=",as_switches)
  192. ignore_param("BSR Patch=") // Obsolete. Ignore.
  193. boolean_param("Debug Info=",debug_info)
  194. boolean_param("Standard Library=",std_lib)
  195. tistring_param("Command Line=",cmd_line)
  196. string_param("Post-Build Process=",post_build)
  197. boolean_param("Use Data Variable=",use_data_var)
  198. tistring_param("Data Variable=",data_var)
  199. boolean_param("Copy Data Variable=",copy_data_var)
  200. boolean_param("Copy Data Variable if Archived=",copy_data_var_arc)
  201. boolean_param("Optimize NOPs=",optimize_nops)
  202. boolean_param("Optimize Returns=",optimize_returns)
  203. boolean_param("Optimize Branches=",optimize_branches)
  204. boolean_param("Optimize Moves=",optimize_moves)
  205. boolean_param("Optimize Tests=",optimize_tests)
  206. boolean_param("Optimize Calculations=",optimize_calcs)
  207. boolean_param("Remove Unused Sections=",remove_unused)
  208. boolean_param("Binary Output=",outputbin)
  209. boolean_param("Fargo=",fargo)
  210. boolean_param("Flash OS=",flash_os)
  211. boolean_param("Cut Unused Ranges=",cut_ranges)
  212. boolean_param("Reorder Sections=",reorder_sections)
  213. boolean_param("Merge Constants=",merge_constants)
  214. boolean_param("Initialize BSS=",initialize_bss)
  215. return l;
  216. #undef boolean_param
  217. #undef tistring_vparam
  218. #undef tistring_param
  219. #undef string_param
  220. #undef ignore_param
  221. }
  222. // Keywords in the [Library Options] section
  223. if(stype == SECTION_LIBOPTS) {
  224. #define boolean_param(token,setting) \
  225. if ( (p=find_param(buffer, token)) ) \
  226. { \
  227. if(!strcmp(p, "0")) dest->libopts.setting = FALSE; \
  228. else if(!strcmp(p, "1")) dest->libopts.setting = TRUE; \
  229. else return l; \
  230. continue; \
  231. } else
  232. #define reloc_param(token,setting) \
  233. if ( (p=find_param(buffer, token)) ) \
  234. { \
  235. if (!strcmp(p,"None")) \
  236. dest->libopts.setting = RT_NONE; \
  237. else if (!strcmp(p,"Direct")) \
  238. dest->libopts.setting = RT_DIRECT; \
  239. else if (!strcmp(p,"AMS")) \
  240. dest->libopts.setting = RT_AMS; \
  241. else if (!strcmp(p, "Precomputed")) \
  242. dest->libopts.setting = RT_PRECOMP; \
  243. else if (!strcmp(p, "Kernel")) \
  244. dest->libopts.setting = RT_KERNEL; \
  245. else if (!strcmp(p, "Compressed")) \
  246. dest->libopts.setting = RT_COMPRESSED; \
  247. else if (!strcmp(p, "MLink")) \
  248. dest->libopts.setting = RT_MLINK; \
  249. else if (!strcmp(p, "F-Line")) \
  250. dest->libopts.setting = RT_FLINE; \
  251. else if (strcmp(p, "Unknown")) \
  252. return l; \
  253. continue; \
  254. } else
  255. //this new macro was added to make merging with save_tpr more consistent.
  256. #define minams_param(token,setting) \
  257. if ( (p=find_param(buffer, "Minimum AMS Version=")) ) \
  258. { \
  259. int major, minor; \
  260. if ((strlen(p)==4) \
  261. && (sscanf(p,"%1d.%2d",&major,&minor)==2)) \
  262. dest->libopts.minams = major * 100 + minor; \
  263. else \
  264. return l; \
  265. continue; \
  266. } else
  267. boolean_param("Use TI-89=",use_ti89)
  268. boolean_param("Use TI-92 Plus=",use_ti92p)
  269. boolean_param("Use V200=",use_v200)
  270. boolean_param("Optimize Calc Consts=",opt_calc_consts)
  271. boolean_param("Use Kernel=",use_kernel)
  272. boolean_param("Use PreOS=",use_preos)
  273. boolean_param("Minimum AMS Version Defined=",use_minams)
  274. minams_param("Minimum AMS Version=",minams);
  275. boolean_param("Unofficial OS Support=",unofficial_os)
  276. reloc_param("Reloc Format=",reloc_format)
  277. reloc_param("ROM Call Format=",rom_call_format)
  278. reloc_param("BSS Ref Format=",bss_ref_format)
  279. reloc_param("Data Ref Format=",data_ref_format)
  280. boolean_param("Use F-Line Jumps=",use_fline_jumps)
  281. boolean_param("Use 4-Byte F-Line Jumps=",use_4b_fline_jumps)
  282. boolean_param("Use Internal F-Line Emulator=",use_internal_fline_emu)
  283. boolean_param("Use Return Value=",use_return_value)
  284. boolean_param("Enable Error Return=",enable_error_return)
  285. boolean_param("Save Screen=",save_screen)
  286. boolean_param("Optimize ROM Calls=",opt_rom_calls)
  287. return l;
  288. #undef boolean_param
  289. #undef reloc_param
  290. #undef minams_param
  291. }
  292. // Keywords in the [File Editing] section
  293. if(stype == SECTION_FILEEDIT)
  294. {
  295. if ( (p=find_param(buffer, "Open File=")) ) \
  296. { \
  297. if (*p) dest->open_file = p; \
  298. continue; \
  299. } else return l;
  300. }
  301. // Keywords in the [Included Files] section
  302. if(stype == SECTION_FILES)
  303. {
  304. int v;
  305. if( (p=find_numbered_param(buffer, "C File %i=", &v)) )
  306. {
  307. QString s = convert_path_separators(p);
  308. dest->c_files.path << s;
  309. dest->c_files.folder << QString::null;
  310. continue;
  311. }
  312. else if( (p=find_numbered_param(buffer, "C File %i Folder=", &v)) )
  313. {
  314. dest->c_files.folder[v-1]=p;
  315. continue;
  316. }
  317. else if( (p=find_numbered_param(buffer, "GNU Assembler File %i=", &v)) )
  318. {
  319. QString s = convert_path_separators(p);
  320. dest->s_files.path << s;
  321. dest->s_files.folder << QString::null;
  322. continue;
  323. }
  324. else if( (p=find_numbered_param(buffer, "GNU Assembler File %i Folder=", &v)) )
  325. {
  326. dest->s_files.folder[v-1]=p;
  327. continue;
  328. }
  329. else if( (p=find_numbered_param(buffer, "Header File %i=", &v)) )
  330. {
  331. QString s = convert_path_separators(p);
  332. dest->h_files.path << s;
  333. dest->h_files.folder << QString::null;
  334. continue;
  335. }
  336. else if( (p=find_numbered_param(buffer, "Header File %i Folder=", &v)) )
  337. {
  338. dest->h_files.folder[v-1]=p;
  339. continue;
  340. }
  341. else if( (p=find_numbered_param(buffer, "Assembler File %i=", &v)) )
  342. {
  343. QString s = convert_path_separators(p);
  344. dest->asm_files.path << s;
  345. dest->asm_files.folder << QString::null;
  346. continue;
  347. }
  348. else if( (p=find_numbered_param(buffer, "Assembler File %i Folder=", &v)) )
  349. {
  350. dest->asm_files.folder[v-1]=p;
  351. continue;
  352. }
  353. else if( (p=find_numbered_param(buffer, "Object File %i=", &v)) )
  354. {
  355. QString s = convert_path_separators(p);
  356. dest->o_files.path << s;
  357. dest->o_files.folder << QString::null;
  358. continue;
  359. }
  360. else if( (p=find_numbered_param(buffer, "Object File %i Folder=", &v)) )
  361. {
  362. dest->o_files.folder[v-1]=p;
  363. continue;
  364. }
  365. else if( (p=find_numbered_param(buffer, "Archive File %i=", &v)) )
  366. {
  367. QString s = convert_path_separators(p);
  368. dest->a_files.path << s;
  369. dest->a_files.folder << QString::null;
  370. continue;
  371. }
  372. else if( (p=find_numbered_param(buffer, "Archive File %i Folder=", &v)) )
  373. {
  374. dest->a_files.folder[v-1]=p;
  375. continue;
  376. }
  377. else if( (p=find_numbered_param(buffer, "Text File %i=", &v)) )
  378. {
  379. QString s = convert_path_separators(p);
  380. dest->txt_files.path << s;
  381. dest->txt_files.folder << QString::null;
  382. continue;
  383. }
  384. else if( (p=find_numbered_param(buffer, "Text File %i Folder=", &v)) )
  385. {
  386. dest->txt_files.folder[v-1]=p;
  387. continue;
  388. }
  389. else if( (p=find_numbered_param(buffer, "Quill File %i=", &v)) )
  390. {
  391. QString s = convert_path_separators(p);
  392. dest->quill_files.path << s;
  393. dest->quill_files.folder << QString::null;
  394. continue;
  395. }
  396. else if( (p=find_numbered_param(buffer, "Quill File %i Folder=", &v)) )
  397. {
  398. dest->quill_files.folder[v-1]=p;
  399. continue;
  400. }
  401. else if( (p=find_numbered_param(buffer, "Other File %i=", &v)) )
  402. {
  403. QString s = convert_path_separators(p);
  404. dest->oth_files.path << s;
  405. dest->oth_files.folder << QString::null;
  406. continue;
  407. }
  408. else if( (p=find_numbered_param(buffer, "Other File %i Folder=", &v)) )
  409. {
  410. dest->oth_files.folder[v-1]=p;
  411. continue;
  412. }
  413. else return l;
  414. }
  415. }
  416. return 0;
  417. }
  418. // returns 0 on success, -1 if it can't open the TPR and a (positive) line
  419. // number if there is an error in the TPR
  420. int loadTPR(const QString &fileName,TPRDataStruct *dest)
  421. {
  422. FILE *f;
  423. int ret;
  424. f = fopen(fileName, "r");
  425. if(f == NULL) {
  426. return -1;
  427. }
  428. ret=parse_file(f,dest);
  429. fclose(f);
  430. return ret;
  431. }
  432. QString loadFileText(const char *fileName)
  433. {
  434. FILE *f;
  435. f=fopen(fileName,"rb");
  436. if (!f)
  437. return QString::null;
  438. fseek(f,0,SEEK_END);
  439. size_t flen=ftell(f);
  440. fseek(f,0,SEEK_SET);
  441. char *buffer = new(std::nothrow) char[flen+1];
  442. if (!buffer) {
  443. fclose(f);
  444. return QString::null;
  445. }
  446. std::memset(buffer,0,flen+1);
  447. QString ret;
  448. if (fread(buffer,1,flen,f)<flen) {
  449. fclose(f);
  450. delete[] buffer;
  451. ret=QString::null;
  452. } else {
  453. fclose(f);
  454. if (preferences.useCalcCharset) {
  455. unsigned short *utf16=ticonv_charset_ti_to_utf16(CALC_TI89,buffer);
  456. delete[] buffer;
  457. if (!utf16)
  458. return QString::null;
  459. ret=QString::fromUcs2(utf16);
  460. g_free(utf16);
  461. } else {
  462. ret=buffer;
  463. delete[] buffer;
  464. }
  465. }
  466. if (!ret.isNull()) {
  467. // convert Windows line endings
  468. ret=ret.replace("\r\n","\n");
  469. // interpret remaining \r characters as Mac line endings
  470. ret=ret.replace('\r','\n');
  471. // remove trailing spaces if requested
  472. if (preferences.removeTrailingSpaces) {
  473. ret=ret.replace(QRegExp("((?!\n)\\s)*\n"),"\n");
  474. ret=ret.remove(QRegExp("((?!\n)\\s)*$"));
  475. }
  476. }
  477. return ret;
  478. }
  479. static QString convert_path_separators_save(QString s)
  480. {
  481. int o;
  482. #ifndef __WIN32__
  483. while ((o=s.find('/',0,TRUE))>=0)
  484. s[o]='\\';
  485. #endif
  486. return s;
  487. }
  488. //this is here because QString::ascii() returns "(null)" on a null string.
  489. const char *smartAscii(const QString &s)
  490. {
  491. if (s.isNull())
  492. return "";
  493. return s.ascii();
  494. }
  495. static int save_tpr(FILE *f,TPRDataStruct *dest)
  496. {
  497. unsigned i=0,e;
  498. QString tmp;
  499. #define boolean_param(token,setting) if (fprintf(f,token "%d\r\n",!!dest->settings.setting)<0) return -2;
  500. #define tistring_vparam(token,var) { \
  501. const unsigned short *utf16=dest->var.ucs2(); \
  502. char *ti=utf16?ticonv_charset_utf16_to_ti(CALC_TI89,utf16):reinterpret_cast<char*>(g_malloc0(1)); \
  503. if (fprintf(f,token "%s\r\n",ti)<0) {g_free(ti); return -2;} \
  504. g_free(ti); \
  505. }
  506. #define tistring_param(token,setting) tistring_vparam(token,settings.setting)
  507. #define string_param(token,setting) if (fprintf(f,token "%s\r\n",smartAscii(dest->settings.setting))<0) return -2;
  508. #define ignore_param(token) /**/
  509. if (fputs("[Settings]\r\n",f)<0) return -2;
  510. boolean_param("Archive=",archive)
  511. boolean_param("Pack=",pack)
  512. tistring_param("Packed Variable=",pack_name)
  513. tistring_vparam("Project Name=",prj_name)
  514. string_param("GCC Switches=",cc_switches)
  515. string_param("Assembler Switches=",a68k_switches)
  516. ignore_param("Linker Switches=") // Obsolete. Ignore.
  517. ignore_param("GNU Linker Switches=") // Obsolete. Ignore.
  518. string_param("GNU Assembler Switches=",as_switches)
  519. ignore_param("BSR Patch=") // Obsolete. Ignore.
  520. boolean_param("Debug Info=",debug_info)
  521. boolean_param("Standard Library=",std_lib)
  522. tistring_param("Command Line=",cmd_line)
  523. string_param("Post-Build Process=",post_build)
  524. boolean_param("Use Data Variable=",use_data_var)
  525. tistring_param("Data Variable=",data_var)
  526. boolean_param("Copy Data Variable=",copy_data_var)
  527. boolean_param("Copy Data Variable if Archived=",copy_data_var_arc)
  528. boolean_param("Optimize NOPs=",optimize_nops)
  529. boolean_param("Optimize Returns=",optimize_returns)
  530. boolean_param("Optimize Branches=",optimize_branches)
  531. boolean_param("Optimize Moves=",optimize_moves)
  532. boolean_param("Optimize Tests=",optimize_tests)
  533. boolean_param("Optimize Calculations=",optimize_calcs)
  534. boolean_param("Remove Unused Sections=",remove_unused)
  535. boolean_param("Binary Output=",outputbin)
  536. boolean_param("Fargo=",fargo)
  537. boolean_param("Flash OS=",flash_os)
  538. boolean_param("Cut Unused Ranges=",cut_ranges)
  539. boolean_param("Reorder Sections=",reorder_sections)
  540. boolean_param("Merge Constants=",merge_constants)
  541. boolean_param("Initialize BSS=",initialize_bss)
  542. #undef boolean_param
  543. #undef tistring_vparam
  544. #undef tistring_param
  545. #undef string_param
  546. #undef ignore_param
  547. #define boolean_param(token,setting) if (fprintf(f,token "%d\r\n",!!dest->libopts.setting)<0) return -2;
  548. #define reloc_param(token,setting) \
  549. switch(dest->libopts.setting) \
  550. { \
  551. case RT_NONE: \
  552. if (fprintf(f,token "None\r\n")<0) return -2; \
  553. break; \
  554. case RT_DIRECT: \
  555. if (fprintf(f,token "Direct\r\n")<0) return -2; \
  556. break; \
  557. case RT_AMS: \
  558. if (fprintf(f,token "AMS\r\n")<0) return -2; \
  559. break; \
  560. case RT_PRECOMP: \
  561. if (fprintf(f,token "Precomputed\r\n")<0) return -2; \
  562. break; \
  563. case RT_KERNEL: \
  564. if (fprintf(f,token "Kernel\r\n")<0) return -2; \
  565. break; \
  566. case RT_COMPRESSED: \
  567. if (fprintf(f,token "Compressed\r\n")<0) return -2; \
  568. break; \
  569. case RT_MLINK: \
  570. if (fprintf(f,token "MLink\r\n")<0) return -2; \
  571. break; \
  572. case RT_FLINE: \
  573. if (fprintf(f,token "F-Line\r\n")<0) return -2; \
  574. break; \
  575. }
  576. #define minams_param(token,setting) \
  577. { \
  578. int major,minor; \
  579. major=dest->libopts.setting/100; \
  580. minor=dest->libopts.setting%100; \
  581. if (fprintf(f,token "%d.%02d\r\n",major,minor)<0) return -2; \
  582. }
  583. if (fputs("\r\n[Library Options]\r\n",f)<0) return -2;
  584. boolean_param("Use TI-89=",use_ti89)
  585. boolean_param("Use TI-92 Plus=",use_ti92p)
  586. boolean_param("Use V200=",use_v200)
  587. boolean_param("Optimize Calc Consts=",opt_calc_consts)
  588. boolean_param("Use Kernel=",use_kernel)
  589. boolean_param("Use PreOS=",use_preos)
  590. boolean_param("Minimum AMS Version Defined=",use_minams)
  591. minams_param("Minimum AMS Version=",minams);
  592. boolean_param("Unofficial OS Support=",unofficial_os)
  593. reloc_param("Reloc Format=",reloc_format)
  594. reloc_param("ROM Call Format=",rom_call_format)
  595. reloc_param("BSS Ref Format=",bss_ref_format)
  596. reloc_param("Data Ref Format=",data_ref_format)
  597. boolean_param("Use F-Line Jumps=",use_fline_jumps)
  598. boolean_param("Use 4-Byte F-Line Jumps=",use_4b_fline_jumps)
  599. boolean_param("Use Internal F-Line Emulator=",use_internal_fline_emu)
  600. boolean_param("Use Return Value=",use_return_value)
  601. boolean_param("Enable Error Return=",enable_error_return)
  602. boolean_param("Save Screen=",save_screen)
  603. boolean_param("Optimize ROM Calls=",opt_rom_calls)
  604. #undef boolean_param
  605. #undef reloc_param
  606. #undef minams_param
  607. if (fprintf(f,"\r\n[File Editing]\r\nOpen File=%s\r\n\r\n[Included Files]\r\n",smartAscii(dest->open_file))<0) return -2;
  608. #define filepath_param(token,filetype) \
  609. e=dest->filetype.path.count(); \
  610. for(i=0;i<e;i++) \
  611. { \
  612. tmp=convert_path_separators_save(smartAscii(dest->filetype.path[i])); \
  613. if (fprintf(f,token " %u=%s\r\n",i+1,smartAscii(tmp))<0) return -2; \
  614. if (!dest->filetype.folder[i].isEmpty()) \
  615. { \
  616. if (fprintf(f,token " %u Folder=%s\r\n",i+1,smartAscii(dest->filetype.folder[i]))<0) return -2; \
  617. } \
  618. }
  619. filepath_param("C File",c_files)
  620. filepath_param("GNU Assembler File",s_files)
  621. filepath_param("Header File",h_files)
  622. filepath_param("Assembler File",asm_files)
  623. filepath_param("Object File",o_files)
  624. filepath_param("Archive File",a_files)
  625. filepath_param("Text File",txt_files)
  626. filepath_param("Quill File",quill_files)
  627. filepath_param("Other File",oth_files)
  628. #undef filepath_param
  629. if (fputs("\r\n",f)<0) return -2;
  630. return 0;
  631. }
  632. void newSettings(tprSettings *settings,tprLibOpts *libopts)
  633. {
  634. tprSettings newSettings;
  635. tprLibOpts newLibOpts;
  636. *settings=newSettings;
  637. *libopts=newLibOpts;
  638. }
  639. //returns 0 on success, -1 if the file couldn't be created or -2 if fprintf,
  640. //fputs or fclose failed
  641. int saveTPR(const QString &fileName,TPRDataStruct *src)
  642. {
  643. FILE *f;
  644. int ret;
  645. f=fopen(fileName,"wb");
  646. if (!f)
  647. {
  648. return -1;
  649. }
  650. ret=save_tpr(f,src);
  651. if (fclose(f)) return -2;
  652. return ret;
  653. }
  654. void mkdir_multi(const char *fileName)
  655. {
  656. int l=strlen(fileName);
  657. char buffer[l+2];
  658. char *ptr;
  659. #ifdef __WIN32__
  660. ptr=strchr(fileName,'\\');
  661. #else
  662. ptr=strchr(fileName,'/');
  663. #endif
  664. while (ptr)
  665. {
  666. memcpy(buffer,fileName,ptr-fileName);
  667. buffer[ptr-fileName]=0;
  668. mkdir(buffer,S_IRWXU | S_IRWXG | S_IRWXO);
  669. #ifdef __WIN32__
  670. ptr=strchr(ptr+1,'\\');
  671. #else
  672. ptr=strchr(ptr+1,'/');
  673. #endif
  674. }
  675. }
  676. static int writeToFile(FILE *f, const QString &text)
  677. {
  678. if (preferences.useCalcCharset) {
  679. const unsigned short *utf16=text.ucs2();
  680. if (utf16) {
  681. char *s=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  682. size_t l=std::strlen(s);
  683. if (fwrite(s,1,l,f)<l) {
  684. g_free(s);
  685. return -2;
  686. }
  687. g_free(s);
  688. }
  689. } else {
  690. const char *s=smartAscii(text);
  691. size_t l=std::strlen(s);
  692. if (fwrite(s,1,l,f)<l) return -2;
  693. }
  694. return 0;
  695. }
  696. enum CharModes {cmNone, cmNormalText, cmNumber, cmMultiSymbol, cmString, cmChar,
  697. cmComment, cmUnchangeableLine, cmExtUnchangeableLine,
  698. cmExtUnchangeableLineString, cmTrigraph};
  699. int saveAndSplitFileText(const char *fileName, const QString &fileText,
  700. bool split, bool addCLineDirective,
  701. bool addASMLineDirective, const QString &origFileName,
  702. LineStartList *pLineStartList, bool addNewline)
  703. {
  704. FILE *f;
  705. LineStartList lineStartList;
  706. // remove trailing spaces if requested
  707. QString text=fileText;
  708. if (preferences.removeTrailingSpaces && !text.isNull()) {
  709. text=text.replace(QRegExp("((?!\n)\\s)*\n"),"\n");
  710. text=text.remove(QRegExp("((?!\n)\\s)*$"));
  711. }
  712. f=fopen(fileName,"wb");
  713. if (!f)
  714. {
  715. mkdir_multi(fileName);
  716. f=fopen(fileName,"wb");
  717. if (!f)
  718. return -1;
  719. }
  720. if (split && preferences.splitSourceFiles && !settings.debug_info) {
  721. unsigned curPos=0, curLine=0, curCol=0, l=text.length();
  722. bool atLineStart;
  723. CharModes curMode=cmNone;
  724. #define INSERT_CHAR(ch) do {if (writeToFile(f,QString((ch)))) {fclose(f); return -2;}} while(0)
  725. #define INSERT_STRING(str) do {if (writeToFile(f,(str))) {fclose(f); return -2;}} while(0)
  726. #define ADD_LINE() do {lineStartList.append(qMakePair(curLine,curCol)); atLineStart=TRUE;} while(0)
  727. #define IS_NEWLINE() (text[curPos]=='\n')
  728. #define ADD_LINE_NEXT() do {lineStartList.append(qMakePair(curLine+(unsigned)(IS_NEWLINE()),(IS_NEWLINE())?0u:(curCol+1u))); atLineStart=TRUE;} while(0)
  729. #define NEW_LINE() do {if((!(atLineStart||IS_NEWLINE())) || (text[curPos]=='#')) {INSERT_CHAR(QChar('\n')); ADD_LINE();} curMode=cmNone;} while(0)
  730. #define SET_MULTI_CHAR_MODE(mode) do {if (curMode!=(mode)) {NEW_LINE(); curMode=(mode);}} while(0)
  731. ADD_LINE(); // Line 0
  732. for (; curPos<l; curPos++) {
  733. bool noInsert=FALSE;
  734. QChar c=text[curPos];
  735. if (c=='\n')
  736. ADD_LINE_NEXT();
  737. switch (curMode) {
  738. case cmString:
  739. if (c=='\"') {
  740. bool b=TRUE;
  741. unsigned i=curPos-1;
  742. while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
  743. b=!b;
  744. if (text[i]=='\\') --i; else i-=3;
  745. }
  746. if (b) {
  747. curMode=cmNone;
  748. noInsert=TRUE;
  749. INSERT_STRING(QString(c)+"\n");
  750. atLineStart=TRUE;
  751. ADD_LINE_NEXT();
  752. }
  753. }
  754. break;
  755. case cmChar:
  756. if (c=='\'') {
  757. bool b=TRUE;
  758. unsigned i=curPos-1;
  759. while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
  760. b=!b;
  761. if (text[i]=='\\') --i; else i-=3;
  762. }
  763. if (b) curMode=cmNone;
  764. }
  765. break;
  766. case cmComment:
  767. if ((c=='/')&&(text[curPos-1]=='*')) curMode=cmNone;
  768. break;
  769. case cmUnchangeableLine:
  770. if (c=='\n') curMode=cmNone;
  771. break;
  772. case cmExtUnchangeableLine:
  773. if ((c=='\n')&&(text[curPos-1]!='\\')) curMode=cmNone;
  774. else if (c=='\"') curMode=cmExtUnchangeableLineString;
  775. break;
  776. case cmExtUnchangeableLineString:
  777. if (c=='\"') {
  778. bool b=TRUE;
  779. unsigned i=curPos-1;
  780. while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
  781. b=!b;
  782. if (text[i]=='\\') --i; else i-=3;
  783. }
  784. if (b) curMode=cmExtUnchangeableLine;
  785. }
  786. break;
  787. case cmTrigraph:
  788. if ((c!='?')&&((curPos+1>=l)||(text[curPos+1]!='?'))) curMode=cmNone;
  789. break;
  790. default:
  791. if (!text.mid(curPos,2).compare("//"))
  792. SET_MULTI_CHAR_MODE(cmUnchangeableLine);
  793. else if (!text.mid(curPos,2).compare("/*"))
  794. SET_MULTI_CHAR_MODE(cmComment);
  795. else if (!text.mid(curPos,3).compare("?""?""="))
  796. SET_MULTI_CHAR_MODE(cmExtUnchangeableLine);
  797. else if (!text.mid(curPos,2).compare("?""?")&&(curPos+2<l)
  798. &&QString("()/\'<>!-").contains(text[curPos+2]))
  799. SET_MULTI_CHAR_MODE(cmTrigraph);
  800. else {
  801. switch(c.unicode()) {
  802. case ' ':
  803. case '\t':
  804. if (curPos && text[curPos-1]!=' ' && text[curPos-1]!='\t')
  805. NEW_LINE();
  806. break;
  807. case 'A' ... 'Z':
  808. case 'a' ... 'z':
  809. case '0' ... '9':
  810. case '_':
  811. case '$':
  812. if (curMode!=cmNormalText && curMode!=cmNumber) {
  813. NEW_LINE();
  814. if (c>=QChar('0') && c<=QChar('9'))
  815. curMode=cmNumber;
  816. else
  817. curMode=cmNormalText;
  818. }
  819. break;
  820. case '\"':
  821. SET_MULTI_CHAR_MODE(cmString);
  822. break;
  823. case '\'':
  824. SET_MULTI_CHAR_MODE(cmChar);
  825. break;
  826. case '#':
  827. SET_MULTI_CHAR_MODE(cmExtUnchangeableLine);
  828. break;
  829. case '.':
  830. if (curMode!=cmNumber) {
  831. if ((curPos+1<l)
  832. &&(text[curPos+1]>=QChar('0')
  833. &&text[curPos+1]<=QChar('9'))) {
  834. NEW_LINE();
  835. curMode=cmNumber;
  836. } else SET_MULTI_CHAR_MODE(cmMultiSymbol);
  837. }
  838. break;
  839. case '+':
  840. case '-':
  841. if ((curMode!=cmNumber)||(curPos<=1)
  842. ||!QString("eEpP").contains(text[curPos-1]))
  843. SET_MULTI_CHAR_MODE(cmMultiSymbol);
  844. break;
  845. default:
  846. if (QString(",;()[]{}").contains(c)) {
  847. if (curMode!=cmNone) {
  848. NEW_LINE();
  849. curMode=cmNone;
  850. }
  851. if ((curPos+1<l)&&text[curPos+1]!='\n') {
  852. noInsert=TRUE;
  853. INSERT_STRING(QString(c)+"\n");
  854. ADD_LINE_NEXT();
  855. }
  856. } else SET_MULTI_CHAR_MODE(cmMultiSymbol);
  857. break;
  858. }
  859. }
  860. break;
  861. }
  862. if (!noInsert) {
  863. // Special cases:
  864. switch(c.unicode()) {
  865. // Surrogate pairs.
  866. case 0xd800 ... 0xdbff:
  867. if (curPos<l && text[curPos+1].unicode()>=0xdc00
  868. && text[curPos+1].unicode()<=0xdfff) {
  869. INSERT_STRING(QString(c)+text[curPos+1]);
  870. // Allow the UI to respond, splitting is a lengthy operation.
  871. if ((curPos++)&127)
  872. QApplication::eventLoop()->processEvents(QEventLoop::AllEvents,1000);
  873. curPos++;
  874. curCol++;
  875. break;
  876. } else goto de_fault;
  877. // x-bar and y-bar are special if we use the calculator charset.
  878. case 0x305:
  879. if (preferences.useCalcCharset && curPos<l
  880. && (text[curPos+1]=='x' || text[curPos+1]=='y')) {
  881. INSERT_STRING(QString(c)+text[curPos+1]);
  882. // Allow the UI to respond, splitting is a lengthy operation.
  883. if ((curPos++)&127)
  884. QApplication::eventLoop()->processEvents(QEventLoop::AllEvents,1000);
  885. curCol++;
  886. break;
  887. }
  888. default:
  889. de_fault:
  890. INSERT_CHAR(c);
  891. break;
  892. }
  893. if (c!='\n') atLineStart=FALSE;
  894. }
  895. if (c=='\n') {
  896. curLine++;
  897. curCol=0;
  898. } else curCol++;
  899. // Allow the UI to respond, splitting is a lengthy operation.
  900. if (curPos&127)
  901. QApplication::eventLoop()->processEvents(QEventLoop::AllEvents,1000);
  902. }
  903. NEW_LINE();
  904. #undef INSERT_CHAR
  905. #undef INSERT_STRING
  906. #undef ADD_LINE
  907. #undef IS_NEWLINE
  908. #undef ADD_LINE_NEXT
  909. #undef NEW_LINE
  910. #undef SET_MULTI_CHAR_MODE
  911. } else {
  912. if ((addCLineDirective || addASMLineDirective) && settings.debug_info) {
  913. QString escapedFileName=origFileName, lineDirective;
  914. escapedFileName.replace("\\","\\\\");
  915. escapedFileName.replace("\"","\\\"");
  916. // These have no business to be in a file name, but someone somewhere may
  917. // have that very bad idea...
  918. escapedFileName.replace("\r","\\r");
  919. escapedFileName.replace("\n","\\n");
  920. lineDirective=QString(addCLineDirective
  921. ?"#line 1 \"%1\"\n"
  922. :".appfile \"%1\"; .appline 1\n").arg(escapedFileName);
  923. // Don't use calc charset for this, it's a host file name.
  924. const char *s=smartAscii(lineDirective);
  925. size_t l=std::strlen(s);
  926. if (fwrite(s,1,l,f)<l) return -2;
  927. }
  928. if (writeToFile(f,text)) {fclose(f); return -2;}
  929. if (addNewline && fwrite("\n",1,1,f)<1) {fclose(f); return -2;}
  930. }
  931. if (fclose(f)) return -2;
  932. if (pLineStartList) *pLineStartList=lineStartList;
  933. return 0;
  934. }
  935. int saveFileText(const char *fileName,const QString &fileText)
  936. {
  937. return saveAndSplitFileText(fileName,fileText,FALSE,FALSE,FALSE,QString::null,
  938. static_cast<LineStartList *>(NULL),FALSE);
  939. }
  940. void kurlNewFileName(KURL &dir,const QString &newFileName)
  941. {
  942. if (newFileName[0]=='/')
  943. dir.setPath(newFileName);
  944. else
  945. dir.setFileName(newFileName);
  946. }
  947. static QString pullOutFileSuffix(const QString &srcFileName,QString &destFileName)
  948. {
  949. int a,b;
  950. QString ret;
  951. destFileName=srcFileName;
  952. a=destFileName.findRev('.');
  953. b=destFileName.findRev('/');
  954. if (a<0)
  955. return QString::null;
  956. if (a<b)
  957. return QString::null;
  958. ret=destFileName.mid(a+1);
  959. destFileName.truncate(a);
  960. return ret;
  961. }
  962. int checkFileName(const QString &fileName,const QStringList &fileNameList)
  963. {
  964. int i;
  965. QString fileName_name,fileName_suffix;
  966. QString name,suffix;
  967. fileName_suffix=pullOutFileSuffix(fileName,fileName_name);
  968. for (i=fileNameList.count()-1;i>=0;i--)
  969. {
  970. suffix=pullOutFileSuffix(fileNameList[i],name);
  971. if (!suffix.compare("c")||!suffix.compare("s")||!suffix.compare("asm")||!suffix.compare("o")||!suffix.compare("qll"))
  972. {
  973. if (!fileName_suffix.compare("c")||!fileName_suffix.compare("s")||!fileName_suffix.compare("asm")||!fileName_suffix.compare("o")||!fileName_suffix.compare("qll"))
  974. {
  975. if (!name.compare(fileName_name))
  976. return 0;
  977. }
  978. }
  979. else
  980. {
  981. if (!fileNameList[i].compare(fileName))
  982. return 0;
  983. }
  984. }
  985. return 1;
  986. }
  987. // returns 0 on success, >0 on read failure, <0 on write failure
  988. int copyFile(const char *src, const char *dest)
  989. {
  990. // This doesn't load everything at once onto the stack because it may be
  991. // used for huge binary files, which don't fit on the stack. So we copy 1KB
  992. // at a time.
  993. FILE *sf=fopen(src,"rb");
  994. if (!sf) return 1;
  995. FILE *df=fopen(dest,"wb");
  996. if (!df) {fclose(sf); return -1;}
  997. char buffer[1024];
  998. while (!ferror(sf) && !feof(sf)) {
  999. size_t bytes_read=fread(buffer,1,1024,sf);
  1000. if (fwrite(buffer,1,bytes_read,df)<bytes_read) {
  1001. fclose(df);
  1002. fclose(sf);
  1003. return -2;
  1004. }
  1005. }
  1006. if (ferror(sf)) {
  1007. fclose(df);
  1008. fclose(sf);
  1009. return 2;
  1010. }
  1011. if (fclose(df)) {fclose(sf); return -3;}
  1012. if (fclose(sf)) return 3;
  1013. return 0;
  1014. }
  1015. // Returns TRUE on success, FALSE on failure.
  1016. bool moveFile(const QString &src, const QString &dest)
  1017. {
  1018. // Trap the obvious case before even bothering.
  1019. if (src==dest) return TRUE;
  1020. QDir qdir;
  1021. // First try a simple rename.
  1022. if (qdir.rename(src,dest)) return TRUE;
  1023. // That didn't work, probably because the files are not on the same file
  1024. // system. So do a copy&delete operation.
  1025. if (copyFile(src,dest)) return FALSE;
  1026. return qdir.remove(src);
  1027. }
  1028. // Replaces the first occurrence of "tempprog" in a pstarter or PPG with name.
  1029. // returns 0 on success, >0 on read failure, <0 on write failure
  1030. int insertName(const char *src, const char *dest, const char *name)
  1031. {
  1032. FILE *sf=std::fopen(src,"rb");
  1033. if (!sf) return 1;
  1034. std::fseek(sf,0,SEEK_END);
  1035. std::size_t flen=std::ftell(sf);
  1036. std::fseek(sf,0,SEEK_SET);
  1037. char *buffer = new(std::nothrow) char[flen];
  1038. if (!buffer) {std::fclose(sf); return 4;}
  1039. if (std::fread(buffer,1,flen,sf)<flen) {
  1040. delete[] buffer;
  1041. std::fclose(sf);
  1042. return 2;
  1043. }
  1044. if (fclose(sf)) {delete[] buffer; return 3;}
  1045. for (std::size_t i=0; i<=flen-8; i++) {
  1046. if (!std::memcmp(buffer+i,"tempprog",8)) {
  1047. std::strncpy(buffer+i,name,8);
  1048. break; // do only one replacement
  1049. }
  1050. }
  1051. FILE *df=std::fopen(dest,"wb");
  1052. if (!df) {delete[] buffer; return -1;}
  1053. if (std::fwrite(buffer,1,flen,df)<flen) {
  1054. delete[] buffer;
  1055. std::fclose(df);
  1056. return -2;
  1057. }
  1058. delete[] buffer;
  1059. if (std::fclose(df)) return -3;
  1060. return 0;
  1061. }
  1062. int getPathType(const QString &thePath)
  1063. {
  1064. struct stat statvar;
  1065. int result=stat(thePath,&statvar);
  1066. if (result)
  1067. return errno==ENOENT?PATH_NOTFOUND:PATH_ERROR;
  1068. if (statvar.st_mode&S_IFDIR)
  1069. return PATH_FOLDER;
  1070. if (statvar.st_mode&S_IFREG)
  1071. return PATH_FILE;
  1072. return PATH_ERROR;
  1073. }
  1074. /*
  1075. Build command line arguments (Library Options section)
  1076. */
  1077. QStringList process_libopts(void)
  1078. {
  1079. QStringList args;
  1080. if (libopts.use_ti89) {
  1081. args.append("-DUSE_TI89");
  1082. }
  1083. if (libopts.use_ti92p) {
  1084. args.append("-DUSE_TI92PLUS");
  1085. }
  1086. if (libopts.use_v200) {
  1087. args.append("-DUSE_V200");
  1088. }
  1089. if (libopts.opt_calc_consts) {
  1090. args.append("-DOPTIMIZE_CALC_CONSTS");
  1091. }
  1092. if (libopts.use_kernel || libopts.use_preos) {
  1093. args.append("-DUSE_KERNEL");
  1094. }
  1095. if (libopts.use_preos) {
  1096. args.append("-DUSE_PREOS_COMPRESSED_TABLES");
  1097. }
  1098. if (libopts.use_minams) {
  1099. args.append(QString("-DMIN_AMS=%1").arg(libopts.minams));
  1100. }
  1101. if (libopts.unofficial_os) {
  1102. args.append("-DUNOFFICIAL_OS_SUPPORT");
  1103. }
  1104. if (libopts.use_preos) {
  1105. if (libopts.bss_ref_format == RT_NONE)
  1106. args.append("-DMERGE_BSS");
  1107. } else {
  1108. switch (libopts.reloc_format) {
  1109. case RT_KERNEL:
  1110. args.append("-DKERNEL_FORMAT_RELOCS");
  1111. break;
  1112. case RT_COMPRESSED:
  1113. args.append("-DCOMPRESSED_FORMAT_RELOCS");
  1114. break;
  1115. case RT_MLINK:
  1116. args.append("-DMLINK_FORMAT_RELOCS");
  1117. break;
  1118. case RT_FLINE:
  1119. args.append("-DUSE_FLINE_JUMPS");
  1120. break;
  1121. default:
  1122. break;
  1123. }
  1124. switch (libopts.rom_call_format) {
  1125. case RT_KERNEL:
  1126. args.append("-DKERNEL_FORMAT_ROM_CALLS");
  1127. break;
  1128. case RT_COMPRESSED:
  1129. args.append("-DCOMPRESSED_FORMAT_ROM_CALLS");
  1130. break;
  1131. case RT_MLINK:
  1132. args.append("-DMLINK_FORMAT_ROM_CALLS");
  1133. break;
  1134. case RT_PRECOMP:
  1135. args.append("-DOPTIMIZE_ROM_CALLS");
  1136. break;
  1137. case RT_FLINE:
  1138. args.append("-DUSE_FLINE_ROM_CALLS");
  1139. args.append("-fno-function-cse");
  1140. break;
  1141. default:
  1142. break;
  1143. }
  1144. if (libopts.opt_rom_calls) {
  1145. args.append("-DOPTIMIZE_ROM_CALLS");
  1146. }
  1147. switch (libopts.bss_ref_format) {
  1148. case RT_NONE:
  1149. args.append("-DMERGE_BSS");
  1150. break;
  1151. case RT_KERNEL:
  1152. args.append("-DKERNEL_FORMAT_BSS");
  1153. break;
  1154. case RT_COMPRESSED:
  1155. args.append("-DCOMPRESSED_FORMAT_BSS");
  1156. break;
  1157. case RT_MLINK:
  1158. args.append("-DMLINK_FORMAT_BSS");
  1159. break;
  1160. default:
  1161. break;
  1162. }
  1163. }
  1164. switch (libopts.data_ref_format) {
  1165. case RT_KERNEL:
  1166. args.append("-DKERNEL_FORMAT_DATA_VAR");
  1167. break;
  1168. case RT_COMPRESSED:
  1169. args.append("-DCOMPRESSED_FORMAT_DATA_VAR");
  1170. break;
  1171. case RT_MLINK:
  1172. args.append("-DMLINK_FORMAT_DATA_VAR");
  1173. break;
  1174. default:
  1175. break;
  1176. }
  1177. if (libopts.use_fline_jumps) {
  1178. args.append("-DUSE_FLINE_JUMPS");
  1179. if (libopts.use_4b_fline_jumps) {
  1180. args.append("-DUSE_4BYTE_FLINE_JUMPS");
  1181. }
  1182. }
  1183. if (libopts.use_internal_fline_emu) {
  1184. args.append("-DUSE_INTERNAL_FLINE_EMULATOR");
  1185. }
  1186. if (libopts.use_return_value) {
  1187. args.append("-DRETURN_VALUE");
  1188. }
  1189. if (libopts.enable_error_return) {
  1190. args.append("-DENABLE_ERROR_RETURN");
  1191. }
  1192. if (libopts.save_screen) {
  1193. args.append("-DSAVE_SCREEN");
  1194. }
  1195. return args;
  1196. }
  1197. /*
  1198. Build linker command line arguments
  1199. */
  1200. QStringList process_settings(const QString &prjNameUnicode,
  1201. QCString &projectName, QCString &dataVarName,
  1202. QCString &packFolder, QCString &packName)
  1203. {
  1204. QStringList args;
  1205. // Convert the project name to the calculator charset.
  1206. {
  1207. const unsigned short *utf16=prjNameUnicode.ucs2();
  1208. if (utf16) {
  1209. char *ti=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  1210. projectName=ti; // This is a hidden strdup (see QCString::operator=).
  1211. g_free(ti);
  1212. } else projectName=QCString();
  1213. }
  1214. // Split the PPG name into folder and file.
  1215. QString packFolderUnicode, packNameUnicode;
  1216. int slashPos=settings.pack_name.find('\\');
  1217. if (slashPos>=0) {
  1218. packFolderUnicode=settings.pack_name.left(slashPos);
  1219. packNameUnicode=settings.pack_name.mid(slashPos+1);
  1220. } else {
  1221. packNameUnicode=settings.pack_name;
  1222. }
  1223. // Convert the PPG folder name to the calculator charset.
  1224. {
  1225. const unsigned short *utf16=packFolderUnicode.ucs2();
  1226. if (utf16) {
  1227. char *ti=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  1228. packFolder=ti; // This is a hidden strdup (see QCString::operator=).
  1229. g_free(ti);
  1230. } else packFolder=QCString();
  1231. }
  1232. // Convert the PPG file name to the calculator charset.
  1233. {
  1234. const unsigned short *utf16=packNameUnicode.ucs2();
  1235. if (utf16) {
  1236. char *ti=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  1237. packName=ti; // This is a hidden strdup (see QCString::operator=).
  1238. g_free(ti);
  1239. } else packName=QCString();
  1240. }
  1241. if (settings.use_data_var && !settings.data_var.isEmpty()) {
  1242. // We can't just append this to the argument list because this needs to be
  1243. // in the calculator charset.
  1244. const unsigned short *utf16=settings.data_var.ucs2();
  1245. if (utf16) {
  1246. char *ti=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  1247. dataVarName=ti; // This is a hidden strdup (see QCString::operator=).
  1248. g_free(ti);
  1249. } else dataVarName=QCString();
  1250. if (!settings.copy_data_var) {
  1251. args.append("--data-var-copy=never");
  1252. } else if (!settings.copy_data_var_arc) {
  1253. args.append("--data-var-copy=always");
  1254. }
  1255. } else dataVarName=QCString();
  1256. if (settings.optimize_nops) {
  1257. args.append("--optimize-nops");
  1258. }
  1259. if (settings.optimize_returns) {
  1260. args.append("--optimize-returns");
  1261. }
  1262. if (settings.optimize_branches) {
  1263. args.append("--optimize-branches");
  1264. }
  1265. if (settings.optimize_moves) {
  1266. args.append("--optimize-moves");
  1267. }
  1268. if (settings.optimize_tests) {
  1269. args.append("--optimize-tests");
  1270. }
  1271. if (settings.optimize_calcs) {
  1272. args.append("--optimize-calcs");
  1273. }
  1274. if (settings.remove_unused) {
  1275. args.append("--remove-unused");
  1276. }
  1277. if (settings.cut_ranges) {
  1278. args.append("--cut-ranges");
  1279. }
  1280. if (settings.reorder_sections) {
  1281. args.append("--reorder-sections");
  1282. }
  1283. if (settings.merge_constants) {
  1284. args.append("--merge-constants");
  1285. }
  1286. if (settings.pack) {
  1287. args.append("--outputbin-main-only");
  1288. } else if (settings.outputbin) {
  1289. args.append("--outputbin");
  1290. }
  1291. if (!settings.initialize_bss) {
  1292. args.append("--omit-bss-init");
  1293. }
  1294. if (settings.fargo) {
  1295. args.append("--fargo");
  1296. }
  1297. if (settings.flash_os) {
  1298. args.append("--flash-os");
  1299. }
  1300. return args;
  1301. }