use the new flexcat's source description file
[AROS.git] / tools / flexcat / src / createcatsrc.c
blob211a17de415c48d1120764e231df39fac34a8506
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 'n':
575 fprintf(fpout, "%d", NumStrings);
576 break;
578 case 'v':
579 fprintf(fpout, "%d", CatVersion);
580 break;
582 case 'l':
583 WriteString(fpout, Language, -1, cs->LenBytes, cs->POformat);
584 break;
586 case 'f':
588 char *tempstr;
590 if((c = *currentline++) == 'v')
592 fputs(VERS, fpout);
594 else
596 tempstr = AllocFileName(CDFile, c - '0');
597 fputs(tempstr, fpout);
599 free(tempstr);
602 break;
604 case 'o':
606 char *tempstr;
608 tempstr = AllocFileName(SourceFile, *currentline++ - '0');
609 fputs(tempstr, fpout);
611 free(tempstr);
613 break;
615 case 'i':
616 NeedRepeat = TRUE;
617 if(cs != NULL)
618 fputs(cs->ID_Str, fpout);
619 break;
621 case 'a':
622 case 't':
623 case 'd':
624 case 'x':
625 case 'c':
626 case '0':
627 case '1':
628 case '2':
629 case '3':
630 case '4':
631 case '5':
632 case '6':
633 case '7':
634 case '8':
635 case '9':
637 int len = 0;
639 while(c >= '0' && c <= '9')
641 len = (c - '0') + len * 10;
642 c = *currentline++;
645 if(c == 'a')
647 int _len = len ? len : 4;
648 char *start;
649 char _StrLen[20 + 1];
651 snprintf(_StrLen, sizeof(_StrLen), "%020lx", (uint32)cs->ID);
652 start = &_StrLen[20 - _len * 2];
653 while(_len > 0)
655 fprintf(fpout, "\\x%.2s", start);
656 start += 2;
657 _len--;
660 else if(c == 't')
662 int _len = len ? len : 4;
663 char *start;
664 char _StrLen[20 + 1];
666 snprintf(_StrLen, sizeof(_StrLen), "%020lx", (uint32)((CalcRealLength(cs->CD_Str) + 1) & 0xfffffe));
667 start = &_StrLen[20 - _len * 2];
668 while(_len > 0)
670 fprintf(fpout, "\\x%.2s", start);
671 start += 2;
672 _len--;
675 else if(c == 'c' || c == 'd' || c == 'x')
677 char buffer[20];
679 if(c == 'c')
680 c = 'o';
681 if(len)
682 snprintf(buffer, sizeof(buffer), "%%0%d%c", len, c);
683 else
684 snprintf(buffer, sizeof(buffer), "%%%c", c);
686 if(cs != NULL)
687 fprintf(fpout, buffer, cs->ID);
690 NeedRepeat = TRUE;
692 break;
694 case 'e':
695 NeedRepeat = TRUE;
696 if(cs != NULL)
697 fprintf(fpout, "%d", cs->Nr);
698 break;
700 case 's':
701 NeedRepeat = TRUE;
702 if(cs != NULL)
704 char *idstr;
705 uint32 len = 0;
707 if(cs->LenBytes)
709 idstr = cs->CD_Str;
710 while(*idstr != '\0')
712 bytesread = ReadChar(&idstr, bytes);
713 if(bytesread > 0)
715 ++len;
720 WriteString(fpout, cs->CD_Str, cs->LenBytes ? len : (uint32)-1, cs->LenBytes, cs->POformat);
722 break;
724 case '(':
725 NeedRepeat = TRUE;
726 while(*currentline != '\0' && *currentline != ')')
728 bytesread = ReadChar(&currentline, bytes);
729 if(bytesread > 0 && cs != NULL && cs->Next != NULL)
731 putc((int)bytes[bytesread - 1], fpout);
735 if(*currentline == '\0')
737 /* FIXME: reuse MSG_ERR_NOTRAILINGBRACKET here? <tactica> */
738 ShowError(MSG_ERR_NOTERMINATEBRACKET);
740 else
742 ++currentline;
744 break;
746 /* !!!! FIXME !!!! */
747 case 'z':
749 int diff = (((CalcRealLength(cs->CD_Str) + 1) & 0xfffffe) - (CalcRealLength(cs->CD_Str)));
751 NeedRepeat = TRUE;
752 while(diff > 0)
754 fprintf(fpout, "\\x00");
755 diff--;
757 break;
760 default:
762 int ch = *currentline++;
764 putc(ch, fpout);
768 else
770 putc((int)bytes[bytesread - 1], fpout);
774 putc('\n', fpout);
776 while(NeedRepeat == TRUE && cs != NULL && (cs = cs->Next) != NULL);
778 free(line);
780 fclose(fpin);
781 fclose(fpout);
783 #ifdef AMIGA
784 SetProtection(SourceFile, FILE_MASK);
785 #endif