2 Compiles swf code (.sc) files into .swf files.
4 Part of the swftools package.
6 Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
29 #include "../config.h"
30 #include "../lib/rfxswf.h"
31 #include "../lib/drawer.h"
32 #include "../lib/log.h"
33 #include "../lib/args.h"
40 static char * filename = 0;
41 static char * outputname = "output.swf";
42 static int verbose = 2;
43 static int optimize = 0;
44 static int override_outputname = 0;
46 static struct options_t options[] = {
55 int args_callback_option(char*name,char*val)
57 if(!strcmp(name, "V")) {
58 printf("swfc - part of %s %s\n", PACKAGE, VERSION);
61 else if(!strcmp(name, "o")) {
63 override_outputname = 1;
66 else if(!strcmp(name, "O")) {
70 else if(!strcmp(name, "v")) {
75 printf("Unknown option: -%s\n", name);
80 int args_callback_longoption(char*name,char*val)
82 return args_long2shortoption(options, name, val);
84 void args_callback_usage(char *name)
87 printf("Usage: %s [-o file.swf] file.sc\n", name);
89 printf("-h , --help Print short help message and exit\n");
90 printf("-V , --version Print version info and exit\n");
91 printf("-v , --verbose Increase verbosity. \n");
92 printf("-o , --output <filename> Set output file to <filename>.\n");
95 int args_callback_command(char*name,char*val)
98 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
105 static struct token_t* file;
114 static void syntaxerror(char*format, ...)
118 va_start(arglist, format);
119 vsprintf(buf, format, arglist);
121 printf("\"%s\", line %d column %d: error- %s\n", filename, line, column, buf);
125 static void warning(char*format, ...)
129 va_start(arglist, format);
130 vsprintf(buf, format, arglist);
132 printf("\"%s\", line %d column %d: warning- %s\n", filename, line, column, buf);
135 static void readToken()
137 type = file[pos].type;
139 syntaxerror("unexpected end of file");
141 text = file[pos].text;
142 textlen = strlen(text);
143 line = file[pos].line;
144 column = file[pos].column;
146 //printf("---> %d(%s) %s\n", type, type_names[type], text);
149 static void pushBack()
152 if(!pos) syntaxerror("internal error 3");
157 textlen = strlen(text);
160 column = file[p].column;
163 static int noMoreTokens()
165 if(file[pos].type == END)
170 // ------------------------------ swf routines ----------------------------
174 int type; //0=swf, 1=sprite, 2=clip, 3=button
180 /* for sprites (1): */
186 dictionary_t oldinstances;
191 static int stackpos = 0;
193 static dictionary_t characters;
194 static dictionary_t images;
195 static dictionary_t outlines;
196 static dictionary_t gradients;
197 static char idmap[65536];
198 static TAG*tag = 0; //current tag
200 static int id; //current character id
201 static int currentframe; //current frame in current level
202 static SRECT currentrect; //current bounding box in current level
203 static U16 currentdepth;
204 static dictionary_t instances;
205 static dictionary_t fonts;
206 static dictionary_t sounds;
208 typedef struct _parameters {
210 float scalex, scaley;
218 typedef struct _character {
224 typedef struct _instance {
225 character_t*character;
227 parameters_t parameters;
228 TAG* lastTag; //last tag which set the object
229 U16 lastFrame; //frame lastTag is in
232 typedef struct _outline {
237 typedef struct _gradient {
243 static void character_init(character_t*c)
245 memset(c, 0, sizeof(character_t));
247 static character_t* character_new()
250 c = (character_t*)malloc(sizeof(character_t));
254 static void instance_init(instance_t*i)
256 memset(i, 0, sizeof(instance_t));
258 static instance_t* instance_new()
261 c = (instance_t*)malloc(sizeof(instance_t));
266 static void incrementid()
270 syntaxerror("Out of character ids.");
275 static void s_addcharacter(char*name, U16 id, TAG*ctag, SRECT r)
277 character_t* c = character_new();
279 c->definingTag = ctag;
282 if(dictionary_lookup(&characters, name))
283 syntaxerror("character %s defined twice", name);
284 dictionary_put2(&characters, name, c);
286 tag = swf_InsertTag(tag, ST_NAMECHARACTER);
288 swf_SetString(tag, name);
289 tag = swf_InsertTag(tag, ST_EXPORTASSETS);
292 swf_SetString(tag, name);
294 static void s_addimage(char*name, U16 id, TAG*ctag, SRECT r)
296 character_t* c = character_new();
297 c->definingTag = ctag;
301 if(dictionary_lookup(&images, name))
302 syntaxerror("image %s defined twice", name);
303 dictionary_put2(&images, name, c);
305 static instance_t* s_addinstance(char*name, character_t*c, U16 depth)
307 instance_t* i = instance_new();
310 //swf_GetMatrix(0, &i->matrix);
311 if(dictionary_lookup(&instances, name))
312 syntaxerror("object %s defined twice", name);
313 dictionary_put2(&instances, name, i);
317 static void parameters_set(parameters_t*p, int x,int y, float scalex, float scaley, float rotate, float shear, SPOINT pivot, SPOINT pin, CXFORM cxform)
320 p->scalex = scalex; p->scaley = scaley;
321 p->pin = pin; p->pivot = pivot;
322 p->rotate = rotate; p->cxform = cxform;
326 static void parameters_clear(parameters_t*p)
329 p->scalex = 1.0; p->scaley = 1.0;
332 p->pivot.x = 0; p->pivot.y = 0;
335 swf_GetCXForm(0, &p->cxform, 1);
338 static void makeMatrix(MATRIX*m, parameters_t*p)
347 sx = p->scalex*cos(p->rotate/360*2*3.14159265358979);
348 r1 = -p->scalex*sin(p->rotate/360*2*3.14159265358979)+sx*p->shear;
349 r0 = p->scaley*sin(p->rotate/360*2*3.14159265358979);
350 sy = p->scaley*cos(p->rotate/360*2*3.14159265358979)+r0*p->shear;
352 m->sx = (int)(sx*65536+0.5);
353 m->r1 = (int)(r1*65536+0.5);
354 m->r0 = (int)(r0*65536+0.5);
355 m->sy = (int)(sy*65536+0.5);
359 h = swf_TurnPoint(p->pin, m);
364 static MATRIX s_instancepos(SRECT rect, parameters_t*p)
369 r = swf_TurnRect(rect, &m);
370 if(currentrect.xmin == 0 && currentrect.ymin == 0 &&
371 currentrect.xmax == 0 && currentrect.ymax == 0)
374 swf_ExpandRect2(¤trect, &r);
378 void s_swf(char*name, SRECT r, int version, int fps, int compress, RGBA background)
380 SWF*swf = (SWF*)malloc(sizeof(SWF));
383 syntaxerror(".swf blocks can't be nested");
385 memset(swf, 0, sizeof(swf));
386 swf->fileVersion = version;
388 swf->frameRate = fps;
389 swf->firstTag = tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
390 swf->compressed = compress;
391 swf_SetRGB(tag,&background);
393 if(stackpos==sizeof(stack)/sizeof(stack[0]))
394 syntaxerror("too many levels of recursion");
396 dictionary_init(&characters);
397 dictionary_init(&images);
398 dictionary_init(&outlines);
399 dictionary_init(&gradients);
400 dictionary_init(&instances);
401 dictionary_init(&fonts);
402 dictionary_init(&sounds);
404 memset(&stack[stackpos], 0, sizeof(stack[0]));
405 stack[stackpos].type = 0;
406 stack[stackpos].filename = strdup(name);
407 stack[stackpos].swf = swf;
408 stack[stackpos].oldframe = -1;
413 memset(¤trect, 0, sizeof(currentrect));
416 memset(idmap, 0, sizeof(idmap));
420 void s_sprite(char*name)
422 tag = swf_InsertTag(tag, ST_DEFINESPRITE);
423 swf_SetU16(tag, id); //id
424 swf_SetU16(tag, 0); //frames
426 memset(&stack[stackpos], 0, sizeof(stack[0]));
427 stack[stackpos].type = 1;
428 stack[stackpos].oldframe = currentframe;
429 stack[stackpos].olddepth = currentdepth;
430 stack[stackpos].oldrect = currentrect;
431 stack[stackpos].oldinstances = instances;
432 stack[stackpos].tag = tag;
433 stack[stackpos].id = id;
434 stack[stackpos].name = strdup(name);
436 /* FIXME: those four fields should be bundled together */
437 dictionary_init(&instances);
440 memset(¤trect, 0, sizeof(currentrect));
446 typedef struct _buttonrecord
454 typedef struct _button
458 buttonrecord_t records[4];
461 static button_t mybutton;
463 void s_button(char*name)
465 tag = swf_InsertTag(tag, ST_DEFINEBUTTON2);
466 swf_SetU16(tag, id); //id
467 swf_ButtonSetFlags(tag, 0); //menu=no
469 memset(&mybutton, 0, sizeof(mybutton));
471 memset(&stack[stackpos], 0, sizeof(stack[0]));
472 stack[stackpos].type = 3;
473 stack[stackpos].tag = tag;
474 stack[stackpos].id = id;
475 stack[stackpos].name = strdup(name);
476 stack[stackpos].oldrect = currentrect;
477 memset(¤trect, 0, sizeof(currentrect));
482 void s_buttonput(char*character, char*as, parameters_t p)
484 character_t* c = dictionary_lookup(&characters, character);
489 if(!stackpos || (stack[stackpos-1].type != 3)) {
490 syntaxerror(".show may only appear in .button");
493 syntaxerror("character %s not known (in .shape %s)", character, character);
495 if(mybutton.endofshapes) {
496 syntaxerror("a .do may not precede a .show", character, character);
499 m = s_instancepos(c->size, &p);
507 if(*s==',' || *s==0) {
508 if(!strncmp(o,"idle",s-o)) {mybutton.records[0]=r;o=s+1;}
509 else if(!strncmp(o,"shape",s-o)) {mybutton.records[0]=r;o=s+1;}
510 else if(!strncmp(o,"hover",s-o)) {mybutton.records[1]=r;o=s+1;}
511 else if(!strncmp(o,"pressed",s-o)) {mybutton.records[2]=r;o=s+1;}
512 else if(!strncmp(o,"area",s-o)) {mybutton.records[3]=r;o=s+1;}
513 else syntaxerror("unknown \"as\" argument: \"%s\"", strdup_n(o,s-o));
520 static void setbuttonrecords(TAG*tag)
522 int flags[] = {BS_UP,BS_OVER,BS_DOWN,BS_HIT};
523 if(!mybutton.endofshapes) {
526 if(!mybutton.records[3].set) {
527 memcpy(&mybutton.records[3], &mybutton.records[0], sizeof(buttonrecord_t));
531 if(mybutton.records[t].set) {
532 swf_ButtonSetRecord(tag,flags[t],mybutton.records[t].id,1,&mybutton.records[t].matrix,&mybutton.records[t].cxform);
535 swf_SetU8(tag,0); // end of button records
536 mybutton.endofshapes = 1;
540 void s_buttonaction(int flags, char*action)
546 setbuttonrecords(stack[stackpos-1].tag);
548 a = swf_ActionCompile(text, stack[0].swf->fileVersion);
550 syntaxerror("Couldn't compile ActionScript");
553 swf_ButtonSetCondition(stack[stackpos-1].tag, flags);
554 swf_ActionSet(stack[stackpos-1].tag, a);
555 mybutton.nr_actions++;
560 static void setactionend(TAG*tag)
562 if(!mybutton.nr_actions) {
563 /* no actions means we didn't have an actionoffset,
564 which means we can't signal the end of the
565 buttonaction records, so, *sigh*, we have
566 to insert a dummy record */
567 swf_SetU16(tag, 0); //offset
568 swf_SetU16(tag, 0); //condition
569 swf_SetU8(tag, 0); //action
573 static void s_endButton()
576 setbuttonrecords(stack[stackpos-1].tag);
577 setactionend(stack[stackpos-1].tag);
580 swf_ButtonPostProcess(stack[stackpos].tag, mybutton.nr_actions);
584 tag = stack[stackpos].tag;
585 currentrect = stack[stackpos].oldrect;
587 s_addcharacter(stack[stackpos].name, stack[stackpos].id, stack[stackpos].tag, r);
588 free(stack[stackpos].name);
591 TAG* removeFromTo(TAG*from, TAG*to)
593 TAG*save = from->prev;
595 TAG*next = from->next;
603 static void s_endSprite()
605 SRECT r = currentrect;
607 if(stack[stackpos].cut)
608 tag = removeFromTo(stack[stackpos].cut, tag);
612 /* TODO: before clearing, prepend "<spritename>." to names and
613 copy into old instances dict */
614 dictionary_clear(&instances);
616 currentframe = stack[stackpos].oldframe;
617 currentrect = stack[stackpos].oldrect;
618 currentdepth = stack[stackpos].olddepth;
619 instances = stack[stackpos].oldinstances;
621 tag = swf_InsertTag(tag, ST_END);
623 tag = stack[stackpos].tag;
626 syntaxerror("internal error(7)");
628 s_addcharacter(stack[stackpos].name, stack[stackpos].id, stack[stackpos].tag, r);
629 free(stack[stackpos].name);
632 static void s_endSWF()
638 if(stack[stackpos].cut)
639 tag = removeFromTo(stack[stackpos].cut, tag);
643 swf = stack[stackpos].swf;
644 filename = stack[stackpos].filename;
646 //tag = swf_InsertTag(tag, ST_SHOWFRAME); //?
648 tag = swf_InsertTag(tag, ST_END);
650 swf_OptimizeTagOrder(swf);
656 if(!(swf->movieSize.xmax-swf->movieSize.xmin) || !(swf->movieSize.ymax-swf->movieSize.ymin)) {
657 swf->movieSize = currentrect; /* "autocrop" */
660 if(!(swf->movieSize.xmax-swf->movieSize.xmin) || !(swf->movieSize.ymax-swf->movieSize.ymin)) {
661 swf->movieSize.xmax += 20; /* 1 by 1 pixels */
662 swf->movieSize.ymax += 20;
665 fi = open(filename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644);
667 syntaxerror("couldn't create output file %s", filename);
670 {if(swf_WriteSWC(fi, swf)<0) syntaxerror("WriteSWC() failed.\n");}
672 {if(swf_WriteSWF(fi, swf)<0) syntaxerror("WriteSWF() failed.\n");}
676 dictionary_clear(&instances);
677 dictionary_clear(&characters);
678 dictionary_clear(&images);
679 dictionary_clear(&outlines);
680 dictionary_clear(&gradients);
681 dictionary_clear(&fonts);
682 dictionary_clear(&sounds);
692 if(stack[stackpos-1].type == 0)
693 syntaxerror("End of file encountered in .flash block");
694 if(stack[stackpos-1].type == 1)
695 syntaxerror("End of file encountered in .sprite block");
696 if(stack[stackpos-1].type == 2)
697 syntaxerror("End of file encountered in .clip block");
706 void s_frame(int nr, int cut, char*name)
711 for(t=currentframe;t<nr;t++) {
712 tag = swf_InsertTag(tag, ST_SHOWFRAME);
713 if(t==nr-1 && name && *name) {
714 tag = swf_InsertTag(tag, ST_FRAMELABEL);
715 swf_SetString(tag, name);
718 if(nr == 0 && currentframe == 0 && name) {
719 tag = swf_InsertTag(tag, ST_FRAMELABEL);
720 swf_SetString(tag, name);
725 syntaxerror("Can't cut, frame empty");
727 stack[stackpos].cut = tag;
733 int parseColor2(char*str, RGBA*color);
735 int addFillStyle(SHAPE*s, SRECT*r, char*texture)
740 if(texture[0] == '#') {
741 parseColor2(texture, &color);
742 return swf_ShapeAddSolidFillStyle(s, &color);
743 } else if((image = dictionary_lookup(&images, texture))) {
745 swf_GetMatrix(0, &m);
746 m.sx = 65536.0*20.0*(r->xmax - r->xmin)/image->size.xmax;
747 m.sy = 65536.0*20.0*(r->ymax - r->ymin)/image->size.ymax;
750 return swf_ShapeAddBitmapFillStyle(s, &m, image->id, 0);
751 } /*else if ((texture = dictionary_lookup(&textures, texture))) {
752 } */ else if ((gradient = dictionary_lookup(&gradients, texture))) {
756 swf_GetMatrix(0, &rot);
757 ccos = cos(-gradient->rotate*2*3.14159265358979/360);
758 csin = sin(-gradient->rotate*2*3.14159265358979/360);
760 rot.r1 = -csin*65536;
763 r2 = swf_TurnRect(*r, &rot);
764 swf_GetMatrix(0, &m);
765 m.sx = (r2.xmax - r2.xmin)*2*ccos;
766 m.r1 = -(r2.xmax - r2.xmin)*2*csin;
767 m.r0 = (r2.ymax - r2.ymin)*2*csin;
768 m.sy = (r2.ymax - r2.ymin)*2*ccos;
769 m.tx = r->xmin + (r->xmax - r->xmin)/2;
770 m.ty = r->ymin + (r->ymax - r->ymin)/2;
771 return swf_ShapeAddGradientFillStyle(s, &m, &gradient->gradient, gradient->radial);
772 } else if (parseColor2(texture, &color)) {
773 return swf_ShapeAddSolidFillStyle(s, &color);
775 syntaxerror("not a color/fillstyle: %s", texture);
780 RGBA black={r:0,g:0,b:0,a:0};
781 void s_box(char*name, int width, int height, RGBA color, int linewidth, char*texture)
790 tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
792 ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
795 fs1 = addFillStyle(s, &r2, texture);
798 r.xmin = r2.xmin-linewidth-linewidth/2;
799 r.ymin = r2.ymin-linewidth-linewidth/2;
800 r.xmax = r2.xmax+linewidth+linewidth/2;
801 r.ymax = r2.ymax+linewidth+linewidth/2;
803 swf_SetShapeHeader(tag,s);
804 swf_ShapeSetAll(tag,s,0,0,ls1,fs1,0);
805 swf_ShapeSetLine(tag,s,width,0);
806 swf_ShapeSetLine(tag,s,0,height);
807 swf_ShapeSetLine(tag,s,-width,0);
808 swf_ShapeSetLine(tag,s,0,-height);
809 swf_ShapeSetEnd(tag);
812 s_addcharacter(name, id, tag, r);
816 void s_filled(char*name, char*outlinename, RGBA color, int linewidth, char*texture)
822 outline = dictionary_lookup(&outlines, outlinename);
824 syntaxerror("outline %s not defined", outlinename);
828 tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
830 ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
832 fs1 = addFillStyle(s, &r2, texture);
834 syntaxerror("non filled outlines not yet supported- please supply a fill=<color/texture> argument");
836 rect.xmin = r2.xmin-linewidth-linewidth/2;
837 rect.ymin = r2.ymin-linewidth-linewidth/2;
838 rect.xmax = r2.xmax+linewidth+linewidth/2;
839 rect.ymax = r2.ymax+linewidth+linewidth/2;
841 swf_SetRect(tag,&rect);
842 swf_SetShapeStyles(tag, s);
843 swf_SetShapeBits(tag, outline->shape); //does not count bits!
844 swf_SetBlock(tag, outline->shape->data, (outline->shape->bitlen+7)/8);
847 s_addcharacter(name, id, tag, rect);
851 void s_circle(char*name, int r, RGBA color, int linewidth, char*texture)
856 r2.xmin = r2.ymin = 0;
860 tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
862 ls1 = swf_ShapeAddLineStyle(s,linewidth,&color);
864 fs1 = addFillStyle(s, &r2, texture);
866 rect.xmin = r2.xmin-linewidth-linewidth/2;
867 rect.ymin = r2.ymin-linewidth-linewidth/2;
868 rect.xmax = r2.xmax+linewidth+linewidth/2;
869 rect.ymax = r2.ymax+linewidth+linewidth/2;
871 swf_SetRect(tag,&rect);
872 swf_SetShapeHeader(tag,s);
873 swf_ShapeSetAll(tag,s,0,0,ls1,fs1,0);
874 swf_ShapeSetCircle(tag, s, r,r,r,r);
875 swf_ShapeSetEnd(tag);
878 s_addcharacter(name, id, tag, rect);
882 void s_textshape(char*name, char*fontname, float size, char*_text)
885 U8*text = (U8*)_text;
889 font = dictionary_lookup(&fonts, fontname);
891 syntaxerror("font \"%s\" not known!", fontname);
893 if(text[0] >= font->maxascii || font->ascii2glyph[text[0]]<0) {
894 warning("no character 0x%02x (%c) in font \"%s\"", text[0], text[0], fontname);
895 s_box(name, 0, 0, black, 20, 0);
898 g = font->ascii2glyph[text[0]];
900 outline = malloc(sizeof(outline_t));
901 memset(outline, 0, sizeof(outline_t));
902 outline->shape = font->glyph[g].shape;
903 outline->bbox = font->layout->bounds[g];
907 swf_Shape11DrawerInit(&draw, 0);
908 swf_DrawText(&draw, font, (int)(size*100), _text);
910 outline->shape = swf_ShapeDrawerToShape(&draw);
911 outline->bbox = swf_ShapeDrawerGetBBox(&draw);
915 if(dictionary_lookup(&outlines, name))
916 syntaxerror("outline %s defined twice", name);
917 dictionary_put2(&outlines, name, outline);
920 void s_text(char*name, char*fontname, char*text, int size, RGBA color)
925 font = dictionary_lookup(&fonts, fontname);
927 syntaxerror("font \"%s\" not known!", fontname);
929 tag = swf_InsertTag(tag, ST_DEFINETEXT2);
931 if(!font->numchars) {
932 s_box(name, 0, 0, black, 20, 0);
935 r = swf_SetDefineText(tag, font, &color, text, size);
937 s_addcharacter(name, id, tag, r);
941 void s_quicktime(char*name, char*url)
946 memset(&r, 0, sizeof(r));
948 tag = swf_InsertTag(tag, ST_DEFINEMOVIE);
950 swf_SetString(tag, url);
952 s_addcharacter(name, id, tag, r);
956 void s_edittext(char*name, char*fontname, int size, int width, int height, char*text, RGBA*color, int maxlength, char*variable, int flags)
959 EditTextLayout layout;
962 font = dictionary_lookup(&fonts, fontname);
964 syntaxerror("font \"%s\" not known!", fontname);
965 tag = swf_InsertTag(tag, ST_DEFINEEDITTEXT);
968 layout.leftmargin = 0;
969 layout.rightmargin = 0;
976 swf_SetEditText(tag, flags|ET_USEOUTLINES, r, text, color, maxlength, font->id, size, &layout, variable);
978 s_addcharacter(name, id, tag, r);
982 /* type: either "jpeg" or "png"
984 void s_image(char*name, char*type, char*filename, int quality)
986 /* an image is actually two folded: 1st bitmap, 2nd character.
987 Both of them can be used separately */
989 /* step 1: the bitmap */
994 warning("image type \"png\" not supported yet!");
995 s_box(name, 0, 0, black, 20, 0);
1000 warning("no jpeg support compiled in");
1001 s_box(name, 0, 0, black, 20, 0);
1004 tag = swf_InsertTag(tag, ST_DEFINEBITSJPEG2);
1005 swf_SetU16(tag, imageID);
1007 if(swf_SetJPEGBits(tag, filename, quality) < 0) {
1008 syntaxerror("Image \"%s\" not found, or contains errors", filename);
1011 swf_GetJPEGSize(filename, &width, &height);
1018 s_addimage(name, id, tag, r);
1023 /* step 2: the character */
1024 tag = swf_InsertTag(tag, ST_DEFINESHAPE); // todo: should be defineshape2/3 once images can be transparent.(?)
1025 swf_SetU16(tag, id);
1026 swf_ShapeSetBitmapRect(tag, imageID, width, height);
1028 s_addcharacter(name, id, tag, r);
1032 void dumpSWF(SWF*swf)
1034 TAG* tag = swf->firstTag;
1035 printf("vvvvvvvvvvvvvvvvvvvvv\n");
1037 printf("%8d %s\n", tag->len, swf_TagGetName(tag));
1040 printf("^^^^^^^^^^^^^^^^^^^^^\n");
1043 void s_font(char*name, char*filename)
1046 font = swf_LoadFont(filename);
1049 warning("Couldn't open font file \"%s\"", filename);
1050 font = (SWFFONT*)malloc(sizeof(SWFFONT));
1051 memset(font, 0, sizeof(SWFFONT));
1052 dictionary_put2(&fonts, name, font);
1058 /* fix the layout. Only needed for old fonts */
1060 for(t=0;t<font->numchars;t++) {
1061 font->glyph[t].advance = 0;
1064 swf_FontCreateLayout(font);
1066 /* just in case this thing is used in .edittext later on */
1067 swf_FontPrepareForEditText(font);
1070 tag = swf_InsertTag(tag, ST_DEFINEFONT2);
1071 swf_FontSetDefine2(tag, font);
1074 if(dictionary_lookup(&fonts, name))
1075 syntaxerror("font %s defined twice", name);
1076 dictionary_put2(&fonts, name, font);
1081 typedef struct _sound_t
1087 void s_sound(char*name, char*filename)
1089 struct WAV wav, wav2;
1094 if(!readWAV(filename, &wav)) {
1095 warning("Couldn't read wav file \"%s\"", filename);
1099 convertWAV2mono(&wav, &wav2, 44100);
1100 samples = (U16*)wav2.data;
1101 numsamples = wav2.size/2;
1105 tag = swf_InsertTag(tag, ST_DEFINESOUND);
1106 swf_SetU16(tag, id); //id
1107 swf_SetSoundDefine(tag, samples, numsamples);
1109 sound = (sound_t*)malloc(sizeof(sound_t)); /* mem leak */
1113 if(dictionary_lookup(&sounds, name))
1114 syntaxerror("sound %s defined twice", name);
1115 dictionary_put2(&sounds, name, sound);
1123 static char* gradient_getToken(const char**p)
1127 while(**p && strchr(" \t\n\r", **p)) {
1131 while(**p && !strchr(" \t\n\r", **p)) {
1134 result = malloc((*p)-start+1);
1135 memcpy(result,start,(*p)-start+1);
1136 result[(*p)-start] = 0;
1140 float parsePercent(char*str);
1141 RGBA parseColor(char*str);
1143 GRADIENT parseGradient(const char*str)
1146 const char* p = str;
1147 memset(&gradient, 0, sizeof(GRADIENT));
1149 char*posstr,*colorstr;
1152 posstr = gradient_getToken(&p);
1155 pos = parsePercent(posstr);
1156 if(!*p) syntaxerror("Error in shape data: Color expected after %s", posstr);
1157 colorstr = gradient_getToken(&p);
1158 color = parseColor(colorstr);
1159 if(gradient.num == sizeof(gradient.ratios)/sizeof(gradient.ratios[0])) {
1160 warning("gradient record too big- max size is 8, rest ignored");
1163 gradient.ratios[gradient.num] = (int)(pos*255.0);
1164 gradient.rgba[gradient.num] = color;
1172 void s_gradient(char*name, const char*text, int radial, int rotate)
1174 gradient_t* gradient;
1175 gradient = malloc(sizeof(gradient_t));
1176 memset(gradient, 0, sizeof(gradient_t));
1177 gradient->gradient = parseGradient(text);
1178 gradient->radial = radial;
1179 gradient->rotate = rotate;
1181 if(dictionary_lookup(&gradients, name))
1182 syntaxerror("gradient %s defined twice", name);
1183 dictionary_put2(&gradients, name, gradient);
1186 void s_action(const char*text)
1189 a = swf_ActionCompile(text, stack[0].swf->fileVersion);
1191 syntaxerror("Couldn't compile ActionScript");
1194 tag = swf_InsertTag(tag, ST_DOACTION);
1196 swf_ActionSet(tag, a);
1201 int s_swf3action(char*name, char*action)
1204 instance_t* object = dictionary_lookup(&instances, name);
1208 a = action_SetTarget(0, name);
1209 if(!strcmp(action, "nextframe")) a = action_NextFrame(a);
1210 else if(!strcmp(action, "previousframe")) a = action_PreviousFrame(a);
1211 else if(!strcmp(action, "stop")) a = action_Stop(a);
1212 else if(!strcmp(action, "play")) a = action_Play(a);
1213 a = action_SetTarget(a, "");
1216 tag = swf_InsertTag(tag, ST_DOACTION);
1217 swf_ActionSet(tag, a);
1222 void s_outline(char*name, char*format, char*source)
1231 swf_Shape11DrawerInit(&draw, 0);
1232 draw_string(&draw, source);
1234 shape = swf_ShapeDrawerToShape(&draw);
1235 //shape2 = swf_ShapeToShape2(shape);
1236 //bounds = swf_GetShapeBoundingBox(shape2);
1237 //swf_Shape2Free(shape2);
1238 bounds = swf_ShapeDrawerGetBBox(&draw);
1239 draw.dealloc(&draw);
1241 outline = (outline_t*)malloc(sizeof(outline_t));
1242 memset(outline, 0, sizeof(outline_t));
1243 outline->shape = shape;
1244 outline->bbox = bounds;
1246 if(dictionary_lookup(&outlines, name))
1247 syntaxerror("outline %s defined twice", name);
1248 dictionary_put2(&outlines, name, outline);
1251 int s_playsound(char*name, int loops, int nomultiple, int stop)
1253 sound_t* sound = dictionary_lookup(&sounds, name);
1258 tag = swf_InsertTag(tag, ST_STARTSOUND);
1259 swf_SetU16(tag, sound->id); //id
1260 memset(&info, 0, sizeof(info));
1263 info.nomultiple = nomultiple;
1264 swf_SetSoundInfo(tag, &info);
1268 void s_includeswf(char*name, char*filename)
1276 U16 cutout[] = {ST_SETBACKGROUNDCOLOR, ST_PROTECT, ST_FREEALL, ST_REFLEX};
1277 f = open(filename,O_RDONLY|O_BINARY);
1279 warning("Couldn't open file \"%s\": %s", filename, strerror(errno));
1280 s_box(name, 0, 0, black, 20, 0);
1283 if (swf_ReadSWF(f,&swf)<0) {
1284 warning("Only SWF files supported in .shape for now. File \"%s\" wasn't SWF.", filename);
1285 s_box(name, 0, 0, black, 20, 0);
1290 /* FIXME: The following sets the bounding Box for the character.
1291 It is wrong for two reasons:
1292 a) It may be too small (in case objects in the movie clip at the borders)
1293 b) it may be too big (because the poor movie never got autocropped)
1297 s = tag = swf_InsertTag(tag, ST_DEFINESPRITE);
1298 swf_SetU16(tag, id);
1301 swf_Relocate(&swf, idmap);
1303 ftag = swf.firstTag;
1307 for(t=0;t<sizeof(cutout)/sizeof(cutout[0]);t++)
1308 if(cutout[t] == ftag->id) {
1312 if(ftag->id == ST_DEFINESPRITE && !swf_IsFolded(ftag))
1314 if(ftag->id == ST_END)
1318 /* We simply dump all tags right after the sprite
1319 header, relying on the fact that swf_OptimizeTagOrder() will
1320 sort things out for us later.
1321 We also rely on the fact that the imported SWF is well-formed.
1323 tag = swf_InsertTag(tag, ftag->id);
1324 swf_SetBlock(tag, ftag->data, ftag->len);
1328 syntaxerror("Included file %s contains errors", filename);
1329 tag = swf_InsertTag(tag, ST_END);
1333 s_addcharacter(name, id, tag, r);
1336 SRECT s_getCharBBox(char*name)
1338 character_t* c = dictionary_lookup(&characters, name);
1339 if(!c) syntaxerror("character '%s' unknown(2)", name);
1342 SRECT s_getInstanceBBox(char*name)
1344 instance_t * i = dictionary_lookup(&instances, name);
1346 if(!i) syntaxerror("instance '%s' unknown(4)", name);
1348 if(!c) syntaxerror("internal error(5)");
1351 parameters_t s_getParameters(char*name)
1353 instance_t * i = dictionary_lookup(&instances, name);
1354 if(!i) syntaxerror("instance '%s' unknown(10)", name);
1355 return i->parameters;
1357 void s_startclip(char*instance, char*character, parameters_t p)
1359 character_t* c = dictionary_lookup(&characters, character);
1363 syntaxerror("character %s not known", character);
1365 i = s_addinstance(instance, c, currentdepth);
1367 m = s_instancepos(i->character->size, &p);
1369 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1370 /* TODO: should be ObjectPlaceClip, with clipdepth backpatched */
1371 swf_ObjectPlace(tag, c->id, currentdepth, &m, &p.cxform, instance);
1373 i->lastFrame= currentframe;
1375 stack[stackpos].tag = tag;
1376 stack[stackpos].type = 2;
1385 swf_SetTagPos(stack[stackpos].tag, 0);
1386 swf_GetPlaceObject(stack[stackpos].tag, &p);
1387 p.clipdepth = currentdepth;
1389 swf_ClearTag(stack[stackpos].tag);
1390 swf_SetPlaceObject(stack[stackpos].tag, &p);
1394 void s_put(char*instance, char*character, parameters_t p)
1396 character_t* c = dictionary_lookup(&characters, character);
1400 syntaxerror("character %s not known (in .put %s=%s)", character, instance, character);
1403 i = s_addinstance(instance, c, currentdepth);
1405 m = s_instancepos(i->character->size, &p);
1407 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1408 swf_ObjectPlace(tag, c->id, currentdepth, &m, &p.cxform, instance);
1410 i->lastFrame = currentframe;
1414 void s_jump(char*instance, parameters_t p)
1416 instance_t* i = dictionary_lookup(&instances, instance);
1419 syntaxerror("instance %s not known", instance);
1423 m = s_instancepos(i->character->size, &p);
1425 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1426 swf_ObjectMove(tag, i->depth, &m, &p.cxform);
1428 i->lastFrame = currentframe;
1431 parameters_t s_interpolate(parameters_t*p1, parameters_t*p2, int pos, int num)
1435 if(num==0 || num==1)
1437 ratio = (float)pos/(float)num;
1439 p.x = (p2->x-p1->x)*ratio + p1->x;
1440 p.y = (p2->y-p1->y)*ratio + p1->y;
1441 p.scalex = (p2->scalex-p1->scalex)*ratio + p1->scalex;
1442 p.scaley = (p2->scaley-p1->scaley)*ratio + p1->scaley;
1443 p.rotate = (p2->rotate-p1->rotate)*ratio + p1->rotate;
1444 p.shear = (p2->shear-p1->shear)*ratio + p1->shear;
1446 p.cxform.r0 = ((float)p2->cxform.r0-(float)p1->cxform.r0)*ratio + p1->cxform.r0;
1447 p.cxform.g0 = ((float)p2->cxform.g0-(float)p1->cxform.g0)*ratio + p1->cxform.g0;
1448 p.cxform.b0 = ((float)p2->cxform.b0-(float)p1->cxform.b0)*ratio + p1->cxform.b0;
1449 p.cxform.a0 = ((float)p2->cxform.a0-(float)p1->cxform.a0)*ratio + p1->cxform.a0;
1451 p.cxform.r1 = (p2->cxform.r1-p1->cxform.r1)*ratio + p1->cxform.r1;
1452 p.cxform.g1 = (p2->cxform.g1-p1->cxform.g1)*ratio + p1->cxform.g1;
1453 p.cxform.b1 = (p2->cxform.b1-p1->cxform.b1)*ratio + p1->cxform.b1;
1454 p.cxform.a1 = (p2->cxform.a1-p1->cxform.a1)*ratio + p1->cxform.a1;
1456 p.pivot.x = (p2->pivot.x-p1->pivot.x)*ratio + p1->pivot.x;
1457 p.pivot.y = (p2->pivot.y-p1->pivot.y)*ratio + p1->pivot.y;
1458 p.pin.x = (p2->pin.x-p1->pin.x)*ratio + p1->pin.x;
1459 p.pin.y = (p2->pin.y-p1->pin.y)*ratio + p1->pin.y;
1463 void s_change(char*instance, parameters_t p2)
1465 instance_t* i = dictionary_lookup(&instances, instance);
1469 int frame, allframes;
1471 syntaxerror("instance %s not known", instance);
1475 allframes = currentframe - i->lastFrame - 1;
1477 warning(".change ignored. can only .put/.change an object once per frame.");
1481 m = s_instancepos(i->character->size, &p2);
1482 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1483 swf_ObjectMove(tag, i->depth, &m, &p2.cxform);
1486 /* o.k., we got the start and end point set. Now iterate though all the
1487 tags in between, inserting object changes after each new frame */
1490 if(!t) syntaxerror("internal error(6)");
1492 while(frame < allframes) {
1493 if(t->id == ST_SHOWFRAME) {
1498 p = s_interpolate(&p1, &p2, frame, allframes);
1499 m = s_instancepos(i->character->size, &p); //needed?
1500 lt = swf_InsertTag(t, ST_PLACEOBJECT2);
1501 i->lastFrame = currentframe;
1502 swf_ObjectMove(lt, i->depth, &m, &p.cxform);
1504 if(frame == allframes)
1509 syntaxerror("internal error(8) (frame=%d/%d)", frame, allframes);
1513 void s_delinstance(char*instance)
1515 instance_t* i = dictionary_lookup(&instances, instance);
1517 syntaxerror("instance %s not known", instance);
1519 tag = swf_InsertTag(tag, ST_REMOVEOBJECT2);
1520 swf_SetU16(tag, i->depth);
1521 dictionary_del(&instances, instance);
1524 void s_qchange(char*instance, parameters_t p)
1531 syntaxerror(".end unexpected");
1532 if(stack[stackpos-1].type == 0)
1534 else if(stack[stackpos-1].type == 1)
1536 else if(stack[stackpos-1].type == 2)
1538 else if(stack[stackpos-1].type == 3)
1540 else syntaxerror("internal error 1");
1543 // ------------------------------------------------------------------------
1545 typedef int command_func_t(map_t*args);
1547 SRECT parseBox(char*str)
1550 float xmin, xmax, ymin, ymax;
1551 char*x = strchr(str, 'x');
1553 if(!strcmp(str, "autocrop")) {
1554 r.xmin = r.ymin = r.xmax = r.ymax = 0;
1558 d1 = strchr(x+1, ':');
1560 d2 = strchr(d1+1, ':');
1562 if(sscanf(str, "%fx%f", &xmax, &ymax) < 2)
1566 else if(d1 && !d2) {
1567 if(sscanf(str, "%fx%f:%f", &xmax, &ymax, &xmin) < 3)
1573 if(sscanf(str, "%fx%f:%f:%f", &xmax, &ymax, &xmin, &ymin) < 4)
1578 r.xmin = (SCOORD)(xmin*20);
1579 r.ymin = (SCOORD)(ymin*20);
1580 r.xmax = (SCOORD)(xmax*20);
1581 r.ymax = (SCOORD)(ymax*20);
1584 syntaxerror("expression %s is not a valid bound Box.\nE.g. 1024x768 or 1024x768:30:30 would have been valid bounding Boxes.", str);
1587 float parseFloat(char*str)
1591 int parseInt(char*str)
1596 if(str[0]=='+' || str[0]=='-')
1600 if(str[t]<'0' || str[t]>'9')
1601 syntaxerror("Not an Integer: \"%s\"", str);
1604 int parseTwip(char*str)
1608 if(str[0]=='+' || str[0]=='-') {
1613 dot = strchr(str, '.');
1617 return sign*parseInt(str)*20;
1619 int l=strlen(++dot);
1621 for(s=str;s<dot-1;s++)
1622 if(*s<'0' || *s>'9')
1623 syntaxerror("Not a coordinate: \"%s\"", str);
1625 if(*s<'0' || *s>'9')
1626 syntaxerror("Not a coordinate: \"%s\"", str);
1628 if(l>2 || (l==2 && (dot[1]!='0' || dot[1]!='5'))) {
1629 warning("precision loss: %s converted to twip", str);
1634 return sign*atoi(str)*20;
1636 return sign*atoi(str)*20+atoi(dot)*2;
1638 return sign*atoi(str)*20+atoi(dot)/5;
1643 int isPoint(char*str)
1645 if(strchr(str, '('))
1651 SPOINT parsePoint(char*str)
1655 int l = strlen(str);
1656 char*comma = strchr(str, ',');
1657 if(str[0]!='(' || str[l-1]!=')' || !comma || l>70)
1658 syntaxerror("\"%s\" is not a valid point of the form (x,y)", str);
1659 strncpy(tmp, str+1, comma-(str+1));tmp[comma-(str+1)]=0;
1660 p.x = parseTwip(tmp);
1661 strncpy(tmp, comma+1, l-1-(comma+1-str));tmp[l-1-(comma+1-str)]=0;
1662 p.y = parseTwip(tmp);
1666 int parseColor2(char*str, RGBA*color)
1668 int l = strlen(str);
1672 struct {unsigned char r,g,b;char*name;} colors[] =
1673 {{255,250,250,"snow"},{220,220,220,"gainsboro"},{250,240,230,"linen"},{255,228,196,"bisque"},
1674 {255,228,181,"moccasin"},{255,248,220,"cornsilk"},{255,255,240,"ivory"},{255,245,238,"seashell"},
1675 {240,255,240,"honeydew"},{240,255,255,"azure"},{230,230,250,"lavender"},{255,255,255,"white"},
1676 {0,0,0,"black"},{190,190,190,"gray"},{190,190,190,"grey"},{0,0,128,"navy"},{0,0,255,"blue"},
1677 {64,224,208,"turquoise"},{0,255,255,"cyan"},{127,255,212,"aquamarine"}, {0,255,0,"green"},
1678 {127,255,0,"chartreuse"},{240,230,140,"khaki"},{255,255,0,"yellow"},
1679 {255,215,0,"gold"},{218,165,32,"goldenrod"},{160,82,45,"sienna"},{205,133,63,"peru"},
1680 {222,184,135,"burlywood"},{245,245,220,"beige"},{245,222,179,"wheat"},{210,180,140,"tan"},
1681 {210,105,30,"chocolate"},{178,34,34,"firebrick"},{165,42,42,"brown"},{250,128,114,"salmon"},
1682 {255,165,0,"orange"},{255,127,80,"coral"},{255,99,71,"tomato"},{255,0,0,"red"},
1683 {255,192,203,"pink"},{176,48,96,"maroon"},{255,0,255,"magenta"},{238,130,238,"violet"},
1684 {221,160,221,"plum"},{218,112,214,"orchid"},{160,32,240,"purple"},{216,191,216,"thistle"}};
1688 if(str[0]=='#' && (l==7 || l==9)) {
1689 if(l == 7 && !(sscanf(str, "#%02x%02x%02x", &r, &g, &b)))
1691 if(l == 9 && !(sscanf(str, "#%02x%02x%02x%02x", &r, &g, &b, &a)))
1693 color->r = r; color->g = g; color->b = b; color->a = a;
1696 for(t=0;t<sizeof(colors)/sizeof(colors[0]);t++)
1697 if(!strcmp(str, colors[t].name)) {
1702 color->r = r; color->g = g; color->b = b; color->a = a;
1708 RGBA parseColor(char*str)
1711 if(!parseColor2(str, &c))
1712 syntaxerror("Expression '%s' is not a color", str);
1716 typedef struct _muladd {
1721 MULADD parseMulAdd(char*str)
1724 char* str2 = (char*)malloc(strlen(str)+5);
1731 if(sscanf(str2, "%f%f %d", &mul, &add, &i)==2+1) { add/=256.0; i=1;}
1732 else if(sscanf(str2, "%f%%%f %d", &mul, &add, &i)==2+1) { mul/=100.0; add/=256.0; i=2;}
1733 else if(sscanf(str2, "%f%f%% %d", &mul, &add, &i)==2+1) { add/=100.0; i=3;}
1734 else if(sscanf(str2, "%f%%%f%% %d", &mul, &add, &i)==2+1) { mul/=100.0; add/=100.0; i=4;}
1735 else if(sscanf(str2, "+%f%% %d", &add, &i)==1+1) { mul=1.0;add/=100.0; i=5;}
1736 else if(sscanf(str2, "+%f %d", &add, &i)==1+1) { mul=1.0;add/=256.0; i=6;}
1737 else if(sscanf(str2, "-%f%% %d", &add, &i)==1+1) { mul=1.0;add/=-100.0; i=7;}
1738 else if(sscanf(str2, "-%f %d", &add, &i)==1+1) { mul=1.0;add/=-256.0; i=8;}
1739 else if(sscanf(str2, "%f%% %d", &mul, &i)==1+1) { mul/=100.0;add=0; i=9;}
1740 else if(sscanf(str2, "%f %d", &mul, &i)==1+1) { add=0; i=10;}
1742 syntaxerror("'%s' is not a valid color transform expression", str);
1744 m.add = (int)(add*256);
1745 m.mul = (int)(mul*256);
1750 MULADD mergeMulAdd(MULADD m1, MULADD m2)
1752 int a = (int)((double)m2.add+((double)m1.add*(double)m2.mul)/256.0);
1753 double m = ((double)m1.mul*(double)m2.mul)/256.0;
1755 if(a<-32768) a=-32768;
1756 if(a>32767) a=32767;
1757 if(m<-32768) m=-32768;
1758 if(m>32767) m=32767;
1764 float parsePercent(char*str)
1766 int l = strlen(str);
1770 return atoi(str)/100.0;
1772 syntaxerror("Expression '%s' is not a percentage", str);
1775 int isPercent(char*str)
1777 return str[strlen(str)-1]=='%';
1779 int parseNewSize(char*str, int size)
1782 return parsePercent(str)*size;
1784 return (int)(atof(str)*20);
1787 int isColor(char*str)
1790 return parseColor2(str, &c);
1793 static char* lu(map_t* args, char*name)
1795 char* value = map_lookup(args, name);
1797 map_dump(args, stdout, "");
1798 syntaxerror("internal error 2: value %s should be set", name);
1803 static int c_flash(map_t*args)
1805 char* name = lu(args, "name");
1806 char* compressstr = lu(args, "compress");
1807 SRECT bbox = parseBox(lu(args, "bbox"));
1808 int version = parseInt(lu(args, "version"));
1809 int fps = (int)(parseFloat(lu(args, "fps"))*256);
1811 RGBA color = parseColor(lu(args, "background"));
1812 if(!strcmp(name, "!default!") || override_outputname)
1815 if(!strcmp(compressstr, "default"))
1816 compress = version==6;
1817 else if(!strcmp(compressstr, "yes") || !strcmp(compressstr, "compress"))
1819 else if(!strcmp(compressstr, "no"))
1821 else syntaxerror("value \"%s\" not supported for the compress argument", compressstr);
1823 s_swf(name, bbox, version, fps, compress, color);
1826 int isRelative(char*str)
1828 return !strncmp(str, "<plus>", 6) ||
1829 !strncmp(str, "<minus>", 7);
1831 char* getOffset(char*str)
1833 if(!strncmp(str, "<plus>", 6))
1835 if(!strncmp(str, "<minus>", 7))
1837 syntaxerror("internal error (347)");
1840 int getSign(char*str)
1842 if(!strncmp(str, "<plus>", 6))
1844 if(!strncmp(str, "<minus>", 7))
1846 syntaxerror("internal error (348)");
1849 static dictionary_t points;
1850 static mem_t mpoints;
1851 int points_initialized = 0;
1853 SPOINT getPoint(SRECT r, char*name)
1856 if(!strcmp(name, "center")) {
1858 p.x = (r.xmin + r.xmax)/2;
1859 p.y = (r.ymin + r.ymax)/2;
1863 if(points_initialized)
1864 l = (int)dictionary_lookup(&points, name);
1866 syntaxerror("Invalid point: \"%s\".", name);
1869 return *(SPOINT*)&mpoints.buffer[l];
1871 static int c_gradient(map_t*args)
1873 char*name = lu(args, "name");
1874 int radial= strcmp(lu(args, "radial"), "radial")?0:1;
1875 int rotate = parseInt(lu(args, "rotate"));
1879 syntaxerror("colon (:) expected");
1881 s_gradient(name, text, radial,rotate);
1884 static int c_point(map_t*args)
1886 char*name = lu(args, "name");
1890 if(!points_initialized) {
1891 dictionary_init(&points);
1893 points_initialized = 1;
1895 p.x = parseTwip(lu(args, "x"));
1896 p.y = parseTwip(lu(args, "y"));
1897 pos = mem_put(&mpoints, &p, sizeof(p));
1898 string_set(&s1, name);
1900 dictionary_put(&points, s1, (void*)pos);
1903 static int c_play(map_t*args)
1905 char*name = lu(args, "name");
1906 char*loop = lu(args, "loop");
1907 char*nomultiple = lu(args, "nomultiple");
1909 if(!strcmp(nomultiple, "nomultiple"))
1912 nm = parseInt(nomultiple);
1914 if(s_playsound(name, parseInt(loop), nm, 0)) {
1916 } else if(s_swf3action(name, "play")) {
1922 static int c_stop(map_t*args)
1924 char*name = lu(args, "name");
1926 if(s_playsound(name, 0,0,1)) {
1928 } else if(s_swf3action(name, "stop")) {
1931 syntaxerror("I don't know anything about sound/movie \"%s\"", name);
1935 static int c_nextframe(map_t*args)
1937 char*name = lu(args, "name");
1939 if(s_swf3action(name, "nextframe")) {
1942 syntaxerror("I don't know anything about movie \"%s\"", name);
1946 static int c_previousframe(map_t*args)
1948 char*name = lu(args, "name");
1950 if(s_swf3action(name, "previousframe")) {
1953 syntaxerror("I don't know anything about movie \"%s\"", name);
1957 static int c_placement(map_t*args, int type)
1959 char*instance = lu(args, (type==0||type==4)?"instance":"name");
1962 char* luminancestr = lu(args, "luminance");
1963 char* scalestr = lu(args, "scale");
1964 char* scalexstr = lu(args, "scalex");
1965 char* scaleystr = lu(args, "scaley");
1966 char* rotatestr = lu(args, "rotate");
1967 char* shearstr = lu(args, "shear");
1968 char* xstr="", *pivotstr="";
1969 char* ystr="", *anglestr="";
1970 char*above = lu(args, "above"); /*FIXME*/
1971 char*below = lu(args, "below");
1972 char* rstr = lu(args, "red");
1973 char* gstr = lu(args, "green");
1974 char* bstr = lu(args, "blue");
1975 char* astr = lu(args, "alpha");
1976 char* pinstr = lu(args, "pin");
1977 char* as = map_lookup(args, "as");
1985 if(type==9) { // (?) .rotate or .arcchange
1986 pivotstr = lu(args, "pivot");
1987 anglestr = lu(args, "angle");
1989 xstr = lu(args, "x");
1990 ystr = lu(args, "y");
1993 luminance = parseMulAdd(luminancestr);
1996 luminance.mul = 256;
2000 if(scalexstr[0]||scaleystr[0])
2001 syntaxerror("scalex/scaley and scale cannot both be set");
2002 scalexstr = scaleystr = scalestr;
2005 if(type == 0 || type == 4) {
2007 character = lu(args, "character");
2008 parameters_clear(&p);
2009 } else if (type == 5) {
2010 character = lu(args, "name");
2011 parameters_clear(&p);
2014 p = s_getParameters(instance);
2019 if(isRelative(xstr)) {
2020 if(type == 0 || type == 4)
2021 syntaxerror("relative x values not allowed for initial put or startclip");
2022 p.x += parseTwip(getOffset(xstr))*getSign(xstr);
2024 p.x = parseTwip(xstr);
2028 if(isRelative(ystr)) {
2029 if(type == 0 || type == 4)
2030 syntaxerror("relative y values not allowed for initial put or startclip");
2031 p.y += parseTwip(getOffset(ystr))*getSign(ystr);
2033 p.y = parseTwip(ystr);
2037 /* scale, scalex, scaley */
2039 oldbbox = s_getCharBBox(character);
2041 oldbbox = s_getInstanceBBox(instance);
2043 oldwidth = oldbbox.xmax - oldbbox.xmin;
2044 oldheight = oldbbox.ymax - oldbbox.ymin;
2046 if(oldwidth==0) p.scalex = 1.0;
2049 p.scalex = (float)(parseNewSize(scalexstr, oldwidth))/oldwidth;
2053 if(oldheight==0) p.scaley = 1.0;
2056 p.scaley = (float)(parseNewSize(scaleystr, oldheight))/oldheight;
2062 if(isRelative(rotatestr)) {
2063 p.rotate += parseFloat(getOffset(rotatestr))*getSign(rotatestr);
2065 p.rotate = parseFloat(rotatestr);
2071 if(isRelative(shearstr)) {
2072 p.shear += parseFloat(getOffset(shearstr))*getSign(shearstr);
2074 p.shear = parseFloat(shearstr);
2079 if(isPoint(pivotstr))
2080 p.pivot = parsePoint(pivotstr);
2082 p.pivot = getPoint(oldbbox, pivotstr);
2086 p.pin = parsePoint(pinstr);
2088 p.pin = getPoint(oldbbox, pinstr);
2091 /* color transform */
2093 if(rstr[0] || luminancestr[0]) {
2096 r = parseMulAdd(rstr);
2098 r.add = p.cxform.r0;
2099 r.mul = p.cxform.r1;
2101 r = mergeMulAdd(r, luminance);
2102 p.cxform.r0 = r.mul;p.cxform.r1 = r.add;
2104 if(gstr[0] || luminancestr[0]) {
2107 g = parseMulAdd(gstr);
2109 g.add = p.cxform.g0;
2110 g.mul = p.cxform.g1;
2112 g = mergeMulAdd(g, luminance);
2113 p.cxform.g0 = g.mul;p.cxform.g1 = g.add;
2115 if(bstr[0] || luminancestr[0]) {
2118 b = parseMulAdd(bstr);
2120 b.add = p.cxform.b0;
2121 b.mul = p.cxform.b1;
2123 b = mergeMulAdd(b, luminance);
2124 p.cxform.b0 = b.mul;p.cxform.b1 = b.add;
2127 MULADD a = parseMulAdd(astr);
2128 p.cxform.a0 = a.mul;p.cxform.a1 = a.add;
2132 s_put(instance, character, p);
2134 s_change(instance, p);
2136 s_qchange(instance, p);
2138 s_jump(instance, p);
2140 s_startclip(instance, character, p);
2141 else if(type == 5) {
2143 s_buttonput(character, as, p);
2145 s_buttonput(character, "shape", p);
2150 static int c_put(map_t*args)
2152 c_placement(args, 0);
2155 static int c_change(map_t*args)
2157 c_placement(args, 1);
2160 static int c_qchange(map_t*args)
2162 c_placement(args, 2);
2165 static int c_arcchange(map_t*args)
2167 c_placement(args, 2);
2170 static int c_jump(map_t*args)
2172 c_placement(args, 3);
2175 static int c_startclip(map_t*args)
2177 c_placement(args, 4);
2180 static int c_show(map_t*args)
2182 c_placement(args, 5);
2185 static int c_del(map_t*args)
2187 char*instance = lu(args, "name");
2188 s_delinstance(instance);
2191 static int c_end(map_t*args)
2196 static int c_sprite(map_t*args)
2198 char* name = lu(args, "name");
2202 static int c_frame(map_t*args)
2204 char*framestr = lu(args, "n");
2205 char*cutstr = lu(args, "cut");
2206 char*name = lu(args, "name");
2209 if(strcmp(cutstr, "no"))
2211 if(isRelative(framestr)) {
2212 frame = s_getframe();
2213 if(getSign(framestr)<0)
2214 syntaxerror("relative frame expressions must be positive");
2215 frame += parseInt(getOffset(framestr));
2218 frame = parseInt(framestr);
2219 if(s_getframe() >= frame
2220 && !(frame==0 && s_getframe()==frame)) // equality is o.k. for frame 0
2221 syntaxerror("frame expression must be >%d (is:%s)", s_getframe(), framestr);
2223 s_frame(frame, cut, name);
2226 static int c_primitive(map_t*args)
2228 char*name = lu(args, "name");
2229 char*command = lu(args, "commandname");
2230 int width=0, height=0, r=0;
2231 int linewidth = parseTwip(lu(args, "line"));
2232 char*colorstr = lu(args, "color");
2233 RGBA color = parseColor(colorstr);
2234 char*fillstr = lu(args, "fill");
2241 if(!strcmp(command, "circle"))
2243 else if(!strcmp(command, "filled"))
2247 width = parseTwip(lu(args, "width"));
2248 height = parseTwip(lu(args, "height"));
2249 } else if (type==1) {
2250 r = parseTwip(lu(args, "r"));
2251 } else if (type==2) {
2252 outline = lu(args, "outline");
2255 if(!strcmp(fillstr, "fill"))
2257 if(!strcmp(fillstr, "none"))
2259 if(width<0 || height<0 || linewidth<0 || r<0)
2260 syntaxerror("values width, height, line, r must be positive");
2262 if(type == 0) s_box(name, width, height, color, linewidth, fillstr);
2263 else if(type==1) s_circle(name, r, color, linewidth, fillstr);
2264 else if(type==2) s_filled(name, outline, color, linewidth, fillstr);
2268 static int c_textshape(map_t*args)
2270 char*name = lu(args, "name");
2271 char*text = lu(args, "text");
2272 char*font = lu(args, "font");
2273 float size = parsePercent(lu(args, "size"));
2275 s_textshape(name, font, size, text);
2279 static int c_swf(map_t*args)
2281 char*name = lu(args, "name");
2282 char*filename = lu(args, "filename");
2283 char*command = lu(args, "commandname");
2284 if(!strcmp(command, "shape"))
2285 warning("Please use .swf instead of .shape");
2286 s_includeswf(name, filename);
2290 static int c_font(map_t*args)
2292 char*name = lu(args, "name");
2293 char*filename = lu(args, "filename");
2294 s_font(name, filename);
2298 static int c_sound(map_t*args)
2300 char*name = lu(args, "name");
2301 char*filename = lu(args, "filename");
2302 s_sound(name, filename);
2306 static int c_text(map_t*args)
2308 char*name = lu(args, "name");
2309 char*text = lu(args, "text");
2310 char*font = lu(args, "font");
2311 float size = parsePercent(lu(args, "size"));
2312 RGBA color = parseColor(lu(args, "color"));
2313 s_text(name, font, text, (int)(size*100), color);
2317 static int c_soundtrack(map_t*args)
2322 static int c_quicktime(map_t*args)
2324 char*name = lu(args, "name");
2325 char*url = lu(args, "url");
2326 s_quicktime(name, url);
2330 static int c_image(map_t*args)
2332 char*command = lu(args, "commandname");
2333 char*name = lu(args, "name");
2334 char*filename = lu(args, "filename");
2335 if(!strcmp(command,"jpeg")) {
2336 int quality = (int)(parsePercent(lu(args, "quality"))*100);
2337 s_image(name, "jpeg", filename, quality);
2339 s_image(name, "png", filename, 0);
2344 static int c_outline(map_t*args)
2346 char*name = lu(args, "name");
2347 char*format = lu(args, "format");
2351 syntaxerror("colon (:) expected");
2353 s_outline(name, format, text);
2357 int fakechar(map_t*args)
2359 char*name = lu(args, "name");
2360 s_box(name, 0, 0, black, 20, 0);
2364 static int c_egon(map_t*args) {return fakechar(args);}
2365 static int c_button(map_t*args) {
2366 char*name = lu(args, "name");
2370 static int current_button_flags = 0;
2371 static int c_on_press(map_t*args)
2373 char*position = lu(args, "position");
2375 if(!strcmp(position, "inside")) {
2376 current_button_flags |= BC_OVERUP_OVERDOWN;
2377 } else if(!strcmp(position, "outside")) {
2378 //current_button_flags |= BC_IDLE_OUTDOWN;
2379 syntaxerror("IDLE_OVERDOWN not supported by SWF");
2380 } else if(!strcmp(position, "anywhere")) {
2381 current_button_flags |= /*BC_IDLE_OUTDOWN|*/BC_OVERUP_OVERDOWN|BC_IDLE_OVERDOWN;
2384 if(type == RAWDATA) {
2386 s_buttonaction(current_button_flags, action);
2387 current_button_flags = 0;
2393 static int c_on_release(map_t*args)
2395 char*position = lu(args, "position");
2397 if(!strcmp(position, "inside")) {
2398 current_button_flags |= BC_OVERDOWN_OVERUP;
2399 } else if(!strcmp(position, "outside")) {
2400 current_button_flags |= BC_OUTDOWN_IDLE;
2401 } else if(!strcmp(position, "anywhere")) {
2402 current_button_flags |= BC_OVERDOWN_OVERUP|BC_OUTDOWN_IDLE|BC_OVERDOWN_IDLE;
2405 if(type == RAWDATA) {
2407 s_buttonaction(current_button_flags, action);
2408 current_button_flags = 0;
2414 static int c_on_move_in(map_t*args)
2416 char*position = lu(args, "state");
2418 if(!strcmp(position, "pressed")) {
2419 current_button_flags |= BC_OUTDOWN_OVERDOWN;
2420 } else if(!strcmp(position, "not_pressed")) {
2421 current_button_flags |= BC_IDLE_OVERUP;
2422 } else if(!strcmp(position, "any")) {
2423 current_button_flags |= BC_OUTDOWN_OVERDOWN|BC_IDLE_OVERUP|BC_IDLE_OVERDOWN;
2426 if(type == RAWDATA) {
2428 s_buttonaction(current_button_flags, action);
2429 current_button_flags = 0;
2435 static int c_on_move_out(map_t*args)
2437 char*position = lu(args, "state");
2439 if(!strcmp(position, "pressed")) {
2440 current_button_flags |= BC_OVERDOWN_OUTDOWN;
2441 } else if(!strcmp(position, "not_pressed")) {
2442 current_button_flags |= BC_OVERUP_IDLE;
2443 } else if(!strcmp(position, "any")) {
2444 current_button_flags |= BC_OVERDOWN_OUTDOWN|BC_OVERUP_IDLE|BC_OVERDOWN_IDLE;
2447 if(type == RAWDATA) {
2449 s_buttonaction(current_button_flags, action);
2450 current_button_flags = 0;
2456 static int c_on_key(map_t*args)
2458 char*key = lu(args, "key");
2460 if(strlen(key)==1) {
2463 current_button_flags |= 0x4000 + (key[0]*0x200);
2465 syntaxerror("invalid character: %c"+key[0]);
2470 <ctrl-x> = 0x200*(x-'a')
2474 syntaxerror("invalid key: %s",key);
2477 if(type == RAWDATA) {
2479 s_buttonaction(current_button_flags, action);
2480 current_button_flags = 0;
2487 static int c_edittext(map_t*args)
2489 //"name font size width height text="" color=black maxlength=0 variable="" @password=0 @wordwrap=0 @multiline=0 @html=0 @noselect=0 @readonly=0"},
2490 char*name = lu(args, "name");
2491 char*font = lu(args, "font");
2492 int size = (int)(1024*parsePercent(lu(args, "size")));
2493 int width = parseTwip(lu(args, "width"));
2494 int height = parseTwip(lu(args, "height"));
2495 char*text = lu(args, "text");
2496 RGBA color = parseColor(lu(args, "color"));
2497 int maxlength = parseInt(lu(args, "maxlength"));
2498 char*variable = lu(args, "variable");
2499 char*passwordstr = lu(args, "password");
2500 char*wordwrapstr = lu(args, "wordwrap");
2501 char*multilinestr = lu(args, "multiline");
2502 char*htmlstr = lu(args, "html");
2503 char*noselectstr = lu(args, "noselect");
2504 char*readonlystr = lu(args, "readonly");
2505 char*borderstr = lu(args, "border");
2508 if(!strcmp(passwordstr, "password")) flags |= ET_PASSWORD;
2509 if(!strcmp(wordwrapstr, "wordwrap")) flags |= ET_WORDWRAP;
2510 if(!strcmp(multilinestr, "multiline")) flags |= ET_MULTILINE;
2511 if(!strcmp(readonlystr, "readonly")) flags |= ET_READONLY;
2512 if(!strcmp(htmlstr, "html")) flags |= ET_HTML;
2513 if(!strcmp(noselectstr, "noselect")) flags |= ET_NOSELECT;
2514 if(!strcmp(borderstr, "border")) flags |= ET_BORDER;
2516 s_edittext(name, font, size, width, height, text, &color, maxlength, variable, flags);
2520 static int c_morphshape(map_t*args) {return fakechar(args);}
2521 static int c_movie(map_t*args) {return fakechar(args);}
2523 static int c_texture(map_t*args) {return 0;}
2525 static int c_action(map_t*args)
2528 if(type != RAWDATA) {
2529 syntaxerror("colon (:) expected");
2539 command_func_t* func;
2542 {{"flash", c_flash, "bbox=autocrop background=black version=5 fps=50 name=!default! @compress=default"},
2543 {"frame", c_frame, "n=<plus>1 name= @cut=no"},
2544 // "import" type stuff
2545 {"swf", c_swf, "name filename"},
2546 {"shape", c_swf, "name filename"},
2547 {"jpeg", c_image, "name filename quality=80%"},
2548 {"png", c_image, "name filename"},
2549 {"movie", c_movie, "name filename"},
2550 {"sound", c_sound, "name filename"},
2551 {"font", c_font, "name filename"},
2552 {"soundtrack", c_soundtrack, "filename"},
2553 {"quicktime", c_quicktime, "url"},
2555 // generators of primitives
2557 {"point", c_point, "name x=0 y=0"},
2558 {"gradient", c_gradient, "name @radial=0 rotate=0"},
2559 {"outline", c_outline, "name format=simple"},
2560 {"textshape", c_textshape, "name font size=100% text"},
2562 // character generators
2563 {"box", c_primitive, "name width height color=white line=1 @fill=none"},
2564 {"circle", c_primitive, "name r color=white line=1 @fill=none"},
2565 {"filled", c_primitive, "name outline color=white line=1 @fill=none"},
2567 {"egon", c_egon, "name vertices color=white line=1 @fill=none"},
2568 {"text", c_text, "name text font size=100% color=white"},
2569 {"edittext", c_edittext, "name font size=100% width height text="" color=white maxlength=0 variable="" @password=0 @wordwrap=0 @multiline=0 @html=0 @noselect=0 @readonly=0 @border=0"},
2570 {"morphshape", c_morphshape, "name start end"},
2571 {"button", c_button, "name"},
2572 {"show", c_show, "name x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= pivot= pin= shear= rotate= ratio= above= below= as="},
2573 {"on_press", c_on_press, "position=inside"},
2574 {"on_release", c_on_release, "position=anywhere"},
2575 {"on_move_in", c_on_move_in, "state=not_pressed"},
2576 {"on_move_out", c_on_move_out, "state=not_pressed"},
2577 {"on_key", c_on_key, "key=any"},
2580 {"play", c_play, "name loop=0 @nomultiple=0"},
2581 {"stop", c_stop, "name"},
2582 {"nextframe", c_nextframe, "name"},
2583 {"previousframe", c_previousframe, "name"},
2585 // object placement tags
2586 {"put", c_put, "<i> x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= pivot= pin= shear= rotate= ratio= above= below="},
2587 {"startclip", c_startclip, "<i> x=0 y=0 red=+0 green=+0 blue=+0 alpha=+0 luminance= scale= scalex= scaley= pivot= pin= shear= rotate= ratio= above= below="},
2588 {"change", c_change, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= pivot= pin= shear= rotate= ratio= above= below="},
2589 {"arcchange", c_arcchange, "name pivot= angle= red= green= blue= alpha= luminance= scale= scalex= scaley= pivot= pin= shear= rotate= ratio= above= below="},
2590 {"qchange", c_qchange, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= pivot= pin= shear= rotate= ratio= above= below="},
2591 {"jump", c_jump, "name x= y= red= green= blue= alpha= luminance= scale= scalex= scaley= pivot= pin= shear= rotate= ratio= above= below="},
2592 {"del", c_del, "name"},
2593 // virtual object placement
2594 {"texture", c_texture, "<i> x=0 y=0 scale= scalex=100% scaley=100% shear=0 rotate=0"},
2596 // commands which start a block
2597 //startclip (see above)
2598 {"sprite", c_sprite, "name"},
2599 {"action", c_action, ""},
2605 static map_t parseArguments(char*command, char*pattern)
2621 string_set(&t1, "commandname");
2622 string_set(&t2, command);
2623 map_put(&result, t1, t2);
2625 if(!pattern || !*pattern)
2632 if(!strncmp("<i> ", x, 3)) {
2634 if(type == COMMAND || type == RAWDATA) {
2636 syntaxerror("character name expected");
2638 name[pos].str = "instance";
2640 value[pos].str = text;
2641 value[pos].len = strlen(text);
2645 if(type == ASSIGNMENT)
2648 name[pos].str = "character";
2650 value[pos].str = text;
2651 value[pos].len = strlen(text);
2659 isboolean[pos] = (x[0] =='@');
2672 name[pos].len = d-x;
2677 name[pos].len = e-x;
2678 value[pos].str = e+1;
2679 value[pos].len = d-e-1;
2687 /* for(t=0;t<len;t++) {
2688 printf("(%d) %s=%s %s\n", t, strdup_n(name[t], namelen[t]), strdup_n(value[t], valuelen[t]),
2689 isboolean[t]?"(boolean)":"");
2694 if(type == RAWDATA || type == COMMAND) {
2699 // first, search for boolean arguments
2700 for(pos=0;pos<len;pos++)
2702 if(!set[pos] && isboolean[pos] && !strncmp(name[pos].str, text, name[pos].len>textlen?name[pos].len:textlen)) {
2704 if(type == ASSIGNMENT)
2706 value[pos].str = text;
2707 value[pos].len = strlen(text);
2708 /*printf("setting boolean parameter %s (to %s)\n",
2709 strdup_n(name[pos], namelen[pos]),
2710 strdup_n(value[pos], valuelen[pos]));*/
2715 // second, search for normal arguments
2717 for(pos=0;pos<len;pos++)
2719 if((type == ASSIGNMENT && !strncmp(name[pos].str, text, name[pos].len>textlen?name[pos].len:textlen)) ||
2720 (type != ASSIGNMENT && !set[pos])) {
2722 syntaxerror("value %s set twice (old value:%s)", text, strdup_n(value[pos].str, value[pos].len));
2724 if(type == ASSIGNMENT)
2727 value[pos].str = text;
2728 value[pos].len = strlen(text);
2730 printf("setting parameter %s (to %s)\n",
2731 strdup_n(name[pos].str, name[pos].len),
2732 strdup_n(value[pos].str, value[pos].len));
2738 syntaxerror("don't know what to do with \"%s\". (All parameters for .%s already set)", text, command);
2742 for(t=0;t<len;t++) {
2743 printf("%s=%s\n", strdup_n(name[t].str, name[t].len), strdup_n(value[t].str, value[t].len));
2746 for(t=0;t<len;t++) {
2747 if(value[t].str && value[t].str[0] == '*') {
2748 //relative default- take value from some other parameter
2750 for(s=0;s<len;s++) {
2751 if(value[s].len == value[t].len-1 &&
2752 !strncmp(&value[t].str[1], value[s].str, value[s].len))
2753 value[t].str = value[s].str;
2756 if(value[t].str == 0) {
2758 syntaxerror("value for parameter %s missing (no default)", strdup_n(name[t].str, name[t].len));
2762 /* ok, now construct the dictionary from the parameters */
2766 map_put(&result, name[t], value[t]);
2770 static void parseArgumentsForCommand(char*command)
2775 msg("<verbose> parse Command: %s (line %d)", command, line);
2777 for(t=0;t<sizeof(arguments)/sizeof(arguments[0]);t++) {
2778 if(!strcmp(arguments[t].command, command)) {
2780 /* ugly hack- will be removed soon (once documentation and .sc generating
2781 utilities have been changed) */
2782 if(!strcmp(command, "swf") && !stackpos) {
2783 warning("Please use .flash instead of .swf- this will be mandatory soon");
2788 args = parseArguments(command, arguments[t].arguments);
2794 syntaxerror("command %s not known", command);
2796 // catch missing .flash directives at the beginning of a file
2797 if(strcmp(command, "flash") && !stackpos)
2799 syntaxerror("No movie defined- use .flash first");
2803 printf(".%s\n", command);fflush(stdout);
2804 map_dump(&args, stdout, "\t");fflush(stdout);
2807 (*arguments[nr].func)(&args);
2809 /*if(!strcmp(command, "button") ||
2810 !strcmp(command, "action")) {
2813 if(type == COMMAND) {
2814 if(!strcmp(text, "end"))
2828 int main (int argc,char ** argv)
2831 processargs(argc, argv);
2832 initLog(0,-1,0,0,-1,verbose);
2835 args_callback_usage(argv[0]);
2839 file = generateTokens(filename);
2841 printf("parser returned error.\n");
2847 while(!noMoreTokens()) {
2850 syntaxerror("command expected");
2851 parseArgumentsForCommand(text);