1 /* $TOG: lexit.c /main/5 1998/04/06 13:13:30 mgreess $ */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company
4 * (c) Copyright 1993, 1994 International Business Machines Corp.
5 * (c) Copyright 1993, 1994 Novell, Inc.
6 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
10 * handcoded lexer to get rid of slow yylook routines
15 #include <EUSCompat.h>
22 #include <sys/param.h>
33 char *externQuotedString;
34 Period_4 externPeriod;
35 Appt_Status_4 externApptStatus;
37 Privacy_Level_4 externPrivacy;
39 static int hash_string P((register char *));
40 static char *strescapes P((char *));
43 static caddr_t start_of_mmapped_area;
44 static caddr_t current_ptr;
47 #define input_char() ((end == current_ptr)?0:(*(current_ptr++)))
48 #define unput_char() (((current_ptr>start_of_mmapped_area)?(current_ptr--):0))
61 the following token entry allows us to combine the
62 hash table, token id and action on token recog
66 typedef struct token_data {
67 const char * name; /* lexical token representation */
68 short first_token; /* index into tokens. points to
69 first token that hashes to this spot.
70 subsequent tokens may be found by following
71 next_token field IN first_token. */
73 void * info_to_change; /* ptr to 4 byte value to change when token
74 is found. Ignored if NULL */
75 int token_value; /* value to set above to. */
76 int return_value; /* value to return from yyylex when this token
80 static u_char parse_buffer[BUFSIZ*3];
81 static u_char initial_mask[255];
82 static u_int sendit_value[255];
85 some macros to save my fingers
88 #define PVAL(a,b) { #a,-1, -1, &externPeriod.period,b,PERIODVAL}
89 #define AVAL(a,b) { #a,-1, -1, &externApptStatus,b,APPTSTATUSVAL}
90 #define TVAL(a,b) { #a,-1, -1, &externTag.tag,b,TAGSVAL }
91 #define SVAL(a,b) { #a,-1, -1, &externPrivacy,b,PRIVACYVAL}
93 #define EMP(a,b) {#a,-1, -1, NULL,NULL,b}
95 token_data_t tokens[] = {
96 PVAL(single, single_4),
98 PVAL(weekly, weekly_4),
99 PVAL(biweekly, biweekly_4),
100 PVAL(monthly, monthly_4),
101 PVAL(yearly, yearly_4),
102 PVAL(nthWeekday, nthWeekday_4),
103 PVAL(everyNthDay, everyNthDay_4),
104 PVAL(everyNthWeek, everyNthWeek_4),
105 PVAL(everyNthMonth, everyNthMonth_4),
106 PVAL(monThruFri, monThruFri_4),
107 PVAL(monWedFri, monWedFri_4),
108 PVAL(tueThur, tueThur_4),
109 PVAL(daysOfWeek, daysOfWeek_4),
111 AVAL(active, active_4),
112 AVAL(pendingAdd, pendingAdd_4),
113 AVAL(pendingDelete, pendingDelete_4),
114 AVAL(committed, committed_4),
115 AVAL(cancelled, cancelled_4),
116 AVAL(completed, completed_4),
118 TVAL(appointment, appointment_4),
119 TVAL(reminder, reminder_4),
120 TVAL(otherTag, otherTag_4),
121 TVAL(holiday, holiday_4),
124 SVAL(public, public_4),
125 SVAL(private, private_4),
126 SVAL(semiprivate, semiprivate_4),
128 EMP(attributes,ATTRIBUTES_4),
129 EMP(attributelist,ATTRIBUTES_5),
131 EMP(Version, VERSION),
132 EMP(calendarattributes,CALATTRS),
133 EMP(duration,DURATION),
136 EMP(enddate,ENDDATE),
139 EMP(details,DETAILS),
141 EMP(exceptions,EXCEPTION),
147 EMP(apptstat,APPTSTATUS),
149 EMP(privacy,PRIVACY),
153 EMP(entrytable, TABLE),
154 EMP(hashedattributes, HASHEDATTRS),
158 #define NUMTOKES (sizeof(tokens)/sizeof(tokens[0]))
161 load parser masks & build
163 we could make this staticly,
164 inititialized, but it would
165 be harder to maintain.
169 static u_char initial_mask[255];
170 static u_int sendit_value[255];
181 initial_mask[i] = ALPHA;
183 initial_mask[i] = DIGIT;
185 initial_mask[i] = IGNORE;
189 initial_mask[i] = DASH;
192 initial_mask[i] = COMMENT;
195 initial_mask[i] = IGNORE;
198 initial_mask[i] = QUOTE;
201 initial_mask[i] = SENDIT;
202 sendit_value[i] = OPENPAREN;
205 initial_mask[i] = SENDIT;
206 sendit_value[i] = CLOSEPAREN;
209 initial_mask[i] = SENDIT;
210 sendit_value[i] = COMMA;
213 initial_mask[i] = SENDIT;
214 sendit_value[i] = COLON;
220 initial_mask[i] = IGNORE;
222 initial_mask[0] = EOFILE;
223 initial_mask['\n'] = NEWLINE;
226 build token hash table
229 for(i=0;i<NUMTOKES;i++) {
230 int bucket = hash_string((char *) tokens[i].name);
232 if(tokens[bucket].first_token == -1)
233 tokens[bucket].first_token = i;
236 bucket = tokens[bucket].first_token;
237 while(tokens[bucket].next_token != -1)
238 j++, bucket = tokens[bucket].next_token;
239 tokens[bucket].next_token = i;
247 static int first_time=1;
255 register u_char * ptr = parse_buffer;
258 switch(initial_mask[ *ptr = input_char()]) {
269 return(sendit_value[*ptr]);
272 /* make sure next input is a number */
273 if( initial_mask[*(++ptr)=input_char()] != DIGIT) {
274 fprintf(stderr, "%s: Unsupported char %c (ascii %d) found in callog file\n",
281 while(initial_mask[*(++ptr)=input_char()] == DIGIT)
288 externNumberVal=atoi((char *)parse_buffer);
294 register token_data_t * t;
296 while(initial_mask[*(++ptr)=input_char()] == ALPHA)
303 if ((bucket = tokens[hash_string((char *) parse_buffer)].first_token)
305 fprintf(stderr, "%s: cannot lex %s in callog file\n",
306 pgname, parse_buffer);
310 while(strcmp(tokens[bucket].name, (char*)parse_buffer) != 0)
311 if((bucket = tokens[bucket].next_token) == -1) /* end of chain */ {
312 fprintf(stderr, "%s: cannot lex %s in callog file\n",
313 pgname, parse_buffer);
318 if(t->info_to_change)
319 *((int *) t->info_to_change) = t->token_value;
320 return(t->return_value);
323 case QUOTE: /* note that code removes leading and trailing quotes
326 switch(*ptr = input_char())
329 *++ptr = input_char(); /* load next char in any case */
334 strescapes((char *) parse_buffer); /* process any escape sequences */
335 externQuotedString = (char *) strdup((char *)parse_buffer);
336 return(QUOTEDSTRING);
340 fprintf(stderr, "%s: missing matching \" in callog file\n", pgname);
355 for(i=0;i<3;i++) /* look for 4 **** as comment lead-in */
356 if(initial_mask[*(++ptr)=input_char()]!= COMMENT) {
358 fprintf(stderr, "%s: cannot lex %s in callog file\n",
359 pgname, parse_buffer);
363 while(input_char() != '\n') /* eat up rest of comment */
365 yyylineno++; /* since we eat the newline here.... */
372 fprintf(stderr, "%s: Unsupported char %c (ascii %d) found in callog file\n",
384 munmap(start_of_mmapped_area, len);
393 if(fstat(fileno(f), & buff) < 0) {
398 if((start_of_mmapped_area =
404 0)) == (caddr_t) -1) { /* mmap failed??? */
409 #if !defined(USL) && !defined(__uxp__) && !defined(linux)
410 /* no madvise so we lose this optimization */
411 madvise(start_of_mmapped_area, len, MADV_SEQUENTIAL);
414 end = start_of_mmapped_area + len;
415 current_ptr = start_of_mmapped_area;
424 hash_string(register char *s)
426 register unsigned result = 0;
430 result = (result << 4) + sum;
432 return(result % NUMTOKES);
435 /*---------------------------------------------------------------------------
436 Strescapes performs escape character processing in a manner similar to the C
437 compiler. It processes a character string passed to it and performs the
438 following substitutions in place:
448 A single \ in front of other characters is ignored(&removed). As with
449 most string routines, strescapes returns it's argument. Note that
450 inserting a \0 will end the string at that location, but the remainder of
451 the string will be processed.
453 ---------------------------------------------------------------------------*/
459 register char * in=s, * out=s;
466 case 'e': /* an escape character */
471 case 't': /* a tab character */
476 case 'n': /* a newline */
480 case 'r': /* a carriage return */
484 case '\\': /* a backslash */
488 case '0': /* a octal constant */
490 register int i,result;
492 for(result=i=0; (i<=3) && (*in >='0') && (*in <= '7') ; )
495 result += (*in++) - '0';
497 *out++ = result & 0377;
501 default: /* not used as escape.... make it disappear */
502 in++; /* this also handles nulls */
515 main(int argc, char ** argv)
521 printf("usage: %s filename\n", argv[0]);
525 if((f = fopen(argv[1], "r")) == NULL) {
530 if(setinput(f) < 0) {
536 printf("received %d, text <%s>\n", d, parse_buffer);