Release 970804
[wine/multimedia.git] / rc / winerc.c
blob66f7efecac9703026984ab2a80e7fc7f21bc5f7f
1 /*
3 * Copyright Martin von Loewis, 1994
5 */
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/stat.h>
11 #include <sys/fcntl.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include "windows.h"
16 #include "parser.h"
18 char usage[]="winerc -bdvc -p prefix -o outfile < infile \n"
19 " -b Create a C array from a binary .res file\n"
20 " -c Add 'const' prefix to C constants\n"
21 " -d Output debugging information\n"
22 " -p prefix Give a prefix for the generated names\n"
23 " -v Show each resource as it is processed\n"
24 " -o file Output to file.c and file.h\n"
25 " -w 16|32 Select win16 or win32 output\n";
27 /*might be overwritten by command line*/
28 char *prefix="_Resource";
29 int win32=1;
30 int verbose,constant;
31 gen_res* g_start;
32 FILE *header,*code;
33 char hname[256],sname[256];
35 int transform_binary_file(void);
36 int yyparse(void);
38 static void *xmalloc (size_t size)
40 void *res;
42 res = malloc (size ? size : 1);
43 if (res == NULL)
45 fprintf (stderr, "Virtual memory exhausted.\n");
46 exit (1);
48 return res;
52 int main(int argc,char *argv[])
54 extern int yydebug;
55 extern char* optarg;
56 int optc,lose,ret,binary;
57 lose=binary=0;
58 while((optc=getopt(argc,argv,"bcdp:vo:w:"))!=EOF)
59 switch(optc)
61 /* bison will print state transitions on stderr */
62 case 'b':binary=1;
63 break;
64 case 'd':yydebug=1;
65 setbuf(stdout,0);
66 setbuf(stderr,0);
67 break;
68 case 'p':prefix=strdup(optarg); break;
69 case 'c':constant=1;break;
70 case 'v':verbose=1;
71 setbuf(stderr,0);
72 break;
73 case 'o':set_out_file(optarg);break;
74 case 'w':if(!strcmp(optarg,"16"))win32=0;
75 else if(!strcmp(optarg,"32"))win32=1;
76 else lose++;
77 break;
78 default: lose++;break;
80 if(lose)return fprintf(stderr,usage),1;
81 if(!header)header=stdout;
82 if(!code)code=stdout;
83 if(binary)
84 ret=transform_binary_file();
85 else
86 ret=yyparse();
87 fclose(header);
88 fclose(code);
89 return ret;
92 void set_out_file(char *prefix)
94 sprintf(sname,"%s.c",prefix);
95 code=fopen(sname,"w");
96 sprintf(hname,"%s.h",prefix);
97 header=fopen(hname,"w");
100 int transform_binary_file()
102 int i,c;
103 fprintf(header,"#define APPLICATION_HAS_RESOURCES 1\n");
104 fprintf(code,"char _Application_resources[]={");
105 for(i=0;;i++)
107 c=getchar();
108 if(c==-1)break;
109 if(i%16==0)fputc('\n',code);
110 fprintf(code,"%3d,",c);
112 fprintf(code,"\n 0};\nint _Application_resources_size=%d;\n",i);
113 return 0;
116 /* SunOS' memcpy is wrong for overlapping arrays */
117 char *save_memcpy(char *d,char* s,int l)
119 if(d<s)
120 for(;l;l--)*d++=*s++;
121 else
122 for(d+=l-1,s+=l-1;l;l--)*d--=*s--;
123 return d;
126 /*allow unaligned access*/
127 void put_WORD(unsigned char* p,WORD w)
129 *p=w&0xFF;
130 *(p+1)=w>>8;
133 void put_DWORD(unsigned char* p,DWORD d)
135 put_WORD(p,d&0xFFFF);
136 put_WORD(p+2,d>>16);
139 WORD get_WORD(unsigned char* p)
141 return *p|(*(p+1)<<8);
144 DWORD get_DWORD(unsigned char* p)
146 return get_WORD(p)|(get_WORD(p+2)<<16);
150 /*create a new gen_res, initial size 100*/
151 gen_res *new_res()
152 { gen_res* ret=xmalloc(sizeof(gen_res)+100);
153 int i;
154 for(i=0;i<sizeof(gen_res)+100;i++)*((char*)ret+i)='\0';
155 ret->g_next=g_start;
156 ret->g_prev=0;
157 g_start=ret;
158 ret->space=100;
159 return ret;
162 /*double the space*/
163 gen_res* grow(gen_res* res)
165 res=realloc(res,sizeof(gen_res)+2*res->space);
166 if(!res)
167 fprintf(stderr,"Out of memory\n"),exit(1);
168 if(!res->g_prev)g_start=res;
169 else res->g_prev->g_next=res;
170 if(res->g_next)res->g_next->g_prev=res;
171 res->space=2*res->space;
172 return res;
176 /* insert bytes at offset 0, increase num_entries */
177 gen_res* insert_at_beginning(gen_res* res,char* entry,int size)
179 while(res->size+size>res->space)res=grow(res);
180 save_memcpy(res->res+size,res->res,res->size);
181 save_memcpy(res->res,entry,size);
182 res->size+=size;
183 res->num_entries++;
184 return res;
187 /* insert length characters from bytes into res, starting at start */
188 gen_res* insert_bytes(gen_res* res,char* bytes,int start,int length)
190 while(res->size+length>res->space)res=grow(res);
191 save_memcpy(res->res+start+length,res->res+start,res->size-start);
192 save_memcpy(res->res+start,bytes,length);
193 res->size+=length;
194 return res;
197 /* insert string into res, starting at start */
198 gen_res* insert_string(gen_res* res,unsigned char* string,int start,int terminating0)
200 unsigned char* p;
201 int lengthA = strlen(string) + (terminating0 ? 1 : 0);
202 int length = (win32 ? 2 : 1) * lengthA;
203 while(res->size+length>res->space)res=grow(res);
204 save_memcpy(res->res+start+length,res->res+start,res->size-start);
205 p=res->res+start;
206 while(lengthA--)
207 if (win32)
209 put_WORD(p, *string++);
210 p+=2;
212 else
213 *p++=*string++;
214 res->size+=length;
215 return res;
218 /* insert string at offset 0, increase num_entries */
219 gen_res* insert_string_at_beginning(gen_res* res,char* entry,int terminating0)
221 res=insert_string(res,entry,0,terminating0);
222 res->num_entries++;
223 return res;
226 /*delete len bytes from res, starting at start*/
227 gen_res* delete_bytes(gen_res* res,int start,int len)
229 save_memcpy(res->res+start,res->res+start+len,res->size-start-len);
230 res->size-=len;
231 return res;
234 /*create a new style*/
235 rc_style *new_style()
237 rc_style *ret=xmalloc(sizeof(rc_style));
238 /*initially, no bits have to be reset*/
239 ret->and=-1;
240 /*initially, no bits are set*/
241 ret->or=WS_CHILD | WS_VISIBLE;
242 return ret;
245 /* entries are inserted at the beginning, starting from the last one */
246 gen_res* add_accelerator(int ev, int id, int flags, gen_res* prev)
248 char accel_entry[5];
249 if(prev->num_entries==0)flags|=0x80; /* last entry */
250 accel_entry[0]=flags;
251 put_WORD(accel_entry+1,ev);
252 put_WORD(accel_entry+3,id);
253 return insert_at_beginning(prev,accel_entry,5);
257 /* create an integer from the event, taking things as "^c" into account
258 add this as new entry */
259 gen_res* add_string_accelerator(char *ev, int id, int flags, gen_res* prev)
261 int event;
262 if(*ev=='^')
263 event=ev[1]-'a';
264 else
265 event=ev[0];
266 return add_accelerator(event,id,flags,prev);
269 /*is there a difference between ASCII and VIRTKEY accelerators? */
271 gen_res* add_ascii_accelerator(int ev, int id, int flags, gen_res* prev)
273 return add_accelerator(ev,id,flags,prev);
276 gen_res* add_vk_accelerator(int ev, int id, int flags, gen_res* prev)
278 return add_accelerator(ev,id,flags,prev);
281 /* create a new dialog header, set all items to 0 */
282 gen_res* new_dialog()
283 { gen_res* ret=new_res();
284 ret->size=win32?24:16; /*all strings "\0", no font*/
285 return ret;
288 /* the STYLE option was specified */
289 gen_res* dialog_style(rc_style* style, gen_res* attr)
291 /* default dialog styles? Do we need style->and? */
292 /* DS_SETFONT might have been specified before */
293 put_DWORD(attr->res,get_DWORD(attr->res)|style->or);
294 return attr;
297 /* menu name is at offset 13 (win32: 18) */
298 int dialog_get_menu(gen_res* attr)
300 return win32?18:13;
303 /* the class is after the menu name */
304 int dialog_get_class(gen_res* attr)
306 int offs=dialog_get_menu(attr);
307 while(attr->res[offs]||(win32&&attr->res[offs+1]))offs+=win32?2:1;
308 offs+=win32?2:1;
309 return offs;
312 /* the caption is after the class */
313 int dialog_get_caption(gen_res* attr)
315 int offs=dialog_get_class(attr);
316 while(attr->res[offs]||(win32&&attr->res[offs+1]))offs+=win32?2:1;
317 offs+=win32?2:1;
318 return offs;
321 /* the fontsize, if present, is after the caption, followed by the font name */
322 int dialog_get_fontsize(gen_res* attr)
324 int offs=dialog_get_caption(attr);
325 while(attr->res[offs]||(win32&&attr->res[offs+1]))offs+=win32?2:1;
326 offs+=win32?2:1;
327 return offs;
331 /* the CAPTION option was specified */
332 gen_res* dialog_caption(char* cap, gen_res*attr)
334 /* we don't need the terminating 0 as it's already there */
335 return insert_string(attr,cap,dialog_get_caption(attr),0);
339 /* the FONT option was specified, set the DS_SETFONT flag */
340 gen_res* dialog_font(short size,char* font,gen_res *attr)
342 char c_size[2];
343 int offs=dialog_get_fontsize(attr);
344 put_DWORD(attr->res,get_DWORD(attr->res)|DS_SETFONT);
345 put_WORD(c_size,size);
346 attr=insert_bytes(attr,c_size,offs,2);
347 offs+=2;
348 /* as there is no font name by default, copy the '\0' */
349 return insert_string(attr,font,offs,1);
352 gen_res* dialog_class(char* cap, gen_res*attr)
354 return insert_string(attr,cap,dialog_get_class(attr),0);
357 gen_res* dialog_menu_id(short nr, gen_res*attr)
359 char c_nr[2];
360 int offs=dialog_get_menu(attr);
361 attr->res[offs] = 0xff;
362 if (win32) attr->res[offs+1] = 0xff;
363 put_WORD(c_nr,nr);
364 return insert_bytes(attr,c_nr,offs+(win32?2:1),2);
366 gen_res* dialog_menu_str(char* cap, gen_res*attr)
368 return insert_string(attr,cap,dialog_get_menu(attr),0);
371 /* set the dialogs id, position, extent, and style */
372 gen_res* create_control_desc(int id,int x,int y,int cx, int cy,rc_style *style)
373 { gen_res* ret=new_res();
374 int s=WS_VISIBLE|WS_CHILD; /*defaults styles for any control*/
375 if(win32)
377 if(style)s=(s|style->or)&style->and;
378 put_DWORD(ret->res+0,s);
379 /* FIXME */
380 /* put_WORD(ret->res+4, exStyle); */
381 put_WORD(ret->res+8,x);
382 put_WORD(ret->res+10,y);
383 put_WORD(ret->res+12,cx);
384 put_WORD(ret->res+14,cy);
385 put_WORD(ret->res+16,id);
386 ret->size=24; /*empty strings, unused byte*/
388 else
390 put_WORD(ret->res+0,x);
391 put_WORD(ret->res+2,y);
392 put_WORD(ret->res+4,cx);
393 put_WORD(ret->res+6,cy);
394 put_WORD(ret->res+8,id);
395 if(style)s=(s|style->or)&style->and;
396 put_DWORD(ret->res+10,s);
397 ret->size=17; /*empty strings, unused byte*/
399 return ret;
402 /* insert the control's label */
403 gen_res* label_control_desc(char* label,gen_res* cd)
405 int offs;
406 if(win32) {
407 if(get_WORD(cd->res+18)==0xffff)offs=20; /* one-character class */
408 else {
409 for(offs=18;get_WORD(cd->res+offs);offs+=2);
410 offs+=2;
413 else {
414 if(cd->res[14]&0x80)offs=15; /* one-character class */
415 else {
416 for(offs=14;cd->res[offs];offs++);
417 offs++;
420 return insert_string(cd,label,offs,0);
423 /* a CONTROL was specified */
424 gen_res* create_generic_control(char* label,int id,char* class,
425 rc_style*style,int x,int y,int cx,int cy)
426 { gen_res* ret=new_res();
427 int s=WS_VISIBLE|WS_CHILD; /*default styles for any control*/
428 if(style)s=(s|style->or)&style->and;
429 if(win32)
431 WORD cl;
432 put_DWORD(ret->res+0,s);
433 /* FIXME */
434 /* put_DWORD(ret->res+4,exstyle->or); */
435 put_WORD(ret->res+8,x);
436 put_WORD(ret->res+10,y);
437 put_WORD(ret->res+12,cx);
438 put_WORD(ret->res+14,cy);
439 put_WORD(ret->res+16,id);
440 ret->size=24;
441 ret=insert_string(ret,label,20,0);
442 /* is it a predefined class? */
443 cl=0;
444 if(!strcasecmp(class,"BUTTON"))cl=CT_BUTTON;
445 if(!strcasecmp(class,"EDIT"))cl=CT_EDIT;
446 if(!strcasecmp(class,"STATIC"))cl=CT_STATIC;
447 if(!strcasecmp(class,"LISTBOX"))cl=CT_LISTBOX;
448 if(!strcasecmp(class,"SCROLLBAR"))cl=CT_SCROLLBAR;
449 if(!strcasecmp(class,"COMBOBOX"))cl=CT_COMBOBOX;
450 if(cl) {
451 char ffff[2]={0xff, 0xff};
452 ret=insert_bytes(ret,ffff,18,2);
453 put_WORD(ret->res+20,cl);
455 else ret=insert_string(ret,class,18,0);
457 else
459 char cl;
460 put_WORD(ret->res+0,x);
461 put_WORD(ret->res+2,y);
462 put_WORD(ret->res+4,cx);
463 put_WORD(ret->res+6,cy);
464 put_WORD(ret->res+8,id);
465 put_DWORD(ret->res+10,s);
466 ret->size=17;
467 ret=insert_string(ret,label,15,0);
468 /* is it a predefined class? */
469 cl=0;
470 if(!strcasecmp(class,"BUTTON"))cl=CT_BUTTON;
471 if(!strcasecmp(class,"EDIT"))cl=CT_EDIT;
472 if(!strcasecmp(class,"STATIC"))cl=CT_STATIC;
473 if(!strcasecmp(class,"LISTBOX"))cl=CT_LISTBOX;
474 if(!strcasecmp(class,"SCROLLBAR"))cl=CT_SCROLLBAR;
475 if(!strcasecmp(class,"COMBOBOX"))cl=CT_COMBOBOX;
476 if(cl)ret->res[14]=cl;
477 else ret=insert_string(ret,class,14,0);
479 return ret;
482 /* insert cd into rest, set the type, add flags */
483 gen_res* add_control(int type,int flags,gen_res*cd,gen_res* rest)
485 char zeros[4]={0,0,0,0};
486 if(win32)
488 char ffff[2]={0xff, 0xff};
489 put_DWORD(cd->res+0,get_DWORD(cd->res+0)|flags);
490 cd=insert_bytes(cd,ffff,18,2);
491 put_WORD(cd->res+20,type);
493 else
495 put_DWORD(cd->res+10,get_DWORD(cd->res+10)|flags);
496 cd->res[14]=type;
498 /* WIN32: First control is on dword boundary */
499 if(win32 && cd->size%4)
500 cd=insert_bytes(cd,zeros,cd->size,4-cd->size%4);
501 return insert_at_beginning(rest,cd->res,cd->size);
504 /* an ICON control was specified, whf contains width, height, and flags */
505 gen_res* add_icon(char* name,int id,int x,int y,gen_res* whf,gen_res* rest)
507 if (win32)
509 put_WORD(whf->res+8,x);
510 put_WORD(whf->res+10,y);
511 put_WORD(whf->res+16,id);
513 else
515 put_WORD(whf->res+0,x);
516 put_WORD(whf->res+2,y);
517 put_WORD(whf->res+8,id);
519 whf=label_control_desc(name,whf);
520 return add_control(CT_STATIC,SS_ICON,whf,rest);
523 /* insert the generic control into rest */
524 gen_res* add_generic_control(gen_res* ctl, gen_res* rest)
526 char zeros[4]={0,0,0,0};
527 /* WIN32: Control is on dword boundary */
528 if(win32 && ctl->size%4)
529 ctl=insert_bytes(ctl,zeros,ctl->size,4-ctl->size%4);
530 return insert_at_beginning(rest,ctl->res,ctl->size);
533 /* create a dialog resource by inserting the header into the controls.
534 Set position and extent */
535 gen_res* make_dialog(gen_res* header,int x,int y,int cx,int cy,gen_res* ctls)
537 char zeros[4]={0,0,0,0};
538 if(win32)
540 put_WORD(header->res+8, ctls->num_entries);
541 header->type=dlg;
542 put_WORD(header->res+10,x);
543 put_WORD(header->res+12,y);
544 put_WORD(header->res+14,cx);
545 put_WORD(header->res+16,cy);
547 else
549 header->res[4]=ctls->num_entries;
550 header->type=dlg;
551 put_WORD(header->res+5,x);
552 put_WORD(header->res+7,y);
553 put_WORD(header->res+9,cx);
554 put_WORD(header->res+11,cy);
556 /* WIN32: First control is on dword boundary */
557 if(win32 && header->size%4)
558 header=insert_bytes(header,zeros,header->size,4-header->size%4);
559 return insert_bytes(header,ctls->res,header->size,ctls->size);
562 /* create {0x15,0x16,0xFF} from '15 16 FF' */
563 gen_res *hex_to_raw(char *hex, gen_res*rest)
565 char r2[16];
566 int i;
567 for(i=0;*hex!='\'';i++)r2[i]=strtoul(hex,&hex,16);
568 return insert_bytes(rest,r2,0,i);
571 /* create a bitmap resource */
572 gen_res *make_bitmap(gen_res* res)
574 res=delete_bytes(res,0,14); /* skip bitmap file header*/
575 res->type=bmp;
576 return res;
579 gen_res *make_icon(gen_res* res)
581 res->type=ico;
582 return res;
585 gen_res *make_cursor(gen_res* res)
587 res->type=cur;
588 return res;
591 /* load resource bytes from the file name */
592 gen_res *load_file(char* name)
594 gen_res *res;
595 struct stat st;
596 int f=open(name,O_RDONLY);
597 if(f<0)
599 perror(name);
600 exit(1);
602 fstat(f,&st);
603 res=new_res();
604 while(res->space<st.st_size)res=grow(res);
605 read(f,res->res,st.st_size);
606 res->size=st.st_size;
607 close(f);
608 return res;
611 /* insert a normal menu item into res, starting from the last item */
612 gen_res *add_menuitem(char* name,int id,int flags,gen_res *res)
614 char item[4];
615 if(res->num_entries==0)flags|=MF_END;
616 put_WORD(item,flags);
617 put_WORD(item+2,id);
618 res=insert_string_at_beginning(res,name,1);
619 res=insert_bytes(res,item,0,4);
620 return res;
623 /* insert a popup item into res */
624 gen_res *add_popup(char *name,short flags, gen_res* body, gen_res*res)
626 char c_flags[2];
627 flags|=MF_POPUP;
628 if(res->num_entries==0)flags|=MF_END;
629 put_WORD(c_flags,flags);
630 res=insert_at_beginning(res,body->res,body->size);
631 res=insert_string(res,name,0,1);
632 res=insert_bytes(res,c_flags,0,2);
633 return res;
636 /* prefix the menu header into res */
637 gen_res *make_menu(gen_res* res)
639 static char header[4]={0,0,0,0};
640 res=insert_at_beginning(res,header,4);
641 res->type=men;
642 return res;
645 /* link top-level resources */
646 gen_res *add_resource(gen_res* first,gen_res *rest)
648 if(first)
650 first->next=rest;
651 return first;
653 else
654 return rest;
657 typedef struct str_tbl_elm{
658 int group;
659 struct str_tbl_elm *next;
660 char* strings[16];
661 } str_tbl_elm;
663 str_tbl_elm* string_table=NULL; /* sorted by group */
665 void add_str_tbl_elm(int id,char* str)
667 int group=(id>>4)+1;
668 int idx=id & 0x000f;
670 str_tbl_elm** elm=&string_table;
671 while(*elm && (*elm)->group<group) elm=&(*elm)->next;
672 if(!*elm || (*elm)->group!=group)
674 int i;
675 str_tbl_elm* new=xmalloc(sizeof(str_tbl_elm));
676 for(i=0; i<16; i++) new->strings[i] = NULL;
677 new->group=group;
678 new->next=*elm;
679 *elm=new;
681 (*elm)->strings[idx]=str;
684 gen_res* add_string_table(gen_res* t)
686 str_tbl_elm* ste;
687 int size,i;
688 gen_res* res;
689 unsigned char* p;
690 unsigned char* q;
692 if(!string_table) return t;
693 for(ste=string_table; ste; ste=ste->next)
695 for(size=0,i=0; i<16; i++)
696 size += (win32 ? 2 : 1) * (ste->strings[i] ? strlen(ste->strings[i])+1 : 1);
697 res=new_res();
698 while(res->space<size)res=grow(res);
699 res->type=str;
700 res->n.i_name=ste->group;
701 res->n_type=0;
702 res->size=size;
703 if (win32)
704 for(p=res->res,i=0; i<16; i++)
705 if((q=ste->strings[i])==NULL)
707 put_WORD(p, 0);
708 p+=2;
710 else
712 put_WORD(p, strlen(q));
713 p+=2;
714 while(*q)
716 put_WORD(p, *q++);
717 p+=2;
720 else
721 for(p=res->res,i=0; i<16; i++)
722 if((q=ste->strings[i])==NULL)
723 *p++ = 0;
724 else
726 *p++ = strlen(q);
727 while(*q) *p++ = *q++;
729 t=add_resource(res,t);
731 return t;
734 char *get_typename(gen_res* t)
736 switch(t->type){
737 case acc:return "ACCELERATOR";
738 case bmp:return "BITMAP";
739 case cur:return "CURSOR";
740 case dlg:return "DIALOG";
741 case fnt:return "FONT";
742 case ico:return "ICON";
743 case men:return "MENU";
744 case rdt:return "RCDATA";
745 case str:return "STRINGTABLE";
746 default: return "UNKNOWN";
750 /* create strings like _Sysres_DIALOG_2 */
751 char *get_resource_name(gen_res*it)
753 static char buf[1000];
754 if(it->n_type)
755 sprintf(buf,"%s_%s_%s",prefix,get_typename(it),it->n.s_name);
756 else
757 sprintf(buf,"%s_%s_%d",prefix,get_typename(it),it->n.i_name);
758 return buf;
761 #define ISCONSTANT (constant ? "const " : "")
763 /* create the final output */
764 void create_output(gen_res* top)
766 gen_res *it;
768 top=add_string_table(top);
770 fprintf( header, "/* %s\n"
771 " * This file is automatically generated. Do not edit!\n"
772 " */\n\n"
773 "#include \"resource.h\"\n", hname );
775 /* Declare the resources */
777 for (it=top;it;it=it->next)
778 fprintf( header,"extern %sstruct resource %s;\n",
779 ISCONSTANT, get_resource_name(it) );
780 fprintf( header,"\nextern %sstruct resource * %s%s_Table[];\n",
781 ISCONSTANT, ISCONSTANT, prefix );
783 /* Print the resources bytes */
785 fprintf( code, "/* %s\n"
786 " * This file is automatically generated. Do not edit!\n"
787 " */\n\n"
788 "#include \"%s\"\n", sname, hname );
790 for(it=top;it;it=it->next)
792 int i;
793 fprintf( code, "static %sunsigned char %s__bytes[]%s = {\n",
794 ISCONSTANT, get_resource_name(it),
795 win32?"\n__attribute__ ((aligned (4)))":"");
796 for (i=0;i<it->size-1;i++)
798 fprintf(code,"0x%02x, ",it->res[i]);
799 if ((i&7)==7)fputc('\n',code);
801 fprintf(code,"0x%02x };\n\n",it->res[i]);
804 /* Print the resources names */
806 if (win32)
807 for(it=top;it;it=it->next)
809 int i;
810 char s_buffer[20], *s_name=s_buffer;
811 if(it->n_type) s_name=it->n.s_name;
812 else sprintf(s_name,"@%d",it->n.i_name);
813 fprintf( code, "static %sunsigned char %s__name[] = {\n",
814 ISCONSTANT, get_resource_name(it) );
815 for (i=0;*s_name;i++,s_name++)
817 fprintf(code,"0x%02x, 0x00, ",*s_name);
818 if ((i&3)==3)fputc('\n',code);
820 fprintf(code,"0x00, 0x00};\n\n");
823 /* Print the resources */
824 for (it=top;it;it=it->next)
826 int type;
827 switch(it->type)
829 case acc:type=(int)RT_ACCELERATOR;break;
830 case bmp:type=(int)RT_BITMAP;break;
831 case cur:type=(int)RT_CURSOR;break;
832 case dlg:type=(int)RT_DIALOG;break;
833 case fnt:type=(int)RT_FONT;break;
834 case ico:type=(int)RT_ICON;break;
835 case men:type=(int)RT_MENU;break;
836 case rdt:type=(int)RT_RCDATA;break;
837 case str:type=(int)RT_STRING;break;
838 default:fprintf(stderr,"Unknown restype\n");type=-1;break;
840 if(win32)
842 if(it->n_type)
843 fprintf(code,"%sstruct resource %s = {0,%d,%s__name,%s__bytes,%d};\n",
844 ISCONSTANT, get_resource_name(it), type, get_resource_name(it),
845 get_resource_name(it), it->size );
846 else
847 fprintf(code,"%sstruct resource %s = {%d,%d,%s__name,%s__bytes,%d};\n",
848 ISCONSTANT, get_resource_name(it), it->n.i_name, type,
849 get_resource_name(it), get_resource_name(it), it->size );
851 else
853 if(it->n_type)
854 fprintf(code,"%sstruct resource %s = {0,%d,\"%s\",%s__bytes,%d};\n",
855 ISCONSTANT, get_resource_name(it), type, it->n.s_name,
856 get_resource_name(it), it->size );
857 else
858 fprintf(code,"%sstruct resource %s = {%d,%d,\"@%d\",%s__bytes,%d};\n",
859 ISCONSTANT, get_resource_name(it), it->n.i_name, type,
860 it->n.i_name, get_resource_name(it), it->size );
864 /* Print the resource table (NULL terminated) */
866 fprintf(code,"\n%sstruct resource * %s%s_Table[] = {\n",
867 ISCONSTANT, ISCONSTANT, prefix);
868 for (it=top;it;it=it->next)
869 fprintf( code, " &%s,\n", get_resource_name(it) );
870 fprintf( code, " 0\n};\n" );
872 /* Perform autoregistration */
873 fprintf( code,
874 "#ifdef WINELIB\n"
875 "static void DoIt() WINE_CONSTRUCTOR;\n"
876 "static void DoIt()\n"
877 "{\n"
878 "\tLIBRES_RegisterResources(%s_Table);\n"
879 "}\n\n"
880 "#ifndef HAVE_WINE_CONSTRUCTOR\n"
881 "void LIBWINE_Register_%s(){\n"
882 "\tDoIt();\n"
883 "}\n"
884 "#endif\n"
885 "#endif /*WINELIB*/\n"
886 ,prefix,prefix);
889 gen_res* make_font(gen_res* res)
891 fprintf(stderr,"Fonts not supported\n");
892 return NULL;
895 gen_res* make_raw(gen_res* res)
897 fprintf(stderr,"RCData not supported\n");
898 return NULL;
901 gen_res* int_to_raw(int i,gen_res* res)
903 fprintf(stderr,"IntToRaw not supported\n");
904 return NULL;
907 /* translate "Hello,\\tworld!\\10" to "Hello,\tworld!\n" */
908 char *parse_c_string(char *in)
910 char *out=xmalloc(strlen(in)-1);
911 char *it;
912 char tmp[5],*tend;
913 for(it=out,in++;*in;in++)
914 if(*in=='\\')
915 switch(*++in)
916 {case 't':*it++='\t';break;
917 case 'r':*it++='\r';break;
918 case 'n':*it++='\n';break;
919 case 'a':*it++='\a';break;
920 case '0':
921 memset(tmp,0,5);/*make sure it doesn't use more than 4 chars*/
922 memcpy(tmp,in,4);
923 *it++=strtoul(tmp,&tend,0);
924 in+=tend-tmp-1;
925 break;
926 case '1':case '2':case '3':case '4':case '5':
927 case '6':case '7':case '8':case '9':
928 memset(tmp,0,5);
929 memcpy(tmp,in,3);
930 *it++=strtoul(tmp,&tend,10);
931 in+=tend-tmp-1;
932 break;
933 case 'x':
934 memset(tmp,0,5);
935 memcpy(tmp,++in,2);
936 *it++=strtoul(tmp,&tend,16);
937 in+=tend-tmp-1;
938 break;
939 default:*it++=*in;
941 else
942 *it++=*in;
943 *(it-1)='\0';
944 return out;