xref: /openbsd/lib/libkeynote/keynote-ver.l (revision 264ca280)
1 %{
2 /* $OpenBSD: keynote-ver.l,v 1.19 2015/12/23 23:55:30 mmcc 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 == NULL) {
54 				    keynote_errno = ERROR_MEMORY;
55 				    return -1;
56 				}
57 				strlcpy(kvlval.s.string, kvtext, len);
58 				BEGIN(MIDDLEPART);
59                                 return VSTRING;
60                               }
61 <KEYSTATE,SECONDPART>{litstring} { kvlval.s.string = calloc(strlen(kvtext) - 1,
62 				  		         sizeof(char));
63                                    if (kvlval.s.string == NULL) {
64 				       keynote_errno = ERROR_MEMORY;
65 				       return -1;
66 				   }
67 				   mystrncpy(kvlval.s.string, kvtext + 1,
68 					     strlen(kvtext) - 2);
69 				   BEGIN(FIRSTPART);
70 				   return STRING;
71                                  }
72 <FIRSTPART,KEYSTATE>{comment} ;
73 [ \t\n]		              ;
74 .                           { keynote_errno = ERROR_SYNTAX; return -1; REJECT; }
75 
76 %%
77 
78 /*
79  * Return RESULT_TRUE if character is octal digit, RESULT_FALSE otherwise.
80  */
81 static int
82 is_octal(char c)
83 {
84     switch (c)
85     {
86 	case '0': case '1': case '2': case '3':
87 	case '4': case '5': case '6': case '7':
88 	    return RESULT_TRUE;
89 
90 	default:
91 	    return RESULT_FALSE;
92     }
93 }
94 
95 /*
96  * Return octal value (non-zero) if argument starts with such a
97  * representation, otherwise 0.
98  */
99 static unsigned char
100 get_octal(char *s, int len, int *adv)
101 {
102     unsigned char res = 0;
103 
104     if (*s == '0')
105     {
106 	if (len > 0)
107 	{
108 	    if (is_octal(*(s + 1)))
109 	    {
110 		res = *(s + 1) - '0';
111 		*adv = 2;
112 
113 		if (is_octal(*(s + 2)) && (len - 1 > 0))
114 		{
115 		    res = res * 8 + (*(s + 2) - '0');
116 		    *adv = 3;
117 		}
118 	    }
119 	}
120     }
121     else
122       if (is_octal(*s) && (len - 1 > 0))  /* Non-zero leading */
123       {
124 	  if (is_octal(*(s + 1)) &&
125 	      is_octal(*(s + 2)))
126 	  {
127 	      *adv = 3;
128 	      res = (((*s) - '0') * 64) +
129 		    (((*(s + 1)) - '0') * 8) +
130 		    ((*(s + 2)) - '0');
131 	  }
132       }
133 
134     return res;
135 }
136 
137 /*
138  * Copy at most len characters to string s1 from string s2, taking
139  * care of escaped characters in the process. String s1 is assumed
140  * to have enough space, and be zero'ed.
141  */
142 void
143 mystrncpy(char *s1, char *s2, int len)
144 {
145     unsigned char c;
146     int advance;
147 
148     if (len == 0)
149       return;
150 
151     while (len-- > 0)
152     {
153         if (*s2 == '\\')
154 	{
155 	    s2++;
156 
157 	    if (len-- <= 0)
158 	      break;
159 
160 	    if (*s2 == '\n')
161 	    {
162 		while (isspace((unsigned char)*(++s2)) && (len-- > 0))
163 		  ;
164 	    }
165 	    else
166 	      if ((c = get_octal(s2, len, &advance)) != 0)
167 	      {
168 		  len -= advance - 1;
169 		  s2 += advance;
170 		  *s1++ = c;
171 	      }
172 	      else
173 		if (*s2 == 'n')  /* Newline */
174 		{
175 		    *s1++ = '\n';
176 		    s2++;
177 		}
178 		else
179 		  if (*s2 == 't')  /* Tab */
180 		  {
181 		      *s1++ = '\t';
182 		      s2++;
183 		  }
184 		  else
185 		    if (*s2 == 'r')  /* Linefeed */
186 		    {
187 			*s1++ = '\r';
188 			s2++;
189 		    }
190 		    else
191 		      if (*s2 == 'f')  /* Formfeed */
192 		      {
193 			  *s1++ = '\f';
194 			  s2++;
195 		      }
196 		      else
197 			if ((*s1++ = *s2++) == 0)
198 			  break;
199 
200 	    continue;
201 	}
202 
203         if ((*s1++ = *s2++) == 0)
204 	  break;
205      }
206 }
207 
208 /*
209  * Parse a file that contains environment variable/value pairs.
210  * Return -1 on failure.
211  */
212 int
213 read_environment(char *filename)
214 {
215     YY_BUFFER_STATE kvfoo;
216     FILE *fp;
217     int i;
218 
219     if ((fp = fopen(filename, "r")) == NULL) {
220 	perror(filename);
221 	return -1;
222     }
223 
224     kvfoo = kv_create_buffer(fp, YY_BUF_SIZE);
225     kv_switch_to_buffer(kvfoo);
226     BEGIN(FIRSTPART);
227     i = kvparse();
228     kv_delete_buffer(kvfoo);
229     fclose(fp);
230     switch (i)
231     {
232 	case 0:
233 	    return 0;
234 
235 	default:
236 	    if (keynote_errno == ERROR_MEMORY)
237 	      fprintf(stderr,
238 		      "Memory error while processing environment file <%s>\n",
239 		      filename);
240 	    else
241 	      fprintf(stderr,
242 		     "Syntax error in environment file <%s>, line %d\n",
243 		     filename, kvlineno);
244 	    return -1;
245     }
246 
247     /* Used to avoid compiler (-Wall) warnings. Never reached */
248     if (0)
249     {
250 	yyunput(0, NULL);
251     }
252 }
253 
254 /*
255  * Parse a key.
256  */
257 void
258 parse_key(char *buf)
259 {
260     YY_BUFFER_STATE key_state;
261     int err;
262 
263     key_state = kv_scan_string(buf);
264     BEGIN(KEYSTATE);
265     err = kvparse();
266     kv_delete_buffer(key_state);
267 
268     if (err != 0)
269       if (keynote_errno == 0)
270 	keynote_errno = ERROR_SYNTAX;
271 }
272