Fixed warnings.
[AROS.git] / tools / flexcat / src / createcatsrc.c
blob9d1b813aa01bf892354e0c4138d17da38b8a67ce
1 /*
2 * $Id$
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.
23 #include "flexcat.h"
24 #include "readprefs.h"
25 #include "swapfuncs.h"
26 #include "showfuncs.h"
27 #include "scancd.h"
28 #include "scanct.h"
29 #include "createcat.h"
30 #include "globals.h"
31 #include "utils.h"
33 enum StringTypes
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 */
43 enum OutputModes
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;
53 FILE *OutputFile;
54 int OutputLen;
55 int LongStrings = TRUE; /* Generate long or short strings */
57 /// CalcRealLength
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)
68 int count = 0;
69 int len;
70 char *src = source;
71 char bytes[10];
73 while(*src != '\0')
75 len = ReadChar(&src, bytes);
76 // substract one byte for double backslashes
77 if(len == 2)
78 len--;
80 count += len;
83 /* printf("%ld: '%s'\n", count, source); */
84 return count;
87 ///
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)
100 OutputLen = 0;
101 OutputFile = fp;
102 OutputMode = OutputMode_None;
104 switch(OutputType)
106 case TYPE_C:
107 case TYPE_OBERON:
108 putc('\"', fp);
109 OutputMode = OutputMode_Ascii;
110 break;
112 case TYPE_E:
113 putc('\'', fp);
115 case TYPE_ASSEMBLER:
116 case TYPE_NONE:
117 break;
122 /// SeparateCatStringOutput
124 /* SeparateCatStringOutput gets called to split a catalog into
125 separate lines. */
127 void SeparateCatStringOutput(void)
129 switch(OutputType)
131 case TYPE_C:
132 if(!LongStrings)
134 fputs("\"\\\n\t\"", OutputFile);
136 break;
138 case TYPE_E:
139 if(!LongStrings)
141 fputs("\' +\n\t\'", OutputFile);
143 break;
145 case TYPE_OBERON:
146 if(!LongStrings)
148 fputs("\"\n\t\"", OutputFile);
150 break;
152 case TYPE_ASSEMBLER:
153 if(!LongStrings)
155 if(OutputMode == OutputMode_Ascii)
157 putc('\'', OutputFile);
159 putc('\n', OutputFile);
160 OutputMode = OutputMode_None;
162 break;
164 case TYPE_NONE:
165 break;
170 /// WriteBinChar
172 /* WriteBinChar writes one binary character into the source file. */
174 void WriteBinChar(int c)
176 switch(OutputType)
178 case TYPE_C:
179 case TYPE_E:
180 case TYPE_OBERON:
181 switch(c)
183 case '\b':
184 fputs("\\b", OutputFile);
185 break;
187 case '\n':
188 fputs("\\n", OutputFile);
189 break;
191 case '\r':
192 fputs("\\r", OutputFile);
193 break;
195 case '\t':
196 fputs("\\t", OutputFile);
197 break;
199 case '\f':
200 fputs("\\f", OutputFile);
201 break;
203 case '\0':
204 fputs("\\000", OutputFile);
205 break;
207 default:
208 if(OutputType == TYPE_E && c == '\033')
210 fputs("\\e", OutputFile);
212 else
214 fprintf(OutputFile, "\\%c%c%c", ((c >> 6) & 3) + '0', ((c >> 3) & 7) + '0', (c & 7) + '0');
216 break;
219 ++OutputLen;
220 OutputMode = OutputMode_Bin;
221 break;
223 case TYPE_ASSEMBLER:
224 switch(OutputMode)
226 case OutputMode_None:
227 fprintf(OutputFile, "\tdc.b\t$%02x", c & 0xff);
228 break;
230 case OutputMode_Ascii:
231 putc('\'', OutputFile);
233 case OutputMode_Bin:
234 fprintf(OutputFile, ",$%02x", c & 0xff);
235 break;
237 ++OutputLen;
238 OutputMode = OutputMode_Bin;
239 break;
241 case TYPE_NONE:
242 ShowError(MSG_ERR_NOBINCHARS);
243 break;
248 /// WriteAsciiChar
250 /* WriteAsciiChar writes one ascii character into the source file. */
252 void WriteAsciiChar(int c)
254 switch(OutputType)
256 case TYPE_C:
257 case TYPE_OBERON:
258 switch(c)
260 case '\"':
261 fputs("\\\"", OutputFile);
262 break;
264 default:
265 putc(c, OutputFile);
266 break;
268 ++OutputLen;
269 OutputMode = OutputMode_Ascii;
270 break;
272 case TYPE_E:
273 switch(c)
275 case '\'':
276 fputs("''", OutputFile);
277 break;
279 default:
280 putc(c, OutputFile);
281 break;
283 ++OutputLen;
284 OutputMode = OutputMode_Ascii;
285 break;
287 case TYPE_ASSEMBLER:
288 if(c == '\'')
290 WriteBinChar(c);
292 else
294 switch(OutputMode)
296 case OutputMode_None:
297 fprintf(OutputFile, "\tdc.b\t\'%c", c);
298 break;
300 case OutputMode_Ascii:
301 putc(c, OutputFile);
302 break;
304 case OutputMode_Bin:
305 fprintf(OutputFile, ",\'%c", c);
306 break;
308 ++OutputLen;
309 OutputMode = OutputMode_Ascii;
311 break;
313 case TYPE_NONE:
314 putc(c, OutputFile);
315 break;
320 /// TerminateCatStringOutput
322 /* TerminateCatStringOutput finishes the output of a catalog string. */
324 void TerminateCatStringOutput(void)
326 switch(OutputType)
328 case TYPE_C:
329 case TYPE_OBERON:
330 putc('\"', OutputFile);
331 break;
333 case TYPE_E:
334 putc('\'', OutputFile);
335 break;
337 case TYPE_ASSEMBLER:
338 switch(OutputMode)
340 case OutputMode_Ascii:
341 putc('\'', OutputFile);
342 // fall through...
344 case OutputMode_Bin:
345 break;
347 case OutputMode_None:
348 break;
350 break;
352 case TYPE_NONE:
353 break;
360 /// WriteString
362 /* This writes a source string. */
364 static void WriteString(FILE * fpout, char *str, int32 Len, int lenbytes, int allbytes)
366 char bytes[10];
367 int bytesread;
368 int needseparate = FALSE;
370 InitCatStringOutput(fpout);
371 if(Len >= 0)
373 int i;
375 for(i = lenbytes; i >= 1; i--)
377 WriteBinChar((int)((char *)&Len)[sizeof(Len) - i]);
382 while(*str != '\0')
384 bytesread = ReadChar(&str, bytes);
385 if(bytesread > 0)
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);
399 else
400 WriteBinChar((int)c);
402 if(allbytes == 0)
403 break;
405 while(--bytesread > 0);
407 else
408 needseparate = TRUE;
411 TerminateCatStringOutput();
415 /// CreateSourceFile
417 /* Finally, the source creation. */
419 void CreateSourceFile(char *SourceFile, char *TemplateFile, char *CDFile)
421 FILE *fpin, *fpout;
422 char *line;
423 char *OrigTemplateFile = TemplateFile;
425 ScanFile = SourceFile;
426 ScanLine = 0;
428 /* Open the source file. This may be found in various places. */
430 if((fpin = fopen(TemplateFile, "r")) == NULL)
432 #ifdef AMIGA
433 if(*prefs_sddir != '\0')
435 TemplateFile = AddFileName(prefs_sddir, OrigTemplateFile);
436 fpin = fopen(TemplateFile, "r");
438 #endif
441 if(fpin == NULL)
443 #ifdef AMIGA
444 char sddir[80];
446 if(GetVar(FLEXCAT_SDDIR, sddir, 80, 0) != 0)
447 #else
448 char *sddir;
450 if((sddir = getenv(FLEXCAT_SDDIR)) != NULL)
451 #endif
453 TemplateFile = AddFileName(sddir, OrigTemplateFile);
454 fpin = fopen(TemplateFile, "r");
458 if(fpin == NULL)
460 TemplateFile = AddFileName(strdup(DEFAULT_FLEXCAT_SDDIR), OrigTemplateFile);
461 fpin = fopen(TemplateFile, "r");
464 if(fpin == NULL)
466 ShowError(MSG_ERR_NOSOURCEDESCRIPTION, OrigTemplateFile);
467 return;
470 if((fpout = fopen(SourceFile, "w")) == NULL)
472 ShowError(MSG_ERR_NOSOURCE, SourceFile);
473 return;
476 if(!NoBufferedIO)
477 setvbuf(fpin, NULL, _IOFBF, buffer_size);
478 if(!NoBufferedIO)
479 setvbuf(fpout, NULL, _IOFBF, buffer_size);
481 while(!feof(fpin) && (line = ReadLine(fpin, FALSE)) != NULL)
483 struct CatString *cs;
484 int NeedRepeat;
485 char bytes[10];
486 int bytesread;
488 cs = FirstCatString;
492 char *currentline = line;
494 NeedRepeat = FALSE;
495 if(*currentline == '#' && *(++currentline) == '#')
497 ++currentline;
498 OverSpace(&currentline);
499 if(Strnicmp(currentline, "rem", 3) == 0)
501 /* We just skip this line. */
502 continue;
505 if(Strnicmp(currentline, "stringtype", 10) == 0)
507 currentline += 10;
508 OverSpace(&currentline);
509 if(Strnicmp(currentline, "c", 1) == 0)
511 OutputType = TYPE_C;
512 ++currentline;
514 else if(Strnicmp(currentline, "assembler", 9) == 0)
516 OutputType = TYPE_ASSEMBLER;
517 currentline += 9;
519 else if(Strnicmp(currentline, "oberon", 6) == 0)
521 OutputType = TYPE_OBERON;
522 currentline += 6;
524 else if(Strnicmp(currentline, "e", 1) == 0)
526 OutputType = TYPE_E;
527 ++currentline;
529 else if(Strnicmp(currentline, "none", 4) == 0)
531 OutputType = TYPE_NONE;
532 currentline += 4;
534 else
536 ShowWarn(MSG_ERR_UNKNOWNSTRINGTYPE);
537 currentline += strlen(currentline);
539 OverSpace(&currentline);
540 if(*currentline != '\0')
542 ShowError(MSG_ERR_EXTRA_CHARACTERS);
544 continue;
546 else if(Strnicmp(currentline, "shortstrings", 12) == 0)
548 currentline += 12;
549 LongStrings = FALSE;
550 OverSpace(&currentline);
551 if(*currentline != '\0')
553 ShowError(MSG_ERR_EXTRA_CHARACTERS);
555 continue;
558 currentline = line;
559 while(*currentline != '\0')
561 bytesread = ReadChar(&currentline, bytes);
562 if(bytesread > 0)
564 if(*bytes == '%')
566 char c = *currentline++;
568 switch(c)
570 case 'b':
571 fputs(BaseName, fpout);
572 break;
574 case 'B':
576 char *basenamestr = BaseName;
577 int i;
578 for (i = 0; i < strlen(BaseName); i++)
580 c = *basenamestr++;
581 if (c >= '0' && c <= '9')
582 putc(c, fpout);
583 else if ((c >= 'A' && c <= 'Z') ||
584 (c >= 'a' && c <= 'z'))
585 putc(c & 0x5F, fpout);
586 else
587 putc('_', fpout);
589 break;
592 case 'n':
593 fprintf(fpout, "%d", NumStrings);
594 break;
596 case 'v':
597 fprintf(fpout, "%d", CatVersion);
598 break;
600 case 'l':
601 WriteString(fpout, Language, -1, cs->LenBytes, cs->POformat);
602 break;
604 case 'f':
606 char *tempstr;
608 if((c = *currentline++) == 'v')
610 fputs(VERS, fpout);
612 else
614 tempstr = AllocFileName(CDFile, c - '0');
615 fputs(tempstr, fpout);
617 free(tempstr);
620 break;
622 case 'o':
624 char *tempstr;
626 tempstr = AllocFileName(SourceFile, *currentline++ - '0');
627 fputs(tempstr, fpout);
629 free(tempstr);
631 break;
633 case 'i':
634 NeedRepeat = TRUE;
635 if(cs != NULL)
636 fputs(cs->ID_Str, fpout);
637 break;
639 case 'a':
640 case 't':
641 case 'd':
642 case 'x':
643 case 'c':
644 case '0':
645 case '1':
646 case '2':
647 case '3':
648 case '4':
649 case '5':
650 case '6':
651 case '7':
652 case '8':
653 case '9':
655 int len = 0;
657 while(c >= '0' && c <= '9')
659 len = (c - '0') + len * 10;
660 c = *currentline++;
663 if(c == 'a')
665 int _len = len ? len : 4;
666 char *start;
667 char _StrLen[20 + 1];
669 snprintf(_StrLen, sizeof(_StrLen), "%020lx", (long unsigned)cs->ID);
670 start = &_StrLen[20 - _len * 2];
671 while(_len > 0)
673 fprintf(fpout, "\\x%.2s", start);
674 start += 2;
675 _len--;
678 else if(c == 't')
680 int _len = len ? len : 4;
681 char *start;
682 char _StrLen[20 + 1];
684 snprintf(_StrLen, sizeof(_StrLen), "%020lx", (long unsigned)((CalcRealLength(cs->CD_Str) + 1) & 0xfffffe));
685 start = &_StrLen[20 - _len * 2];
686 while(_len > 0)
688 fprintf(fpout, "\\x%.2s", start);
689 start += 2;
690 _len--;
693 else if(c == 'c' || c == 'd' || c == 'x')
695 char buffer[20];
697 if(c == 'c')
698 c = 'o';
699 if(len)
700 snprintf(buffer, sizeof(buffer), "%%0%d%c", len, c);
701 else
702 snprintf(buffer, sizeof(buffer), "%%%c", c);
704 if(cs != NULL)
705 fprintf(fpout, buffer, cs->ID);
708 NeedRepeat = TRUE;
710 break;
712 case 'e':
713 NeedRepeat = TRUE;
714 if(cs != NULL)
715 fprintf(fpout, "%d", cs->Nr);
716 break;
718 case 's':
719 NeedRepeat = TRUE;
720 if(cs != NULL)
722 char *idstr;
723 uint32 len = 0;
725 if(cs->LenBytes)
727 idstr = cs->CD_Str;
728 while(*idstr != '\0')
730 bytesread = ReadChar(&idstr, bytes);
731 if(bytesread > 0)
733 ++len;
738 WriteString(fpout, cs->CD_Str, cs->LenBytes ? len : (uint32)-1, cs->LenBytes, cs->POformat);
740 break;
742 case '(':
743 NeedRepeat = TRUE;
744 while(*currentline != '\0' && *currentline != ')')
746 bytesread = ReadChar(&currentline, 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);
758 else
760 ++currentline;
762 break;
764 /* !!!! FIXME !!!! */
765 case 'z':
767 int diff = (((CalcRealLength(cs->CD_Str) + 1) & 0xfffffe) - (CalcRealLength(cs->CD_Str)));
769 NeedRepeat = TRUE;
770 while(diff > 0)
772 fprintf(fpout, "\\x00");
773 diff--;
775 break;
778 default:
780 int ch = *currentline++;
782 putc(ch, fpout);
786 else
788 putc((int)bytes[bytesread - 1], fpout);
792 putc('\n', fpout);
794 while(NeedRepeat == TRUE && cs != NULL && (cs = cs->Next) != NULL);
796 free(line);
798 fclose(fpin);
799 fclose(fpout);
801 #ifdef AMIGA
802 SetProtection(SourceFile, FILE_MASK);
803 #endif