resrc.c 82 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394
  1. /* resrc.c -- read and write Windows rc files.
  2. Copyright (C) 1997-2022 Free Software Foundation, Inc.
  3. Written by Ian Lance Taylor, Cygnus Support.
  4. Rewritten by Kai Tietz, Onevision.
  5. This file is part of GNU Binutils.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
  17. 02110-1301, USA. */
  18. /* This file contains functions that read and write Windows rc files.
  19. These are text files that represent resources. */
  20. #include "sysdep.h"
  21. #include "bfd.h"
  22. #include "bucomm.h"
  23. #include "libiberty.h"
  24. #include "safe-ctype.h"
  25. #include "windres.h"
  26. #include <assert.h>
  27. #ifdef HAVE_SYS_WAIT_H
  28. #include <sys/wait.h>
  29. #else /* ! HAVE_SYS_WAIT_H */
  30. #if ! defined (_WIN32) || defined (__CYGWIN__)
  31. #ifndef WIFEXITED
  32. #define WIFEXITED(w) (((w)&0377) == 0)
  33. #endif
  34. #ifndef WIFSIGNALED
  35. #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
  36. #endif
  37. #ifndef WTERMSIG
  38. #define WTERMSIG(w) ((w) & 0177)
  39. #endif
  40. #ifndef WEXITSTATUS
  41. #define WEXITSTATUS(w) (((w) >> 8) & 0377)
  42. #endif
  43. #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
  44. #ifndef WIFEXITED
  45. #define WIFEXITED(w) (((w) & 0xff) == 0)
  46. #endif
  47. #ifndef WIFSIGNALED
  48. #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
  49. #endif
  50. #ifndef WTERMSIG
  51. #define WTERMSIG(w) ((w) & 0x7f)
  52. #endif
  53. #ifndef WEXITSTATUS
  54. #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
  55. #endif
  56. #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
  57. #endif /* ! HAVE_SYS_WAIT_H */
  58. #ifndef STDOUT_FILENO
  59. #define STDOUT_FILENO 1
  60. #endif
  61. #if defined (_WIN32) && ! defined (__CYGWIN__)
  62. #define popen _popen
  63. #define pclose _pclose
  64. #endif
  65. /* The default preprocessor. */
  66. #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
  67. /* We read the directory entries in a cursor or icon file into
  68. instances of this structure. */
  69. struct icondir
  70. {
  71. /* Width of image. */
  72. bfd_byte width;
  73. /* Height of image. */
  74. bfd_byte height;
  75. /* Number of colors in image. */
  76. bfd_byte colorcount;
  77. union
  78. {
  79. struct
  80. {
  81. /* Color planes. */
  82. unsigned short planes;
  83. /* Bits per pixel. */
  84. unsigned short bits;
  85. } icon;
  86. struct
  87. {
  88. /* X coordinate of hotspot. */
  89. unsigned short xhotspot;
  90. /* Y coordinate of hotspot. */
  91. unsigned short yhotspot;
  92. } cursor;
  93. } u;
  94. /* Bytes in image. */
  95. unsigned long bytes;
  96. /* File offset of image. */
  97. unsigned long offset;
  98. };
  99. /* The name of the rc file we are reading. */
  100. char *rc_filename;
  101. /* The line number in the rc file. */
  102. int rc_lineno;
  103. /* The pipe we are reading from, so that we can close it if we exit. */
  104. FILE *cpp_pipe;
  105. /* The temporary file used if we're not using popen, so we can delete it
  106. if we exit. */
  107. static char *cpp_temp_file;
  108. /* Input stream is either a file or a pipe. */
  109. static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
  110. /* As we read the rc file, we attach information to this structure. */
  111. static rc_res_directory *resources;
  112. /* The number of cursor resources we have written out. */
  113. static int cursors;
  114. /* The number of font resources we have written out. */
  115. static int fonts;
  116. /* Font directory information. */
  117. rc_fontdir *fontdirs;
  118. /* Resource info to use for fontdirs. */
  119. rc_res_res_info fontdirs_resinfo;
  120. /* The number of icon resources we have written out. */
  121. static int icons;
  122. /* The windres target bfd . */
  123. static windres_bfd wrtarget =
  124. {
  125. (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET
  126. };
  127. /* Local functions for rcdata based resource definitions. */
  128. static void define_font_rcdata (rc_res_id, const rc_res_res_info *,
  129. rc_rcdata_item *);
  130. static void define_icon_rcdata (rc_res_id, const rc_res_res_info *,
  131. rc_rcdata_item *);
  132. static void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *,
  133. rc_rcdata_item *);
  134. static void define_cursor_rcdata (rc_res_id, const rc_res_res_info *,
  135. rc_rcdata_item *);
  136. static void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *,
  137. rc_rcdata_item *);
  138. static void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *,
  139. rc_rcdata_item *);
  140. static rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *);
  141. static bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *);
  142. static int run_cmd (char *, const char *);
  143. static FILE *open_input_stream (char *);
  144. static FILE *look_for_default
  145. (char *, const char *, int, const char *, const char *);
  146. static void close_input_stream (void);
  147. static void unexpected_eof (const char *);
  148. static int get_word (FILE *, const char *);
  149. static unsigned long get_long (FILE *, const char *);
  150. static void get_data (FILE *, bfd_byte *, rc_uint_type, const char *);
  151. static void define_fontdirs (void);
  152. /* Run `cmd' and redirect the output to `redir'. */
  153. static int
  154. run_cmd (char *cmd, const char *redir)
  155. {
  156. char *s;
  157. int pid, wait_status, retcode;
  158. int i;
  159. const char **argv;
  160. char *errmsg_fmt, *errmsg_arg;
  161. char *temp_base = choose_temp_base ();
  162. int in_quote;
  163. char sep;
  164. int redir_handle = -1;
  165. int stdout_save = -1;
  166. /* Count the args. */
  167. i = 0;
  168. for (s = cmd; *s; s++)
  169. if (*s == ' ')
  170. i++;
  171. i++;
  172. argv = xmalloc (sizeof (char *) * (i + 3));
  173. i = 0;
  174. s = cmd;
  175. while (1)
  176. {
  177. while (*s == ' ' && *s != 0)
  178. s++;
  179. if (*s == 0)
  180. break;
  181. in_quote = (*s == '\'' || *s == '"');
  182. sep = (in_quote) ? *s++ : ' ';
  183. argv[i++] = s;
  184. while (*s != sep && *s != 0)
  185. s++;
  186. if (*s == 0)
  187. break;
  188. *s++ = 0;
  189. if (in_quote)
  190. s++;
  191. }
  192. argv[i++] = NULL;
  193. /* Setup the redirection. We can't use the usual fork/exec and redirect
  194. since we may be running on non-POSIX Windows host. */
  195. fflush (stdout);
  196. fflush (stderr);
  197. /* Open temporary output file. */
  198. redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
  199. if (redir_handle == -1)
  200. fatal (_("can't open temporary file `%s': %s"), redir,
  201. strerror (errno));
  202. /* Duplicate the stdout file handle so it can be restored later. */
  203. stdout_save = dup (STDOUT_FILENO);
  204. if (stdout_save == -1)
  205. fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
  206. /* Redirect stdout to our output file. */
  207. dup2 (redir_handle, STDOUT_FILENO);
  208. pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
  209. &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
  210. free (argv);
  211. /* Restore stdout to its previous setting. */
  212. dup2 (stdout_save, STDOUT_FILENO);
  213. /* Close response file. */
  214. close (redir_handle);
  215. if (pid == -1)
  216. {
  217. fatal ("%s %s: %s", errmsg_fmt, errmsg_arg, strerror (errno));
  218. return 1;
  219. }
  220. retcode = 0;
  221. pid = pwait (pid, &wait_status, 0);
  222. if (pid == -1)
  223. {
  224. fatal (_("wait: %s"), strerror (errno));
  225. retcode = 1;
  226. }
  227. else if (WIFSIGNALED (wait_status))
  228. {
  229. fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
  230. retcode = 1;
  231. }
  232. else if (WIFEXITED (wait_status))
  233. {
  234. if (WEXITSTATUS (wait_status) != 0)
  235. {
  236. fatal (_("%s exited with status %d"), cmd,
  237. WEXITSTATUS (wait_status));
  238. retcode = 1;
  239. }
  240. }
  241. else
  242. retcode = 1;
  243. return retcode;
  244. }
  245. static FILE *
  246. open_input_stream (char *cmd)
  247. {
  248. if (istream_type == ISTREAM_FILE)
  249. {
  250. char *fileprefix;
  251. fileprefix = choose_temp_base ();
  252. cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
  253. sprintf (cpp_temp_file, "%s.irc", fileprefix);
  254. free (fileprefix);
  255. if (run_cmd (cmd, cpp_temp_file))
  256. fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
  257. cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);
  258. if (cpp_pipe == NULL)
  259. fatal (_("can't open temporary file `%s': %s"),
  260. cpp_temp_file, strerror (errno));
  261. if (verbose)
  262. fprintf (stderr,
  263. _("Using temporary file `%s' to read preprocessor output\n"),
  264. cpp_temp_file);
  265. }
  266. else
  267. {
  268. cpp_pipe = popen (cmd, FOPEN_RT);
  269. if (cpp_pipe == NULL)
  270. fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
  271. if (verbose)
  272. fprintf (stderr, _("Using popen to read preprocessor output\n"));
  273. }
  274. xatexit (close_input_stream);
  275. return cpp_pipe;
  276. }
  277. /* Determine if FILENAME contains special characters that
  278. can cause problems unless the entire filename is quoted. */
  279. static int
  280. filename_need_quotes (const char *filename)
  281. {
  282. if (filename == NULL || (filename[0] == '-' && filename[1] == 0))
  283. return 0;
  284. while (*filename != 0)
  285. {
  286. switch (*filename)
  287. {
  288. case '&':
  289. case ' ':
  290. case '<':
  291. case '>':
  292. case '|':
  293. case '%':
  294. return 1;
  295. }
  296. ++filename;
  297. }
  298. return 0;
  299. }
  300. /* Look for the preprocessor program. */
  301. static FILE *
  302. look_for_default (char *cmd, const char *prefix, int end_prefix,
  303. const char *preprocargs, const char *filename)
  304. {
  305. char *space;
  306. int found;
  307. struct stat s;
  308. const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
  309. strcpy (cmd, prefix);
  310. sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
  311. space = strchr (cmd + end_prefix, ' ');
  312. if (space)
  313. *space = 0;
  314. if (
  315. #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
  316. strchr (cmd, '\\') ||
  317. #endif
  318. strchr (cmd, '/'))
  319. {
  320. found = (stat (cmd, &s) == 0
  321. #ifdef HAVE_EXECUTABLE_SUFFIX
  322. || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
  323. #endif
  324. );
  325. if (! found)
  326. {
  327. if (verbose)
  328. fprintf (stderr, _("Tried `%s'\n"), cmd);
  329. return NULL;
  330. }
  331. }
  332. strcpy (cmd, prefix);
  333. sprintf (cmd + end_prefix, "%s %s %s%s%s",
  334. DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes);
  335. if (verbose)
  336. fprintf (stderr, _("Using `%s'\n"), cmd);
  337. cpp_pipe = open_input_stream (cmd);
  338. return cpp_pipe;
  339. }
  340. /* Read an rc file. */
  341. rc_res_directory *
  342. read_rc_file (const char *filename, const char *preprocessor,
  343. const char *preprocargs, int language, int use_temp_file)
  344. {
  345. char *cmd;
  346. const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
  347. if (filename == NULL)
  348. filename = "-";
  349. /* Setup the default resource import path taken from input file. */
  350. else if (strchr (filename, '/') != NULL || strchr (filename, '\\') != NULL)
  351. {
  352. char *edit, *dir;
  353. if (filename[0] == '/'
  354. || filename[0] == '\\'
  355. || filename[1] == ':')
  356. /* Absolute path. */
  357. edit = dir = xstrdup (filename);
  358. else
  359. {
  360. /* Relative path. */
  361. edit = dir = xmalloc (strlen (filename) + 3);
  362. sprintf (dir, "./%s", filename);
  363. }
  364. /* Walk dir backwards stopping at the first directory separator. */
  365. edit += strlen (dir);
  366. while (edit > dir && (edit[-1] != '\\' && edit[-1] != '/'))
  367. {
  368. --edit;
  369. edit[0] = 0;
  370. }
  371. /* Cut off trailing slash. */
  372. --edit;
  373. edit[0] = 0;
  374. /* Convert all back slashes to forward slashes. */
  375. while ((edit = strchr (dir, '\\')) != NULL)
  376. *edit = '/';
  377. windres_add_include_dir (dir);
  378. }
  379. istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
  380. if (preprocargs == NULL)
  381. preprocargs = "";
  382. if (preprocessor)
  383. {
  384. cmd = xmalloc (strlen (preprocessor)
  385. + strlen (preprocargs)
  386. + strlen (filename)
  387. + strlen (fnquotes) * 2
  388. + 10);
  389. sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs,
  390. fnquotes, filename, fnquotes);
  391. cpp_pipe = open_input_stream (cmd);
  392. }
  393. else
  394. {
  395. char *dash, *slash, *cp;
  396. preprocessor = DEFAULT_PREPROCESSOR;
  397. cmd = xmalloc (strlen (program_name)
  398. + strlen (preprocessor)
  399. + strlen (preprocargs)
  400. + strlen (filename)
  401. + strlen (fnquotes) * 2
  402. #ifdef HAVE_EXECUTABLE_SUFFIX
  403. + strlen (EXECUTABLE_SUFFIX)
  404. #endif
  405. + 10);
  406. dash = slash = 0;
  407. for (cp = program_name; *cp; cp++)
  408. {
  409. if (*cp == '-')
  410. dash = cp;
  411. if (
  412. #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
  413. *cp == ':' || *cp == '\\' ||
  414. #endif
  415. *cp == '/')
  416. {
  417. slash = cp;
  418. dash = 0;
  419. }
  420. }
  421. cpp_pipe = 0;
  422. if (dash)
  423. {
  424. /* First, try looking for a prefixed gcc in the windres
  425. directory, with the same prefix as windres */
  426. cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1,
  427. preprocargs, filename);
  428. }
  429. if (slash && ! cpp_pipe)
  430. {
  431. /* Next, try looking for a gcc in the same directory as
  432. that windres */
  433. cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1,
  434. preprocargs, filename);
  435. }
  436. if (! cpp_pipe)
  437. {
  438. /* Sigh, try the default */
  439. cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
  440. }
  441. }
  442. free (cmd);
  443. rc_filename = xstrdup (filename);
  444. rc_lineno = 1;
  445. if (language != -1)
  446. rcparse_set_language (language);
  447. yyparse ();
  448. rcparse_discard_strings ();
  449. close_input_stream ();
  450. if (fontdirs != NULL)
  451. define_fontdirs ();
  452. free (rc_filename);
  453. rc_filename = NULL;
  454. return resources;
  455. }
  456. /* Close the input stream if it is open. */
  457. static void
  458. close_input_stream (void)
  459. {
  460. if (istream_type == ISTREAM_FILE)
  461. {
  462. if (cpp_pipe != NULL)
  463. fclose (cpp_pipe);
  464. if (cpp_temp_file != NULL)
  465. {
  466. int errno_save = errno;
  467. unlink (cpp_temp_file);
  468. errno = errno_save;
  469. free (cpp_temp_file);
  470. }
  471. }
  472. else
  473. {
  474. if (cpp_pipe != NULL)
  475. {
  476. int err;
  477. err = pclose (cpp_pipe);
  478. /* We are reading from a pipe, therefore we don't
  479. know if cpp failed or succeeded until pclose. */
  480. if (err != 0 || errno == ECHILD)
  481. {
  482. /* Since this is also run via xatexit, safeguard. */
  483. cpp_pipe = NULL;
  484. cpp_temp_file = NULL;
  485. fatal (_("preprocessing failed."));
  486. }
  487. }
  488. }
  489. /* Since this is also run via xatexit, safeguard. */
  490. cpp_pipe = NULL;
  491. cpp_temp_file = NULL;
  492. }
  493. /* Report an error while reading an rc file. */
  494. void
  495. yyerror (const char *msg)
  496. {
  497. fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
  498. }
  499. /* Issue a warning while reading an rc file. */
  500. void
  501. rcparse_warning (const char *msg)
  502. {
  503. fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
  504. }
  505. /* Die if we get an unexpected end of file. */
  506. static void
  507. unexpected_eof (const char *msg)
  508. {
  509. fatal (_("%s: unexpected EOF"), msg);
  510. }
  511. /* Read a 16 bit word from a file. The data is assumed to be little
  512. endian. */
  513. static int
  514. get_word (FILE *e, const char *msg)
  515. {
  516. int b1, b2;
  517. b1 = getc (e);
  518. b2 = getc (e);
  519. if (feof (e))
  520. unexpected_eof (msg);
  521. return ((b2 & 0xff) << 8) | (b1 & 0xff);
  522. }
  523. /* Read a 32 bit word from a file. The data is assumed to be little
  524. endian. */
  525. static unsigned long
  526. get_long (FILE *e, const char *msg)
  527. {
  528. int b1, b2, b3, b4;
  529. b1 = getc (e);
  530. b2 = getc (e);
  531. b3 = getc (e);
  532. b4 = getc (e);
  533. if (feof (e))
  534. unexpected_eof (msg);
  535. return (((((((b4 & 0xff) << 8)
  536. | (b3 & 0xff)) << 8)
  537. | (b2 & 0xff)) << 8)
  538. | (b1 & 0xff));
  539. }
  540. /* Read data from a file. This is a wrapper to do error checking. */
  541. static void
  542. get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg)
  543. {
  544. rc_uint_type got; /* $$$d */
  545. got = (rc_uint_type) fread (p, 1, c, e);
  546. if (got == c)
  547. return;
  548. fatal (_("%s: read of %lu returned %lu"),
  549. msg, (unsigned long) c, (unsigned long) got);
  550. }
  551. /* Define an accelerator resource. */
  552. void
  553. define_accelerator (rc_res_id id, const rc_res_res_info *resinfo,
  554. rc_accelerator *data)
  555. {
  556. rc_res_resource *r;
  557. r = define_standard_resource (&resources, RT_ACCELERATOR, id,
  558. resinfo->language, 0);
  559. r->type = RES_TYPE_ACCELERATOR;
  560. r->u.acc = data;
  561. r->res_info = *resinfo;
  562. }
  563. /* Define a bitmap resource. Bitmap data is stored in a file. The
  564. first 14 bytes of the file are a standard header, which is not
  565. included in the resource data. */
  566. #define BITMAP_SKIP (14)
  567. void
  568. define_bitmap (rc_res_id id, const rc_res_res_info *resinfo,
  569. const char *filename)
  570. {
  571. FILE *e;
  572. char *real_filename;
  573. struct stat s;
  574. bfd_byte *data;
  575. rc_uint_type i;
  576. rc_res_resource *r;
  577. e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
  578. if (stat (real_filename, &s) < 0)
  579. fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
  580. strerror (errno));
  581. data = (bfd_byte *) res_alloc (s.st_size - BITMAP_SKIP);
  582. for (i = 0; i < BITMAP_SKIP; i++)
  583. getc (e);
  584. get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
  585. fclose (e);
  586. free (real_filename);
  587. r = define_standard_resource (&resources, RT_BITMAP, id,
  588. resinfo->language, 0);
  589. r->type = RES_TYPE_BITMAP;
  590. r->u.data.length = s.st_size - BITMAP_SKIP;
  591. r->u.data.data = data;
  592. r->res_info = *resinfo;
  593. }
  594. /* Define a cursor resource. A cursor file may contain a set of
  595. bitmaps, each representing the same cursor at various different
  596. resolutions. They each get written out with a different ID. The
  597. real cursor resource is then a group resource which can be used to
  598. select one of the actual cursors. */
  599. void
  600. define_cursor (rc_res_id id, const rc_res_res_info *resinfo,
  601. const char *filename)
  602. {
  603. FILE *e;
  604. char *real_filename;
  605. int type, count, i;
  606. struct icondir *icondirs;
  607. int first_cursor;
  608. rc_res_resource *r;
  609. rc_group_cursor *first, **pp;
  610. e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
  611. /* A cursor file is basically an icon file. The start of the file
  612. is a three word structure. The first word is ignored. The
  613. second word is the type of data. The third word is the number of
  614. entries. */
  615. get_word (e, real_filename);
  616. type = get_word (e, real_filename);
  617. count = get_word (e, real_filename);
  618. if (type != 2)
  619. fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
  620. /* Read in the icon directory entries. */
  621. icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
  622. for (i = 0; i < count; i++)
  623. {
  624. icondirs[i].width = getc (e);
  625. icondirs[i].height = getc (e);
  626. icondirs[i].colorcount = getc (e);
  627. getc (e);
  628. icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
  629. icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
  630. icondirs[i].bytes = get_long (e, real_filename);
  631. icondirs[i].offset = get_long (e, real_filename);
  632. if (feof (e))
  633. unexpected_eof (real_filename);
  634. }
  635. /* Define each cursor as a unique resource. */
  636. first_cursor = cursors;
  637. for (i = 0; i < count; i++)
  638. {
  639. bfd_byte *data;
  640. rc_res_id name;
  641. rc_cursor *c;
  642. if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
  643. fatal (_("%s: fseek to %lu failed: %s"), real_filename,
  644. icondirs[i].offset, strerror (errno));
  645. data = (bfd_byte *) res_alloc (icondirs[i].bytes);
  646. get_data (e, data, icondirs[i].bytes, real_filename);
  647. c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
  648. c->xhotspot = icondirs[i].u.cursor.xhotspot;
  649. c->yhotspot = icondirs[i].u.cursor.yhotspot;
  650. c->length = icondirs[i].bytes;
  651. c->data = data;
  652. ++cursors;
  653. name.named = 0;
  654. name.u.id = cursors;
  655. r = define_standard_resource (&resources, RT_CURSOR, name,
  656. resinfo->language, 0);
  657. r->type = RES_TYPE_CURSOR;
  658. r->u.cursor = c;
  659. r->res_info = *resinfo;
  660. }
  661. fclose (e);
  662. free (real_filename);
  663. /* Define a cursor group resource. */
  664. first = NULL;
  665. pp = &first;
  666. for (i = 0; i < count; i++)
  667. {
  668. rc_group_cursor *cg;
  669. cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
  670. cg->next = NULL;
  671. cg->width = icondirs[i].width;
  672. cg->height = 2 * icondirs[i].height;
  673. /* FIXME: What should these be set to? */
  674. cg->planes = 1;
  675. cg->bits = 1;
  676. cg->bytes = icondirs[i].bytes + 4;
  677. cg->index = first_cursor + i + 1;
  678. *pp = cg;
  679. pp = &(*pp)->next;
  680. }
  681. free (icondirs);
  682. r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
  683. resinfo->language, 0);
  684. r->type = RES_TYPE_GROUP_CURSOR;
  685. r->u.group_cursor = first;
  686. r->res_info = *resinfo;
  687. }
  688. /* Define a dialog resource. */
  689. void
  690. define_dialog (rc_res_id id, const rc_res_res_info *resinfo,
  691. const rc_dialog *dialog)
  692. {
  693. rc_dialog *copy;
  694. rc_res_resource *r;
  695. copy = (rc_dialog *) res_alloc (sizeof *copy);
  696. *copy = *dialog;
  697. r = define_standard_resource (&resources, RT_DIALOG, id,
  698. resinfo->language, 0);
  699. r->type = RES_TYPE_DIALOG;
  700. r->u.dialog = copy;
  701. r->res_info = *resinfo;
  702. }
  703. /* Define a dialog control. This does not define a resource, but
  704. merely allocates and fills in a structure. */
  705. rc_dialog_control *
  706. define_control (const rc_res_id iid, rc_uint_type id, rc_uint_type x,
  707. rc_uint_type y, rc_uint_type width, rc_uint_type height,
  708. const rc_res_id class, rc_uint_type style,
  709. rc_uint_type exstyle)
  710. {
  711. rc_dialog_control *n;
  712. n = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
  713. n->next = NULL;
  714. n->id = id;
  715. n->style = style;
  716. n->exstyle = exstyle;
  717. n->x = x;
  718. n->y = y;
  719. n->width = width;
  720. n->height = height;
  721. n->class = class;
  722. n->text = iid;
  723. n->data = NULL;
  724. n->help = 0;
  725. return n;
  726. }
  727. rc_dialog_control *
  728. define_icon_control (rc_res_id iid, rc_uint_type id, rc_uint_type x,
  729. rc_uint_type y, rc_uint_type style,
  730. rc_uint_type exstyle, rc_uint_type help,
  731. rc_rcdata_item *data, rc_dialog_ex *ex)
  732. {
  733. rc_dialog_control *n;
  734. rc_res_id tid;
  735. rc_res_id cid;
  736. if (style == 0)
  737. style = SS_ICON | WS_CHILD | WS_VISIBLE;
  738. res_string_to_id (&tid, "");
  739. cid.named = 0;
  740. cid.u.id = CTL_STATIC;
  741. n = define_control (tid, id, x, y, 0, 0, cid, style, exstyle);
  742. n->text = iid;
  743. if (help && ! ex)
  744. rcparse_warning (_("help ID requires DIALOGEX"));
  745. if (data && ! ex)
  746. rcparse_warning (_("control data requires DIALOGEX"));
  747. n->help = help;
  748. n->data = data;
  749. return n;
  750. }
  751. /* Define a font resource. */
  752. void
  753. define_font (rc_res_id id, const rc_res_res_info *resinfo,
  754. const char *filename)
  755. {
  756. FILE *e;
  757. char *real_filename;
  758. struct stat s;
  759. bfd_byte *data;
  760. rc_res_resource *r;
  761. long offset;
  762. long fontdatalength;
  763. bfd_byte *fontdata;
  764. rc_fontdir *fd;
  765. const char *device, *face;
  766. rc_fontdir **pp;
  767. e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
  768. if (stat (real_filename, &s) < 0)
  769. fatal (_("stat failed on font file `%s': %s"), real_filename,
  770. strerror (errno));
  771. data = (bfd_byte *) res_alloc (s.st_size);
  772. get_data (e, data, s.st_size, real_filename);
  773. fclose (e);
  774. free (real_filename);
  775. r = define_standard_resource (&resources, RT_FONT, id,
  776. resinfo->language, 0);
  777. r->type = RES_TYPE_FONT;
  778. r->u.data.length = s.st_size;
  779. r->u.data.data = data;
  780. r->res_info = *resinfo;
  781. /* For each font resource, we must add an entry in the FONTDIR
  782. resource. The FONTDIR resource includes some strings in the font
  783. file. To find them, we have to do some magic on the data we have
  784. read. */
  785. offset = ((((((data[47] << 8)
  786. | data[46]) << 8)
  787. | data[45]) << 8)
  788. | data[44]);
  789. if (offset > 0 && offset < s.st_size)
  790. device = (char *) data + offset;
  791. else
  792. device = "";
  793. offset = ((((((data[51] << 8)
  794. | data[50]) << 8)
  795. | data[49]) << 8)
  796. | data[48]);
  797. if (offset > 0 && offset < s.st_size)
  798. face = (char *) data + offset;
  799. else
  800. face = "";
  801. ++fonts;
  802. fontdatalength = 58 + strlen (device) + strlen (face);
  803. fontdata = (bfd_byte *) res_alloc (fontdatalength);
  804. memcpy (fontdata, data, 56);
  805. strcpy ((char *) fontdata + 56, device);
  806. strcpy ((char *) fontdata + 57 + strlen (device), face);
  807. fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
  808. fd->next = NULL;
  809. fd->index = fonts;
  810. fd->length = fontdatalength;
  811. fd->data = fontdata;
  812. for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
  813. ;
  814. *pp = fd;
  815. /* For the single fontdirs resource, we always use the resource
  816. information of the last font. I don't know what else to do. */
  817. fontdirs_resinfo = *resinfo;
  818. }
  819. static void
  820. define_font_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
  821. rc_rcdata_item *data)
  822. {
  823. rc_res_resource *r;
  824. rc_uint_type len_data;
  825. bfd_byte *pb_data;
  826. r = define_standard_resource (&resources, RT_FONT, id,
  827. resinfo->language, 0);
  828. pb_data = rcdata_render_as_buffer (data, &len_data);
  829. r->type = RES_TYPE_FONT;
  830. r->u.data.length = len_data;
  831. r->u.data.data = pb_data;
  832. r->res_info = *resinfo;
  833. }
  834. /* Define the fontdirs resource. This is called after the entire rc
  835. file has been parsed, if any font resources were seen. */
  836. static void
  837. define_fontdirs (void)
  838. {
  839. rc_res_resource *r;
  840. rc_res_id id;
  841. id.named = 0;
  842. id.u.id = 1;
  843. r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
  844. r->type = RES_TYPE_FONTDIR;
  845. r->u.fontdir = fontdirs;
  846. r->res_info = fontdirs_resinfo;
  847. }
  848. static bfd_byte *
  849. rcdata_render_as_buffer (const rc_rcdata_item *data, rc_uint_type *plen)
  850. {
  851. const rc_rcdata_item *d;
  852. bfd_byte *ret = NULL, *pret;
  853. rc_uint_type len = 0;
  854. for (d = data; d != NULL; d = d->next)
  855. len += rcdata_copy (d, NULL);
  856. if (len != 0)
  857. {
  858. ret = pret = (bfd_byte *) res_alloc (len);
  859. for (d = data; d != NULL; d = d->next)
  860. pret += rcdata_copy (d, pret);
  861. }
  862. if (plen)
  863. *plen = len;
  864. return ret;
  865. }
  866. static void
  867. define_fontdir_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
  868. rc_rcdata_item *data)
  869. {
  870. rc_res_resource *r;
  871. rc_fontdir *fd, *fd_first, *fd_cur;
  872. rc_uint_type len_data;
  873. bfd_byte *pb_data;
  874. rc_uint_type c;
  875. fd_cur = fd_first = NULL;
  876. r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
  877. pb_data = rcdata_render_as_buffer (data, &len_data);
  878. if (pb_data)
  879. {
  880. rc_uint_type off = 2;
  881. c = windres_get_16 (&wrtarget, pb_data, len_data);
  882. for (; c > 0; c--)
  883. {
  884. size_t len;
  885. rc_uint_type safe_pos = off;
  886. const struct bin_fontdir_item *bfi;
  887. bfi = (const struct bin_fontdir_item *) pb_data + off;
  888. fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
  889. fd->index = windres_get_16 (&wrtarget, bfi->index, len_data - off);
  890. fd->data = pb_data + off;
  891. off += 56;
  892. len = strlen ((char *) bfi->device_name) + 1;
  893. off += (rc_uint_type) len;
  894. off += (rc_uint_type) strlen ((char *) bfi->device_name + len) + 1;
  895. fd->length = (off - safe_pos);
  896. fd->next = NULL;
  897. if (fd_first == NULL)
  898. fd_first = fd;
  899. else
  900. fd_cur->next = fd;
  901. fd_cur = fd;
  902. }
  903. }
  904. r->type = RES_TYPE_FONTDIR;
  905. r->u.fontdir = fd_first;
  906. r->res_info = *resinfo;
  907. }
  908. static void define_messagetable_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
  909. rc_rcdata_item *data)
  910. {
  911. rc_res_resource *r;
  912. rc_uint_type len_data;
  913. bfd_byte *pb_data;
  914. r = define_standard_resource (&resources, RT_MESSAGETABLE, id, resinfo->language, 0);
  915. pb_data = rcdata_render_as_buffer (data, &len_data);
  916. r->type = RES_TYPE_MESSAGETABLE;
  917. r->u.data.length = len_data;
  918. r->u.data.data = pb_data;
  919. r->res_info = *resinfo;
  920. }
  921. /* Define an icon resource. An icon file may contain a set of
  922. bitmaps, each representing the same icon at various different
  923. resolutions. They each get written out with a different ID. The
  924. real icon resource is then a group resource which can be used to
  925. select one of the actual icon bitmaps. */
  926. void
  927. define_icon (rc_res_id id, const rc_res_res_info *resinfo,
  928. const char *filename)
  929. {
  930. FILE *e;
  931. char *real_filename;
  932. int type, count, i;
  933. struct icondir *icondirs;
  934. int first_icon;
  935. rc_res_resource *r;
  936. rc_group_icon *first, **pp;
  937. e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
  938. /* The start of an icon file is a three word structure. The first
  939. word is ignored. The second word is the type of data. The third
  940. word is the number of entries. */
  941. get_word (e, real_filename);
  942. type = get_word (e, real_filename);
  943. count = get_word (e, real_filename);
  944. if (type != 1)
  945. fatal (_("icon file `%s' does not contain icon data"), real_filename);
  946. /* Read in the icon directory entries. */
  947. icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
  948. for (i = 0; i < count; i++)
  949. {
  950. icondirs[i].width = getc (e);
  951. icondirs[i].height = getc (e);
  952. icondirs[i].colorcount = getc (e);
  953. getc (e);
  954. icondirs[i].u.icon.planes = get_word (e, real_filename);
  955. icondirs[i].u.icon.bits = get_word (e, real_filename);
  956. icondirs[i].bytes = get_long (e, real_filename);
  957. icondirs[i].offset = get_long (e, real_filename);
  958. if (feof (e))
  959. unexpected_eof (real_filename);
  960. }
  961. /* Define each icon as a unique resource. */
  962. first_icon = icons;
  963. for (i = 0; i < count; i++)
  964. {
  965. bfd_byte *data;
  966. rc_res_id name;
  967. if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
  968. fatal (_("%s: fseek to %lu failed: %s"), real_filename,
  969. icondirs[i].offset, strerror (errno));
  970. data = (bfd_byte *) res_alloc (icondirs[i].bytes);
  971. get_data (e, data, icondirs[i].bytes, real_filename);
  972. ++icons;
  973. name.named = 0;
  974. name.u.id = icons;
  975. r = define_standard_resource (&resources, RT_ICON, name,
  976. resinfo->language, 0);
  977. r->type = RES_TYPE_ICON;
  978. r->u.data.length = icondirs[i].bytes;
  979. r->u.data.data = data;
  980. r->res_info = *resinfo;
  981. }
  982. fclose (e);
  983. free (real_filename);
  984. /* Define an icon group resource. */
  985. first = NULL;
  986. pp = &first;
  987. for (i = 0; i < count; i++)
  988. {
  989. rc_group_icon *cg;
  990. /* For some reason, at least in some files the planes and bits
  991. are zero. We instead set them from the color. This is
  992. copied from rcl. */
  993. cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
  994. cg->next = NULL;
  995. cg->width = icondirs[i].width;
  996. cg->height = icondirs[i].height;
  997. cg->colors = icondirs[i].colorcount;
  998. if (icondirs[i].u.icon.planes)
  999. cg->planes = icondirs[i].u.icon.planes;
  1000. else
  1001. cg->planes = 1;
  1002. if (icondirs[i].u.icon.bits)
  1003. cg->bits = icondirs[i].u.icon.bits;
  1004. else
  1005. {
  1006. cg->bits = 0;
  1007. while ((1L << cg->bits) < cg->colors)
  1008. ++cg->bits;
  1009. }
  1010. cg->bytes = icondirs[i].bytes;
  1011. cg->index = first_icon + i + 1;
  1012. *pp = cg;
  1013. pp = &(*pp)->next;
  1014. }
  1015. free (icondirs);
  1016. r = define_standard_resource (&resources, RT_GROUP_ICON, id,
  1017. resinfo->language, 0);
  1018. r->type = RES_TYPE_GROUP_ICON;
  1019. r->u.group_icon = first;
  1020. r->res_info = *resinfo;
  1021. }
  1022. static void
  1023. define_group_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
  1024. rc_rcdata_item *data)
  1025. {
  1026. rc_res_resource *r;
  1027. rc_group_icon *cg, *first, *cur;
  1028. rc_uint_type len_data;
  1029. bfd_byte *pb_data;
  1030. pb_data = rcdata_render_as_buffer (data, &len_data);
  1031. cur = NULL;
  1032. first = NULL;
  1033. while (len_data >= 6)
  1034. {
  1035. int c, i;
  1036. unsigned short type;
  1037. type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
  1038. if (type != 1)
  1039. fatal (_("unexpected group icon type %d"), type);
  1040. c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
  1041. len_data -= 6;
  1042. pb_data += 6;
  1043. for (i = 0; i < c; i++)
  1044. {
  1045. if (len_data < 14)
  1046. fatal ("too small group icon rcdata");
  1047. cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
  1048. cg->next = NULL;
  1049. cg->width = pb_data[0];
  1050. cg->height = pb_data[1];
  1051. cg->colors = pb_data[2];
  1052. cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
  1053. cg->bits = windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
  1054. cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
  1055. cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
  1056. if (! first)
  1057. first = cg;
  1058. else
  1059. cur->next = cg;
  1060. cur = cg;
  1061. pb_data += 14;
  1062. len_data -= 14;
  1063. }
  1064. }
  1065. r = define_standard_resource (&resources, RT_GROUP_ICON, id,
  1066. resinfo->language, 0);
  1067. r->type = RES_TYPE_GROUP_ICON;
  1068. r->u.group_icon = first;
  1069. r->res_info = *resinfo;
  1070. }
  1071. static void
  1072. define_group_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
  1073. rc_rcdata_item *data)
  1074. {
  1075. rc_res_resource *r;
  1076. rc_group_cursor *cg, *first, *cur;
  1077. rc_uint_type len_data;
  1078. bfd_byte *pb_data;
  1079. pb_data = rcdata_render_as_buffer (data, &len_data);
  1080. first = cur = NULL;
  1081. while (len_data >= 6)
  1082. {
  1083. int c, i;
  1084. unsigned short type;
  1085. type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
  1086. if (type != 2)
  1087. fatal (_("unexpected group cursor type %d"), type);
  1088. c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
  1089. len_data -= 6;
  1090. pb_data += 6;
  1091. for (i = 0; i < c; i++)
  1092. {
  1093. if (len_data < 14)
  1094. fatal ("too small group icon rcdata");
  1095. cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
  1096. cg->next = NULL;
  1097. cg->width = windres_get_16 (&wrtarget, pb_data, len_data);
  1098. cg->height = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
  1099. cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
  1100. cg->bits = windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
  1101. cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
  1102. cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
  1103. if (! first)
  1104. first = cg;
  1105. else
  1106. cur->next = cg;
  1107. cur = cg;
  1108. pb_data += 14;
  1109. len_data -= 14;
  1110. }
  1111. }
  1112. r = define_standard_resource (&resources, RT_GROUP_ICON, id,
  1113. resinfo->language, 0);
  1114. r->type = RES_TYPE_GROUP_CURSOR;
  1115. r->u.group_cursor = first;
  1116. r->res_info = *resinfo;
  1117. }
  1118. static void
  1119. define_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
  1120. rc_rcdata_item *data)
  1121. {
  1122. rc_cursor *c;
  1123. rc_res_resource *r;
  1124. rc_uint_type len_data;
  1125. bfd_byte *pb_data;
  1126. pb_data = rcdata_render_as_buffer (data, &len_data);
  1127. c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
  1128. c->xhotspot = windres_get_16 (&wrtarget, pb_data, len_data);
  1129. c->yhotspot = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
  1130. c->length = len_data - BIN_CURSOR_SIZE;
  1131. c->data = (const bfd_byte *) (data + BIN_CURSOR_SIZE);
  1132. r = define_standard_resource (&resources, RT_CURSOR, id, resinfo->language, 0);
  1133. r->type = RES_TYPE_CURSOR;
  1134. r->u.cursor = c;
  1135. r->res_info = *resinfo;
  1136. }
  1137. static void
  1138. define_bitmap_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
  1139. rc_rcdata_item *data)
  1140. {
  1141. rc_res_resource *r;
  1142. rc_uint_type len_data;
  1143. bfd_byte *pb_data;
  1144. pb_data = rcdata_render_as_buffer (data, &len_data);
  1145. r = define_standard_resource (&resources, RT_BITMAP, id, resinfo->language, 0);
  1146. r->type = RES_TYPE_BITMAP;
  1147. r->u.data.length = len_data;
  1148. r->u.data.data = pb_data;
  1149. r->res_info = *resinfo;
  1150. }
  1151. static void
  1152. define_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
  1153. rc_rcdata_item *data)
  1154. {
  1155. rc_res_resource *r;
  1156. rc_uint_type len_data;
  1157. bfd_byte *pb_data;
  1158. pb_data = rcdata_render_as_buffer (data, &len_data);
  1159. r = define_standard_resource (&resources, RT_ICON, id, resinfo->language, 0);
  1160. r->type = RES_TYPE_ICON;
  1161. r->u.data.length = len_data;
  1162. r->u.data.data = pb_data;
  1163. r->res_info = *resinfo;
  1164. }
  1165. /* Define a menu resource. */
  1166. void
  1167. define_menu (rc_res_id id, const rc_res_res_info *resinfo,
  1168. rc_menuitem *menuitems)
  1169. {
  1170. rc_menu *m;
  1171. rc_res_resource *r;
  1172. m = (rc_menu *) res_alloc (sizeof (rc_menu));
  1173. m->items = menuitems;
  1174. m->help = 0;
  1175. r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
  1176. r->type = RES_TYPE_MENU;
  1177. r->u.menu = m;
  1178. r->res_info = *resinfo;
  1179. }
  1180. /* Define a menu item. This does not define a resource, but merely
  1181. allocates and fills in a structure. */
  1182. rc_menuitem *
  1183. define_menuitem (const unichar *text, rc_uint_type menuid, rc_uint_type type,
  1184. rc_uint_type state, rc_uint_type help,
  1185. rc_menuitem *menuitems)
  1186. {
  1187. rc_menuitem *mi;
  1188. mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
  1189. mi->next = NULL;
  1190. mi->type = type;
  1191. mi->state = state;
  1192. mi->id = menuid;
  1193. mi->text = unichar_dup (text);
  1194. mi->help = help;
  1195. mi->popup = menuitems;
  1196. return mi;
  1197. }
  1198. /* Define a messagetable resource. */
  1199. void
  1200. define_messagetable (rc_res_id id, const rc_res_res_info *resinfo,
  1201. const char *filename)
  1202. {
  1203. FILE *e;
  1204. char *real_filename;
  1205. struct stat s;
  1206. bfd_byte *data;
  1207. rc_res_resource *r;
  1208. e = open_file_search (filename, FOPEN_RB, "messagetable file",
  1209. &real_filename);
  1210. if (stat (real_filename, &s) < 0)
  1211. fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
  1212. strerror (errno));
  1213. data = (bfd_byte *) res_alloc (s.st_size);
  1214. get_data (e, data, s.st_size, real_filename);
  1215. fclose (e);
  1216. free (real_filename);
  1217. r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
  1218. resinfo->language, 0);
  1219. r->type = RES_TYPE_MESSAGETABLE;
  1220. r->u.data.length = s.st_size;
  1221. r->u.data.data = data;
  1222. r->res_info = *resinfo;
  1223. }
  1224. /* Define an rcdata resource. */
  1225. void
  1226. define_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
  1227. rc_rcdata_item *data)
  1228. {
  1229. rc_res_resource *r;
  1230. r = define_standard_resource (&resources, RT_RCDATA, id,
  1231. resinfo->language, 0);
  1232. r->type = RES_TYPE_RCDATA;
  1233. r->u.rcdata = data;
  1234. r->res_info = *resinfo;
  1235. }
  1236. /* Create an rcdata item holding a string. */
  1237. rc_rcdata_item *
  1238. define_rcdata_string (const char *string, rc_uint_type len)
  1239. {
  1240. rc_rcdata_item *ri;
  1241. char *s;
  1242. ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  1243. ri->next = NULL;
  1244. ri->type = RCDATA_STRING;
  1245. ri->u.string.length = len;
  1246. s = (char *) res_alloc (len);
  1247. memcpy (s, string, len);
  1248. ri->u.string.s = s;
  1249. return ri;
  1250. }
  1251. /* Create an rcdata item holding a unicode string. */
  1252. rc_rcdata_item *
  1253. define_rcdata_unistring (const unichar *string, rc_uint_type len)
  1254. {
  1255. rc_rcdata_item *ri;
  1256. unichar *s;
  1257. ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  1258. ri->next = NULL;
  1259. ri->type = RCDATA_WSTRING;
  1260. ri->u.wstring.length = len;
  1261. s = (unichar *) res_alloc (len * sizeof (unichar));
  1262. memcpy (s, string, len * sizeof (unichar));
  1263. ri->u.wstring.w = s;
  1264. return ri;
  1265. }
  1266. /* Create an rcdata item holding a number. */
  1267. rc_rcdata_item *
  1268. define_rcdata_number (rc_uint_type val, int dword)
  1269. {
  1270. rc_rcdata_item *ri;
  1271. ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  1272. ri->next = NULL;
  1273. ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
  1274. ri->u.word = val;
  1275. return ri;
  1276. }
  1277. /* Define a stringtable resource. This is called for each string
  1278. which appears in a STRINGTABLE statement. */
  1279. void
  1280. define_stringtable (const rc_res_res_info *resinfo,
  1281. rc_uint_type stringid, const unichar *string, int len)
  1282. {
  1283. unichar *h;
  1284. rc_res_id id;
  1285. rc_res_resource *r;
  1286. id.named = 0;
  1287. id.u.id = (stringid >> 4) + 1;
  1288. r = define_standard_resource (&resources, RT_STRING, id,
  1289. resinfo->language, 1);
  1290. if (r->type == RES_TYPE_UNINITIALIZED)
  1291. {
  1292. int i;
  1293. r->type = RES_TYPE_STRINGTABLE;
  1294. r->u.stringtable = ((rc_stringtable *)
  1295. res_alloc (sizeof (rc_stringtable)));
  1296. for (i = 0; i < 16; i++)
  1297. {
  1298. r->u.stringtable->strings[i].length = 0;
  1299. r->u.stringtable->strings[i].string = NULL;
  1300. }
  1301. r->res_info = *resinfo;
  1302. }
  1303. h = (unichar *) res_alloc ((len + 1) * sizeof (unichar));
  1304. if (len)
  1305. memcpy (h, string, len * sizeof (unichar));
  1306. h[len] = 0;
  1307. r->u.stringtable->strings[stringid & 0xf].length = (rc_uint_type) len;
  1308. r->u.stringtable->strings[stringid & 0xf].string = h;
  1309. }
  1310. void
  1311. define_toolbar (rc_res_id id, rc_res_res_info *resinfo, rc_uint_type width, rc_uint_type height,
  1312. rc_toolbar_item *items)
  1313. {
  1314. rc_toolbar *t;
  1315. rc_res_resource *r;
  1316. t = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
  1317. t->button_width = width;
  1318. t->button_height = height;
  1319. t->nitems = 0;
  1320. t->items = items;
  1321. while (items != NULL)
  1322. {
  1323. t->nitems+=1;
  1324. items = items->next;
  1325. }
  1326. r = define_standard_resource (&resources, RT_TOOLBAR, id, resinfo->language, 0);
  1327. r->type = RES_TYPE_TOOLBAR;
  1328. r->u.toolbar = t;
  1329. r->res_info = *resinfo;
  1330. }
  1331. /* Define a user data resource where the data is in the rc file. */
  1332. void
  1333. define_user_data (rc_res_id id, rc_res_id type,
  1334. const rc_res_res_info *resinfo,
  1335. rc_rcdata_item *data)
  1336. {
  1337. rc_res_id ids[3];
  1338. rc_res_resource *r;
  1339. bfd_byte *pb_data;
  1340. rc_uint_type len_data;
  1341. /* We have to check if the binary data is parsed specially. */
  1342. if (type.named == 0)
  1343. {
  1344. switch (type.u.id)
  1345. {
  1346. case RT_FONTDIR:
  1347. define_fontdir_rcdata (id, resinfo, data);
  1348. return;
  1349. case RT_FONT:
  1350. define_font_rcdata (id, resinfo, data);
  1351. return;
  1352. case RT_ICON:
  1353. define_icon_rcdata (id, resinfo, data);
  1354. return;
  1355. case RT_BITMAP:
  1356. define_bitmap_rcdata (id, resinfo, data);
  1357. return;
  1358. case RT_CURSOR:
  1359. define_cursor_rcdata (id, resinfo, data);
  1360. return;
  1361. case RT_GROUP_ICON:
  1362. define_group_icon_rcdata (id, resinfo, data);
  1363. return;
  1364. case RT_GROUP_CURSOR:
  1365. define_group_cursor_rcdata (id, resinfo, data);
  1366. return;
  1367. case RT_MESSAGETABLE:
  1368. define_messagetable_rcdata (id, resinfo, data);
  1369. return;
  1370. default:
  1371. /* Treat as normal user-data. */
  1372. break;
  1373. }
  1374. }
  1375. ids[0] = type;
  1376. ids[1] = id;
  1377. ids[2].named = 0;
  1378. ids[2].u.id = resinfo->language;
  1379. r = define_resource (& resources, 3, ids, 0);
  1380. r->type = RES_TYPE_USERDATA;
  1381. r->u.userdata = ((rc_rcdata_item *)
  1382. res_alloc (sizeof (rc_rcdata_item)));
  1383. r->u.userdata->next = NULL;
  1384. r->u.userdata->type = RCDATA_BUFFER;
  1385. pb_data = rcdata_render_as_buffer (data, &len_data);
  1386. r->u.userdata->u.buffer.length = len_data;
  1387. r->u.userdata->u.buffer.data = pb_data;
  1388. r->res_info = *resinfo;
  1389. }
  1390. void
  1391. define_rcdata_file (rc_res_id id, const rc_res_res_info *resinfo,
  1392. const char *filename)
  1393. {
  1394. rc_rcdata_item *ri;
  1395. FILE *e;
  1396. char *real_filename;
  1397. struct stat s;
  1398. bfd_byte *data;
  1399. e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
  1400. if (stat (real_filename, &s) < 0)
  1401. fatal (_("stat failed on file `%s': %s"), real_filename,
  1402. strerror (errno));
  1403. data = (bfd_byte *) res_alloc (s.st_size);
  1404. get_data (e, data, s.st_size, real_filename);
  1405. fclose (e);
  1406. free (real_filename);
  1407. ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
  1408. ri->next = NULL;
  1409. ri->type = RCDATA_BUFFER;
  1410. ri->u.buffer.length = s.st_size;
  1411. ri->u.buffer.data = data;
  1412. define_rcdata (id, resinfo, ri);
  1413. }
  1414. /* Define a user data resource where the data is in a file. */
  1415. void
  1416. define_user_file (rc_res_id id, rc_res_id type,
  1417. const rc_res_res_info *resinfo, const char *filename)
  1418. {
  1419. FILE *e;
  1420. char *real_filename;
  1421. struct stat s;
  1422. bfd_byte *data;
  1423. rc_res_id ids[3];
  1424. rc_res_resource *r;
  1425. e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
  1426. if (stat (real_filename, &s) < 0)
  1427. fatal (_("stat failed on file `%s': %s"), real_filename,
  1428. strerror (errno));
  1429. data = (bfd_byte *) res_alloc (s.st_size);
  1430. get_data (e, data, s.st_size, real_filename);
  1431. fclose (e);
  1432. free (real_filename);
  1433. ids[0] = type;
  1434. ids[1] = id;
  1435. ids[2].named = 0;
  1436. ids[2].u.id = resinfo->language;
  1437. r = define_resource (&resources, 3, ids, 0);
  1438. r->type = RES_TYPE_USERDATA;
  1439. r->u.userdata = ((rc_rcdata_item *)
  1440. res_alloc (sizeof (rc_rcdata_item)));
  1441. r->u.userdata->next = NULL;
  1442. r->u.userdata->type = RCDATA_BUFFER;
  1443. r->u.userdata->u.buffer.length = s.st_size;
  1444. r->u.userdata->u.buffer.data = data;
  1445. r->res_info = *resinfo;
  1446. }
  1447. /* Define a versioninfo resource. */
  1448. void
  1449. define_versioninfo (rc_res_id id, rc_uint_type language,
  1450. rc_fixed_versioninfo *fixedverinfo,
  1451. rc_ver_info *verinfo)
  1452. {
  1453. rc_res_resource *r;
  1454. r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
  1455. r->type = RES_TYPE_VERSIONINFO;
  1456. r->u.versioninfo = ((rc_versioninfo *)
  1457. res_alloc (sizeof (rc_versioninfo)));
  1458. r->u.versioninfo->fixed = fixedverinfo;
  1459. r->u.versioninfo->var = verinfo;
  1460. r->res_info.language = language;
  1461. }
  1462. /* Add string version info to a list of version information. */
  1463. rc_ver_info *
  1464. append_ver_stringfileinfo (rc_ver_info *verinfo,
  1465. rc_ver_stringtable *stringtables)
  1466. {
  1467. rc_ver_info *vi, **pp;
  1468. vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
  1469. vi->next = NULL;
  1470. vi->type = VERINFO_STRING;
  1471. vi->u.string.stringtables = stringtables;
  1472. for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
  1473. ;
  1474. *pp = vi;
  1475. return verinfo;
  1476. }
  1477. rc_ver_stringtable *
  1478. append_ver_stringtable (rc_ver_stringtable *stringtable,
  1479. const char *language,
  1480. rc_ver_stringinfo *strings)
  1481. {
  1482. rc_ver_stringtable *vst, **pp;
  1483. vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable));
  1484. vst->next = NULL;
  1485. unicode_from_ascii ((rc_uint_type *) NULL, &vst->language, language);
  1486. vst->strings = strings;
  1487. for (pp = &stringtable; *pp != NULL; pp = &(*pp)->next)
  1488. ;
  1489. *pp = vst;
  1490. return stringtable;
  1491. }
  1492. /* Add variable version info to a list of version information. */
  1493. rc_ver_info *
  1494. append_ver_varfileinfo (rc_ver_info *verinfo, const unichar *key,
  1495. rc_ver_varinfo *var)
  1496. {
  1497. rc_ver_info *vi, **pp;
  1498. vi = (rc_ver_info *) res_alloc (sizeof *vi);
  1499. vi->next = NULL;
  1500. vi->type = VERINFO_VAR;
  1501. vi->u.var.key = unichar_dup (key);
  1502. vi->u.var.var = var;
  1503. for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
  1504. ;
  1505. *pp = vi;
  1506. return verinfo;
  1507. }
  1508. /* Append version string information to a list. */
  1509. rc_ver_stringinfo *
  1510. append_verval (rc_ver_stringinfo *strings, const unichar *key,
  1511. const unichar *value)
  1512. {
  1513. rc_ver_stringinfo *vs, **pp;
  1514. vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo));
  1515. vs->next = NULL;
  1516. vs->key = unichar_dup (key);
  1517. vs->value = unichar_dup (value);
  1518. for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
  1519. ;
  1520. *pp = vs;
  1521. return strings;
  1522. }
  1523. /* Append version variable information to a list. */
  1524. rc_ver_varinfo *
  1525. append_vertrans (rc_ver_varinfo *var, rc_uint_type language,
  1526. rc_uint_type charset)
  1527. {
  1528. rc_ver_varinfo *vv, **pp;
  1529. vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
  1530. vv->next = NULL;
  1531. vv->language = language;
  1532. vv->charset = charset;
  1533. for (pp = &var; *pp != NULL; pp = &(*pp)->next)
  1534. ;
  1535. *pp = vv;
  1536. return var;
  1537. }
  1538. /* Local functions used to write out an rc file. */
  1539. static void indent (FILE *, int);
  1540. static void write_rc_directory (FILE *, const rc_res_directory *, const rc_res_id *,
  1541. const rc_res_id *, rc_uint_type *, int);
  1542. static void write_rc_subdir (FILE *, const rc_res_entry *, const rc_res_id *,
  1543. const rc_res_id *, rc_uint_type *, int);
  1544. static void write_rc_resource (FILE *, const rc_res_id *, const rc_res_id *,
  1545. const rc_res_resource *, rc_uint_type *);
  1546. static void write_rc_accelerators (FILE *, const rc_accelerator *);
  1547. static void write_rc_cursor (FILE *, const rc_cursor *);
  1548. static void write_rc_group_cursor (FILE *, const rc_group_cursor *);
  1549. static void write_rc_dialog (FILE *, const rc_dialog *);
  1550. static void write_rc_dialog_control (FILE *, const rc_dialog_control *);
  1551. static void write_rc_fontdir (FILE *, const rc_fontdir *);
  1552. static void write_rc_group_icon (FILE *, const rc_group_icon *);
  1553. static void write_rc_menu (FILE *, const rc_menu *, int);
  1554. static void write_rc_toolbar (FILE *, const rc_toolbar *);
  1555. static void write_rc_menuitems (FILE *, const rc_menuitem *, int, int);
  1556. static void write_rc_messagetable (FILE *, rc_uint_type , const bfd_byte *);
  1557. static void write_rc_datablock (FILE *, rc_uint_type , const bfd_byte *, int, int, int);
  1558. static void write_rc_rcdata (FILE *, const rc_rcdata_item *, int);
  1559. static void write_rc_stringtable (FILE *, const rc_res_id *, const rc_stringtable *);
  1560. static void write_rc_versioninfo (FILE *, const rc_versioninfo *);
  1561. /* Indent a given number of spaces. */
  1562. static void
  1563. indent (FILE *e, int c)
  1564. {
  1565. int i;
  1566. for (i = 0; i < c; i++)
  1567. putc (' ', e);
  1568. }
  1569. /* Dump the resources we have read in the format of an rc file.
  1570. Reasoned by the fact, that some resources need to be stored into file and
  1571. refer to that file, we use the user-data model for that to express it binary
  1572. without the need to store it somewhere externally. */
  1573. void
  1574. write_rc_file (const char *filename, const rc_res_directory *res_dir)
  1575. {
  1576. FILE *e;
  1577. rc_uint_type language;
  1578. if (filename == NULL)
  1579. e = stdout;
  1580. else
  1581. {
  1582. e = fopen (filename, FOPEN_WT);
  1583. if (e == NULL)
  1584. fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
  1585. }
  1586. language = (rc_uint_type) ((bfd_signed_vma) -1);
  1587. write_rc_directory (e, res_dir, (const rc_res_id *) NULL,
  1588. (const rc_res_id *) NULL, &language, 1);
  1589. }
  1590. /* Write out a directory. E is the file to write to. RD is the
  1591. directory. TYPE is a pointer to the level 1 ID which serves as the
  1592. resource type. NAME is a pointer to the level 2 ID which serves as
  1593. an individual resource name. LANGUAGE is a pointer to the current
  1594. language. LEVEL is the level in the tree. */
  1595. static void
  1596. write_rc_directory (FILE *e, const rc_res_directory *rd,
  1597. const rc_res_id *type, const rc_res_id *name,
  1598. rc_uint_type *language, int level)
  1599. {
  1600. const rc_res_entry *re;
  1601. /* Print out some COFF information that rc files can't represent. */
  1602. if (rd->time != 0 || rd->characteristics != 0 || rd->major != 0 || rd->minor != 0)
  1603. {
  1604. wr_printcomment (e, "COFF information not part of RC");
  1605. if (rd->time != 0)
  1606. wr_printcomment (e, "Time stamp: %u", rd->time);
  1607. if (rd->characteristics != 0)
  1608. wr_printcomment (e, "Characteristics: %u", rd->characteristics);
  1609. if (rd->major != 0 || rd->minor != 0)
  1610. wr_printcomment (e, "Version major:%d minor:%d", rd->major, rd->minor);
  1611. }
  1612. for (re = rd->entries; re != NULL; re = re->next)
  1613. {
  1614. switch (level)
  1615. {
  1616. case 1:
  1617. /* If we're at level 1, the key of this resource is the
  1618. type. This normally duplicates the information we have
  1619. stored with the resource itself, but we need to remember
  1620. the type if this is a user define resource type. */
  1621. type = &re->id;
  1622. break;
  1623. case 2:
  1624. /* If we're at level 2, the key of this resource is the name
  1625. we are going to use in the rc printout. */
  1626. name = &re->id;
  1627. break;
  1628. case 3:
  1629. /* If we're at level 3, then this key represents a language.
  1630. Use it to update the current language. */
  1631. if (! re->id.named
  1632. && re->id.u.id != (unsigned long) (unsigned int) *language
  1633. && (re->id.u.id & 0xffff) == re->id.u.id)
  1634. {
  1635. wr_print (e, "LANGUAGE %u, %u\n",
  1636. re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
  1637. (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
  1638. *language = re->id.u.id;
  1639. }
  1640. break;
  1641. default:
  1642. break;
  1643. }
  1644. if (re->subdir)
  1645. write_rc_subdir (e, re, type, name, language, level);
  1646. else
  1647. {
  1648. if (level == 3)
  1649. {
  1650. /* This is the normal case: the three levels are
  1651. TYPE/NAME/LANGUAGE. NAME will have been set at level
  1652. 2, and represents the name to use. We probably just
  1653. set LANGUAGE, and it will probably match what the
  1654. resource itself records if anything. */
  1655. write_rc_resource (e, type, name, re->u.res, language);
  1656. }
  1657. else
  1658. {
  1659. wr_printcomment (e, "Resource at unexpected level %d", level);
  1660. write_rc_resource (e, type, (rc_res_id *) NULL, re->u.res,
  1661. language);
  1662. }
  1663. }
  1664. }
  1665. if (rd->entries == NULL)
  1666. {
  1667. wr_print_flush (e);
  1668. }
  1669. }
  1670. /* Write out a subdirectory entry. E is the file to write to. RE is
  1671. the subdirectory entry. TYPE and NAME are pointers to higher level
  1672. IDs, or NULL. LANGUAGE is a pointer to the current language.
  1673. LEVEL is the level in the tree. */
  1674. static void
  1675. write_rc_subdir (FILE *e, const rc_res_entry *re,
  1676. const rc_res_id *type, const rc_res_id *name,
  1677. rc_uint_type *language, int level)
  1678. {
  1679. fprintf (e, "\n");
  1680. switch (level)
  1681. {
  1682. case 1:
  1683. wr_printcomment (e, "Type: ");
  1684. if (re->id.named)
  1685. res_id_print (e, re->id, 1);
  1686. else
  1687. {
  1688. const char *s;
  1689. switch (re->id.u.id)
  1690. {
  1691. case RT_CURSOR: s = "cursor"; break;
  1692. case RT_BITMAP: s = "bitmap"; break;
  1693. case RT_ICON: s = "icon"; break;
  1694. case RT_MENU: s = "menu"; break;
  1695. case RT_DIALOG: s = "dialog"; break;
  1696. case RT_STRING: s = "stringtable"; break;
  1697. case RT_FONTDIR: s = "fontdir"; break;
  1698. case RT_FONT: s = "font"; break;
  1699. case RT_ACCELERATOR: s = "accelerators"; break;
  1700. case RT_RCDATA: s = "rcdata"; break;
  1701. case RT_MESSAGETABLE: s = "messagetable"; break;
  1702. case RT_GROUP_CURSOR: s = "group cursor"; break;
  1703. case RT_GROUP_ICON: s = "group icon"; break;
  1704. case RT_VERSION: s = "version"; break;
  1705. case RT_DLGINCLUDE: s = "dlginclude"; break;
  1706. case RT_PLUGPLAY: s = "plugplay"; break;
  1707. case RT_VXD: s = "vxd"; break;
  1708. case RT_ANICURSOR: s = "anicursor"; break;
  1709. case RT_ANIICON: s = "aniicon"; break;
  1710. case RT_TOOLBAR: s = "toolbar"; break;
  1711. case RT_HTML: s = "html"; break;
  1712. default: s = NULL; break;
  1713. }
  1714. if (s != NULL)
  1715. fprintf (e, "%s", s);
  1716. else
  1717. res_id_print (e, re->id, 1);
  1718. }
  1719. break;
  1720. case 2:
  1721. wr_printcomment (e, "Name: ");
  1722. res_id_print (e, re->id, 1);
  1723. break;
  1724. case 3:
  1725. wr_printcomment (e, "Language: ");
  1726. res_id_print (e, re->id, 1);
  1727. break;
  1728. default:
  1729. wr_printcomment (e, "Level %d: ", level);
  1730. res_id_print (e, re->id, 1);
  1731. }
  1732. write_rc_directory (e, re->u.dir, type, name, language, level + 1);
  1733. }
  1734. /* Write out a single resource. E is the file to write to. TYPE is a
  1735. pointer to the type of the resource. NAME is a pointer to the name
  1736. of the resource; it will be NULL if there is a level mismatch. RES
  1737. is the resource data. LANGUAGE is a pointer to the current
  1738. language. */
  1739. static void
  1740. write_rc_resource (FILE *e, const rc_res_id *type,
  1741. const rc_res_id *name, const rc_res_resource *res,
  1742. rc_uint_type *language)
  1743. {
  1744. const char *s;
  1745. int rt;
  1746. int menuex = 0;
  1747. switch (res->type)
  1748. {
  1749. default:
  1750. abort ();
  1751. case RES_TYPE_ACCELERATOR:
  1752. s = "ACCELERATORS";
  1753. rt = RT_ACCELERATOR;
  1754. break;
  1755. case RES_TYPE_BITMAP:
  1756. s = "2 /* RT_BITMAP */";
  1757. rt = RT_BITMAP;
  1758. break;
  1759. case RES_TYPE_CURSOR:
  1760. s = "1 /* RT_CURSOR */";
  1761. rt = RT_CURSOR;
  1762. break;
  1763. case RES_TYPE_GROUP_CURSOR:
  1764. s = "12 /* RT_GROUP_CURSOR */";
  1765. rt = RT_GROUP_CURSOR;
  1766. break;
  1767. case RES_TYPE_DIALOG:
  1768. if (extended_dialog (res->u.dialog))
  1769. s = "DIALOGEX";
  1770. else
  1771. s = "DIALOG";
  1772. rt = RT_DIALOG;
  1773. break;
  1774. case RES_TYPE_FONT:
  1775. s = "8 /* RT_FONT */";
  1776. rt = RT_FONT;
  1777. break;
  1778. case RES_TYPE_FONTDIR:
  1779. s = "7 /* RT_FONTDIR */";
  1780. rt = RT_FONTDIR;
  1781. break;
  1782. case RES_TYPE_ICON:
  1783. s = "3 /* RT_ICON */";
  1784. rt = RT_ICON;
  1785. break;
  1786. case RES_TYPE_GROUP_ICON:
  1787. s = "14 /* RT_GROUP_ICON */";
  1788. rt = RT_GROUP_ICON;
  1789. break;
  1790. case RES_TYPE_MENU:
  1791. if (extended_menu (res->u.menu))
  1792. {
  1793. s = "MENUEX";
  1794. menuex = 1;
  1795. }
  1796. else
  1797. {
  1798. s = "MENU";
  1799. menuex = 0;
  1800. }
  1801. rt = RT_MENU;
  1802. break;
  1803. case RES_TYPE_MESSAGETABLE:
  1804. s = "11 /* RT_MESSAGETABLE */";
  1805. rt = RT_MESSAGETABLE;
  1806. break;
  1807. case RES_TYPE_RCDATA:
  1808. s = "RCDATA";
  1809. rt = RT_RCDATA;
  1810. break;
  1811. case RES_TYPE_STRINGTABLE:
  1812. s = "STRINGTABLE";
  1813. rt = RT_STRING;
  1814. break;
  1815. case RES_TYPE_USERDATA:
  1816. s = NULL;
  1817. rt = 0;
  1818. break;
  1819. case RES_TYPE_VERSIONINFO:
  1820. s = "VERSIONINFO";
  1821. rt = RT_VERSION;
  1822. break;
  1823. case RES_TYPE_TOOLBAR:
  1824. s = "TOOLBAR";
  1825. rt = RT_TOOLBAR;
  1826. break;
  1827. }
  1828. if (rt != 0
  1829. && type != NULL
  1830. && (type->named || type->u.id != (unsigned long) rt))
  1831. {
  1832. wr_printcomment (e, "Unexpected resource type mismatch: ");
  1833. res_id_print (e, *type, 1);
  1834. fprintf (e, " != %d", rt);
  1835. }
  1836. if (res->coff_info.codepage != 0)
  1837. wr_printcomment (e, "Code page: %u", res->coff_info.codepage);
  1838. if (res->coff_info.reserved != 0)
  1839. wr_printcomment (e, "COFF reserved value: %u", res->coff_info.reserved);
  1840. wr_print (e, "\n");
  1841. if (rt == RT_STRING)
  1842. ;
  1843. else
  1844. {
  1845. if (name != NULL)
  1846. res_id_print (e, *name, 1);
  1847. else
  1848. fprintf (e, "??Unknown-Name??");
  1849. fprintf (e, " ");
  1850. }
  1851. if (s != NULL)
  1852. fprintf (e, "%s", s);
  1853. else if (type != NULL)
  1854. {
  1855. if (type->named == 0)
  1856. {
  1857. #define PRINT_RT_NAME(NAME) case NAME: \
  1858. fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
  1859. break
  1860. switch (type->u.id)
  1861. {
  1862. default:
  1863. res_id_print (e, *type, 0);
  1864. break;
  1865. PRINT_RT_NAME(RT_MANIFEST);
  1866. PRINT_RT_NAME(RT_ANICURSOR);
  1867. PRINT_RT_NAME(RT_ANIICON);
  1868. PRINT_RT_NAME(RT_RCDATA);
  1869. PRINT_RT_NAME(RT_ICON);
  1870. PRINT_RT_NAME(RT_CURSOR);
  1871. PRINT_RT_NAME(RT_BITMAP);
  1872. PRINT_RT_NAME(RT_PLUGPLAY);
  1873. PRINT_RT_NAME(RT_VXD);
  1874. PRINT_RT_NAME(RT_FONT);
  1875. PRINT_RT_NAME(RT_FONTDIR);
  1876. PRINT_RT_NAME(RT_HTML);
  1877. PRINT_RT_NAME(RT_MESSAGETABLE);
  1878. PRINT_RT_NAME(RT_DLGINCLUDE);
  1879. PRINT_RT_NAME(RT_DLGINIT);
  1880. }
  1881. #undef PRINT_RT_NAME
  1882. }
  1883. else
  1884. res_id_print (e, *type, 1);
  1885. }
  1886. else
  1887. fprintf (e, "??Unknown-Type??");
  1888. if (res->res_info.memflags != 0)
  1889. {
  1890. if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
  1891. fprintf (e, " MOVEABLE");
  1892. if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
  1893. fprintf (e, " PURE");
  1894. if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
  1895. fprintf (e, " PRELOAD");
  1896. if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
  1897. fprintf (e, " DISCARDABLE");
  1898. }
  1899. if (res->type == RES_TYPE_DIALOG)
  1900. {
  1901. fprintf (e, " %d, %d, %d, %d",
  1902. (int) res->u.dialog->x, (int) res->u.dialog->y,
  1903. (int) res->u.dialog->width, (int) res->u.dialog->height);
  1904. if (res->u.dialog->ex != NULL
  1905. && res->u.dialog->ex->help != 0)
  1906. fprintf (e, ", %u", (unsigned int) res->u.dialog->ex->help);
  1907. }
  1908. else if (res->type == RES_TYPE_TOOLBAR)
  1909. {
  1910. fprintf (e, " %d, %d", (int) res->u.toolbar->button_width,
  1911. (int) res->u.toolbar->button_height);
  1912. }
  1913. fprintf (e, "\n");
  1914. if ((res->res_info.language != 0 && res->res_info.language != *language)
  1915. || res->res_info.characteristics != 0
  1916. || res->res_info.version != 0)
  1917. {
  1918. int modifiers;
  1919. switch (res->type)
  1920. {
  1921. case RES_TYPE_ACCELERATOR:
  1922. case RES_TYPE_DIALOG:
  1923. case RES_TYPE_MENU:
  1924. case RES_TYPE_RCDATA:
  1925. case RES_TYPE_STRINGTABLE:
  1926. modifiers = 1;
  1927. break;
  1928. default:
  1929. modifiers = 0;
  1930. break;
  1931. }
  1932. if (res->res_info.language != 0 && res->res_info.language != *language)
  1933. fprintf (e, "%sLANGUAGE %d, %d\n",
  1934. modifiers ? "// " : "",
  1935. (int) res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
  1936. (int) (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
  1937. if (res->res_info.characteristics != 0)
  1938. fprintf (e, "%sCHARACTERISTICS %u\n",
  1939. modifiers ? "// " : "",
  1940. (unsigned int) res->res_info.characteristics);
  1941. if (res->res_info.version != 0)
  1942. fprintf (e, "%sVERSION %u\n",
  1943. modifiers ? "// " : "",
  1944. (unsigned int) res->res_info.version);
  1945. }
  1946. switch (res->type)
  1947. {
  1948. default:
  1949. abort ();
  1950. case RES_TYPE_ACCELERATOR:
  1951. write_rc_accelerators (e, res->u.acc);
  1952. break;
  1953. case RES_TYPE_CURSOR:
  1954. write_rc_cursor (e, res->u.cursor);
  1955. break;
  1956. case RES_TYPE_GROUP_CURSOR:
  1957. write_rc_group_cursor (e, res->u.group_cursor);
  1958. break;
  1959. case RES_TYPE_DIALOG:
  1960. write_rc_dialog (e, res->u.dialog);
  1961. break;
  1962. case RES_TYPE_FONTDIR:
  1963. write_rc_fontdir (e, res->u.fontdir);
  1964. break;
  1965. case RES_TYPE_GROUP_ICON:
  1966. write_rc_group_icon (e, res->u.group_icon);
  1967. break;
  1968. case RES_TYPE_MENU:
  1969. write_rc_menu (e, res->u.menu, menuex);
  1970. break;
  1971. case RES_TYPE_RCDATA:
  1972. write_rc_rcdata (e, res->u.rcdata, 0);
  1973. break;
  1974. case RES_TYPE_STRINGTABLE:
  1975. write_rc_stringtable (e, name, res->u.stringtable);
  1976. break;
  1977. case RES_TYPE_USERDATA:
  1978. write_rc_rcdata (e, res->u.userdata, 0);
  1979. break;
  1980. case RES_TYPE_TOOLBAR:
  1981. write_rc_toolbar (e, res->u.toolbar);
  1982. break;
  1983. case RES_TYPE_VERSIONINFO:
  1984. write_rc_versioninfo (e, res->u.versioninfo);
  1985. break;
  1986. case RES_TYPE_BITMAP:
  1987. case RES_TYPE_FONT:
  1988. case RES_TYPE_ICON:
  1989. write_rc_datablock (e, res->u.data.length, res->u.data.data, 0, 1, 0);
  1990. break;
  1991. case RES_TYPE_MESSAGETABLE:
  1992. write_rc_messagetable (e, res->u.data.length, res->u.data.data);
  1993. break;
  1994. }
  1995. }
  1996. /* Write out accelerator information. */
  1997. static void
  1998. write_rc_accelerators (FILE *e, const rc_accelerator *accelerators)
  1999. {
  2000. const rc_accelerator *acc;
  2001. fprintf (e, "BEGIN\n");
  2002. for (acc = accelerators; acc != NULL; acc = acc->next)
  2003. {
  2004. int printable;
  2005. fprintf (e, " ");
  2006. if ((acc->key & 0x7f) == acc->key
  2007. && ISPRINT (acc->key)
  2008. && (acc->flags & ACC_VIRTKEY) == 0)
  2009. {
  2010. fprintf (e, "\"%c\"", (char) acc->key);
  2011. printable = 1;
  2012. }
  2013. else
  2014. {
  2015. fprintf (e, "%d", (int) acc->key);
  2016. printable = 0;
  2017. }
  2018. fprintf (e, ", %d", (int) acc->id);
  2019. if (! printable)
  2020. {
  2021. if ((acc->flags & ACC_VIRTKEY) != 0)
  2022. fprintf (e, ", VIRTKEY");
  2023. else
  2024. fprintf (e, ", ASCII");
  2025. }
  2026. if ((acc->flags & ACC_SHIFT) != 0)
  2027. fprintf (e, ", SHIFT");
  2028. if ((acc->flags & ACC_CONTROL) != 0)
  2029. fprintf (e, ", CONTROL");
  2030. if ((acc->flags & ACC_ALT) != 0)
  2031. fprintf (e, ", ALT");
  2032. fprintf (e, "\n");
  2033. }
  2034. fprintf (e, "END\n");
  2035. }
  2036. /* Write out cursor information. This would normally be in a separate
  2037. file, which the rc file would include. */
  2038. static void
  2039. write_rc_cursor (FILE *e, const rc_cursor *cursor)
  2040. {
  2041. fprintf (e, "BEGIN\n");
  2042. indent (e, 2);
  2043. fprintf (e, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d. */\n",
  2044. (unsigned int) cursor->xhotspot, (unsigned int) cursor->yhotspot,
  2045. (int) cursor->xhotspot, (int) cursor->yhotspot);
  2046. write_rc_datablock (e, (rc_uint_type) cursor->length, (const bfd_byte *) cursor->data,
  2047. 0, 0, 0);
  2048. fprintf (e, "END\n");
  2049. }
  2050. /* Write out group cursor data. This would normally be built from the
  2051. cursor data. */
  2052. static void
  2053. write_rc_group_cursor (FILE *e, const rc_group_cursor *group_cursor)
  2054. {
  2055. const rc_group_cursor *gc;
  2056. int c;
  2057. for (c = 0, gc = group_cursor; gc != NULL; gc = gc->next, c++)
  2058. ;
  2059. fprintf (e, "BEGIN\n");
  2060. indent (e, 2);
  2061. fprintf (e, "0, 2, %d%s\t /* Having %d items. */\n", c, (c != 0 ? "," : ""), c);
  2062. indent (e, 4);
  2063. fprintf (e, "/* width, height, planes, bits, bytes, index. */\n");
  2064. for (c = 1, gc = group_cursor; gc != NULL; gc = gc->next, c++)
  2065. {
  2066. indent (e, 4);
  2067. fprintf (e, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
  2068. (int) gc->width, (int) gc->height, (int) gc->planes, (int) gc->bits,
  2069. (unsigned int) gc->bytes, (int) gc->index, (gc->next != NULL ? "," : ""), c);
  2070. fprintf (e, "/* width: %d; height %d; planes %d; bits %d. */\n",
  2071. (int) gc->width, (int) gc->height, (int) gc->planes,
  2072. (int) gc->bits);
  2073. }
  2074. fprintf (e, "END\n");
  2075. }
  2076. /* Write dialog data. */
  2077. static void
  2078. write_rc_dialog (FILE *e, const rc_dialog *dialog)
  2079. {
  2080. const rc_dialog_control *control;
  2081. fprintf (e, "STYLE 0x%x\n", dialog->style);
  2082. if (dialog->exstyle != 0)
  2083. fprintf (e, "EXSTYLE 0x%x\n", (unsigned int) dialog->exstyle);
  2084. if ((dialog->class.named && dialog->class.u.n.length > 0)
  2085. || dialog->class.u.id != 0)
  2086. {
  2087. fprintf (e, "CLASS ");
  2088. res_id_print (e, dialog->class, 1);
  2089. fprintf (e, "\n");
  2090. }
  2091. if (dialog->caption != NULL)
  2092. {
  2093. fprintf (e, "CAPTION ");
  2094. unicode_print_quoted (e, dialog->caption, -1);
  2095. fprintf (e, "\n");
  2096. }
  2097. if ((dialog->menu.named && dialog->menu.u.n.length > 0)
  2098. || dialog->menu.u.id != 0)
  2099. {
  2100. fprintf (e, "MENU ");
  2101. res_id_print (e, dialog->menu, 0);
  2102. fprintf (e, "\n");
  2103. }
  2104. if (dialog->font != NULL)
  2105. {
  2106. fprintf (e, "FONT %d, ", (int) dialog->pointsize);
  2107. unicode_print_quoted (e, dialog->font, -1);
  2108. if (dialog->ex != NULL
  2109. && (dialog->ex->weight != 0
  2110. || dialog->ex->italic != 0
  2111. || dialog->ex->charset != 1))
  2112. fprintf (e, ", %d, %d, %d",
  2113. (int) dialog->ex->weight,
  2114. (int) dialog->ex->italic,
  2115. (int) dialog->ex->charset);
  2116. fprintf (e, "\n");
  2117. }
  2118. fprintf (e, "BEGIN\n");
  2119. for (control = dialog->controls; control != NULL; control = control->next)
  2120. write_rc_dialog_control (e, control);
  2121. fprintf (e, "END\n");
  2122. }
  2123. /* For each predefined control keyword, this table provides the class
  2124. and the style. */
  2125. struct control_info
  2126. {
  2127. const char *name;
  2128. unsigned short class;
  2129. unsigned long style;
  2130. };
  2131. static const struct control_info control_info[] =
  2132. {
  2133. { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
  2134. { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
  2135. { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
  2136. { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
  2137. { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
  2138. { "CTEXT", CTL_STATIC, SS_CENTER },
  2139. { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
  2140. { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
  2141. { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
  2142. { "ICON", CTL_STATIC, SS_ICON },
  2143. { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
  2144. { "LTEXT", CTL_STATIC, SS_LEFT },
  2145. { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
  2146. { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
  2147. { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
  2148. { "RTEXT", CTL_STATIC, SS_RIGHT },
  2149. { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
  2150. { "STATE3", CTL_BUTTON, BS_3STATE },
  2151. /* It's important that USERBUTTON come after all the other button
  2152. types, so that it won't be matched too early. */
  2153. { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
  2154. { NULL, 0, 0 }
  2155. };
  2156. /* Write a dialog control. */
  2157. static void
  2158. write_rc_dialog_control (FILE *e, const rc_dialog_control *control)
  2159. {
  2160. const struct control_info *ci;
  2161. fprintf (e, " ");
  2162. if (control->class.named)
  2163. ci = NULL;
  2164. else
  2165. {
  2166. for (ci = control_info; ci->name != NULL; ++ci)
  2167. if (ci->class == control->class.u.id
  2168. && (ci->style == (unsigned long) -1
  2169. || ci->style == (control->style & 0xff)))
  2170. break;
  2171. }
  2172. if (ci == NULL)
  2173. fprintf (e, "CONTROL");
  2174. else if (ci->name != NULL)
  2175. fprintf (e, "%s", ci->name);
  2176. else
  2177. {
  2178. fprintf (e, "CONTROL");
  2179. ci = NULL;
  2180. }
  2181. /* For EDITTEXT, COMBOBOX, LISTBOX, and SCROLLBAR don't dump text. */
  2182. if ((control->text.named || control->text.u.id != 0)
  2183. && (!ci
  2184. || (ci->class != CTL_EDIT
  2185. && ci->class != CTL_COMBOBOX
  2186. && ci->class != CTL_LISTBOX
  2187. && ci->class != CTL_SCROLLBAR)))
  2188. {
  2189. fprintf (e, " ");
  2190. res_id_print (e, control->text, 1);
  2191. fprintf (e, ",");
  2192. }
  2193. fprintf (e, " %d, ", (int) control->id);
  2194. if (ci == NULL)
  2195. {
  2196. if (control->class.named)
  2197. fprintf (e, "\"");
  2198. res_id_print (e, control->class, 0);
  2199. if (control->class.named)
  2200. fprintf (e, "\"");
  2201. fprintf (e, ", 0x%x, ", (unsigned int) control->style);
  2202. }
  2203. fprintf (e, "%d, %d", (int) control->x, (int) control->y);
  2204. if (control->style != SS_ICON
  2205. || control->exstyle != 0
  2206. || control->width != 0
  2207. || control->height != 0
  2208. || control->help != 0)
  2209. {
  2210. fprintf (e, ", %d, %d", (int) control->width, (int) control->height);
  2211. /* FIXME: We don't need to print the style if it is the default.
  2212. More importantly, in certain cases we actually need to turn
  2213. off parts of the forced style, by using NOT. */
  2214. if (ci != NULL)
  2215. fprintf (e, ", 0x%x", (unsigned int) control->style);
  2216. if (control->exstyle != 0 || control->help != 0)
  2217. fprintf (e, ", 0x%x, %u", (unsigned int) control->exstyle,
  2218. (unsigned int) control->help);
  2219. }
  2220. fprintf (e, "\n");
  2221. if (control->data != NULL)
  2222. write_rc_rcdata (e, control->data, 2);
  2223. }
  2224. /* Write out font directory data. This would normally be built from
  2225. the font data. */
  2226. static void
  2227. write_rc_fontdir (FILE *e, const rc_fontdir *fontdir)
  2228. {
  2229. const rc_fontdir *fc;
  2230. int c;
  2231. for (c = 0, fc = fontdir; fc != NULL; fc = fc->next, c++)
  2232. ;
  2233. fprintf (e, "BEGIN\n");
  2234. indent (e, 2);
  2235. fprintf (e, "%d%s\t /* Has %d elements. */\n", c, (c != 0 ? "," : ""), c);
  2236. for (c = 1, fc = fontdir; fc != NULL; fc = fc->next, c++)
  2237. {
  2238. indent (e, 4);
  2239. fprintf (e, "%d,\t/* Font no %d with index %d. */\n",
  2240. (int) fc->index, c, (int) fc->index);
  2241. write_rc_datablock (e, (rc_uint_type) fc->length - 2,
  2242. (const bfd_byte *) fc->data + 4,fc->next != NULL,
  2243. 0, 0);
  2244. }
  2245. fprintf (e, "END\n");
  2246. }
  2247. /* Write out group icon data. This would normally be built from the
  2248. icon data. */
  2249. static void
  2250. write_rc_group_icon (FILE *e, const rc_group_icon *group_icon)
  2251. {
  2252. const rc_group_icon *gi;
  2253. int c;
  2254. for (c = 0, gi = group_icon; gi != NULL; gi = gi->next, c++)
  2255. ;
  2256. fprintf (e, "BEGIN\n");
  2257. indent (e, 2);
  2258. fprintf (e, " 0, 1, %d%s\t /* Has %d elements. */\n", c, (c != 0 ? "," : ""), c);
  2259. indent (e, 4);
  2260. fprintf (e, "/* \"width height colors pad\", planes, bits, bytes, index. */\n");
  2261. for (c = 1, gi = group_icon; gi != NULL; gi = gi->next, c++)
  2262. {
  2263. indent (e, 4);
  2264. fprintf (e, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d. */\n",
  2265. gi->width, gi->height, gi->colors, 0, (int) gi->planes, (int) gi->bits,
  2266. (unsigned int) gi->bytes, (int) gi->index, (gi->next != NULL ? "," : ""), c);
  2267. }
  2268. fprintf (e, "END\n");
  2269. }
  2270. /* Write out a menu resource. */
  2271. static void
  2272. write_rc_menu (FILE *e, const rc_menu *menu, int menuex)
  2273. {
  2274. if (menu->help != 0)
  2275. fprintf (e, "// Help ID: %u\n", (unsigned int) menu->help);
  2276. write_rc_menuitems (e, menu->items, menuex, 0);
  2277. }
  2278. static void
  2279. write_rc_toolbar (FILE *e, const rc_toolbar *tb)
  2280. {
  2281. rc_toolbar_item *it;
  2282. indent (e, 0);
  2283. fprintf (e, "BEGIN\n");
  2284. it = tb->items;
  2285. while(it != NULL)
  2286. {
  2287. indent (e, 2);
  2288. if (it->id.u.id == 0)
  2289. fprintf (e, "SEPARATOR\n");
  2290. else
  2291. fprintf (e, "BUTTON %d\n", (int) it->id.u.id);
  2292. it = it->next;
  2293. }
  2294. indent (e, 0);
  2295. fprintf (e, "END\n");
  2296. }
  2297. /* Write out menuitems. */
  2298. static void
  2299. write_rc_menuitems (FILE *e, const rc_menuitem *menuitems, int menuex,
  2300. int ind)
  2301. {
  2302. const rc_menuitem *mi;
  2303. indent (e, ind);
  2304. fprintf (e, "BEGIN\n");
  2305. for (mi = menuitems; mi != NULL; mi = mi->next)
  2306. {
  2307. indent (e, ind + 2);
  2308. if (mi->popup == NULL)
  2309. fprintf (e, "MENUITEM");
  2310. else
  2311. fprintf (e, "POPUP");
  2312. if (! menuex
  2313. && mi->popup == NULL
  2314. && mi->text == NULL
  2315. && mi->type == 0
  2316. && mi->id == 0)
  2317. {
  2318. fprintf (e, " SEPARATOR\n");
  2319. continue;
  2320. }
  2321. if (mi->text == NULL)
  2322. fprintf (e, " \"\"");
  2323. else
  2324. {
  2325. fprintf (e, " ");
  2326. unicode_print_quoted (e, mi->text, -1);
  2327. }
  2328. if (! menuex)
  2329. {
  2330. if (mi->popup == NULL)
  2331. fprintf (e, ", %d", (int) mi->id);
  2332. if ((mi->type & MENUITEM_CHECKED) != 0)
  2333. fprintf (e, ", CHECKED");
  2334. if ((mi->type & MENUITEM_GRAYED) != 0)
  2335. fprintf (e, ", GRAYED");
  2336. if ((mi->type & MENUITEM_HELP) != 0)
  2337. fprintf (e, ", HELP");
  2338. if ((mi->type & MENUITEM_INACTIVE) != 0)
  2339. fprintf (e, ", INACTIVE");
  2340. if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
  2341. fprintf (e, ", MENUBARBREAK");
  2342. if ((mi->type & MENUITEM_MENUBREAK) != 0)
  2343. fprintf (e, ", MENUBREAK");
  2344. if ((mi->type & MENUITEM_OWNERDRAW) != 0)
  2345. fprintf (e, ", OWNERDRAW");
  2346. if ((mi->type & MENUITEM_BITMAP) != 0)
  2347. fprintf (e, ", BITMAP");
  2348. }
  2349. else
  2350. {
  2351. if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
  2352. {
  2353. fprintf (e, ", %d", (int) mi->id);
  2354. if (mi->type != 0 || mi->state != 0 || mi->help != 0)
  2355. {
  2356. fprintf (e, ", %u", (unsigned int) mi->type);
  2357. if (mi->state != 0 || mi->help != 0)
  2358. {
  2359. fprintf (e, ", %u", (unsigned int) mi->state);
  2360. if (mi->help != 0)
  2361. fprintf (e, ", %u", (unsigned int) mi->help);
  2362. }
  2363. }
  2364. }
  2365. }
  2366. fprintf (e, "\n");
  2367. if (mi->popup != NULL)
  2368. write_rc_menuitems (e, mi->popup, menuex, ind + 2);
  2369. }
  2370. indent (e, ind);
  2371. fprintf (e, "END\n");
  2372. }
  2373. static int
  2374. test_rc_datablock_unicode (rc_uint_type length, const bfd_byte *data)
  2375. {
  2376. rc_uint_type i;
  2377. if ((length & 1) != 0)
  2378. return 0;
  2379. for (i = 0; i < length; i += 2)
  2380. {
  2381. if (data[i] == 0 && data[i + 1] == 0 && (i + 2) < length)
  2382. return 0;
  2383. if (data[i] == 0xff && data[i + 1] == 0xff)
  2384. return 0;
  2385. }
  2386. return 1;
  2387. }
  2388. static int
  2389. test_rc_datablock_text (rc_uint_type length, const bfd_byte *data)
  2390. {
  2391. int has_nl;
  2392. rc_uint_type c;
  2393. rc_uint_type i;
  2394. if (length <= 1)
  2395. return 0;
  2396. has_nl = 0;
  2397. for (i = 0, c = 0; i < length; i++)
  2398. {
  2399. if (! ISPRINT (data[i]) && data[i] != '\n'
  2400. && ! (data[i] == '\r' && (i + 1) < length && data[i + 1] == '\n')
  2401. && data[i] != '\t'
  2402. && ! (data[i] == 0 && (i + 1) != length))
  2403. {
  2404. if (data[i] <= 7)
  2405. return 0;
  2406. c++;
  2407. }
  2408. else if (data[i] == '\n') has_nl++;
  2409. }
  2410. if (length > 80 && ! has_nl)
  2411. return 0;
  2412. c = (((c * 10000) + (i / 100) - 1)) / i;
  2413. if (c >= 150)
  2414. return 0;
  2415. return 1;
  2416. }
  2417. static void
  2418. write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data)
  2419. {
  2420. int has_error = 0;
  2421. const struct bin_messagetable *mt;
  2422. fprintf (e, "BEGIN\n");
  2423. write_rc_datablock (e, length, data, 0, 0, 0);
  2424. fprintf (e, "\n");
  2425. wr_printcomment (e, "MC syntax dump");
  2426. if (length < BIN_MESSAGETABLE_SIZE)
  2427. has_error = 1;
  2428. else
  2429. do
  2430. {
  2431. rc_uint_type m, i;
  2432. mt = (const struct bin_messagetable *) data;
  2433. m = windres_get_32 (&wrtarget, mt->cblocks, length);
  2434. if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE))
  2435. {
  2436. has_error = 1;
  2437. break;
  2438. }
  2439. for (i = 0; i < m; i++)
  2440. {
  2441. rc_uint_type low, high, offset;
  2442. const struct bin_messagetable_item *mti;
  2443. low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4);
  2444. high = windres_get_32 (&wrtarget, mt->items[i].highid, 4);
  2445. offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4);
  2446. while (low <= high)
  2447. {
  2448. rc_uint_type elen, flags;
  2449. if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length)
  2450. {
  2451. has_error = 1;
  2452. break;
  2453. }
  2454. mti = (const struct bin_messagetable_item *) &data[offset];
  2455. elen = windres_get_16 (&wrtarget, mti->length, 2);
  2456. flags = windres_get_16 (&wrtarget, mti->flags, 2);
  2457. if ((offset + elen) > length)
  2458. {
  2459. has_error = 1;
  2460. break;
  2461. }
  2462. wr_printcomment (e, "MessageId = 0x%x", low);
  2463. wr_printcomment (e, "");
  2464. if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE)
  2465. {
  2466. /* PR 17512: file: 5c3232dc. */
  2467. if (elen > BIN_MESSAGETABLE_ITEM_SIZE * 2)
  2468. unicode_print (e, (const unichar *) mti->data,
  2469. (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2);
  2470. }
  2471. else
  2472. {
  2473. if (elen > BIN_MESSAGETABLE_ITEM_SIZE)
  2474. ascii_print (e, (const char *) mti->data,
  2475. (elen - BIN_MESSAGETABLE_ITEM_SIZE));
  2476. }
  2477. wr_printcomment (e,"");
  2478. ++low;
  2479. offset += elen;
  2480. }
  2481. }
  2482. }
  2483. while (0);
  2484. if (has_error)
  2485. wr_printcomment (e, "Illegal data");
  2486. wr_print_flush (e);
  2487. fprintf (e, "END\n");
  2488. }
  2489. static void
  2490. write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_next,
  2491. int hasblock, int show_comment)
  2492. {
  2493. int plen;
  2494. if (hasblock)
  2495. fprintf (e, "BEGIN\n");
  2496. if (show_comment == -1)
  2497. {
  2498. if (test_rc_datablock_text(length, data))
  2499. {
  2500. rc_uint_type i, c;
  2501. for (i = 0; i < length;)
  2502. {
  2503. indent (e, 2);
  2504. fprintf (e, "\"");
  2505. for (c = 0; i < length && c < 160 && data[i] != '\n'; c++, i++)
  2506. ;
  2507. if (i < length && data[i] == '\n')
  2508. ++i, ++c;
  2509. ascii_print(e, (const char *) &data[i - c], c);
  2510. fprintf (e, "\"");
  2511. if (i < length)
  2512. fprintf (e, "\n");
  2513. }
  2514. if (i == 0)
  2515. {
  2516. indent (e, 2);
  2517. fprintf (e, "\"\"");
  2518. }
  2519. if (has_next)
  2520. fprintf (e, ",");
  2521. fprintf (e, "\n");
  2522. if (hasblock)
  2523. fprintf (e, "END\n");
  2524. return;
  2525. }
  2526. if (test_rc_datablock_unicode (length, data))
  2527. {
  2528. rc_uint_type i, c;
  2529. for (i = 0; i < length;)
  2530. {
  2531. const unichar *u;
  2532. u = (const unichar *) &data[i];
  2533. indent (e, 2);
  2534. fprintf (e, "L\"");
  2535. for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2)
  2536. ;
  2537. if (i < length && u[c] == '\n')
  2538. i += 2, ++c;
  2539. unicode_print (e, u, c);
  2540. fprintf (e, "\"");
  2541. if (i < length)
  2542. fprintf (e, "\n");
  2543. }
  2544. if (i == 0)
  2545. {
  2546. indent (e, 2);
  2547. fprintf (e, "L\"\"");
  2548. }
  2549. if (has_next)
  2550. fprintf (e, ",");
  2551. fprintf (e, "\n");
  2552. if (hasblock)
  2553. fprintf (e, "END\n");
  2554. return;
  2555. }
  2556. show_comment = 0;
  2557. }
  2558. if (length != 0)
  2559. {
  2560. rc_uint_type i, max_row;
  2561. int first = 1;
  2562. max_row = (show_comment ? 4 : 8);
  2563. indent (e, 2);
  2564. for (i = 0; i + 3 < length;)
  2565. {
  2566. rc_uint_type k;
  2567. rc_uint_type comment_start;
  2568. comment_start = i;
  2569. if (! first)
  2570. indent (e, 2);
  2571. for (k = 0; k < max_row && i + 3 < length; k++, i += 4)
  2572. {
  2573. if (k == 0)
  2574. plen = fprintf (e, "0x%lxL",
  2575. (unsigned long) windres_get_32 (&wrtarget, data + i, length - i));
  2576. else
  2577. plen = fprintf (e, " 0x%lxL",
  2578. (unsigned long) windres_get_32 (&wrtarget, data + i, length - i)) - 1;
  2579. if (has_next || (i + 4) < length)
  2580. {
  2581. if (plen>0 && plen < 11)
  2582. indent (e, 11 - plen);
  2583. fprintf (e, ",");
  2584. }
  2585. }
  2586. if (show_comment)
  2587. {
  2588. fprintf (e, "\t/* ");
  2589. ascii_print (e, (const char *) &data[comment_start], i - comment_start);
  2590. fprintf (e, ". */");
  2591. }
  2592. fprintf (e, "\n");
  2593. first = 0;
  2594. }
  2595. if (i + 1 < length)
  2596. {
  2597. if (! first)
  2598. indent (e, 2);
  2599. plen = fprintf (e, "0x%x",
  2600. (int) windres_get_16 (&wrtarget, data + i, length - i));
  2601. if (has_next || i + 2 < length)
  2602. {
  2603. if (plen > 0 && plen < 11)
  2604. indent (e, 11 - plen);
  2605. fprintf (e, ",");
  2606. }
  2607. if (show_comment)
  2608. {
  2609. fprintf (e, "\t/* ");
  2610. ascii_print (e, (const char *) &data[i], 2);
  2611. fprintf (e, ". */");
  2612. }
  2613. fprintf (e, "\n");
  2614. i += 2;
  2615. first = 0;
  2616. }
  2617. if (i < length)
  2618. {
  2619. if (! first)
  2620. indent (e, 2);
  2621. fprintf (e, "\"");
  2622. ascii_print (e, (const char *) &data[i], 1);
  2623. fprintf (e, "\"");
  2624. if (has_next)
  2625. fprintf (e, ",");
  2626. fprintf (e, "\n");
  2627. first = 0;
  2628. }
  2629. }
  2630. if (hasblock)
  2631. fprintf (e, "END\n");
  2632. }
  2633. /* Write out an rcdata resource. This is also used for other types of
  2634. resources that need to print arbitrary data. */
  2635. static void
  2636. write_rc_rcdata (FILE *e, const rc_rcdata_item *rcdata, int ind)
  2637. {
  2638. const rc_rcdata_item *ri;
  2639. indent (e, ind);
  2640. fprintf (e, "BEGIN\n");
  2641. for (ri = rcdata; ri != NULL; ri = ri->next)
  2642. {
  2643. if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
  2644. continue;
  2645. switch (ri->type)
  2646. {
  2647. default:
  2648. abort ();
  2649. case RCDATA_WORD:
  2650. indent (e, ind + 2);
  2651. fprintf (e, "%ld", (long) (ri->u.word & 0xffff));
  2652. break;
  2653. case RCDATA_DWORD:
  2654. indent (e, ind + 2);
  2655. fprintf (e, "%luL", (unsigned long) ri->u.dword);
  2656. break;
  2657. case RCDATA_STRING:
  2658. indent (e, ind + 2);
  2659. fprintf (e, "\"");
  2660. ascii_print (e, ri->u.string.s, ri->u.string.length);
  2661. fprintf (e, "\"");
  2662. break;
  2663. case RCDATA_WSTRING:
  2664. indent (e, ind + 2);
  2665. fprintf (e, "L\"");
  2666. unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
  2667. fprintf (e, "\"");
  2668. break;
  2669. case RCDATA_BUFFER:
  2670. write_rc_datablock (e, (rc_uint_type) ri->u.buffer.length,
  2671. (const bfd_byte *) ri->u.buffer.data,
  2672. ri->next != NULL, 0, -1);
  2673. break;
  2674. }
  2675. if (ri->type != RCDATA_BUFFER)
  2676. {
  2677. if (ri->next != NULL)
  2678. fprintf (e, ",");
  2679. fprintf (e, "\n");
  2680. }
  2681. }
  2682. indent (e, ind);
  2683. fprintf (e, "END\n");
  2684. }
  2685. /* Write out a stringtable resource. */
  2686. static void
  2687. write_rc_stringtable (FILE *e, const rc_res_id *name,
  2688. const rc_stringtable *stringtable)
  2689. {
  2690. rc_uint_type offset;
  2691. int i;
  2692. if (name != NULL && ! name->named)
  2693. offset = (name->u.id - 1) << 4;
  2694. else
  2695. {
  2696. fprintf (e, "/* %s string table name. */\n",
  2697. name == NULL ? "Missing" : "Invalid");
  2698. offset = 0;
  2699. }
  2700. fprintf (e, "BEGIN\n");
  2701. for (i = 0; i < 16; i++)
  2702. {
  2703. if (stringtable->strings[i].length != 0)
  2704. {
  2705. fprintf (e, " %lu, ", (unsigned long) offset + i);
  2706. unicode_print_quoted (e, stringtable->strings[i].string,
  2707. stringtable->strings[i].length);
  2708. fprintf (e, "\n");
  2709. }
  2710. }
  2711. fprintf (e, "END\n");
  2712. }
  2713. /* Write out a versioninfo resource. */
  2714. static void
  2715. write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo)
  2716. {
  2717. const rc_fixed_versioninfo *f;
  2718. const rc_ver_info *vi;
  2719. f = versioninfo->fixed;
  2720. if (f->file_version_ms != 0 || f->file_version_ls != 0)
  2721. fprintf (e, " FILEVERSION %u, %u, %u, %u\n",
  2722. (unsigned int) ((f->file_version_ms >> 16) & 0xffff),
  2723. (unsigned int) (f->file_version_ms & 0xffff),
  2724. (unsigned int) ((f->file_version_ls >> 16) & 0xffff),
  2725. (unsigned int) (f->file_version_ls & 0xffff));
  2726. if (f->product_version_ms != 0 || f->product_version_ls != 0)
  2727. fprintf (e, " PRODUCTVERSION %u, %u, %u, %u\n",
  2728. (unsigned int) ((f->product_version_ms >> 16) & 0xffff),
  2729. (unsigned int) (f->product_version_ms & 0xffff),
  2730. (unsigned int) ((f->product_version_ls >> 16) & 0xffff),
  2731. (unsigned int) (f->product_version_ls & 0xffff));
  2732. if (f->file_flags_mask != 0)
  2733. fprintf (e, " FILEFLAGSMASK 0x%x\n", (unsigned int) f->file_flags_mask);
  2734. if (f->file_flags != 0)
  2735. fprintf (e, " FILEFLAGS 0x%x\n", (unsigned int) f->file_flags);
  2736. if (f->file_os != 0)
  2737. fprintf (e, " FILEOS 0x%x\n", (unsigned int) f->file_os);
  2738. if (f->file_type != 0)
  2739. fprintf (e, " FILETYPE 0x%x\n", (unsigned int) f->file_type);
  2740. if (f->file_subtype != 0)
  2741. fprintf (e, " FILESUBTYPE 0x%x\n", (unsigned int) f->file_subtype);
  2742. if (f->file_date_ms != 0 || f->file_date_ls != 0)
  2743. fprintf (e, "/* Date: %u, %u. */\n",
  2744. (unsigned int) f->file_date_ms, (unsigned int) f->file_date_ls);
  2745. fprintf (e, "BEGIN\n");
  2746. for (vi = versioninfo->var; vi != NULL; vi = vi->next)
  2747. {
  2748. switch (vi->type)
  2749. {
  2750. case VERINFO_STRING:
  2751. {
  2752. const rc_ver_stringtable *vst;
  2753. const rc_ver_stringinfo *vs;
  2754. fprintf (e, " BLOCK \"StringFileInfo\"\n");
  2755. fprintf (e, " BEGIN\n");
  2756. for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next)
  2757. {
  2758. fprintf (e, " BLOCK ");
  2759. unicode_print_quoted (e, vst->language, -1);
  2760. fprintf (e, "\n");
  2761. fprintf (e, " BEGIN\n");
  2762. for (vs = vst->strings; vs != NULL; vs = vs->next)
  2763. {
  2764. fprintf (e, " VALUE ");
  2765. unicode_print_quoted (e, vs->key, -1);
  2766. fprintf (e, ", ");
  2767. unicode_print_quoted (e, vs->value, -1);
  2768. fprintf (e, "\n");
  2769. }
  2770. fprintf (e, " END\n");
  2771. }
  2772. fprintf (e, " END\n");
  2773. break;
  2774. }
  2775. case VERINFO_VAR:
  2776. {
  2777. const rc_ver_varinfo *vv;
  2778. fprintf (e, " BLOCK \"VarFileInfo\"\n");
  2779. fprintf (e, " BEGIN\n");
  2780. fprintf (e, " VALUE ");
  2781. unicode_print_quoted (e, vi->u.var.key, -1);
  2782. for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
  2783. fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
  2784. (int) vv->charset);
  2785. fprintf (e, "\n END\n");
  2786. break;
  2787. }
  2788. }
  2789. }
  2790. fprintf (e, "END\n");
  2791. }
  2792. static rc_uint_type
  2793. rcdata_copy (const rc_rcdata_item *src, bfd_byte *dst)
  2794. {
  2795. if (! src)
  2796. return 0;
  2797. switch (src->type)
  2798. {
  2799. case RCDATA_WORD:
  2800. if (dst)
  2801. windres_put_16 (&wrtarget, dst, (rc_uint_type) src->u.word);
  2802. return 2;
  2803. case RCDATA_DWORD:
  2804. if (dst)
  2805. windres_put_32 (&wrtarget, dst, (rc_uint_type) src->u.dword);
  2806. return 4;
  2807. case RCDATA_STRING:
  2808. if (dst && src->u.string.length)
  2809. memcpy (dst, src->u.string.s, src->u.string.length);
  2810. return (rc_uint_type) src->u.string.length;
  2811. case RCDATA_WSTRING:
  2812. if (dst && src->u.wstring.length)
  2813. memcpy (dst, src->u.wstring.w, src->u.wstring.length * sizeof (unichar));
  2814. return (rc_uint_type) (src->u.wstring.length * sizeof (unichar));
  2815. case RCDATA_BUFFER:
  2816. if (dst && src->u.buffer.length)
  2817. memcpy (dst, src->u.buffer.data, src->u.buffer.length);
  2818. return (rc_uint_type) src->u.buffer.length;
  2819. default:
  2820. abort ();
  2821. }
  2822. /* Never reached. */
  2823. return 0;
  2824. }