]> www.wagner.pp.ru Git - oss/catdoc.git/blob - src/substmap.c
Fix resource leak
[oss/catdoc.git] / src / substmap.c
1 /*****************************************************************/
2 /* Substitution maps to replace some unicode characters with     */
3 /* multicharacter sequences                                      */
4 /*                                                               */
5 /* This file is part of catdoc project                           */
6 /* (c) Victor Wagner 1998-2003, (c) Alex Ott 2003                    */
7 /*****************************************************************/
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 #include <string.h>
12 #include <ctype.h>
13 #include <stdlib.h>
14 #include "catdoc.h"
15 SUBSTMAP spec_chars, replacements;
16 char *map_path=CHARSETPATH;
17 void map_insert(SUBSTMAP map, int uc, const char *s) ;
18 int longest_sequence=6;/* six is longest character sequence which can be
19                                                   generated by catdoc internally*/
20
21 /******************************************************************/
22 /* checks for terminator of character sequence. If stop is something
23  * like quote - check for same char. If it is \n, check for any space
24  ********************************************************************/ 
25 int isstop(char  c, char stop) {
26         if (stop=='\n') {
27                 return isspace(c);
28         } else {
29                 return c==stop;
30         }
31 }
32 /************************************************************************/
33 /* Reads substitution map file.                                         */
34 /************************************************************************/
35 SUBSTMAP read_substmap(char* filename) {
36         FILE *f;
37         SUBSTMAP map=calloc(sizeof(char **),256);
38         char *path, line[1024], *p, *q;
39         char s[256];
40         char stopchar;
41         int escaped, lineno=0, i;
42     int32_t uc;
43         path=find_file(filename,add_exe_path(map_path));
44         if (!path) {
45                 free(map);
46                 return(NULL);
47         }   
48         if (!map) {
49                 fprintf(stderr,"Insufficient memory\n");
50                 exit(1);
51         }
52         f=fopen(path,"rb");
53         if (!f) {
54                 perror(path);
55                 free(map);
56                 return NULL;
57         }
58         if (input_buffer)
59                 setvbuf(f,input_buffer,_IOFBF,FILE_BUFFER);
60
61         while (!feof(f)) {
62                 if (!fgets(line,1024,f)) continue;
63                 lineno++;
64                 /* parse line */
65
66                 /* skip leading space */
67                 for(p=line;*p && isspace(*p);p++);
68                 /* if #, it is comment */
69                 if (!*p ||
70 #ifdef  __MSDOS__
71                                 *p==0x1A || /* DOS have strange habit of using ^Z as eof */
72 #endif
73                                 *p=='#') continue;
74                 /* read hexadecimal code */
75                 uc = strtol(p,&p,16);
76                 if (!isspace(*p)|| uc<0 || uc>0xfffd) {
77                         fprintf(stderr,"Error parsing %s(%d)\n",path,lineno);
78                         continue;
79                 }
80                 /* skip space between  code and sequence */
81                 for(;*p && isspace(*p);p++);
82                 if (!p) continue;
83                 switch (*p) {
84                         case '\'':
85                         case '"':
86                                 stopchar=*p;
87                                 break;
88                         case '(':
89                                 stopchar=')';
90                                 break;
91                         case '[':
92                                 stopchar=']';
93                                 break;
94                         case '{':
95                                 stopchar='}';
96                                 break;
97                         default:
98                                 p--;
99                                 stopchar='\n';
100                 }
101                 p++;
102                 q=p;
103                 escaped=0;
104                 while (*q && (!isstop(*q,stopchar) || escaped)) {
105                         if (escaped) {
106                                 escaped=0;
107                         } else {
108                                 escaped= (*q=='\\');
109                         }
110                         q++;
111                 }
112                 if (*q!=stopchar && !(isspace(*q) && stopchar=='\n')) {
113                         fprintf(stderr,"Error parsing %s(%d): unterminated sequence\n",
114                                         path,lineno);
115                         continue;
116                 }
117                 /* HERE SHOULD BE BACKSLASH ESCAPE PROCESSING !!!*/
118                 *q=0;
119                 for (q=s,i=0;*p && i<256;q++,i++) {
120                         if (*p!='\\') {
121                                 *q=*p++;
122                         } else {
123                                 switch (*(++p)) {
124                                         case 'n': *q='\n'; break;
125                                         case 'r': *q='\r'; break;
126                                         case 't': *q='\t'; break;
127                                         case 'b': *q='\b'; break;
128                                                           case '\"': *q='\"'; break;
129                                         case '\'': *q='\''; break;
130                                         case '0': *q=strtol(p,&p,8); p--; break;
131                                         case '\\':
132                                         default:
133                                                           *q=*p;
134                                 }
135                                 p++;
136                         }
137                 }
138                 *q=0;
139                 if (i>longest_sequence)
140                         longest_sequence=i;
141                 map_insert(map,uc,s);
142         }
143         fclose(f);
144         free(path);
145         return map;
146 }
147
148 /*************************************************************************/
149 /* searches for string in the substituton map. Returns NULL if not found */
150 /*************************************************************************/
151 char * map_subst ( SUBSTMAP map, int uc) {
152         char **p=map[(unsigned)uc >>8];
153         if (!p) return NULL;
154         return p[uc & 0xff];
155 }
156
157 /*************************************************************************/
158 /*  inserts string + unicode code into map                               */
159 /*************************************************************************/
160 void map_insert(SUBSTMAP map, int uc, const char *s) {
161         SUBSTMAP p=map+((unsigned)uc>>8);
162
163         if (!*p) {
164                 *p= calloc(sizeof(char*),256);
165                 if (!*p) { 
166                         fprintf(stderr,"Insufficient memory\n");
167                         exit(1);
168                 }
169         }
170         (*p)[uc & 0xff] = strdup(s);
171 }