1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hidclex.l,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // Suppress any warnings from generated code:
33 #pragma GCC system_header
34 #elif defined __SUNPRO_CC
36 #elif defined _MSC_VER
37 #pragma warning(push, 1)
40 static char const Revision[] = "$Revision: 1.9 $" ;
55 XX XXXX XXX XX XX XXX XXX XX XXXXX XX XXX
56 XX XX XX XX X XX XX XX XX XX XX X XXX XX
57 XX X XX XX XX X XX XX XX XX XX XXXXXXX XX
58 XX XX XX XX XX XX XXXXX XX XX XX XX
59 XXXX XXXX XXX XXX XX XXXX XXXX XXXXX XXXX
65 /* length of buffer for reading with lex */
67 /* enlarge token buffer to tokenize whole strings */
71 int exclude_bracelevel=0; /* count braces in that start state */
72 static YY_BUFFER_STATE InputFiles[127]; // for recursive parse
73 static int nInputFileDepth = 0;
83 void freestring( char const * ); //forward
85 char* dot2underline( char* str )
87 size_t len=strlen(str);
88 for( size_t i=0; i<len; i++ )
89 if( str[i]=='.' ) str[i]='_';
93 void dotappend( char*& base, char const * suffix )
95 // append like "str.suffix" if suffix else "str"
101 if( (siz=strlen(suffix)) == 0 )
104 size_t siz2 = base==NULL ? 0 : strlen(base);
108 {//do never forget to increment/decrement alloc_cnt
109 newstr = (char*) malloc( (siz2+siz+1) +1 /*for "." */ );
114 fprintf( stderr,"error: dotappend() could not malloc() \n"), exit(1);
117 strcpy( newstr, base );
123 strcat( newstr, "." );
124 strcat( newstr, suffix );
128 void dotsubtract( char*& base, char const * suffix )
130 // remove dotted suffix from base.suffix --> base
132 if( base == NULL || suffix == NULL )
134 if( strlen(suffix) == 0 )
136 if( (strlen(suffix)+1) > strlen(base) )
138 char * pos=strstr( base, suffix);
139 if( pos && (pos-1 >= base) && ( *(pos-1) == '.') )
140 if( *(pos+strlen(suffix)) == '\0' ) //only if at end of base
146 char levelbuffer[512];
148 void adjust_levelbuffer()
151 for(i=0; i<level;i++) {
152 levelbuffer[i] = '\t';
154 levelbuffer[i] = '\0';
157 void freestring( char const * ptr )
160 adjust_levelbuffer();
161 //fprintf(stderr,"%sinfo: freestring line %d\n",levelbuffer, __LINE__);
162 free(const_cast< char * >(ptr)), ptr = NULL;
165 void makestring(char** newstr, char* oldstr)
168 adjust_levelbuffer();
170 fprintf(stderr,"%sinfo: makestring on line %d\n",levelbuffer,__LINE__);
172 strcpy( (*newstr=(char*)malloc(strlen(oldstr)+1)), oldstr);
173 if( *newstr==NULL ) {
175 "error: cannot malloc for makestring() alloc_cnt==%d \n", alloc_cnt);
181 int strcmpi(char const * stra, char const * strb)
183 // like strcmp() but case insensitive
187 a = (char) tolower(stra[i]);
188 b = (char) tolower(strb[i]);
193 if( a == '\0' && b == '\0' )
199 /* variables for listfile ( with project + pathname of src file ) */
201 #define MAXSRCFILES 2048
202 char* filename_tab[MAXSRCFILES];
203 char* project_tab[MAXSRCFILES];
205 //int fileno = 0; /* currently used filenumber */
207 /* globale variablen */
209 char const *filename = ""; //incl. path
210 //char *basename = "";
211 char const *project = "";
212 char const *subpath = ""; //from project name downwards like source\ui\xxx.src
221 //nicht aendern wg externer Abfrage ->size() == 2
230 for(int i=0; i<MAXRING;i++)
237 for(int i=0; i<MAXRING;i++) {
238 if( ring[i] != NULL )
239 freestring( ring[i] );
244 void set_broken() { broken = 1; }
262 char* extract_last(){
266 char* ttt=ring[last];
272 char* extract_actual() {
276 char *ttt=ring[ringpos];
283 ringpos= (++ringpos) % MAXRING;
284 if( ring[ringpos] != NULL )
285 freestring( ring[ringpos] ); /*otherwise: memory lost*/
286 ring[ ringpos ] = id;
288 // "info: ring[%d] == %s broken==%d \n"
289 // ,ringpos,ring[ringpos],broken
292 if( !(ringpos==0 && last==-1) )
293 last = (++last) % MAXRING;
298 /* Notnagel: die letzten identifier/number merken, fuer klasse & globalID */
304 #define TOK_SEMICOLON ';'
305 #define TOK_EQUAL '='
306 #define TOK_OPENBRACKET '['
307 #define TOK_CLOSEBRACKET ']'
308 #define TOK_OPENBRACE '{'
309 #define TOK_CLOSEBRACE '}'
310 #define TOK_KOMMA ','
312 #define TOK_GREATER '>'
313 #define TOK_OPENPAREN '('
314 #define TOK_CLOSEPAREN ')'
316 #define TOK_MINUS '-'
318 #define TOK_SLASH '/'
320 #define TOK_POSorSIZE 146
321 #define TOK_POSSIZE 147
322 #define TOK_TEXTTAG 148
323 #define TOK_IDNUM 149
325 #define TOK_EXTRADATA 151
327 #define TOK_MESSAGE 153
328 #define TOK_HELPTEXT 154
330 #define TOK_FALSE 156
332 #define TOK_RESID 180
334 #define TOK_STRING 190
336 #define TOK_INVALID (-1)
338 token lasttoken = TOK_INVALID;
345 char *globalID = const_cast< char * >("");
346 char const *globalKLASSE = NULL;
348 void reset_globalID() {
350 if( globalID && (strlen(globalID) > 0 ) ) {
351 freestring( globalID );
352 globalID = const_cast< char * >("");
357 //--------------------------------------------------------------------
361 resource ( const resource& ); //copy-ctor soll keiner benutzen
362 void operator=( const resource& ); // zuweisung auch nicht
368 token lasttoken; //before opening {
375 resource *ares ; /* aktuell bearbeitete resource */
377 resource::~resource()
379 if( klasse != NULL ) freestring(klasse);
380 if( localID != NULL ) freestring(localID);
381 if( helpID != NULL ) freestring(helpID);
388 lasttoken= TOK_INVALID;
395 int residfound = 0; // "Identifier = " auf momentanem level gefunden
398 resource* stack[MAXSTACK]; /* resource stack */
399 #define EMPTYSTACK (-1)
400 int stackptr = EMPTYSTACK;
402 void push_resource( resource* r )
405 if( stackptr >= MAXSTACK ) {
406 fprintf( stderr, "error: resource stack is full %d \n", stackptr);
409 stack[ stackptr ] = r;
412 resource* pop_resource()
415 fprintf( stderr, "error: pop resource from empty stack \n");
418 return stack[ stackptr-- ];
423 int eat_cpp_comment();
425 /*===================================================*/
427 // '+' im identifier wg basic\source\classes\sb.src
429 // '<' im identifier wg sc subtdlg.src
431 // '&' im identifier wg scerror.src so2..nocode.src svxerr.src scwarngs.src
434 //string (\"[^"]*\") alter einfacher string ohne "
439 %option never-interactive
444 string \"{simple}((((\\\\)*(\\\"))?){simple})*\"
449 resfilelist ([Ff][Ii][Ll][Ee][Ll][Ii][Ss][Tt])
450 resstringlist ([Ss][Tt][Rr][Ii][Nn][Gg][Ll][Ii][Ss][Tt])
451 resstring ([Ss][Tt][Rr][Ii][Nn][Gg])
453 identifier ([a-z_A-Z]+[a-z_A-Z<+&0-9]*)
454 number (([0-9]+)|(0x[0-9a-fA-F]+))
455 residentifier ([Ii][Dd][Ee][Nn][Tt][Ii][Ff][Ii][Ee][Rr])
457 wspecial ([\\ \t\n]*)
458 texttag (([Tt][Ii][Tt][Ll][Ee])|([Tt][Ee][Xx][Tt])|([Mm][Ee][Ss][Ss][Aa][Gg][Ee]))
459 qhelptag (([Qq][Uu][Ii][Cc][Kk])?([Hh][Ee][Ll][Pp][Tt][Ee][Xx][Tt]))
461 helptag ([Hh][Ee][Ll][Pp][Ii][Dd])
462 helpid ([a-zA-Z_0-9]+)
463 num2tag (([Pp][Oo][Ss])|([Ss][Ii][Zz][Ee]))
464 num4tag (([Pp][Oo][Ss][Ss][Ii][Zz][Ee]))
468 /* forget whitespace */;
471 ^[ \t]*#include.*\.src[">].* {
472 char NewFile[255]; //long names???
478 // nicht schoen aber geht...
479 for (i = 0; yytext[i+1] != 0; i++)
483 if ( yytext[i] == '"' || yytext[i] == '>' )
486 NewFile[j++] = yytext[i];
488 if ( yytext[i] == '"' || yytext[i] == '<' )
493 pFile = fopen( NewFile, "r" );
494 if( pFile == NULL ) {
495 fprintf( stderr, "warning: could not open inputfile %s \n", NewFile );
496 // try the new *_tmpl.src version instead
497 // this hack was introduced to allow localisation of included src files
498 const char* sStrTmpl = "_tmpl";
500 for ( i = 0 ; i <5 ; i++,j++ )
502 NewFile[j+5] = NewFile[j];
503 NewFile[j] = sStrTmpl[i];
506 fprintf( stderr, "trying inputfile %s \n", NewFile );
507 pFile = fopen( NewFile, "r" );
508 if( pFile == NULL ) {
509 fprintf( stderr, "error: could not open inputfile %s \n", NewFile );
513 InputFiles[ nInputFileDepth ] = yy_create_buffer( pFile, YY_BUF_SIZE );
514 yy_switch_to_buffer( InputFiles[ nInputFileDepth ] );
516 printf( "%s //ATTENTION!! %s gets included here\n", yytext, NewFile );
517 fprintf( outfile, "// %s //ATTENTION!! %s gets included here\n\n", yytext, NewFile );
521 fprintf( outfile, "%s\n\n", yytext );
524 ^[ \t]*#(if|ifdef|ifndef|elif).* {
535 ^[ \t]*#(undef|error|pragma).* {
540 fprintf( outfile, "%s", yytext );
544 <INITIAL,MACRO_STATE>"/*" {
548 <INITIAL,MACRO_STATE>"//" {
553 fprintf( outfile, "%s\n", yytext );
558 fprintf( outfile, "\\\n" );
559 ;/* macro schadet nicht, koennte gebraucht werden */
564 fprintf( outfile, "%s", yytext );
565 ;/* ignore all this unused input */
568 ";" {ring->set_zero(); lasttoken = TOK_SEMICOLON; }
569 "=" {ring->set_zero(); lasttoken = TOK_EQUAL; }
570 "[" {ring->set_broken(); lasttoken = TOK_OPENBRACKET; }
571 "]" {ring->set_broken(); lasttoken = TOK_CLOSEBRACKET; }
575 exclude_bracelevel += 1;
576 //fprintf( stderr,"info: lev %d : found {\n", exclude_bracelevel );
583 // or a brace opens a block
585 if( in_define && !strcmp(yytext,"\\\n") ) {
587 if( in_define++ == 1 )
596 dotappend( globalID, ares->localID );
597 ares->residfound = residfound;
598 push_resource( ares );
603 ares->residfound = 0;
605 ares->lineno = yylineno;
606 ares->lasttoken = lasttoken;
607 if( ring->size() == 2 ) {
608 ares->klasse = ring->extract_last();
609 ares->localID = ring->extract_actual();
610 } else if(ring->size() == 1) {
611 ares->klasse = ring->extract_actual();
613 if( level==1 ){ //Ausnahme: Resource auf Ebene 1
614 globalID= ares->localID;
615 ares->localID = NULL;
616 globalKLASSE= ares->klasse;
619 //fprintf(stderr,"info: { level: %d\n", level);
622 lasttoken = TOK_OPENBRACE;
627 //-----------------------------
628 exclude_bracelevel -= 1;
629 //fprintf( stderr,"info: lev %d : found }\n", exclude_bracelevel );
630 if( exclude_bracelevel==1 ) {
632 exclude_bracelevel=0;
639 //fprintf(stderr,"info: } level: %d\n",level);
641 if( !strcmp(yytext,"}") )
643 else if( in_define && (!strcmp(yytext,"\n") )) {
645 //no continuation line for #define
650 //there was a continuation line for #define
661 char const * globklasse =
662 globalKLASSE==NULL ? LEER:globalKLASSE;
664 ares->localID==NULL ? LEER:ares->localID;
665 char const * klasse =
666 ares->klasse==NULL ? LEER:ares->klasse;
668 globalID==NULL ? LEER:globalID;
671 //wg. Starview-Klasse String in ehdl.c und doc.c
672 // wenn generierte C++-Quellen compiliert werden
674 //if( !strcmp(globklasse,"String" )) globklasse = "string";
675 //if( !strcmp(klasse,"String" )) klasse = "string";
678 //---------------------------------------------------
679 // generate the body of a new C main program,
680 // which is filled with printf statements
681 // to compute (via preproseccor & compiler)
682 // the codenumbers for resource names like menu$RID_SVX$xyz
686 fprintf(outfile, "#include \"starview.hid\" \n\n");
687 fprintf(outfile, " int main() { \n\n\n");
691 strcpy(globunder,glob);
692 dot2underline( globunder );
693 char const * globsuffix = strrchr(glob,'.');
694 globsuffix = globsuffix==NULL ? glob:globsuffix+1;
697 fprintf( outfile,"\n\t printf(\"%s \\t %cs %cu \\n\",\n",
698 ares->helpID,'%','%');
699 fprintf(outfile,"\t\"HelpID\", (%s) ); \n", ares->helpID);
701 else if( ares->localID ) {
702 fprintf( outfile,"\n\t printf(\"%s:%s:%s:%s \\t %cs %cu %cs %cu \\n\",\n",
703 project,klasse,globunder,local,'%','%','%','%');
704 fprintf( outfile,"\t\"Norm %s\", (%s), \"%s\", (%s) );\n",
705 globklasse,globsuffix, klasse,local);
707 else if( (strcmpi("MenuItem",klasse)==0) ||
708 (strcmpi("ToolBoxItem",klasse)==0) ) {
709 ; //no output (99% is a separator)
712 fprintf( outfile,"\n\t printf(\"%s:%s:%s \\t %cs %cu %cs \\n\",\n",
713 project,klasse,globunder,'%','%','%');
714 fprintf( outfile,"\t\"Norm %s\", (%s), \"%s\" );\n",
715 globklasse,globsuffix, klasse);
728 ares = pop_resource();
729 residfound = ares->residfound;
730 dotsubtract( globalID, ares->localID );
734 lasttoken = TOK_CLOSEBRACE;
739 "," {ring->set_broken(); lasttoken = TOK_KOMMA; }
741 "<" {ring->set_broken(); lasttoken = TOK_LESS; }
742 ">" {ring->set_broken(); lasttoken = TOK_GREATER; }
744 "(" {ring->set_broken(); lasttoken = TOK_OPENPAREN; }
745 ")" {ring->set_broken(); lasttoken = TOK_CLOSEPAREN; }
746 "+" {ring->set_broken(); lasttoken = TOK_PLUS; }
747 "-" {ring->set_broken(); lasttoken = TOK_MINUS; }
748 "*" {ring->set_broken(); lasttoken = TOK_STAR; }
749 "/" {ring->set_broken(); lasttoken = TOK_SLASH; }
752 {helptag}{w}"="{w}{helpid}{w}";" {
754 // extract text for helpid and put to ares
755 char* pos = strchr(yytext,'=');
756 size_t offset = strspn(pos+1," \t\n");
757 char* start = pos+1+offset;
758 size_t offset2= strcspn( start, "; \t\n");
759 char* end = start+offset2;
762 makestring( &helpid, start );
763 ares->helpID = helpid;
766 {residentifier}{w}"="[ \t\n]*({identifier}|{number}) {
768 lasttoken = TOK_RESID;
771 //extract resource id and store as localID
772 char *after = strrchr(yytext,'=');
773 char *resid = after + strspn(after,"= \t\n");
775 makestring( &localID, resid );
776 ares->localID = localID;
783 exclude_bracelevel = 1;
784 //fprintf( stderr,"info: lev %d : found exclusion\n", exclude_bracelevel );
790 /* identifier/number in einem ring ablegen */
792 char *def=strstr(yytext,"#define");
795 makestring( &identifier, def+1 );
798 makestring( &identifier, yytext );
799 ring->set( identifier );
800 lasttoken = TOK_IDNUM;
803 <INITIAL,EXCLUDE_STATE>{string} {
805 lasttoken = TOK_STRING;
806 //printf("%6s %11s %8d %s \n",project,filename,yylineno, yytext);
810 <INITIAL,EXCLUDE_STATE>. { //fprintf( stderr,"warning: unused input on line %d of %s \n%s\n",
811 //yylineno, filename, yytext);
815 ; //do nothing, ignore
822 void makeversion( char* version )
824 char const *pos = strpbrk( Revision, "0123456789." );
825 size_t siz = strspn( pos, "0123456789." );
827 strncpy(version, pos, siz);
828 strcat( version, " ");
831 strcpy( version," unknown " );
834 int main( int argc, char* argv[] )
836 static char const *Compiler = "HID-Compiler ";
837 static char const *Author = "OG ";
838 static char HIDCompiler[100];
839 static char Version[100];
842 makeversion( Version );
843 strcpy( HIDCompiler, Compiler );
844 strcat( HIDCompiler, Version );
845 strcat( HIDCompiler, Author );
846 fprintf( stderr, "\n %s \n\n", HIDCompiler);
850 "usage: hidc file.src file.c project \n"
852 "You must give exactly 3 arguments.\n"
853 "1 - an existing SRC file.\n"
854 "2 - C file to be generated (which generates the HID file when run).\n"
855 "3 - the project name (an arbitrary name).\n\n"
862 char *outfilename = argv[2];
863 if( (outfile=fopen( outfilename , "w" )) ==NULL ) {
864 fprintf(stderr,"error: could not open outputfile '%s' \n", outfilename);
871 pFile = fopen( filename, "r" );
872 if( pFile == NULL ) {
873 fprintf( stderr, "error: could not open inputfile %s \n", filename );
876 InputFiles[ nInputFileDepth ] = yy_create_buffer( pFile, YY_BUF_SIZE );
877 yy_switch_to_buffer( InputFiles[ nInputFileDepth ] );
878 ring = new ident_ring;
881 fprintf(outfile, "/* Generated from %s */\n\n", HIDCompiler );
882 fprintf(outfile, "/* Source was: %s */\n", filename );
885 yylex(); /* do the real work here */
888 fprintf(outfile, "#include \"starview.hid\" \n\n");
889 fprintf(outfile, " int main() { \n\n\n");
891 fprintf(outfile, "\nreturn 0;");
892 fprintf(outfile, "\n} /*main*/\n");
898 yy_delete_buffer( InputFiles[ nInputFileDepth ] );
899 if ( nInputFileDepth == 0 )
900 return 1;/* keine src files mehr */
904 fprintf(outfile, "// Done reading file\n\n");
905 yy_switch_to_buffer( InputFiles[ nInputFileDepth ] );
914 while( (c=yyinput()) != EOF ) {
917 else if( c=='/' && lastc=='*' )
918 break; /* end of comment found */
924 int eat_cpp_comment()
927 while( (c=yyinput()) != EOF ) {
933 unput(c); /* because next #.... line was not found */