4 * Copyright (C) 1993-1999 by Jochen Wiedmann and Marcin Orlowski
5 * Copyright (C) 2002-2017 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"
36 TYPE_C
, /* Produce C strings */
37 TYPE_ASSEMBLER
, /* Produce Assembler strings */
38 TYPE_OBERON
, /* Produce Oberon strings */
39 TYPE_E
, /* Produce E strings. (Oops, thought
40 it allows only 32 bit integers? ;-) */
41 TYPE_NONE
/* Simple strings */
46 OutputMode_None
, /* Nothing written yet */
47 OutputMode_Bin
, /* Last character written was binary */
48 OutputMode_Ascii
/* Last character written was Ascii */
51 int OutputMode
= OutputMode_None
;
52 int OutputType
= TYPE_C
;
56 int LongStrings
= TRUE
; /* Generate long or short strings */
60 /* This function measures the real (binary) length of source
61 string. It correctly process 'slash chars' (\n, \000 etc),
62 and gives the real length such source string have.
64 Inputs: source - pointer to NULL terminated source string
65 Result: real length */
67 int CalcRealLength(char *source
)
76 len
= ReadChar(&src
, bytes
);
77 // substract one byte for double backslashes
84 /* printf("%ld: '%s'\n", count, source); */
89 /// InitCatStringOutput
91 /* InitCatStringOutput gets called before writing a catalog string as source.
92 Inputs: fp = file pointer to the output file
93 type = one of TYPE_C create C strings
94 TYPE_ASSEMBLER create Assembler strings
95 TYPE_OBERON create Oberon strings
96 TYPE_E create E strings
97 TYPE_NONE create simple strings */
99 void InitCatStringOutput(FILE *fp
)
103 OutputMode
= OutputMode_None
;
110 OutputMode
= OutputMode_Ascii
;
123 /// SeparateCatStringOutput
125 /* SeparateCatStringOutput gets called to split a catalog into
128 void SeparateCatStringOutput(void)
135 fputs("\"\\\n\t\"", OutputFile
);
142 fputs("\' +\n\t\'", OutputFile
);
149 fputs("\"\n\t\"", OutputFile
);
156 if(OutputMode
== OutputMode_Ascii
)
158 putc('\'', OutputFile
);
160 putc('\n', OutputFile
);
161 OutputMode
= OutputMode_None
;
173 /* WriteBinChar writes one binary character into the source file. */
175 void WriteBinChar(int c
)
185 fputs("\\b", OutputFile
);
189 fputs("\\n", OutputFile
);
193 fputs("\\r", OutputFile
);
197 fputs("\\t", OutputFile
);
201 fputs("\\f", OutputFile
);
205 fputs("\\000", OutputFile
);
209 if(OutputType
== TYPE_E
&& c
== '\033')
211 fputs("\\e", OutputFile
);
215 fprintf(OutputFile
, "\\%c%c%c", ((c
>> 6) & 3) + '0', ((c
>> 3) & 7) + '0', (c
& 7) + '0');
221 OutputMode
= OutputMode_Bin
;
227 case OutputMode_None
:
228 fprintf(OutputFile
, "\tdc.b\t$%02x", c
& 0xff);
231 case OutputMode_Ascii
:
232 putc('\'', OutputFile
);
235 fprintf(OutputFile
, ",$%02x", c
& 0xff);
239 OutputMode
= OutputMode_Bin
;
243 ShowError(MSG_ERR_NOBINCHARS
);
251 /* WriteAsciiChar writes one ascii character into the source file. */
253 void WriteAsciiChar(int c
)
262 fputs("\\\"", OutputFile
);
270 OutputMode
= OutputMode_Ascii
;
277 fputs("''", OutputFile
);
285 OutputMode
= OutputMode_Ascii
;
297 case OutputMode_None
:
298 fprintf(OutputFile
, "\tdc.b\t\'%c", c
);
301 case OutputMode_Ascii
:
306 fprintf(OutputFile
, ",\'%c", c
);
310 OutputMode
= OutputMode_Ascii
;
321 /// TerminateCatStringOutput
323 /* TerminateCatStringOutput finishes the output of a catalog string. */
325 void TerminateCatStringOutput(void)
331 putc('\"', OutputFile
);
335 putc('\'', OutputFile
);
341 case OutputMode_Ascii
:
342 putc('\'', OutputFile
);
348 case OutputMode_None
:
363 /* This writes a source string. */
365 static void WriteString(FILE * fpout
, char *str
, int32 Len
, int lenbytes
, int allbytes
)
369 int needseparate
= FALSE
;
371 InitCatStringOutput(fpout
);
376 for(i
= lenbytes
; i
>= 1; i
--)
378 WriteBinChar((int)((char *)&Len
)[sizeof(Len
) - i
]);
385 bytesread
= ReadChar(&str
, bytes
);
388 if(needseparate
== TRUE
)
390 SeparateCatStringOutput();
391 needseparate
= FALSE
;
396 unsigned char c
= bytes
[bytesread
- 1];
398 if((c
>= 0x20 && c
< 0x7f) || c
>= 0xa0)
399 WriteAsciiChar((int)c
);
401 WriteBinChar((int)c
);
406 while(--bytesread
> 0);
412 TerminateCatStringOutput();
418 /* Finally, the source creation. */
420 void CreateSourceFile(char *SourceFile
, char *TemplateFile
, char *CDFile
)
424 char *OrigTemplateFile
= TemplateFile
;
426 ScanFile
= SourceFile
;
429 /* Open the source file. This may be found in various places. */
431 if((fpin
= fopen(TemplateFile
, "r")) == NULL
)
434 if(*prefs_sddir
!= '\0')
436 TemplateFile
= AddFileName(prefs_sddir
, OrigTemplateFile
);
437 fpin
= fopen(TemplateFile
, "r");
447 if(GetVar(FLEXCAT_SDDIR
, sddir
, 80, 0) != 0)
451 if((sddir
= getenv(FLEXCAT_SDDIR
)) != NULL
)
454 TemplateFile
= AddFileName(sddir
, OrigTemplateFile
);
455 fpin
= fopen(TemplateFile
, "r");
461 TemplateFile
= AddFileName(strdup(DEFAULT_FLEXCAT_SDDIR
), OrigTemplateFile
);
462 fpin
= fopen(TemplateFile
, "r");
467 ShowError(MSG_ERR_NOSOURCEDESCRIPTION
, OrigTemplateFile
);
471 if((fpout
= fopen(SourceFile
, "w")) == NULL
)
473 ShowError(MSG_ERR_NOSOURCE
, SourceFile
);
478 setvbuf(fpin
, NULL
, _IOFBF
, buffer_size
);
480 setvbuf(fpout
, NULL
, _IOFBF
, buffer_size
);
482 // initialize "line" ahead of the loop
483 // the loop will bail out early for empty files
485 while(!feof(fpin
) && (line
= ReadLine(fpin
, FALSE
)) != NULL
)
487 struct CatString
*cs
;
496 char *currentline
= line
;
499 if(*currentline
== '#' && *(++currentline
) == '#')
502 OverSpace(¤tline
);
503 if(Strnicmp(currentline
, "rem", 3) == 0)
505 /* We just skip this line. */
509 if(Strnicmp(currentline
, "stringtype", 10) == 0)
512 OverSpace(¤tline
);
513 if(Strnicmp(currentline
, "c", 1) == 0)
518 else if(Strnicmp(currentline
, "assembler", 9) == 0)
520 OutputType
= TYPE_ASSEMBLER
;
523 else if(Strnicmp(currentline
, "oberon", 6) == 0)
525 OutputType
= TYPE_OBERON
;
528 else if(Strnicmp(currentline
, "e", 1) == 0)
533 else if(Strnicmp(currentline
, "none", 4) == 0)
535 OutputType
= TYPE_NONE
;
540 ShowWarn(MSG_ERR_UNKNOWNSTRINGTYPE
);
541 currentline
+= strlen(currentline
);
543 OverSpace(¤tline
);
544 if(*currentline
!= '\0')
546 ShowError(MSG_ERR_EXTRA_CHARACTERS
);
550 else if(Strnicmp(currentline
, "shortstrings", 12) == 0)
554 OverSpace(¤tline
);
555 if(*currentline
!= '\0')
557 ShowError(MSG_ERR_EXTRA_CHARACTERS
);
563 while(*currentline
!= '\0')
565 bytesread
= ReadChar(¤tline
, bytes
);
570 char c
= *currentline
++;
575 fputs(BaseName
, fpout
);
580 char *basenamestr
= BaseName
;
582 for (i
= 0; i
< strlen(BaseName
); i
++)
585 if (c
>= '0' && c
<= '9')
587 else if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z'))
588 putc(c
& 0x5F, fpout
);
596 fprintf(fpout
, "%d", NumStrings
);
600 fprintf(fpout
, "%d", CatVersion
);
604 WriteString(fpout
, Language
, -1, cs
->LenBytes
, cs
->POformat
);
611 if((c
= *currentline
++) == 'v')
617 tempstr
= AllocFileName(CDFile
, c
- '0');
618 fputs(tempstr
, fpout
);
629 tempstr
= AllocFileName(SourceFile
, *currentline
++ - '0');
630 fputs(tempstr
, fpout
);
639 fputs(cs
->ID_Str
, fpout
);
660 while(c
>= '0' && c
<= '9')
662 len
= (c
- '0') + len
* 10;
668 int _len
= len
? len
: 4;
670 char _StrLen
[20 + 1];
672 snprintf(_StrLen
, sizeof(_StrLen
), "%020" PRIx32
, (uint32
)cs
->ID
);
673 start
= &_StrLen
[20 - _len
* 2];
676 fprintf(fpout
, "\\x%.2s", start
);
683 int _len
= len
? len
: 4;
685 char _StrLen
[20 + 1];
687 snprintf(_StrLen
, sizeof(_StrLen
), "%020" PRIx32
, (uint32
)((CalcRealLength(cs
->CD_Str
) + 1) & 0xfffffe));
688 start
= &_StrLen
[20 - _len
* 2];
691 fprintf(fpout
, "\\x%.2s", start
);
696 else if(c
== 'c' || c
== 'd' || c
== 'x')
703 snprintf(buffer
, sizeof(buffer
), "%%0%d%c", len
, c
);
705 snprintf(buffer
, sizeof(buffer
), "%%%c", c
);
708 fprintf(fpout
, buffer
, cs
->ID
);
718 fprintf(fpout
, "%d", cs
->Nr
);
731 while(*idstr
!= '\0')
733 bytesread
= ReadChar(&idstr
, bytes
);
741 WriteString(fpout
, cs
->CD_Str
, cs
->LenBytes
? len
: (uint32
)-1, cs
->LenBytes
, cs
->POformat
);
747 while(*currentline
!= '\0' && *currentline
!= ')')
749 bytesread
= ReadChar(¤tline
, bytes
);
750 if(bytesread
> 0 && cs
!= NULL
&& cs
->Next
!= NULL
)
752 putc((int)bytes
[bytesread
- 1], fpout
);
756 if(*currentline
== '\0')
758 /* FIXME: reuse MSG_ERR_NOTRAILINGBRACKET here? <tactica> */
759 ShowError(MSG_ERR_NOTERMINATEBRACKET
);
767 /* !!!! FIXME !!!! */
770 int diff
= (((CalcRealLength(cs
->CD_Str
) + 1) & 0xfffffe) - (CalcRealLength(cs
->CD_Str
)));
775 fprintf(fpout
, "\\x00");
783 int ch
= *currentline
++;
791 putc((int)bytes
[bytesread
- 1], fpout
);
797 while(NeedRepeat
== TRUE
&& cs
!= NULL
&& (cs
= cs
->Next
) != NULL
);
805 SetProtection(SourceFile
, FILE_MASK
);