4 * Copyright (C) 1993-1999 by Jochen Wiedmann and Marcin Orlowski
5 * Copyright (C) 2002-2010 by the FlexCat Open Source Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "readprefs.h"
25 #include "swapfuncs.h"
26 #include "showfuncs.h"
29 #include "createcat.h"
35 TYPE_C
, /* Produce C strings */
36 TYPE_ASSEMBLER
, /* Produce Assembler strings */
37 TYPE_OBERON
, /* Produce Oberon strings */
38 TYPE_E
, /* Produce E strings. (Oops, thought
39 it allows only 32 bit integers? ;-) */
40 TYPE_NONE
/* Simple strings */
45 OutputMode_None
, /* Nothing written yet */
46 OutputMode_Bin
, /* Last character written was binary */
47 OutputMode_Ascii
/* Last character written was Ascii */
50 int OutputMode
= OutputMode_None
;
51 int OutputType
= TYPE_C
;
55 int LongStrings
= TRUE
; /* Generate long or short strings */
59 /* This function measures the real (binary) length of source
60 string. It correctly process 'slash chars' (\n, \000 etc),
61 and gives the real length such source string have.
63 Inputs: source - pointer to NULL terminated source string
64 Result: real length */
66 int CalcRealLength(char *source
)
75 len
= ReadChar(&src
, bytes
);
76 // substract one byte for double backslashes
83 /* printf("%ld: '%s'\n", count, source); */
88 /// InitCatStringOutput
90 /* InitCatStringOutput gets called before writing a catalog string as source.
91 Inputs: fp = file pointer to the output file
92 type = one of TYPE_C create C strings
93 TYPE_ASSEMBLER create Assembler strings
94 TYPE_OBERON create Oberon strings
95 TYPE_E create E strings
96 TYPE_NONE create simple strings */
98 void InitCatStringOutput(FILE *fp
)
102 OutputMode
= OutputMode_None
;
109 OutputMode
= OutputMode_Ascii
;
122 /// SeparateCatStringOutput
124 /* SeparateCatStringOutput gets called to split a catalog into
127 void SeparateCatStringOutput(void)
134 fputs("\"\\\n\t\"", OutputFile
);
141 fputs("\' +\n\t\'", OutputFile
);
148 fputs("\"\n\t\"", OutputFile
);
155 if(OutputMode
== OutputMode_Ascii
)
157 putc('\'', OutputFile
);
159 putc('\n', OutputFile
);
160 OutputMode
= OutputMode_None
;
172 /* WriteBinChar writes one binary character into the source file. */
174 void WriteBinChar(int c
)
184 fputs("\\b", OutputFile
);
188 fputs("\\n", OutputFile
);
192 fputs("\\r", OutputFile
);
196 fputs("\\t", OutputFile
);
200 fputs("\\f", OutputFile
);
204 fputs("\\000", OutputFile
);
208 if(OutputType
== TYPE_E
&& c
== '\033')
210 fputs("\\e", OutputFile
);
214 fprintf(OutputFile
, "\\%c%c%c", ((c
>> 6) & 3) + '0', ((c
>> 3) & 7) + '0', (c
& 7) + '0');
220 OutputMode
= OutputMode_Bin
;
226 case OutputMode_None
:
227 fprintf(OutputFile
, "\tdc.b\t$%02x", c
& 0xff);
230 case OutputMode_Ascii
:
231 putc('\'', OutputFile
);
234 fprintf(OutputFile
, ",$%02x", c
& 0xff);
238 OutputMode
= OutputMode_Bin
;
242 ShowError(MSG_ERR_NOBINCHARS
);
250 /* WriteAsciiChar writes one ascii character into the source file. */
252 void WriteAsciiChar(int c
)
261 fputs("\\\"", OutputFile
);
269 OutputMode
= OutputMode_Ascii
;
276 fputs("''", OutputFile
);
284 OutputMode
= OutputMode_Ascii
;
296 case OutputMode_None
:
297 fprintf(OutputFile
, "\tdc.b\t\'%c", c
);
300 case OutputMode_Ascii
:
305 fprintf(OutputFile
, ",\'%c", c
);
309 OutputMode
= OutputMode_Ascii
;
320 /// TerminateCatStringOutput
322 /* TerminateCatStringOutput finishes the output of a catalog string. */
324 void TerminateCatStringOutput(void)
330 putc('\"', OutputFile
);
334 putc('\'', OutputFile
);
340 case OutputMode_Ascii
:
341 putc('\'', OutputFile
);
347 case OutputMode_None
:
362 /* This writes a source string. */
364 static void WriteString(FILE * fpout
, char *str
, int32 Len
, int lenbytes
, int allbytes
)
368 int needseparate
= FALSE
;
370 InitCatStringOutput(fpout
);
375 for(i
= lenbytes
; i
>= 1; i
--)
377 WriteBinChar((int)((char *)&Len
)[sizeof(Len
) - i
]);
384 bytesread
= ReadChar(&str
, bytes
);
387 if(needseparate
== TRUE
)
389 SeparateCatStringOutput();
390 needseparate
= FALSE
;
395 unsigned char c
= bytes
[bytesread
- 1];
397 if((c
>= 0x20 && c
< 0x7f) || c
>= 0xa0)
398 WriteAsciiChar((int)c
);
400 WriteBinChar((int)c
);
405 while(--bytesread
> 0);
411 TerminateCatStringOutput();
417 /* Finally, the source creation. */
419 void CreateSourceFile(char *SourceFile
, char *TemplateFile
, char *CDFile
)
423 char *OrigTemplateFile
= TemplateFile
;
425 ScanFile
= SourceFile
;
428 /* Open the source file. This may be found in various places. */
430 if((fpin
= fopen(TemplateFile
, "r")) == NULL
)
433 if(*prefs_sddir
!= '\0')
435 TemplateFile
= AddFileName(prefs_sddir
, OrigTemplateFile
);
436 fpin
= fopen(TemplateFile
, "r");
446 if(GetVar(FLEXCAT_SDDIR
, sddir
, 80, 0) != 0)
450 if((sddir
= getenv(FLEXCAT_SDDIR
)) != NULL
)
453 TemplateFile
= AddFileName(sddir
, OrigTemplateFile
);
454 fpin
= fopen(TemplateFile
, "r");
460 TemplateFile
= AddFileName(strdup(DEFAULT_FLEXCAT_SDDIR
), OrigTemplateFile
);
461 fpin
= fopen(TemplateFile
, "r");
466 ShowError(MSG_ERR_NOSOURCEDESCRIPTION
, OrigTemplateFile
);
470 if((fpout
= fopen(SourceFile
, "w")) == NULL
)
472 ShowError(MSG_ERR_NOSOURCE
, SourceFile
);
477 setvbuf(fpin
, NULL
, _IOFBF
, buffer_size
);
479 setvbuf(fpout
, NULL
, _IOFBF
, buffer_size
);
481 while(!feof(fpin
) && (line
= ReadLine(fpin
, FALSE
)) != NULL
)
483 struct CatString
*cs
;
492 char *currentline
= line
;
495 if(*currentline
== '#' && *(++currentline
) == '#')
498 OverSpace(¤tline
);
499 if(Strnicmp(currentline
, "rem", 3) == 0)
501 /* We just skip this line. */
505 if(Strnicmp(currentline
, "stringtype", 10) == 0)
508 OverSpace(¤tline
);
509 if(Strnicmp(currentline
, "c", 1) == 0)
514 else if(Strnicmp(currentline
, "assembler", 9) == 0)
516 OutputType
= TYPE_ASSEMBLER
;
519 else if(Strnicmp(currentline
, "oberon", 6) == 0)
521 OutputType
= TYPE_OBERON
;
524 else if(Strnicmp(currentline
, "e", 1) == 0)
529 else if(Strnicmp(currentline
, "none", 4) == 0)
531 OutputType
= TYPE_NONE
;
536 ShowWarn(MSG_ERR_UNKNOWNSTRINGTYPE
);
537 currentline
+= strlen(currentline
);
539 OverSpace(¤tline
);
540 if(*currentline
!= '\0')
542 ShowError(MSG_ERR_EXTRA_CHARACTERS
);
546 else if(Strnicmp(currentline
, "shortstrings", 12) == 0)
550 OverSpace(¤tline
);
551 if(*currentline
!= '\0')
553 ShowError(MSG_ERR_EXTRA_CHARACTERS
);
559 while(*currentline
!= '\0')
561 bytesread
= ReadChar(¤tline
, bytes
);
566 char c
= *currentline
++;
571 fputs(BaseName
, fpout
);
576 char *basenamestr
= BaseName
;
578 for (i
= 0; i
< strlen(BaseName
); i
++)
581 if (c
>= '0' && c
<= '9')
583 else if ((c
>= 'A' && c
<= 'Z') ||
584 (c
>= 'a' && c
<= 'z'))
585 putc(c
& 0x5F, fpout
);
593 fprintf(fpout
, "%d", NumStrings
);
597 fprintf(fpout
, "%d", CatVersion
);
601 WriteString(fpout
, Language
, -1, cs
->LenBytes
, cs
->POformat
);
608 if((c
= *currentline
++) == 'v')
614 tempstr
= AllocFileName(CDFile
, c
- '0');
615 fputs(tempstr
, fpout
);
626 tempstr
= AllocFileName(SourceFile
, *currentline
++ - '0');
627 fputs(tempstr
, fpout
);
636 fputs(cs
->ID_Str
, fpout
);
657 while(c
>= '0' && c
<= '9')
659 len
= (c
- '0') + len
* 10;
665 int _len
= len
? len
: 4;
667 char _StrLen
[20 + 1];
669 snprintf(_StrLen
, sizeof(_StrLen
), "%020lx", (uint32
)cs
->ID
);
670 start
= &_StrLen
[20 - _len
* 2];
673 fprintf(fpout
, "\\x%.2s", start
);
680 int _len
= len
? len
: 4;
682 char _StrLen
[20 + 1];
684 snprintf(_StrLen
, sizeof(_StrLen
), "%020lx", (uint32
)((CalcRealLength(cs
->CD_Str
) + 1) & 0xfffffe));
685 start
= &_StrLen
[20 - _len
* 2];
688 fprintf(fpout
, "\\x%.2s", start
);
693 else if(c
== 'c' || c
== 'd' || c
== 'x')
700 snprintf(buffer
, sizeof(buffer
), "%%0%d%c", len
, c
);
702 snprintf(buffer
, sizeof(buffer
), "%%%c", c
);
705 fprintf(fpout
, buffer
, cs
->ID
);
715 fprintf(fpout
, "%d", cs
->Nr
);
728 while(*idstr
!= '\0')
730 bytesread
= ReadChar(&idstr
, bytes
);
738 WriteString(fpout
, cs
->CD_Str
, cs
->LenBytes
? len
: (uint32
)-1, cs
->LenBytes
, cs
->POformat
);
744 while(*currentline
!= '\0' && *currentline
!= ')')
746 bytesread
= ReadChar(¤tline
, bytes
);
747 if(bytesread
> 0 && cs
!= NULL
&& cs
->Next
!= NULL
)
749 putc((int)bytes
[bytesread
- 1], fpout
);
753 if(*currentline
== '\0')
755 /* FIXME: reuse MSG_ERR_NOTRAILINGBRACKET here? <tactica> */
756 ShowError(MSG_ERR_NOTERMINATEBRACKET
);
764 /* !!!! FIXME !!!! */
767 int diff
= (((CalcRealLength(cs
->CD_Str
) + 1) & 0xfffffe) - (CalcRealLength(cs
->CD_Str
)));
772 fprintf(fpout
, "\\x00");
780 int ch
= *currentline
++;
788 putc((int)bytes
[bytesread
- 1], fpout
);
794 while(NeedRepeat
== TRUE
&& cs
!= NULL
&& (cs
= cs
->Next
) != NULL
);
802 SetProtection(SourceFile
, FILE_MASK
);