tpr.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437
  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. QString ret;
  447. if (fread(buffer,1,flen,f)<flen) {
  448. fclose(f);
  449. delete[] buffer;
  450. ret=QString::null;
  451. } else {
  452. fclose(f);
  453. if (preferences.useCalcCharset) {
  454. unsigned short *utf16=ticonv_charset_ti_to_utf16(CALC_TI89,buffer);
  455. delete[] buffer;
  456. if (!utf16)
  457. return QString::null;
  458. ret=QString::fromUcs2(utf16);
  459. g_free(utf16);
  460. } else {
  461. ret=buffer;
  462. delete[] buffer;
  463. }
  464. }
  465. if (!ret.isNull()) {
  466. // convert Windows line endings
  467. ret=ret.replace("\r\n","\n");
  468. // interpret remaining \r characters as Mac line endings
  469. ret=ret.replace('\r','\n');
  470. // remove trailing spaces if requested
  471. if (preferences.removeTrailingSpaces) {
  472. ret=ret.replace(QRegExp("((?!\n)\\s)*\n"),"\n");
  473. ret=ret.remove(QRegExp("((?!\n)\\s)*$"));
  474. }
  475. }
  476. return ret;
  477. }
  478. static QString convert_path_separators_save(QString s)
  479. {
  480. int o;
  481. #ifndef __WIN32__
  482. while ((o=s.find('/',0,TRUE))>=0)
  483. s[o]='\\';
  484. #endif
  485. return s;
  486. }
  487. //this is here because QString::ascii() returns "(null)" on a null string.
  488. const char *smartAscii(const QString &s)
  489. {
  490. if (s.isNull())
  491. return "";
  492. return s.ascii();
  493. }
  494. static int save_tpr(FILE *f,TPRDataStruct *dest)
  495. {
  496. unsigned i=0,e;
  497. QString tmp;
  498. #define boolean_param(token,setting) if (fprintf(f,token "%d\r\n",!!dest->settings.setting)<0) return -2;
  499. #define tistring_vparam(token,var) { \
  500. const unsigned short *utf16=dest->var.ucs2(); \
  501. char *ti=utf16?ticonv_charset_utf16_to_ti(CALC_TI89,utf16):reinterpret_cast<char*>(g_malloc0(1)); \
  502. if (fprintf(f,token "%s\r\n",ti)<0) {g_free(ti); return -2;} \
  503. g_free(ti); \
  504. }
  505. #define tistring_param(token,setting) tistring_vparam(token,settings.setting)
  506. #define string_param(token,setting) if (fprintf(f,token "%s\r\n",smartAscii(dest->settings.setting))<0) return -2;
  507. #define ignore_param(token) /**/
  508. if (fputs("[Settings]\r\n",f)<0) return -2;
  509. boolean_param("Archive=",archive)
  510. boolean_param("Pack=",pack)
  511. tistring_param("Packed Variable=",pack_name)
  512. tistring_vparam("Project Name=",prj_name)
  513. string_param("GCC Switches=",cc_switches)
  514. string_param("Assembler Switches=",a68k_switches)
  515. ignore_param("Linker Switches=") // Obsolete. Ignore.
  516. ignore_param("GNU Linker Switches=") // Obsolete. Ignore.
  517. string_param("GNU Assembler Switches=",as_switches)
  518. ignore_param("BSR Patch=") // Obsolete. Ignore.
  519. boolean_param("Debug Info=",debug_info)
  520. boolean_param("Standard Library=",std_lib)
  521. tistring_param("Command Line=",cmd_line)
  522. string_param("Post-Build Process=",post_build)
  523. boolean_param("Use Data Variable=",use_data_var)
  524. tistring_param("Data Variable=",data_var)
  525. boolean_param("Copy Data Variable=",copy_data_var)
  526. boolean_param("Copy Data Variable if Archived=",copy_data_var_arc)
  527. boolean_param("Optimize NOPs=",optimize_nops)
  528. boolean_param("Optimize Returns=",optimize_returns)
  529. boolean_param("Optimize Branches=",optimize_branches)
  530. boolean_param("Optimize Moves=",optimize_moves)
  531. boolean_param("Optimize Tests=",optimize_tests)
  532. boolean_param("Optimize Calculations=",optimize_calcs)
  533. boolean_param("Remove Unused Sections=",remove_unused)
  534. boolean_param("Binary Output=",outputbin)
  535. boolean_param("Fargo=",fargo)
  536. boolean_param("Flash OS=",flash_os)
  537. boolean_param("Cut Unused Ranges=",cut_ranges)
  538. boolean_param("Reorder Sections=",reorder_sections)
  539. boolean_param("Merge Constants=",merge_constants)
  540. boolean_param("Initialize BSS=",initialize_bss)
  541. #undef boolean_param
  542. #undef tistring_vparam
  543. #undef tistring_param
  544. #undef string_param
  545. #undef ignore_param
  546. #define boolean_param(token,setting) if (fprintf(f,token "%d\r\n",!!dest->libopts.setting)<0) return -2;
  547. #define reloc_param(token,setting) \
  548. switch(dest->libopts.setting) \
  549. { \
  550. case RT_NONE: \
  551. if (fprintf(f,token "None\r\n")<0) return -2; \
  552. break; \
  553. case RT_DIRECT: \
  554. if (fprintf(f,token "Direct\r\n")<0) return -2; \
  555. break; \
  556. case RT_AMS: \
  557. if (fprintf(f,token "AMS\r\n")<0) return -2; \
  558. break; \
  559. case RT_PRECOMP: \
  560. if (fprintf(f,token "Precomputed\r\n")<0) return -2; \
  561. break; \
  562. case RT_KERNEL: \
  563. if (fprintf(f,token "Kernel\r\n")<0) return -2; \
  564. break; \
  565. case RT_COMPRESSED: \
  566. if (fprintf(f,token "Compressed\r\n")<0) return -2; \
  567. break; \
  568. case RT_MLINK: \
  569. if (fprintf(f,token "MLink\r\n")<0) return -2; \
  570. break; \
  571. case RT_FLINE: \
  572. if (fprintf(f,token "F-Line\r\n")<0) return -2; \
  573. break; \
  574. }
  575. #define minams_param(token,setting) \
  576. { \
  577. int major,minor; \
  578. major=dest->libopts.setting/100; \
  579. minor=dest->libopts.setting%100; \
  580. if (fprintf(f,token "%d.%02d\r\n",major,minor)<0) return -2; \
  581. }
  582. if (fputs("\r\n[Library Options]\r\n",f)<0) return -2;
  583. boolean_param("Use TI-89=",use_ti89)
  584. boolean_param("Use TI-92 Plus=",use_ti92p)
  585. boolean_param("Use V200=",use_v200)
  586. boolean_param("Optimize Calc Consts=",opt_calc_consts)
  587. boolean_param("Use Kernel=",use_kernel)
  588. boolean_param("Use PreOS=",use_preos)
  589. boolean_param("Minimum AMS Version Defined=",use_minams)
  590. minams_param("Minimum AMS Version=",minams);
  591. boolean_param("Unofficial OS Support=",unofficial_os)
  592. reloc_param("Reloc Format=",reloc_format)
  593. reloc_param("ROM Call Format=",rom_call_format)
  594. reloc_param("BSS Ref Format=",bss_ref_format)
  595. reloc_param("Data Ref Format=",data_ref_format)
  596. boolean_param("Use F-Line Jumps=",use_fline_jumps)
  597. boolean_param("Use 4-Byte F-Line Jumps=",use_4b_fline_jumps)
  598. boolean_param("Use Internal F-Line Emulator=",use_internal_fline_emu)
  599. boolean_param("Use Return Value=",use_return_value)
  600. boolean_param("Enable Error Return=",enable_error_return)
  601. boolean_param("Save Screen=",save_screen)
  602. boolean_param("Optimize ROM Calls=",opt_rom_calls)
  603. #undef boolean_param
  604. #undef reloc_param
  605. #undef minams_param
  606. 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;
  607. #define filepath_param(token,filetype) \
  608. e=dest->filetype.path.count(); \
  609. for(i=0;i<e;i++) \
  610. { \
  611. tmp=convert_path_separators_save(smartAscii(dest->filetype.path[i])); \
  612. if (fprintf(f,token " %u=%s\r\n",i+1,smartAscii(tmp))<0) return -2; \
  613. if (!dest->filetype.folder[i].isEmpty()) \
  614. { \
  615. if (fprintf(f,token " %u Folder=%s\r\n",i+1,smartAscii(dest->filetype.folder[i]))<0) return -2; \
  616. } \
  617. }
  618. filepath_param("C File",c_files)
  619. filepath_param("GNU Assembler File",s_files)
  620. filepath_param("Header File",h_files)
  621. filepath_param("Assembler File",asm_files)
  622. filepath_param("Object File",o_files)
  623. filepath_param("Archive File",a_files)
  624. filepath_param("Text File",txt_files)
  625. filepath_param("Quill File",quill_files)
  626. filepath_param("Other File",oth_files)
  627. #undef filepath_param
  628. if (fputs("\r\n",f)<0) return -2;
  629. return 0;
  630. }
  631. void newSettings(tprSettings *settings,tprLibOpts *libopts)
  632. {
  633. tprSettings newSettings;
  634. tprLibOpts newLibOpts;
  635. *settings=newSettings;
  636. *libopts=newLibOpts;
  637. }
  638. //returns 0 on success, -1 if the file couldn't be created or -2 if fprintf,
  639. //fputs or fclose failed
  640. int saveTPR(const QString &fileName,TPRDataStruct *src)
  641. {
  642. FILE *f;
  643. int ret;
  644. f=fopen(fileName,"wb");
  645. if (!f)
  646. {
  647. return -1;
  648. }
  649. ret=save_tpr(f,src);
  650. if (fclose(f)) return -2;
  651. return ret;
  652. }
  653. void mkdir_multi(const char *fileName)
  654. {
  655. int l=strlen(fileName);
  656. char buffer[l+2];
  657. char *ptr;
  658. #ifdef __WIN32__
  659. ptr=strchr(fileName,'\\');
  660. #else
  661. ptr=strchr(fileName,'/');
  662. #endif
  663. while (ptr)
  664. {
  665. memcpy(buffer,fileName,ptr-fileName);
  666. buffer[ptr-fileName]=0;
  667. mkdir(buffer,S_IRWXU | S_IRWXG | S_IRWXO);
  668. #ifdef __WIN32__
  669. ptr=strchr(ptr+1,'\\');
  670. #else
  671. ptr=strchr(ptr+1,'/');
  672. #endif
  673. }
  674. }
  675. static int writeToFile(FILE *f, const QString &text)
  676. {
  677. if (preferences.useCalcCharset) {
  678. const unsigned short *utf16=text.ucs2();
  679. if (utf16) {
  680. char *s=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  681. size_t l=std::strlen(s);
  682. if (fwrite(s,1,l,f)<l) {
  683. g_free(s);
  684. return -2;
  685. }
  686. g_free(s);
  687. }
  688. } else {
  689. const char *s=smartAscii(text);
  690. size_t l=text.length();
  691. if (fwrite(s,1,l,f)<l) return -2;
  692. }
  693. return 0;
  694. }
  695. enum CharModes {cmNone, cmNormalText, cmNumber, cmMultiSymbol, cmString, cmChar,
  696. cmComment, cmUnchangeableLine, cmExtUnchangeableLine,
  697. cmExtUnchangeableLineString, cmTrigraph};
  698. int saveAndSplitFileText(const char *fileName, const QString &fileText,
  699. bool split, bool addCLineDirective,
  700. bool addASMLineDirective, const QString &origFileName,
  701. LineStartList *pLineStartList)
  702. {
  703. FILE *f;
  704. LineStartList lineStartList;
  705. // remove trailing spaces if requested
  706. QString text=fileText;
  707. if (preferences.removeTrailingSpaces && !text.isNull()) {
  708. text=text.replace(QRegExp("((?!\n)\\s)*\n"),"\n");
  709. text=text.remove(QRegExp("((?!\n)\\s)*$"));
  710. }
  711. f=fopen(fileName,"wb");
  712. if (!f)
  713. {
  714. mkdir_multi(fileName);
  715. f=fopen(fileName,"wb");
  716. if (!f)
  717. return -1;
  718. }
  719. if (split && preferences.splitSourceFiles && !settings.debug_info) {
  720. unsigned curPos=0, curLine=0, curCol=0, l=text.length();
  721. bool atLineStart;
  722. CharModes curMode=cmNone;
  723. #define INSERT_CHAR(ch) do {if (writeToFile(f,QString((ch)))) {fclose(f); return -2;}} while(0)
  724. #define INSERT_STRING(str) do {if (writeToFile(f,(str))) {fclose(f); return -2;}} while(0)
  725. #define ADD_LINE() do {lineStartList.append(qMakePair(curLine,curCol)); atLineStart=TRUE;} while(0)
  726. #define IS_NEWLINE() (text[curPos]=='\n')
  727. #define ADD_LINE_NEXT() do {lineStartList.append(qMakePair(curLine+(unsigned)(IS_NEWLINE()),(IS_NEWLINE())?0u:(curCol+1u))); atLineStart=TRUE;} while(0)
  728. #define NEW_LINE() do {if((!(atLineStart||IS_NEWLINE())) || (text[curPos]=='#')) {INSERT_CHAR(QChar('\n')); ADD_LINE();} curMode=cmNone;} while(0)
  729. #define SET_MULTI_CHAR_MODE(mode) do {if (curMode!=(mode)) {NEW_LINE(); curMode=(mode);}} while(0)
  730. ADD_LINE(); // Line 0
  731. for (; curPos<l; curPos++) {
  732. bool noInsert=FALSE;
  733. QChar c=text[curPos];
  734. if (c=='\n')
  735. ADD_LINE_NEXT();
  736. switch (curMode) {
  737. case cmString:
  738. if (c=='\"') {
  739. bool b=TRUE;
  740. unsigned i=curPos-1;
  741. while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
  742. b=!b;
  743. if (text[i]=='\\') --i; else i-=3;
  744. }
  745. if (b) {
  746. curMode=cmNone;
  747. noInsert=TRUE;
  748. INSERT_STRING(QString(c)+"\n");
  749. atLineStart=TRUE;
  750. ADD_LINE_NEXT();
  751. }
  752. }
  753. break;
  754. case cmChar:
  755. if (c=='\'') {
  756. bool b=TRUE;
  757. unsigned i=curPos-1;
  758. while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
  759. b=!b;
  760. if (text[i]=='\\') --i; else i-=3;
  761. }
  762. if (b) curMode=cmNone;
  763. }
  764. break;
  765. case cmComment:
  766. if ((c=='/')&&(text[curPos-1]=='*')) curMode=cmNone;
  767. break;
  768. case cmUnchangeableLine:
  769. if (c=='\n') curMode=cmNone;
  770. break;
  771. case cmExtUnchangeableLine:
  772. if ((c=='\n')&&(text[curPos-1]!='\\')) curMode=cmNone;
  773. else if (c=='\"') curMode=cmExtUnchangeableLineString;
  774. break;
  775. case cmExtUnchangeableLineString:
  776. if (c=='\"') {
  777. bool b=TRUE;
  778. unsigned i=curPos-1;
  779. while (i && ((text[i]=='\\')||(i>=2&&!text.mid(i-2,3).compare("?""?""/")))) {
  780. b=!b;
  781. if (text[i]=='\\') --i; else i-=3;
  782. }
  783. if (b) curMode=cmExtUnchangeableLine;
  784. }
  785. break;
  786. case cmTrigraph:
  787. if ((c!='?')&&((curPos+1>=l)||(text[curPos+1]!='?'))) curMode=cmNone;
  788. break;
  789. default:
  790. if (!text.mid(curPos,2).compare("//"))
  791. SET_MULTI_CHAR_MODE(cmUnchangeableLine);
  792. else if (!text.mid(curPos,2).compare("/*"))
  793. SET_MULTI_CHAR_MODE(cmComment);
  794. else if (!text.mid(curPos,2).compare("?""?""="))
  795. SET_MULTI_CHAR_MODE(cmExtUnchangeableLine);
  796. else if (!text.mid(curPos,2).compare("?""?")&&(curPos+2<l)
  797. &&QString("()/\'<>!-").contains(text[curPos+2]))
  798. SET_MULTI_CHAR_MODE(cmTrigraph);
  799. else {
  800. switch(c.unicode()) {
  801. case ' ':
  802. case '\t':
  803. if (curPos && text[curPos-1]!=' ' && text[curPos-1]!='\t')
  804. NEW_LINE();
  805. break;
  806. case 'A' ... 'Z':
  807. case 'a' ... 'z':
  808. case '0' ... '9':
  809. case '_':
  810. case '$':
  811. if (curMode!=cmNormalText && curMode!=cmNumber) {
  812. NEW_LINE();
  813. if (c>=QChar('0') && c<=QChar('9'))
  814. curMode=cmNumber;
  815. else
  816. curMode=cmNormalText;
  817. }
  818. break;
  819. case '\"':
  820. SET_MULTI_CHAR_MODE(cmString);
  821. break;
  822. case '\'':
  823. SET_MULTI_CHAR_MODE(cmChar);
  824. break;
  825. case '#':
  826. SET_MULTI_CHAR_MODE(cmExtUnchangeableLine);
  827. break;
  828. case '.':
  829. if (curMode!=cmNumber) {
  830. if ((curPos+1<l)
  831. &&(text[curPos+1]>=QChar('0')
  832. &&text[curPos+1]<=QChar('9'))) {
  833. NEW_LINE();
  834. curMode=cmNumber;
  835. } else SET_MULTI_CHAR_MODE(cmMultiSymbol);
  836. }
  837. break;
  838. case '+':
  839. case '-':
  840. if ((curMode!=cmNumber)||(curPos<=1)
  841. ||!QString("eEpP").contains(text[curPos-1]))
  842. SET_MULTI_CHAR_MODE(cmMultiSymbol);
  843. break;
  844. default:
  845. if (QString(",;()[]{}").contains(c)) {
  846. if (curMode!=cmNone) {
  847. NEW_LINE();
  848. curMode=cmNone;
  849. }
  850. if ((curPos+1<l)&&text[curPos+1]!='\n') {
  851. noInsert=TRUE;
  852. INSERT_STRING(QString(c)+"\n");
  853. ADD_LINE_NEXT();
  854. } else SET_MULTI_CHAR_MODE(cmMultiSymbol);
  855. }
  856. break;
  857. }
  858. }
  859. break;
  860. }
  861. if (!noInsert) {
  862. // Special cases:
  863. switch(c.unicode()) {
  864. // Surrogate pairs.
  865. case 0xd800 ... 0xdbff:
  866. if (curPos<l && text[curPos+1].unicode()>=0xdc00
  867. && text[curPos+1].unicode()<=0xdfff) {
  868. INSERT_STRING(QString(c)+text[curPos+1]);
  869. // Allow the UI to respond, splitting is a lengthy operation.
  870. if ((curPos++)&127)
  871. QApplication::eventLoop()->processEvents(QEventLoop::AllEvents,1000);
  872. curPos++;
  873. curCol++;
  874. break;
  875. } else goto de_fault;
  876. // x-bar and y-bar are special if we use the calculator charset.
  877. case 0x305:
  878. if (preferences.useCalcCharset && curPos<l
  879. && (text[curPos+1]=='x' || text[curPos+1]=='y')) {
  880. INSERT_STRING(QString(c)+text[curPos+1]);
  881. // Allow the UI to respond, splitting is a lengthy operation.
  882. if ((curPos++)&127)
  883. QApplication::eventLoop()->processEvents(QEventLoop::AllEvents,1000);
  884. curCol++;
  885. break;
  886. }
  887. default:
  888. de_fault:
  889. INSERT_CHAR(c);
  890. break;
  891. }
  892. if (c!='\n') atLineStart=FALSE;
  893. }
  894. if (c=='\n') {
  895. curLine++;
  896. curCol=0;
  897. } else curCol++;
  898. // Allow the UI to respond, splitting is a lengthy operation.
  899. if (curPos&127)
  900. QApplication::eventLoop()->processEvents(QEventLoop::AllEvents,1000);
  901. }
  902. NEW_LINE();
  903. #undef INSERT_CHAR
  904. #undef INSERT_STRING
  905. #undef ADD_LINE
  906. #undef IS_NEWLINE
  907. #undef ADD_LINE_NEXT
  908. #undef NEW_LINE
  909. #undef SET_MULTI_CHAR_MODE
  910. } else {
  911. if ((addCLineDirective || addASMLineDirective) && settings.debug_info) {
  912. QString escapedFileName=origFileName, lineDirective;
  913. escapedFileName.replace("\\","\\\\");
  914. escapedFileName.replace("\"","\\\"");
  915. // These have no business to be in a file name, but someone somewhere may
  916. // have that very bad idea...
  917. escapedFileName.replace("\r","\\r");
  918. escapedFileName.replace("\n","\\n");
  919. lineDirective=QString(addCLineDirective
  920. ?"#line 1 \"%1\"\n"
  921. :".appfile \"%1\"; .appline 1\n").arg(escapedFileName);
  922. // Don't use calc charset for this, it's a host file name.
  923. const char *s=smartAscii(lineDirective);
  924. size_t l=lineDirective.length();
  925. if (fwrite(s,1,l,f)<l) return -2;
  926. }
  927. if (writeToFile(f,text)) {fclose(f); return -2;}
  928. if (fwrite("\n",1,1,f)<1) {fclose(f); return -2;}
  929. }
  930. if (fclose(f)) return -2;
  931. if (pLineStartList) *pLineStartList=lineStartList;
  932. return 0;
  933. }
  934. int saveFileText(const char *fileName,const QString &fileText)
  935. {
  936. return saveAndSplitFileText(fileName,fileText,FALSE,FALSE,FALSE,QString::null,
  937. static_cast<LineStartList *>(NULL));
  938. }
  939. void kurlNewFileName(KURL &dir,const QString &newFileName)
  940. {
  941. if (newFileName[0]=='/')
  942. dir.setPath(newFileName);
  943. else
  944. dir.setFileName(newFileName);
  945. }
  946. static QString pullOutFileSuffix(const QString &srcFileName,QString &destFileName)
  947. {
  948. int a,b;
  949. QString ret;
  950. destFileName=srcFileName;
  951. a=destFileName.findRev('.');
  952. b=destFileName.findRev('/');
  953. if (a<0)
  954. return QString::null;
  955. if (a<b)
  956. return QString::null;
  957. ret=destFileName.mid(a+1);
  958. destFileName.truncate(a);
  959. return ret;
  960. }
  961. int checkFileName(const QString &fileName,const QStringList &fileNameList)
  962. {
  963. int i;
  964. QString fileName_name,fileName_suffix;
  965. QString name,suffix;
  966. fileName_suffix=pullOutFileSuffix(fileName,fileName_name);
  967. for (i=fileNameList.count()-1;i>=0;i--)
  968. {
  969. suffix=pullOutFileSuffix(fileNameList[i],name);
  970. if (!suffix.compare("c")||!suffix.compare("s")||!suffix.compare("asm")||!suffix.compare("o")||!suffix.compare("qll"))
  971. {
  972. if (!fileName_suffix.compare("c")||!fileName_suffix.compare("s")||!fileName_suffix.compare("asm")||!fileName_suffix.compare("o")||!fileName_suffix.compare("qll"))
  973. {
  974. if (!name.compare(fileName_name))
  975. return 0;
  976. }
  977. }
  978. else
  979. {
  980. if (!fileNameList[i].compare(fileName))
  981. return 0;
  982. }
  983. }
  984. return 1;
  985. }
  986. // returns 0 on success, >0 on read failure, <0 on write failure
  987. int copyFile(const char *src, const char *dest)
  988. {
  989. // This doesn't load everything at once onto the stack because it may be
  990. // used for huge binary files, which don't fit on the stack. So we copy 1KB
  991. // at a time.
  992. FILE *sf=fopen(src,"rb");
  993. if (!sf) return 1;
  994. FILE *df=fopen(dest,"wb");
  995. if (!df) {fclose(sf); return -1;}
  996. char buffer[1024];
  997. while (!ferror(sf) && !feof(sf)) {
  998. size_t bytes_read=fread(buffer,1,1024,sf);
  999. if (fwrite(buffer,1,bytes_read,df)<bytes_read) {
  1000. fclose(df);
  1001. fclose(sf);
  1002. return -2;
  1003. }
  1004. }
  1005. if (ferror(sf)) {
  1006. fclose(df);
  1007. fclose(sf);
  1008. return 2;
  1009. }
  1010. if (fclose(df)) {fclose(sf); return -3;}
  1011. if (fclose(sf)) return 3;
  1012. return 0;
  1013. }
  1014. // Returns TRUE on success, FALSE on failure.
  1015. bool moveFile(const QString &src, const QString &dest)
  1016. {
  1017. // Trap the obvious case before even bothering.
  1018. if (src==dest) return TRUE;
  1019. QDir qdir;
  1020. // First try a simple rename.
  1021. if (qdir.rename(src,dest)) return TRUE;
  1022. // That didn't work, probably because the files are not on the same file
  1023. // system. So do a copy&delete operation.
  1024. if (copyFile(src,dest)) return FALSE;
  1025. return qdir.remove(src);
  1026. }
  1027. // Replaces the first occurrence of "tempprog" in a pstarter or PPG with name.
  1028. // returns 0 on success, >0 on read failure, <0 on write failure
  1029. int insertName(const char *src, const char *dest, const char *name)
  1030. {
  1031. FILE *sf=std::fopen(src,"rb");
  1032. if (!sf) return 1;
  1033. std::fseek(sf,0,SEEK_END);
  1034. std::size_t flen=std::ftell(sf);
  1035. std::fseek(sf,0,SEEK_SET);
  1036. char *buffer = new(std::nothrow) char[flen];
  1037. if (!buffer) {std::fclose(sf); return 4;}
  1038. if (std::fread(buffer,1,flen,sf)<flen) {
  1039. delete[] buffer;
  1040. std::fclose(sf);
  1041. return 2;
  1042. }
  1043. if (fclose(sf)) {delete[] buffer; return 3;}
  1044. for (std::size_t i=0; i<=flen-8; i++) {
  1045. if (!std::memcmp(buffer+i,"tempprog",8)) {
  1046. std::strncpy(buffer+i,name,8);
  1047. break; // do only one replacement
  1048. }
  1049. }
  1050. FILE *df=std::fopen(dest,"wb");
  1051. if (!df) {delete[] buffer; return -1;}
  1052. if (std::fwrite(buffer,1,flen,df)<flen) {
  1053. delete[] buffer;
  1054. std::fclose(df);
  1055. return -2;
  1056. }
  1057. delete[] buffer;
  1058. if (std::fclose(df)) return -3;
  1059. return 0;
  1060. }
  1061. int getPathType(const QString &thePath)
  1062. {
  1063. struct stat statvar;
  1064. int result=stat(thePath,&statvar);
  1065. if (result)
  1066. return errno==ENOENT?PATH_NOTFOUND:PATH_ERROR;
  1067. if (statvar.st_mode&S_IFDIR)
  1068. return PATH_FOLDER;
  1069. if (statvar.st_mode&S_IFREG)
  1070. return PATH_FILE;
  1071. return PATH_ERROR;
  1072. }
  1073. /*
  1074. Build command line arguments (Library Options section)
  1075. */
  1076. QStringList process_libopts(void)
  1077. {
  1078. QStringList args;
  1079. if (libopts.use_ti89) {
  1080. args.append("-DUSE_TI89");
  1081. }
  1082. if (libopts.use_ti92p) {
  1083. args.append("-DUSE_TI92PLUS");
  1084. }
  1085. if (libopts.use_v200) {
  1086. args.append("-DUSE_V200");
  1087. }
  1088. if (libopts.opt_calc_consts) {
  1089. args.append("-DOPTIMIZE_CALC_CONSTS");
  1090. }
  1091. if (libopts.use_kernel || libopts.use_preos) {
  1092. args.append("-DUSE_KERNEL");
  1093. }
  1094. if (libopts.use_preos) {
  1095. args.append("-DUSE_PREOS_COMPRESSED_TABLES");
  1096. }
  1097. if (libopts.use_minams) {
  1098. args.append(QString("-DMIN_AMS=%1").arg(libopts.minams));
  1099. }
  1100. if (libopts.unofficial_os) {
  1101. args.append("-DUNOFFICIAL_OS_SUPPORT");
  1102. }
  1103. if (libopts.use_preos) {
  1104. if (libopts.bss_ref_format == RT_NONE)
  1105. args.append("-DMERGE_BSS");
  1106. } else {
  1107. switch (libopts.reloc_format) {
  1108. case RT_KERNEL:
  1109. args.append("-DKERNEL_FORMAT_RELOCS");
  1110. break;
  1111. case RT_COMPRESSED:
  1112. args.append("-DCOMPRESSED_FORMAT_RELOCS");
  1113. break;
  1114. case RT_MLINK:
  1115. args.append("-DMLINK_FORMAT_RELOCS");
  1116. break;
  1117. case RT_FLINE:
  1118. args.append("-DUSE_FLINE_JUMPS");
  1119. break;
  1120. default:
  1121. break;
  1122. }
  1123. switch (libopts.rom_call_format) {
  1124. case RT_KERNEL:
  1125. args.append("-DKERNEL_FORMAT_ROM_CALLS");
  1126. break;
  1127. case RT_COMPRESSED:
  1128. args.append("-DCOMPRESSED_FORMAT_ROM_CALLS");
  1129. break;
  1130. case RT_MLINK:
  1131. args.append("-DMLINK_FORMAT_ROM_CALLS");
  1132. break;
  1133. case RT_PRECOMP:
  1134. args.append("-DOPTIMIZE_ROM_CALLS");
  1135. break;
  1136. case RT_FLINE:
  1137. args.append("-DUSE_FLINE_ROM_CALLS");
  1138. args.append("-fno-function-cse");
  1139. break;
  1140. default:
  1141. break;
  1142. }
  1143. if (libopts.opt_rom_calls) {
  1144. args.append("-DOPTIMIZE_ROM_CALLS");
  1145. }
  1146. switch (libopts.bss_ref_format) {
  1147. case RT_NONE:
  1148. args.append("-DMERGE_BSS");
  1149. break;
  1150. case RT_KERNEL:
  1151. args.append("-DKERNEL_FORMAT_BSS");
  1152. break;
  1153. case RT_COMPRESSED:
  1154. args.append("-DCOMPRESSED_FORMAT_BSS");
  1155. break;
  1156. case RT_MLINK:
  1157. args.append("-DMLINK_FORMAT_BSS");
  1158. break;
  1159. default:
  1160. break;
  1161. }
  1162. }
  1163. switch (libopts.data_ref_format) {
  1164. case RT_KERNEL:
  1165. args.append("-DKERNEL_FORMAT_DATA_VAR");
  1166. break;
  1167. case RT_COMPRESSED:
  1168. args.append("-DCOMPRESSED_FORMAT_DATA_VAR");
  1169. break;
  1170. case RT_MLINK:
  1171. args.append("-DMLINK_FORMAT_DATA_VAR");
  1172. break;
  1173. default:
  1174. break;
  1175. }
  1176. if (libopts.use_fline_jumps) {
  1177. args.append("-DUSE_FLINE_JUMPS");
  1178. if (libopts.use_4b_fline_jumps) {
  1179. args.append("-DUSE_4BYTE_FLINE_JUMPS");
  1180. }
  1181. }
  1182. if (libopts.use_internal_fline_emu) {
  1183. args.append("-DUSE_INTERNAL_FLINE_EMULATOR");
  1184. }
  1185. if (libopts.use_return_value) {
  1186. args.append("-DRETURN_VALUE");
  1187. }
  1188. if (libopts.enable_error_return) {
  1189. args.append("-DENABLE_ERROR_RETURN");
  1190. }
  1191. if (libopts.save_screen) {
  1192. args.append("-DSAVE_SCREEN");
  1193. }
  1194. return args;
  1195. }
  1196. /*
  1197. Build linker command line arguments
  1198. */
  1199. QStringList process_settings(const QString &prjNameUnicode,
  1200. QCString &projectName, QCString &dataVarName,
  1201. QCString &packFolder, QCString &packName)
  1202. {
  1203. QStringList args;
  1204. // Convert the project name to the calculator charset.
  1205. {
  1206. const unsigned short *utf16=prjNameUnicode.ucs2();
  1207. if (utf16) {
  1208. char *ti=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  1209. projectName=ti; // This is a hidden strdup (see QCString::operator=).
  1210. g_free(ti);
  1211. } else projectName=QCString();
  1212. }
  1213. // Split the PPG name into folder and file.
  1214. QString packFolderUnicode, packNameUnicode;
  1215. int slashPos=settings.pack_name.find('\\');
  1216. if (slashPos>=0) {
  1217. packFolderUnicode=settings.pack_name.left(slashPos);
  1218. packNameUnicode=settings.pack_name.mid(slashPos+1);
  1219. } else {
  1220. packNameUnicode=settings.pack_name;
  1221. }
  1222. // Convert the PPG folder name to the calculator charset.
  1223. {
  1224. const unsigned short *utf16=packFolderUnicode.ucs2();
  1225. if (utf16) {
  1226. char *ti=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  1227. packFolder=ti; // This is a hidden strdup (see QCString::operator=).
  1228. g_free(ti);
  1229. } else packFolder=QCString();
  1230. }
  1231. // Convert the PPG file name to the calculator charset.
  1232. {
  1233. const unsigned short *utf16=packNameUnicode.ucs2();
  1234. if (utf16) {
  1235. char *ti=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  1236. packName=ti; // This is a hidden strdup (see QCString::operator=).
  1237. g_free(ti);
  1238. } else packName=QCString();
  1239. }
  1240. if (settings.use_data_var && !settings.data_var.isEmpty()) {
  1241. // We can't just append this to the argument list because this needs to be
  1242. // in the calculator charset.
  1243. const unsigned short *utf16=settings.data_var.ucs2();
  1244. if (utf16) {
  1245. char *ti=ticonv_charset_utf16_to_ti(CALC_TI89,utf16);
  1246. dataVarName=ti; // This is a hidden strdup (see QCString::operator=).
  1247. g_free(ti);
  1248. } else dataVarName=QCString();
  1249. if (!settings.copy_data_var) {
  1250. args.append("--data-var-copy=never");
  1251. } else if (!settings.copy_data_var_arc) {
  1252. args.append("--data-var-copy=always");
  1253. }
  1254. } else dataVarName=QCString();
  1255. if (settings.optimize_nops) {
  1256. args.append("--optimize-nops");
  1257. }
  1258. if (settings.optimize_returns) {
  1259. args.append("--optimize-returns");
  1260. }
  1261. if (settings.optimize_branches) {
  1262. args.append("--optimize-branches");
  1263. }
  1264. if (settings.optimize_moves) {
  1265. args.append("--optimize-moves");
  1266. }
  1267. if (settings.optimize_tests) {
  1268. args.append("--optimize-tests");
  1269. }
  1270. if (settings.optimize_calcs) {
  1271. args.append("--optimize-calcs");
  1272. }
  1273. if (settings.remove_unused) {
  1274. args.append("--remove-unused");
  1275. }
  1276. if (settings.cut_ranges) {
  1277. args.append("--cut-ranges");
  1278. }
  1279. if (settings.reorder_sections) {
  1280. args.append("--reorder-sections");
  1281. }
  1282. if (settings.merge_constants) {
  1283. args.append("--merge-constants");
  1284. }
  1285. if (settings.pack) {
  1286. args.append("--outputbin-main-only");
  1287. } else if (settings.outputbin) {
  1288. args.append("--outputbin");
  1289. }
  1290. if (!settings.initialize_bss) {
  1291. args.append("--omit-bss-init");
  1292. }
  1293. if (settings.fargo) {
  1294. args.append("--fargo");
  1295. }
  1296. if (settings.flash_os) {
  1297. args.append("--flash-os");
  1298. }
  1299. return args;
  1300. }