2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: lexit.c /main/5 1998/04/06 13:13:30 mgreess $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company
26 * (c) Copyright 1993, 1994 International Business Machines Corp.
27 * (c) Copyright 1993, 1994 Novell, Inc.
28 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
32 * handcoded lexer to get rid of slow yylook routines
37 #include <EUSCompat.h>
44 #include <sys/param.h>
55 char *externQuotedString;
56 Period_4 externPeriod;
57 Appt_Status_4 externApptStatus;
59 Privacy_Level_4 externPrivacy;
61 static int hash_string P((register char *));
62 static char *strescapes P((char *));
65 static caddr_t start_of_mmapped_area;
66 static caddr_t current_ptr;
69 #define input_char() ((end == current_ptr)?0:(*(current_ptr++)))
70 #define unput_char() (((current_ptr>start_of_mmapped_area)?(current_ptr--):0))
83 the following token entry allows us to combine the
84 hash table, token id and action on token recog
88 typedef struct token_data {
89 const char * name; /* lexical token representation */
90 short first_token; /* index into tokens. points to
91 first token that hashes to this spot.
92 subsequent tokens may be found by following
93 next_token field IN first_token. */
95 void * info_to_change; /* ptr to 4 byte value to change when token
96 is found. Ignored if NULL */
97 int token_value; /* value to set above to. */
98 int return_value; /* value to return from yyylex when this token
102 static u_char parse_buffer[BUFSIZ*3];
103 static u_char initial_mask[255];
104 static u_int sendit_value[255];
107 some macros to save my fingers
110 #define PVAL(a,b) { #a,-1, -1, &externPeriod.period,b,PERIODVAL}
111 #define AVAL(a,b) { #a,-1, -1, &externApptStatus,b,APPTSTATUSVAL}
112 #define TVAL(a,b) { #a,-1, -1, &externTag.tag,b,TAGSVAL }
113 #define SVAL(a,b) { #a,-1, -1, &externPrivacy,b,PRIVACYVAL}
115 #define EMP(a,b) {#a,-1, -1, 0, 0,b}
117 token_data_t tokens[] = {
118 PVAL(single, single_4),
119 PVAL(daily, daily_4),
120 PVAL(weekly, weekly_4),
121 PVAL(biweekly, biweekly_4),
122 PVAL(monthly, monthly_4),
123 PVAL(yearly, yearly_4),
124 PVAL(nthWeekday, nthWeekday_4),
125 PVAL(everyNthDay, everyNthDay_4),
126 PVAL(everyNthWeek, everyNthWeek_4),
127 PVAL(everyNthMonth, everyNthMonth_4),
128 PVAL(monThruFri, monThruFri_4),
129 PVAL(monWedFri, monWedFri_4),
130 PVAL(tueThur, tueThur_4),
131 PVAL(daysOfWeek, daysOfWeek_4),
133 AVAL(active, active_4),
134 AVAL(pendingAdd, pendingAdd_4),
135 AVAL(pendingDelete, pendingDelete_4),
136 AVAL(committed, committed_4),
137 AVAL(cancelled, cancelled_4),
138 AVAL(completed, completed_4),
140 TVAL(appointment, appointment_4),
141 TVAL(reminder, reminder_4),
142 TVAL(otherTag, otherTag_4),
143 TVAL(holiday, holiday_4),
146 SVAL(public, public_4),
147 SVAL(private, private_4),
148 SVAL(semiprivate, semiprivate_4),
150 EMP(attributes,ATTRIBUTES_4),
151 EMP(attributelist,ATTRIBUTES_5),
153 EMP(Version, VERSION),
154 EMP(calendarattributes,CALATTRS),
155 EMP(duration,DURATION),
158 EMP(enddate,ENDDATE),
161 EMP(details,DETAILS),
163 EMP(exceptions,EXCEPTION),
169 EMP(apptstat,APPTSTATUS),
171 EMP(privacy,PRIVACY),
175 EMP(entrytable, TABLE),
176 EMP(hashedattributes, HASHEDATTRS),
180 #define NUMTOKES (sizeof(tokens)/sizeof(tokens[0]))
183 load parser masks & build
185 we could make this staticly,
186 inititialized, but it would
187 be harder to maintain.
191 static u_char initial_mask[255];
192 static u_int sendit_value[255];
203 initial_mask[i] = ALPHA;
205 initial_mask[i] = DIGIT;
207 initial_mask[i] = IGNORE;
211 initial_mask[i] = DASH;
214 initial_mask[i] = COMMENT;
217 initial_mask[i] = IGNORE;
220 initial_mask[i] = QUOTE;
223 initial_mask[i] = SENDIT;
224 sendit_value[i] = OPENPAREN;
227 initial_mask[i] = SENDIT;
228 sendit_value[i] = CLOSEPAREN;
231 initial_mask[i] = SENDIT;
232 sendit_value[i] = COMMA;
235 initial_mask[i] = SENDIT;
236 sendit_value[i] = COLON;
242 initial_mask[i] = IGNORE;
244 initial_mask[0] = EOFILE;
245 initial_mask['\n'] = NEWLINE;
248 build token hash table
251 for(i=0;i<NUMTOKES;i++) {
252 int bucket = hash_string((char *) tokens[i].name);
254 if(tokens[bucket].first_token == -1)
255 tokens[bucket].first_token = i;
258 bucket = tokens[bucket].first_token;
259 while(tokens[bucket].next_token != -1)
260 j++, bucket = tokens[bucket].next_token;
261 tokens[bucket].next_token = i;
269 static int first_time=1;
277 register u_char * ptr = parse_buffer;
280 switch(initial_mask[ *ptr = input_char()]) {
291 return(sendit_value[*ptr]);
294 /* make sure next input is a number */
295 if( initial_mask[*(++ptr)=input_char()] != DIGIT) {
296 fprintf(stderr, "%s: Unsupported char %c (ascii %d) found in callog file\n",
303 while(initial_mask[*(++ptr)=input_char()] == DIGIT)
310 externNumberVal=atoi((char *)parse_buffer);
316 register token_data_t * t;
318 while(initial_mask[*(++ptr)=input_char()] == ALPHA)
325 if ((bucket = tokens[hash_string((char *) parse_buffer)].first_token)
327 fprintf(stderr, "%s: cannot lex %s in callog file\n",
328 pgname, parse_buffer);
332 while(strcmp(tokens[bucket].name, (char*)parse_buffer) != 0)
333 if((bucket = tokens[bucket].next_token) == -1) /* end of chain */ {
334 fprintf(stderr, "%s: cannot lex %s in callog file\n",
335 pgname, parse_buffer);
340 if(t->info_to_change)
341 *((int *) t->info_to_change) = t->token_value;
342 return(t->return_value);
345 case QUOTE: /* note that code removes leading and trailing quotes
348 switch(*ptr = input_char())
351 *++ptr = input_char(); /* load next char in any case */
356 strescapes((char *) parse_buffer); /* process any escape sequences */
357 externQuotedString = (char *) strdup((char *)parse_buffer);
358 return(QUOTEDSTRING);
362 fprintf(stderr, "%s: missing matching \" in callog file\n", pgname);
377 for(i=0;i<3;i++) /* look for 4 **** as comment lead-in */
378 if(initial_mask[*(++ptr)=input_char()]!= COMMENT) {
380 fprintf(stderr, "%s: cannot lex %s in callog file\n",
381 pgname, parse_buffer);
385 while(input_char() != '\n') /* eat up rest of comment */
387 yyylineno++; /* since we eat the newline here.... */
394 fprintf(stderr, "%s: Unsupported char %c (ascii %d) found in callog file\n",
406 munmap(start_of_mmapped_area, len);
415 if(fstat(fileno(f), & buff) < 0) {
420 if((start_of_mmapped_area =
426 0)) == (caddr_t) -1) { /* mmap failed??? */
432 /* no madvise so we lose this optimization */
433 madvise(start_of_mmapped_area, len, MADV_SEQUENTIAL);
436 end = start_of_mmapped_area + len;
437 current_ptr = start_of_mmapped_area;
446 hash_string(register char *s)
448 register unsigned result = 0;
452 result = (result << 4) + sum;
454 return(result % NUMTOKES);
457 /*---------------------------------------------------------------------------
458 Strescapes performs escape character processing in a manner similar to the C
459 compiler. It processes a character string passed to it and performs the
460 following substitutions in place:
470 A single \ in front of other characters is ignored(&removed). As with
471 most string routines, strescapes returns it's argument. Note that
472 inserting a \0 will end the string at that location, but the remainder of
473 the string will be processed.
475 ---------------------------------------------------------------------------*/
481 register char * in=s, * out=s;
488 case 'e': /* an escape character */
493 case 't': /* a tab character */
498 case 'n': /* a newline */
502 case 'r': /* a carriage return */
506 case '\\': /* a backslash */
510 case '0': /* a octal constant */
512 register int i,result;
514 for(result=i=0; (i<=3) && (*in >='0') && (*in <= '7') ; )
517 result += (*in++) - '0';
519 *out++ = result & 0377;
523 default: /* not used as escape.... make it disappear */
524 in++; /* this also handles nulls */
537 main(int argc, char ** argv)
543 printf("usage: %s filename\n", argv[0]);
547 if((f = fopen(argv[1], "r")) == NULL) {
552 if(setinput(f) < 0) {
558 printf("received %d, text <%s>\n", d, parse_buffer);