xref: /openbsd/lib/libkeynote/keynote-ver.l (revision 898184e3)
1 %{
2 /* $OpenBSD: keynote-ver.l,v 1.15 2011/04/06 11:36:23 miod Exp $ */
3 /*
4  * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
5  *
6  * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
7  * in April-May 1998
8  *
9  * Copyright (C) 1998, 1999 by Angelos D. Keromytis.
10  *
11  * Permission to use, copy, and modify this software with or without fee
12  * is hereby granted, provided that this entire notice is included in
13  * all copies of any software which is or includes a copy or
14  * modification of this software.
15  *
16  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
18  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
19  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
20  * PURPOSE.
21  */
22 
23 #include <sys/time.h>
24 #include <sys/types.h>
25 
26 #include <ctype.h>
27 #include <regex.h>
28 #include <string.h>
29 #include <time.h>
30 #include <unistd.h>
31 
32 #include "z.tab.h"
33 #include "header.h"
34 #include "keynote.h"
35 
36 static void mystrncpy(char *, char *, int);
37 %}
38 vstring		[a-zA-Z0-9][a-zA-Z0-9_]*
39 litstring       \"(((\\\n)|(\\.)|(\\\\)|([^\\\n\"]))*)\"
40 comment         "#"[^\n]*
41 %s FIRSTPART MIDDLEPART SECONDPART KEYSTATE
42 %pointer
43 %option noyywrap yylineno never-interactive
44 %%
45 
46 <MIDDLEPART>"="               {
47 				BEGIN(SECONDPART);
48 			        return EQ;
49 			      }
50 <FIRSTPART>{vstring}          {
51 				int len = strlen(kvtext) + 1;
52 				kvlval.s.string = calloc(len, sizeof(char));
53                                 if (kvlval.s.string == (char *) NULL)
54 				{
55 				    keynote_errno = ERROR_MEMORY;
56 				    return -1;
57 				}
58 				strlcpy(kvlval.s.string, kvtext, len);
59 				BEGIN(MIDDLEPART);
60                                 return VSTRING;
61                               }
62 <KEYSTATE,SECONDPART>{litstring} { kvlval.s.string = calloc(strlen(kvtext) - 1,
63 				  		         sizeof(char));
64                                    if (kvlval.s.string == (char *) NULL)
65 				   {
66 				       keynote_errno = ERROR_MEMORY;
67 				       return -1;
68 				   }
69 				   mystrncpy(kvlval.s.string, kvtext + 1,
70 					     strlen(kvtext) - 2);
71 				   BEGIN(FIRSTPART);
72 				   return STRING;
73                                  }
74 <FIRSTPART,KEYSTATE>{comment} ;
75 [ \t\n]		              ;
76 .                           { keynote_errno = ERROR_SYNTAX; return -1; REJECT; }
77 
78 %%
79 
80 /*
81  * Return RESULT_TRUE if character is octal digit, RESULT_FALSE otherwise.
82  */
83 static int
84 is_octal(char c)
85 {
86     switch (c)
87     {
88 	case '0': case '1': case '2': case '3':
89 	case '4': case '5': case '6': case '7':
90 	    return RESULT_TRUE;
91 
92 	default:
93 	    return RESULT_FALSE;
94     }
95 }
96 
97 /*
98  * Return octal value (non-zero) if argument starts with such a
99  * representation, otherwise 0.
100  */
101 static unsigned char
102 get_octal(char *s, int len, int *adv)
103 {
104     unsigned char res = 0;
105 
106     if (*s == '0')
107     {
108 	if (len > 0)
109 	{
110 	    if (is_octal(*(s + 1)))
111 	    {
112 		res = *(s + 1) - '0';
113 		*adv = 2;
114 
115 		if (is_octal(*(s + 2)) && (len - 1 > 0))
116 		{
117 		    res = res * 8 + (*(s + 2) - '0');
118 		    *adv = 3;
119 		}
120 	    }
121 	}
122     }
123     else
124       if (is_octal(*s) && (len - 1 > 0))  /* Non-zero leading */
125       {
126 	  if (is_octal(*(s + 1)) &&
127 	      is_octal(*(s + 2)))
128 	  {
129 	      *adv = 3;
130 	      res = (((*s) - '0') * 64) +
131 		    (((*(s + 1)) - '0') * 8) +
132 		    ((*(s + 2)) - '0');
133 	  }
134       }
135 
136     return res;
137 }
138 
139 /*
140  * Copy at most len characters to string s1 from string s2, taking
141  * care of escaped characters in the process. String s1 is assumed
142  * to have enough space, and be zero'ed.
143  */
144 void
145 mystrncpy(char *s1, char *s2, int len)
146 {
147     unsigned char c;
148     int advance;
149 
150     if (len == 0)
151       return;
152 
153     while (len-- > 0)
154     {
155         if (*s2 == '\\')
156 	{
157 	    s2++;
158 
159 	    if (len-- <= 0)
160 	      break;
161 
162 	    if (*s2 == '\n')
163 	    {
164 		while (isspace((int) *(++s2)) && (len-- > 0))
165 		  ;
166 	    }
167 	    else
168 	      if ((c = get_octal(s2, len, &advance)) != 0)
169 	      {
170 		  len -= advance - 1;
171 		  s2 += advance;
172 		  *s1++ = c;
173 	      }
174 	      else
175 		if (*s2 == 'n')  /* Newline */
176 		{
177 		    *s1++ = '\n';
178 		    s2++;
179 		}
180 		else
181 		  if (*s2 == 't')  /* Tab */
182 		  {
183 		      *s1++ = '\t';
184 		      s2++;
185 		  }
186 		  else
187 		    if (*s2 == 'r')  /* Linefeed */
188 		    {
189 			*s1++ = '\r';
190 			s2++;
191 		    }
192 		    else
193 		      if (*s2 == 'f')  /* Formfeed */
194 		      {
195 			  *s1++ = '\f';
196 			  s2++;
197 		      }
198 		      else
199 			if ((*s1++ = *s2++) == 0)
200 			  break;
201 
202 	    continue;
203 	}
204 
205         if ((*s1++ = *s2++) == 0)
206 	  break;
207      }
208 }
209 
210 /*
211  * Parse a file that contains environment variable/value pairs.
212  * Return -1 on failure.
213  */
214 int
215 read_environment(char *filename)
216 {
217     YY_BUFFER_STATE kvfoo;
218     FILE *fp;
219     int i;
220 
221     fp = fopen(filename, "r");
222     if (fp == (FILE *) NULL)
223     {
224 	perror(filename);
225 	return -1;
226     }
227 
228     kvfoo = kv_create_buffer(fp, YY_BUF_SIZE);
229     kv_switch_to_buffer(kvfoo);
230     BEGIN(FIRSTPART);
231     i = kvparse();
232     kv_delete_buffer(kvfoo);
233     fclose(fp);
234     switch (i)
235     {
236 	case 0:
237 	    return 0;
238 
239 	default:
240 	    if (keynote_errno == ERROR_MEMORY)
241 	      fprintf(stderr,
242 		      "Memory error while processing environment file <%s>\n",
243 		      filename);
244 	    else
245 	      fprintf(stderr,
246 		     "Syntax error in environment file <%s>, line %d\n",
247 		     filename, kvlineno);
248 	    return -1;
249     }
250 
251     /* Used to avoid compiler (-Wall) warnings. Never reached */
252     if (0)
253     {
254 	yyunput(0, NULL);
255 	yy_flex_realloc(0, 0);
256     }
257 }
258 
259 /*
260  * Parse a key.
261  */
262 void
263 parse_key(char *buf)
264 {
265     YY_BUFFER_STATE key_state;
266     int err;
267 
268     key_state = kv_scan_string(buf);
269     BEGIN(KEYSTATE);
270     err = kvparse();
271     kv_delete_buffer(key_state);
272 
273     if (err != 0)
274       if (keynote_errno == 0)
275 	keynote_errno = ERROR_SYNTAX;
276 }
277