1 /* $XConsortium: reparser.y /main/2 1996/11/11 11:52:15 drk $ */
4 * (c) Copyright 1993, 1994 Hewlett-Packard Company
5 * (c) Copyright 1993, 1994 International Business Machines Corp.
6 * (c) Copyright 1993, 1994 Novell, Inc.
7 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
10 #include <EUSCompat.h>
19 /* The parsed rule is stored in this structure */
20 RepeatEvent *_DtCm_repeat_info;
23 extern void yyerror(char*);
25 static int CompareNums(const void *, const void *);
26 static int CompareDayTime(const void *, const void *);
27 static int CompareWeekDayTime(const void *, const void *);
28 static unsigned int *ConvertNumList(NumberList *, unsigned int * /* Return */);
29 static WeekDayTime *ConvertWeekDayTime(WeekDayTimeList *, unsigned int *);
30 static NumberList *AllocNumber(unsigned int);
31 static WeekDayTimeList *AllocWeekDayTimeList(NumberList*, NumberList *,
33 static RepeatEvent *HandleEndDate(RepeatEvent *, time_t);
34 static RepeatEvent *DeriveMinuteEvent(unsigned int, unsigned int);
35 static RepeatEvent *DeriveDailyEvent(unsigned int, NumberList *,
36 unsigned int, RepeatEvent *);
37 static RepeatEvent *DeriveWeeklyEvent(unsigned int, DayTimeList *,
38 unsigned int, RepeatEvent *);
39 static RepeatEvent *DeriveMonthlyEvent(RepeatType, unsigned int, void *,
40 unsigned int, RepeatEvent *);
41 static RepeatEvent *DeriveYearlyEvent(RepeatType, unsigned int, NumberList *,
42 unsigned int, RepeatEvent *);
46 %token ERROR ENDMARKER DURATION NUMBER FIRSTWEEK SECONDWEEK THIRDWEEK
47 %token FOURTHWEEK FIFTHWEEK LASTWEEK SECONDLAST THIRDLAST FOURTHLAST
48 %token FIFTHLAST MINUTECOMMAND DAILYCOMMAND WEEKLYCOMMAND MONTHPOSCOMMAND
49 %token MONTHDAYCOMMAND YEARDAYCOMMAND YEARMONTHCOMMAND LASTDAY SUNDAY
50 %token MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY DATE
60 WeekDayTimeList *wdtl;
65 %type <re> start begin minuteEvent dailyEvent weeklyEvent monthlyPosEvent
66 monthlyDayEvent yearlyByMonth yearlyByDay
67 %type <nl> time0List timeList dayOfMonthList monthOfYearList
68 dayOfYearList occurrenceList genericNumberList
69 generic0NumberList weekdayList
70 %type <weekday> SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY
72 %type <number> duration NUMBER occurrence endMarker time
73 %type <dtl> weekdayTimeList
74 %type <wdtl> weekDayTime
75 %type <dt> weekdayTimePair
77 %type <enddate> endDate
79 %% /* Beginning of rules section */
83 _DtCm_repeat_info = $$;
88 * XXX: Memory leak: We need to free up any portion
89 * of the re struct that has be allocated before the
90 * error was encountered.
92 _DtCm_repeat_info = NULL;
96 begin : minuteEvent endDate
98 $$ = HandleEndDate($1, $2);
102 $$ = HandleEndDate($1, $2);
104 | weeklyEvent endDate
106 $$ = HandleEndDate($1, $2);
108 | monthlyPosEvent endDate
110 $$ = HandleEndDate($1, $2);
112 | monthlyDayEvent endDate
114 $$ = HandleEndDate($1, $2);
116 | yearlyByMonth endDate
118 $$ = HandleEndDate($1, $2);
120 | yearlyByDay endDate
122 $$ = HandleEndDate($1, $2);
126 minuteEvent : /* empty */
130 | MINUTECOMMAND NUMBER duration
133 $$ = DeriveMinuteEvent($2, $3);
141 : DAILYCOMMAND NUMBER time0List duration minuteEvent
143 $$ = DeriveDailyEvent($2, $3, $4, $5);
149 : WEEKLYCOMMAND NUMBER weekdayTimeList duration minuteEvent
151 $$ = DeriveWeeklyEvent($2, $3, $4, $5);
154 | WEEKLYCOMMAND NUMBER duration minuteEvent
156 $$ = DeriveWeeklyEvent($2, NULL, $3, $4);
162 : MONTHPOSCOMMAND NUMBER weekDayTime duration minuteEvent
164 $$ = DeriveMonthlyEvent(RT_MONTHLY_POSITION,
168 | MONTHPOSCOMMAND NUMBER weekDayTime duration dailyEvent
170 $$ = DeriveMonthlyEvent(RT_MONTHLY_POSITION,
174 | MONTHPOSCOMMAND NUMBER weekDayTime duration weeklyEvent
176 $$ = DeriveMonthlyEvent(RT_MONTHLY_POSITION,
182 monthlyDayEvent : MONTHDAYCOMMAND NUMBER dayOfMonthList duration minuteEvent
184 $$ = DeriveMonthlyEvent(RT_MONTHLY_DAY, $2, $3, $4, $5);
187 | MONTHDAYCOMMAND NUMBER dayOfMonthList duration dailyEvent
189 $$ = DeriveMonthlyEvent(RT_MONTHLY_DAY, $2, $3, $4, $5);
192 | MONTHDAYCOMMAND NUMBER dayOfMonthList duration weeklyEvent
194 $$ = DeriveMonthlyEvent(RT_MONTHLY_DAY, $2, $3, $4, $5);
199 yearlyByMonth : YEARMONTHCOMMAND NUMBER monthOfYearList duration minuteEvent
201 $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
204 | YEARMONTHCOMMAND NUMBER monthOfYearList duration dailyEvent
206 $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
209 | YEARMONTHCOMMAND NUMBER monthOfYearList duration weeklyEvent
211 $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
214 | YEARMONTHCOMMAND NUMBER monthOfYearList duration
217 $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
220 | YEARMONTHCOMMAND NUMBER monthOfYearList duration
223 $$ = DeriveYearlyEvent(RT_YEARLY_MONTH, $2, $3, $4, $5);
228 yearlyByDay : YEARDAYCOMMAND NUMBER dayOfYearList duration minuteEvent
230 $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
233 | YEARDAYCOMMAND NUMBER dayOfYearList duration dailyEvent
235 $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
238 | YEARDAYCOMMAND NUMBER dayOfYearList duration weeklyEvent
240 $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
243 | YEARDAYCOMMAND NUMBER dayOfYearList duration monthlyPosEvent
245 $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
248 | YEARDAYCOMMAND NUMBER dayOfYearList duration monthlyDayEvent
250 $$ = DeriveYearlyEvent(RT_YEARLY_DAY, $2, $3, $4, $5);
255 /* e.g. 1W MO TU 1300 1400 */
256 weekDayTime : /* empty */
260 | weekDayTime occurrenceList weekdayList
262 WeekDayTimeList *wdtl;
264 wdtl = AllocWeekDayTimeList($2, $3, NULL);
269 wdtl->wdtl_next = $$->wdtl_next;
270 $$->wdtl_next = wdtl;
273 | weekDayTime occurrenceList weekdayList timeList
275 WeekDayTimeList *wdtl;
277 wdtl = AllocWeekDayTimeList($2, $3, $4);
282 wdtl->wdtl_next = $$->wdtl_next;
283 $$->wdtl_next = wdtl;
288 /* e.g. MO TU WE TH */
289 weekdayList : weekday
291 $$ = AllocNumber($1);
293 | weekdayList weekday
297 nl = AllocNumber($2);
302 nl->nl_next = $$->nl_next;
308 /* e.g. 1W 3W 2L LW */
309 occurrenceList : occurrence
311 $$ = AllocNumber($1);
313 | occurrenceList occurrence
317 nl = AllocNumber($2);
322 nl->nl_next = $$->nl_next;
328 /* e.g. MO 1300 1500 2000 */
329 weekdayTimePair : weekday time0List
333 dt = (DayTime *)calloc(1, sizeof(DayTime));
336 /* Convert from list to array, sort */
339 (Time *)ConvertNumList($2, &(dt->dt_ntime));
344 /* e.g. MO 1300 1500 2000 TU 1200 1400 */
345 weekdayTimeList : weekdayTimePair
349 dtl = (DayTimeList *)calloc(1, sizeof(DayTimeList));
351 dtl->dtl_daytime = $1;
352 dtl->dtl_next = NULL;
357 | weekdayTimeList weekdayTimePair
362 dtl = (DayTimeList *)calloc(1, sizeof(DayTimeList));
364 dtl->dtl_daytime = $2;
365 dtl->dtl_next = NULL;
370 /* Insert the new entry at the end. This is
371 * so that MO TU 200 300 TH will maintain the
372 * same order in the list since MO uses the
373 * times next to TU and TH is dependent on the
377 while (dtl_end->dtl_next)
378 dtl_end = dtl_end->dtl_next;
380 dtl_end->dtl_next = dtl;
385 /* e.g. 1+ 2+ 3- 1- */
386 occurrence : FIRSTWEEK endMarker
389 if ($2) RE_SET_FLAG($$);
391 | SECONDWEEK endMarker
394 if ($2) RE_SET_FLAG($$);
396 | THIRDWEEK endMarker
399 if ($2) RE_SET_FLAG($$);
401 | FOURTHWEEK endMarker
404 if ($2) RE_SET_FLAG($$);
406 | FIFTHWEEK endMarker
409 if ($2) RE_SET_FLAG($$);
414 if ($2) RE_SET_FLAG($$);
416 | SECONDLAST endMarker
419 if ($2) RE_SET_FLAG($$);
421 | THIRDLAST endMarker
424 if ($2) RE_SET_FLAG($$);
426 | FOURTHLAST endMarker
429 if ($2) RE_SET_FLAG($$);
431 | FIFTHLAST endMarker
434 if ($2) RE_SET_FLAG($$);
438 endDate : /* empty */
444 if (_csa_iso8601_to_tick($1, &$$) == -1)
450 weekday : SUNDAY endMarker
453 if ($2) RE_SET_FLAG($$);
458 if ($2) RE_SET_FLAG($$);
463 if ($2) RE_SET_FLAG($$);
465 | WEDNESDAY endMarker
468 if ($2) RE_SET_FLAG($$);
473 if ($2) RE_SET_FLAG($$);
478 if ($2) RE_SET_FLAG($$);
483 if ($2) RE_SET_FLAG($$);
487 /* e.g. 0100 1200 1300 or NULL */
488 time0List : /* empty */
496 nl = AllocNumber($2);
501 nl->nl_next = $$->nl_next;
508 time : NUMBER endMarker
518 endMarker : /* empty */
529 duration : /* empty */
531 /* If no duration then default to 2 - set later if
538 /* If duration == 0 then repeat forever */
546 timeList : genericNumberList
547 dayOfMonthList : generic0NumberList
548 monthOfYearList : generic0NumberList
549 dayOfYearList : generic0NumberList
551 generic0NumberList: /* empty */
566 $$ = AllocNumber($1);
570 int number = RE_LASTDAY;
575 $$ = AllocNumber(number);
577 | genericNumberList NUMBER endMarker
584 nl = AllocNumber($2);
589 nl->nl_next = $$->nl_next;
593 | genericNumberList LASTDAY endMarker
596 int number = RE_LASTDAY;
601 nl = AllocNumber(number);
606 nl->nl_next = $$->nl_next;
615 * Convert the NumberList (linked list) to an array, sort the array.
617 static unsigned int *
622 NumberList *nl_head = nl;
626 if (!nl) return (unsigned int *)NULL;
633 array = (unsigned int *) calloc(i, sizeof(unsigned int));
635 /* Convert the list into an array */
640 array[i] = nl->nl_number;
652 qsort((void *)array, i, sizeof(unsigned int), CompareNums);
658 * Convert the DayTimeList to an array, sort the array.
665 DayTimeList *dtl_head = dtl;
666 DayTime *daytime_array;
670 if (!dtl) return (DayTime *)NULL;
677 daytime_array = (DayTime *) calloc(i, sizeof(DayTime));
679 /* Convert the list into an array */
682 DayTimeList *dtl_prev;
684 daytime_array[i].dt_day = dtl->dtl_daytime->dt_day;
685 daytime_array[i].dt_ntime = dtl->dtl_daytime->dt_ntime;
686 daytime_array[i].dt_time = dtl->dtl_daytime->dt_time;
691 /* alloc'ed in <weekdayTimeList> */
697 for (i = 0; i < *count; i++) {
698 if (daytime_array[i].dt_time == NULL) {
705 for (j = no_time; j < i; j++) {
706 daytime_array[j].dt_ntime =
707 daytime_array[i].dt_ntime;
708 daytime_array[j].dt_time =
710 daytime_array[j].dt_ntime,
712 memcpy(daytime_array[j].dt_time,
713 daytime_array[i].dt_time,
714 daytime_array[j].dt_ntime *
723 qsort((void *)daytime_array, *count, sizeof(DayTime), CompareDayTime);
725 return daytime_array;
736 const unsigned int *i = (const unsigned int *)data1;
737 const unsigned int *j = (const unsigned int *)data2;
739 if ((unsigned )RE_MASK_STOP(*i) > (unsigned )RE_MASK_STOP(*j))
741 if ((unsigned )RE_MASK_STOP(*i) < (unsigned )RE_MASK_STOP(*j))
754 const DayTime *i = (const DayTime *)data1;
755 const DayTime *j = (const DayTime *)data2;
757 if ((unsigned )RE_MASK_STOP(i->dt_day) >
758 (unsigned )RE_MASK_STOP(j->dt_day))
760 if ((unsigned )RE_MASK_STOP(i->dt_day) <
761 (unsigned )RE_MASK_STOP(j->dt_day))
774 const WeekDayTime *i = (const WeekDayTime *)data1;
775 const WeekDayTime *j = (const WeekDayTime *)data2;
777 if ((unsigned )RE_MASK_STOP(i->wdt_week[0]) >
778 (unsigned )RE_MASK_STOP(j->wdt_week[0]))
780 if ((unsigned )RE_MASK_STOP(i->wdt_week[0]) <
781 (unsigned )RE_MASK_STOP(j->wdt_week[0]))
792 nl = (NumberList *)calloc(1, sizeof(NumberList));
801 * Given three NumberLists convert them into arrays and return a WeekDayTime.
803 static WeekDayTimeList *
804 AllocWeekDayTimeList(
805 NumberList *week_list,
806 NumberList *day_list,
807 NumberList *time_list)
810 WeekDayTimeList *wdtl;
812 wdt = (WeekDayTime *)calloc(1, sizeof(WeekDayTime));
813 wdtl = (WeekDayTimeList *)calloc(1, sizeof(WeekDayTimeList));
816 (WeekNumber *)ConvertNumList(week_list, &(wdt->wdt_nweek));
818 (WeekDay *)ConvertNumList(day_list, &(wdt->wdt_nday));
820 (Time *)ConvertNumList(time_list, &(wdt->wdt_ntime));
821 wdtl->wdtl_weektime = wdt;
827 * Convert the DayTimeList to an array, sort the array.
831 WeekDayTimeList *wdtl,
834 WeekDayTimeList *wdtl_head = wdtl;
838 if (!wdtl) return (WeekDayTime *)NULL;
842 wdtl = wdtl->wdtl_next;
845 array = (WeekDayTime *) calloc(i, sizeof(WeekDayTime));
847 /* Convert the list into an array */
850 WeekDayTimeList *wdtl_prev;
852 array[i].wdt_day = wdtl->wdtl_weektime->wdt_day;
853 array[i].wdt_nday = wdtl->wdtl_weektime->wdt_nday;
854 array[i].wdt_time = wdtl->wdtl_weektime->wdt_time;
855 array[i].wdt_ntime = wdtl->wdtl_weektime->wdt_ntime;
856 array[i].wdt_week = wdtl->wdtl_weektime->wdt_week;
857 array[i].wdt_nweek = wdtl->wdtl_weektime->wdt_nweek;
861 wdtl = wdtl->wdtl_next;
869 qsort((void *)array, i, sizeof(WeekDayTime), CompareWeekDayTime);
881 re->re_end_date = enddate;
882 } else if (re->re_duration == RE_NOTSET) {
890 * Create a RepeatEvent for the minute portion of a rule.
894 unsigned int interval,
895 unsigned int duration)
902 re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
904 re->re_interval = interval;
905 re->re_duration = duration;
906 re->re_type = RT_MINUTE;
912 * Create a RepeatEvent for the daily portion of a rule.
916 unsigned int interval,
917 NumberList *time_list,
918 unsigned int duration,
919 RepeatEvent *other_event)
924 dd = (DailyData *)calloc(1, sizeof(DailyData));
926 /* Convert from list to array, sort */
927 dd->dd_time = (Time *)ConvertNumList(time_list, &(dd->dd_ntime));
934 re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
936 re->re_interval = interval;
937 re->re_duration = duration;
938 re->re_type = RT_DAILY;
939 re->re_data.re_daily = dd;
941 /* If there is a minuteEvent, tack it on */
943 re->re_next = other_event;
944 other_event->re_prev = re;
951 * Create a RepeatEvent for the weekly portion of a rule.
955 unsigned int interval,
957 unsigned int duration,
958 RepeatEvent *other_event)
963 wd = (WeeklyData *)calloc(1, sizeof(WeeklyData));
965 /* Convert from list to array, sort */
966 wd->wd_daytime = ConvertDayTime(dtl, &(wd->wd_ndaytime));
973 re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
975 re->re_interval = interval;
976 re->re_duration = duration;
977 re->re_type = RT_WEEKLY;
978 re->re_data.re_weekly = wd;
981 re->re_next = other_event;
982 other_event->re_prev = re;
989 * Create a RepeatEvent for the monthly portion of a rule.
994 unsigned int interval,
996 unsigned int duration,
997 RepeatEvent *other_event)
1002 md = (MonthlyData *)calloc(1, sizeof(MonthlyData));
1004 /* Convert from list to array, sort */
1005 if (type == RT_MONTHLY_POSITION) {
1006 md->md_weektime = ConvertWeekDayTime(
1007 (WeekDayTimeList *)data_list, &(md->md_nitems));
1009 md->md_days = ConvertNumList(
1010 (NumberList *)data_list, &(md->md_nitems));
1018 re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
1020 re->re_interval = interval;
1021 re->re_duration = duration;
1023 re->re_data.re_monthly = md;
1025 /* If there is an another event, tack it on */
1027 re->re_next = other_event;
1028 other_event->re_prev = re;
1035 * Create a RepeatEvent for the yearly portion of a rule.
1037 static RepeatEvent *
1040 unsigned int interval,
1042 unsigned int duration,
1043 RepeatEvent *other_event)
1048 yd = (YearlyData *)calloc(1, sizeof(YearlyData));
1050 /* Convert from list to array, sort */
1051 yd->yd_items = ConvertNumList(nl, &(yd->yd_nitems));
1058 re = (RepeatEvent *)calloc(1, sizeof(RepeatEvent));
1060 re->re_interval = interval;
1061 re->re_duration = duration;
1063 re->re_data.re_yearly = yd;
1065 /* If there is an another event, tack it on */
1067 re->re_next = other_event;
1068 other_event->re_prev = re;
1078 /* Don't do anything */