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 <proto/codesets.h>
30 #include "readprefs.h"
31 #include "swapfuncs.h"
32 #include "showfuncs.h"
35 #include "createcat.h"
39 #include "SDI_compiler.h"
41 const char VString
[] = VERS
" [" SYSTEMSHORT
"/" CPU
"] (" EXE_DATE
")\n" EXE_COPYRIGHT
;
42 const char EString
[] = "Contact: http://sf.net/p/flexcat/";
49 if((NumberOfWarnings
> 0 || Code
!= 0) && !NoBeep
)
52 CloseFlexCatCatalog();
66 * This array is designed for mapping upper and lower case letters
67 * together for a case independent comparison. The mappings are
68 * based upon ascii character sequences.
71 typedef unsigned char uc
;
72 static const unsigned char charmap
[] =
74 (uc
)'\000', (uc
)'\001', (uc
)'\002', (uc
)'\003', (uc
)'\004', (uc
)'\005', (uc
)'\006', (uc
)'\007',
75 (uc
)'\010', (uc
)'\011', (uc
)'\012', (uc
)'\013', (uc
)'\014', (uc
)'\015', (uc
)'\016', (uc
)'\017',
76 (uc
)'\020', (uc
)'\021', (uc
)'\022', (uc
)'\023', (uc
)'\024', (uc
)'\025', (uc
)'\026', (uc
)'\027',
77 (uc
)'\030', (uc
)'\031', (uc
)'\032', (uc
)'\033', (uc
)'\034', (uc
)'\035', (uc
)'\036', (uc
)'\037',
78 (uc
)'\040', (uc
)'\041', (uc
)'\042', (uc
)'\043', (uc
)'\044', (uc
)'\045', (uc
)'\046', (uc
)'\047',
79 (uc
)'\050', (uc
)'\051', (uc
)'\052', (uc
)'\053', (uc
)'\054', (uc
)'\055', (uc
)'\056', (uc
)'\057',
80 (uc
)'\060', (uc
)'\061', (uc
)'\062', (uc
)'\063', (uc
)'\064', (uc
)'\065', (uc
)'\066', (uc
)'\067',
81 (uc
)'\070', (uc
)'\071', (uc
)'\072', (uc
)'\073', (uc
)'\074', (uc
)'\075', (uc
)'\076', (uc
)'\077',
82 (uc
)'\100', (uc
)'\141', (uc
)'\142', (uc
)'\143', (uc
)'\144', (uc
)'\145', (uc
)'\146', (uc
)'\147',
83 (uc
)'\150', (uc
)'\151', (uc
)'\152', (uc
)'\153', (uc
)'\154', (uc
)'\155', (uc
)'\156', (uc
)'\157',
84 (uc
)'\160', (uc
)'\161', (uc
)'\162', (uc
)'\163', (uc
)'\164', (uc
)'\165', (uc
)'\166', (uc
)'\167',
85 (uc
)'\170', (uc
)'\171', (uc
)'\172', (uc
)'\133', (uc
)'\134', (uc
)'\135', (uc
)'\136', (uc
)'\137',
86 (uc
)'\140', (uc
)'\141', (uc
)'\142', (uc
)'\143', (uc
)'\144', (uc
)'\145', (uc
)'\146', (uc
)'\147',
87 (uc
)'\150', (uc
)'\151', (uc
)'\152', (uc
)'\153', (uc
)'\154', (uc
)'\155', (uc
)'\156', (uc
)'\157',
88 (uc
)'\160', (uc
)'\161', (uc
)'\162', (uc
)'\163', (uc
)'\164', (uc
)'\165', (uc
)'\166', (uc
)'\167',
89 (uc
)'\170', (uc
)'\171', (uc
)'\172', (uc
)'\173', (uc
)'\174', (uc
)'\175', (uc
)'\176', (uc
)'\177',
90 (uc
)'\200', (uc
)'\201', (uc
)'\202', (uc
)'\203', (uc
)'\204', (uc
)'\205', (uc
)'\206', (uc
)'\207',
91 (uc
)'\210', (uc
)'\211', (uc
)'\212', (uc
)'\213', (uc
)'\214', (uc
)'\215', (uc
)'\216', (uc
)'\217',
92 (uc
)'\220', (uc
)'\221', (uc
)'\222', (uc
)'\223', (uc
)'\224', (uc
)'\225', (uc
)'\226', (uc
)'\227',
93 (uc
)'\230', (uc
)'\231', (uc
)'\232', (uc
)'\233', (uc
)'\234', (uc
)'\235', (uc
)'\236', (uc
)'\237',
94 (uc
)'\240', (uc
)'\241', (uc
)'\242', (uc
)'\243', (uc
)'\244', (uc
)'\245', (uc
)'\246', (uc
)'\247',
95 (uc
)'\250', (uc
)'\251', (uc
)'\252', (uc
)'\253', (uc
)'\254', (uc
)'\255', (uc
)'\256', (uc
)'\257',
96 (uc
)'\260', (uc
)'\261', (uc
)'\262', (uc
)'\263', (uc
)'\264', (uc
)'\265', (uc
)'\266', (uc
)'\267',
97 (uc
)'\270', (uc
)'\271', (uc
)'\272', (uc
)'\273', (uc
)'\274', (uc
)'\275', (uc
)'\276', (uc
)'\277',
98 (uc
)'\300', (uc
)'\341', (uc
)'\342', (uc
)'\343', (uc
)'\344', (uc
)'\345', (uc
)'\346', (uc
)'\347',
99 (uc
)'\350', (uc
)'\351', (uc
)'\352', (uc
)'\353', (uc
)'\354', (uc
)'\355', (uc
)'\356', (uc
)'\357',
100 (uc
)'\360', (uc
)'\361', (uc
)'\362', (uc
)'\363', (uc
)'\364', (uc
)'\365', (uc
)'\366', (uc
)'\367',
101 (uc
)'\370', (uc
)'\371', (uc
)'\372', (uc
)'\333', (uc
)'\334', (uc
)'\335', (uc
)'\336', (uc
)'\337',
102 (uc
)'\340', (uc
)'\341', (uc
)'\342', (uc
)'\343', (uc
)'\344', (uc
)'\345', (uc
)'\346', (uc
)'\347',
103 (uc
)'\350', (uc
)'\351', (uc
)'\352', (uc
)'\353', (uc
)'\354', (uc
)'\355', (uc
)'\356', (uc
)'\357',
104 (uc
)'\360', (uc
)'\361', (uc
)'\362', (uc
)'\363', (uc
)'\364', (uc
)'\365', (uc
)'\366', (uc
)'\367',
105 (uc
)'\370', (uc
)'\371', (uc
)'\372', (uc
)'\373', (uc
)'\374', (uc
)'\375', (uc
)'\376', (uc
)'\377',
110 int Stricmp(const char *str1
, const char *str2
)
112 unsigned char u1
, u2
;
116 u1
= (unsigned char)*str1
++;
117 u2
= (unsigned char)*str2
++;
119 if(charmap
[u1
] != charmap
[u2
])
120 return charmap
[u1
] - charmap
[u2
];
130 int Strnicmp(const char *str1
, const char *str2
, int len
)
132 unsigned char u1
, u2
;
134 for(; len
!= 0; --len
)
136 u1
= (unsigned char)*str1
++;
137 u2
= (unsigned char)*str2
++;
138 if(charmap
[u1
] != charmap
[u2
])
139 return charmap
[u1
] - charmap
[u2
];
151 /* This allocates a string */
153 char *AllocString(const char *str
)
157 if((ptr
= malloc(strlen(str
) + 1)) == NULL
)
166 /// Add a string to an already allocated one
168 char *AddString(char *str
, const char *astr
)
172 if((ptr
= malloc(strlen(str
) + strlen(astr
) + 1)) == NULL
)
184 /// Convert a string from one charset to another
187 char *ConvertString(char *str
, const char *from_charset
, const char *to_charset
)
190 BOOL fromIsUTF8
= (Stricmp(from_charset
, "UTF-8") == 0 || Stricmp(from_charset
, "UTF8") == 0);
191 BOOL toIsUTF8
= (Stricmp(to_charset
, "UTF-8") == 0 || Stricmp(to_charset
, "UTF8") == 0);
193 if(fromIsUTF8
== TRUE
&& toIsUTF8
== TRUE
)
195 // no need to convert from UTF8 to UTF8
196 // just return a plain copy of the string
197 result
= strdup(str
);
201 struct codeset
*dstCodeset
;
203 dstCodeset
= CodesetsFind((STRPTR
)to_charset
,
204 CSA_FallbackToDefault
, FALSE
,
206 if(dstCodeset
!= NULL
)
209 char *dstText
= NULL
;
211 if(fromIsUTF8
== TRUE
)
213 dstText
= CodesetsUTF8ToStr(CSA_Source
, str
,
214 CSA_DestCodeset
, dstCodeset
,
215 CSA_DestLenPtr
, &dstLen
,
220 struct codeset
*srcCodeset
;
222 srcCodeset
= CodesetsFind((STRPTR
)from_charset
,
223 CSA_FallbackToDefault
, FALSE
,
226 if(srcCodeset
!= NULL
)
228 dstText
= CodesetsConvertStr(CSA_Source
, str
,
229 CSA_SourceCodeset
, srcCodeset
,
230 CSA_DestCodeset
, dstCodeset
,
231 CSA_DestLenPtr
, &dstLen
,
236 if(dstText
!= NULL
&& dstLen
!= 0)
240 // copy the converted string into a separate allocated string
241 if((buf
= malloc(dstLen
+1)) != NULL
)
243 memcpy(buf
, dstText
, dstLen
);
248 CodesetsFreeA(dstText
, NULL
);
256 char *ConvertString(char *str
, const char *from_charset
, const char *to_charset
)
261 if((ict
= iconv_open(to_charset
, from_charset
)) != (iconv_t
)-1)
263 size_t inleft
= strlen(str
);
266 if((buf
= malloc((inleft
+1)*sizeof(char))) != NULL
)
268 size_t outleft
= inleft
;
271 if(iconv(ict
, &str
, &inleft
, &outbuf
, &outleft
) != (size_t)-1)
278 printf("ERROR: iconv()\n");
288 printf("ERROR: iconv_open()\n");
295 /// Add catalog chunk
297 /* This adds a new catalog chunk to the list of catalog
300 char *AddCatalogChunk(char *ID
, const char *string
)
302 struct CatalogChunk
*cc
, **ccptr
;
304 if((cc
= malloc(sizeof(*cc
))) == NULL
)
308 cc
->ID
= *((ULONG
*)ID
);
309 cc
->ChunkStr
= AllocString(string
);
311 /* Put the new chunk at the end of the chunk list. */
313 for(ccptr
= &FirstChunk
; *ccptr
!= NULL
; ccptr
= &(*ccptr
)->Next
)
324 /* This translates an hex character. */
328 if(c
>= '0' && c
<= '9')
330 else if(c
>= 'a' && c
<= 'f')
332 else if(c
>= 'A' && c
<= 'F')
335 ShowError(MSG_ERR_EXPECTEDHEX
);
343 /* This translates an octal digit. */
347 if(c
>= '0' && c
<= '7')
350 ShowError(MSG_ERR_EXPECTEDOCTAL
);
358 /* Reading a line is somewhat complicated in order to allow lines of any
361 Inputs: fp - the file, where the input comes from
362 AllowComment - TRUE if a leading semicolon should force the
363 line to be interpreted as a comment */
365 char *ReadLine(FILE *fp
, UNUSED
int AllowComment
)
367 char *NewLine
= NULL
;
369 int Len
= 0, LineLen
= 0;
370 int FirstChar
= TRUE
;
371 int BackslashSeen
= FALSE
;
372 int BackslashSeenOn
= 0; /* Position where the last backslash was seen. */
373 int CommentLine
= FALSE
; /* If TRUE, we should ignore any trailing \'s */
377 if(Len
+ 10 > LineLen
)
379 NewLine
= realloc(NewLine
, LineLen
+ BUFSIZE
);
412 BackslashSeen
= FALSE
;
420 /* Check for trailing \\ */
427 if(BackslashSeenOn
==(Len
- 1))
429 BackslashSeen
= FALSE
;
435 BackslashSeen
= TRUE
;
436 BackslashSeenOn
= Len
;
445 BackslashSeen
= FALSE
;
459 /* This removes trailing blanks. */
461 void OverSpace(char **strptr
)
465 while((c
= **strptr
) == ' ' || c
== '\t')
479 struct Library
*localeBase
;
481 // this may look utterly wrong since we are trying to RemLibrary() a library
482 // which we just opened. But this is the most convenient way to invoke the
483 // Expunge() function of locale.library, which will just remove any still
484 // opened but unused catalog file from memory without removing locale.library
486 if((localeBase
= OpenLibrary( "locale.library", 0)) != NULL
)
488 RemLibrary(localeBase
);
489 CloseLibrary(localeBase
);
498 /* ReadChar scans an input line and translates the backslash characters.
499 Inputs: char * - a pointer to a string pointer; the latter points
500 to the next character to be read and points behind
501 the read bytes after executing ReadChar
502 dest - a pointer to a buffer, where the read bytes should be
504 Result: number of bytes that are written to dest (between 0 and 2) */
506 int ReadChar(char **strptr
, char *dest
)
511 switch(c
= *((*strptr
)++))
515 switch(c
= tolower((int)*((*strptr
)++)))
559 *dest
= gethex((int)**strptr
);
562 if((c
>= '0' && c
<= '9') ||
563 (c
>= 'a' && c
<= 'f') ||
564 (c
>= 'A' && c
<= 'F'))
566 *dest
=(*dest
<< 4) + gethex((int)c
);
581 *dest
= getoctal((int)c
);
583 for(i
= 0; i
< 2; i
++)
586 if(c
>= '0' && c
<= '7')
588 *dest
=(*dest
<< 3) + getoctal((int)c
);
621 /* This function creates a copy of a filename, and optionally
622 removes an ending and pathname components, if desired.
623 Inputs: filename - the filename to copy
624 howto - a set of bits
625 bit 0: 1 = remove ending, 0 = leave it
626 bit 1: 1 = remove pathname, 0 = leave it
627 Result: the copy of the filename
630 char *AllocFileName(char *filename
, int howto
)
634 if((tempstr
= strdup(filename
)) == NULL
)
640 /* Remove pathname components, if desired. */
644 if((ptr
= strchr(tempstr
, ':')) != NULL
)
648 if((ptr
= strrchr(tempstr
, '/')) != NULL
)
654 /* Remove ending, if desired. */
658 if((ptr
= strrchr(tempstr
, '.')) != NULL
)
670 /* This function adds a pathname and a filename to a full
672 Inputs: pathname - the leading pathname
673 filename - the filename
674 Result: The new filename */
676 char *AddFileName(char *pathname
, char *filename
)
681 int size
= strlen(pathname
) + strlen(filename
) + 2;
683 if((buffer
= malloc(size
)) == NULL
)
689 strcpy(buffer
, pathname
);
690 AddPart((char *)buffer
, (char *)filename
, size
);
692 if(asprintf(&buffer
, "%s/%s", pathname
, filename
) < 0)
705 /* The Usage function describes the program's calling syntax. */
709 fprintf(stderr
, "%s\n", VString
);
710 fprintf(stderr
, "%s\n", EString
);
714 " FlexCat CDFILE/A,CTFILE,POFILE,CATALOG/K,NEWCTFILE/K,SOURCES/M,\n" \
715 " WARNCTGAPS/S,NOOPTIM/S,FILL/S,FLUSH/S,NOBEEP/S,\n" \
716 " QUIET/S,NOLANGTOLOWER/S,NOBUFFEREDIO/S,MODIFIED/S,\n" \
717 " CODESET/K,COPYMSGNEW/S,OLDMSGNEW/K\n" \
718 "\n", MSG_USAGE_HEAD
);
719 fprintf(stderr
, "%s\n", MSG_USAGE
);
726 /* Dice's entry point for workbench programs */
728 #if defined(AMIGA) && defined(_DCC)
729 void wbmain(struct WBStartup
*wbmsg
)
731 fprintf(stderr
, "FlexCat can't be run from Workbench!\n\n");
732 fprintf(stderr
, "Open a shell session and type FlexCat\n");
733 fprintf(stderr
, "for syntax and more information.\n");