1 /* proplist.l - for parsing NSString property lists -*- c -*- */
2
3 /* definition section */
4
5 /* literal block */
6 %{
7 #include "proplist.h"
8 #include "proplist_y.h"
9 #include "util.h"
10 #include "util.h"
11
12
13 #ifdef yywrap
14 #undef yywrap
15 #endif
16
yywrap(void)17 int yywrap(void) {
18 return 1;
19 }
20
21 #define return_data(str) yylval.obj = str2data(str); return DATA
22
23 char * unescstr(char * src);
24 proplist_t str2data(char * str);
25
26 extern char plinput[];
27 extern char *plinputptr;
28 extern char *plinputlim;
29 int pl_line_count = 1;
30
31
32 static int level;
33 %}
34
35 /* pattern definitions */
36 ws [ \t\r]
37 nl \n
38 wsnl [ \t\r\n]
39 hexdigit [0-9A-Fa-f]
40 hexbyte {hexdigit}{2}
41 hexword {hexbyte}{4}
42 hexnum {hexbyte}{1,3}
43 qstring [^"]*\"
44 noquote [$./0-9A-Z_a-z]
45 unqstring {noquote}+
46 hexdata \<{ws}*({hexword}{ws}*)*{hexnum}{0,1}{ws}*\>
47 /* exclusive states */
48 %x QUOTE COMMENT LINE_COMMENT
49
50 /* rules section */
51 %%
52
53 "/*" {++level; BEGIN COMMENT;}
54 "//" {BEGIN LINE_COMMENT;}
55
56 <QUOTE>{qstring} {
57 if(yyleng==1) {
58 BEGIN INITIAL;
59 yylval.obj = PLMakeString("");
60 return STRING;
61 }
62 if(yytext[yyleng-2] == '\\') {
63 yymore();
64 } else {
65 char *unesc;
66 BEGIN INITIAL;
67 unesc = unescstr(yytext);
68 yylval.obj = PLMakeString(unesc);
69 MyFree(__FILE__, __LINE__, unesc);
70 return STRING;
71 }
72 }
73
74 <COMMENT>"*/" {if(!--level) BEGIN INITIAL;}
75 <COMMENT>. ;
76 <COMMENT><<EOF>> {return 0;}
77
78 <LINE_COMMENT>\n {BEGIN INITIAL; pl_line_count++;}
79 <LINE_COMMENT>. ;
80
81 {unqstring} {yylval.obj = PLMakeString(yytext); return STRING;}
82
83 {hexdata} {return_data(yytext);}
84
85 \" {BEGIN QUOTE;}
86
87 {ws}+ ;
88 {nl}+ {pl_line_count += yyleng;} /* skip whitespace */
89
90 <<EOF>> {return 0;}
91
92 . {return yytext[0];} /* return unmatched characters
93 literally*/
94 %%
95
96 /* C code section */
97 #define inrange(ch,min,max) ((ch)>=(min) && (ch)<=(max))
98 #define char2num(ch) \
99 inrange(ch,'0','9') \
100 ? ((ch)-0x30) \
101 : (inrange(ch,'a','f') \
102 ? ((ch)-0x57) : ((ch)-0x37))
103
104 proplist_t
105 str2data (char *str)
106 {
107 unsigned char *buf, *str_ptr, *buf_ptr;
108 char ch;
109 int len;
110 proplist_t data;
111
112 buf=(unsigned char *)MyMalloc(__FILE__, __LINE__, strlen(str));
113
114 for (str_ptr=(unsigned char *)str+1, buf_ptr=buf,len=0;
115 (ch = *str_ptr) != '>';
116 str_ptr++)
117 {
118 if(ch==' ' || ch=='\n' || ch=='\t' || ch=='\r')
119 continue; /* ignore whitespace */
120 *buf_ptr = (char2num(ch))<<4;
121 ch = *++str_ptr;
122 *buf_ptr |= char2num(ch);
123 len++; buf_ptr++;
124 }
125
126 data = PLMakeData(buf,len);
127 MyFree(__FILE__, __LINE__, buf);
128
129 return data;
130 }
131
132 char *
133 unescstr (char *src)
134 {
135 char *dest=(char*) MyMalloc (__FILE__, __LINE__, strlen(src));
136 char *src_ptr, *dest_ptr;
137 char ch;
138
139 /* blow away that terminating quote for good measure */
140 src[strlen(src)-1] = '\0';
141
142 for (src_ptr=src,dest_ptr=dest;
143 *src_ptr;
144 src_ptr++, dest_ptr++)
145 {
146 if(*src_ptr != '\\')
147 *dest_ptr = *src_ptr;
148 else
149 {
150 ch = *(++src_ptr);
151 if((ch>='0') && (ch<='3')) /* assume next 2 chars are octal too */
152 {
153 *dest_ptr = ((ch & 07) << 6);
154 *dest_ptr |= ((*(++src_ptr)&07)<<3);
155 *dest_ptr |= (*(++src_ptr))&07;
156 }
157 else
158 {
159 switch(ch)
160 {
161 case 'a' : *dest_ptr = '\a'; break;
162 case 'b' : *dest_ptr = '\b'; break;
163 case 't' : *dest_ptr = '\t'; break;
164 case 'r' : *dest_ptr = '\r'; break;
165 case 'n' : *dest_ptr = '\n'; break;
166 case 'v' : *dest_ptr = '\v'; break;
167 case 'f' : *dest_ptr = '\f'; break;
168 default : *dest_ptr = *src_ptr;
169 }
170 }
171 }
172 }
173
174 *dest_ptr = '\0'; /* terminate dest */
175
176 return dest;
177 }
178