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